From 9b11b95c5b64d88e97f8a53b32c0b4b326b8afee Mon Sep 17 00:00:00 2001 From: 23rd <23rd@vivaldi.net> Date: Fri, 17 May 2024 03:37:56 +0300 Subject: [PATCH] Added api support of invoice payments for credits. --- .../payments/payments_checkout_process.cpp | 22 ++++++++++++ .../payments/payments_checkout_process.h | 4 +++ .../SourceFiles/payments/payments_form.cpp | 11 ++++++ Telegram/SourceFiles/payments/payments_form.h | 15 +++++++- .../SourceFiles/settings/settings_credits.cpp | 35 +++++++++++++++++++ 5 files changed, 86 insertions(+), 1 deletion(-) diff --git a/Telegram/SourceFiles/payments/payments_checkout_process.cpp b/Telegram/SourceFiles/payments/payments_checkout_process.cpp index e9fb12d269..108376084d 100644 --- a/Telegram/SourceFiles/payments/payments_checkout_process.cpp +++ b/Telegram/SourceFiles/payments/payments_checkout_process.cpp @@ -139,6 +139,28 @@ void CheckoutProcess::Start( j->second->requestActivate(); } +void CheckoutProcess::Start( + InvoiceCredits creditsInvoice, + Fn reactivate) { + const auto randomId = creditsInvoice.randomId; + auto id = InvoiceId{ std::move(creditsInvoice) }; + auto &processes = LookupSessionProcesses(SessionFromId(id)); + const auto i = processes.byRandomId.find(randomId); + if (i != end(processes.byRandomId)) { + i->second->setReactivateCallback(std::move(reactivate)); + i->second->requestActivate(); + return; + } + const auto j = processes.byRandomId.emplace( + randomId, + std::make_unique( + std::move(id), + Mode::Payment, + std::move(reactivate), + PrivateTag{})).first; + j->second->requestActivate(); +} + std::optional CheckoutProcess::InvoicePaid( not_null item) { const auto session = &item->history()->session(); diff --git a/Telegram/SourceFiles/payments/payments_checkout_process.h b/Telegram/SourceFiles/payments/payments_checkout_process.h index dd995324ff..9a87039272 100644 --- a/Telegram/SourceFiles/payments/payments_checkout_process.h +++ b/Telegram/SourceFiles/payments/payments_checkout_process.h @@ -37,6 +37,7 @@ namespace Payments { class Form; struct FormUpdate; struct Error; +struct InvoiceCredits; struct InvoiceId; struct InvoicePremiumGiftCode; @@ -73,6 +74,9 @@ public: static void Start( InvoicePremiumGiftCode giftCodeInvoice, Fn reactivate); + static void Start( + InvoiceCredits creditsInvoice, + Fn reactivate); [[nodiscard]] static std::optional InvoicePaid( not_null item); [[nodiscard]] static std::optional InvoicePaid( diff --git a/Telegram/SourceFiles/payments/payments_form.cpp b/Telegram/SourceFiles/payments/payments_form.cpp index 16469cb1ed..c02ea408b7 100644 --- a/Telegram/SourceFiles/payments/payments_form.cpp +++ b/Telegram/SourceFiles/payments/payments_form.cpp @@ -117,6 +117,8 @@ not_null SessionFromId(const InvoiceId &id) { return &message->peer->session(); } else if (const auto slug = std::get_if(&id.value)) { return slug->session; + } else if (const auto slug = std::get_if(&id.value)) { + return slug->session; } const auto &giftCode = v::get(id.value); const auto users = std::get_if( @@ -314,6 +316,15 @@ MTPInputInvoice Form::inputInvoice() const { MTP_int(message->itemId.bare)); } else if (const auto slug = std::get_if(&_id.value)) { return MTP_inputInvoiceSlug(MTP_string(slug->slug)); + } else if (const auto credits = std::get_if(&_id.value)) { + return MTP_inputInvoiceStars(MTP_starsTopupOption( + credits->product.isEmpty() + ? MTP_flags(0) + : MTP_flags(MTPDstarsTopupOption::Flag::f_store_product), + MTP_long(credits->credits), + MTP_string(credits->product), + MTP_string(credits->currency), + MTP_long(credits->amount))); } const auto &giftCode = v::get(_id.value); using Flag = MTPDpremiumGiftCodeOption::Flag; diff --git a/Telegram/SourceFiles/payments/payments_form.h b/Telegram/SourceFiles/payments/payments_form.h index 68cb75cebe..92448feb6d 100644 --- a/Telegram/SourceFiles/payments/payments_form.h +++ b/Telegram/SourceFiles/payments/payments_form.h @@ -216,8 +216,21 @@ struct InvoicePremiumGiftCode { int months = 0; }; +struct InvoiceCredits { + not_null session; + uint64 randomId = 0; + uint64 credits = 0; + QString product; + QString currency; + uint64 amount = 0; +}; + struct InvoiceId { - std::variant value; + std::variant< + InvoiceMessage, + InvoiceSlug, + InvoicePremiumGiftCode, + InvoiceCredits> value; }; [[nodiscard]] not_null SessionFromId(const InvoiceId &id); diff --git a/Telegram/SourceFiles/settings/settings_credits.cpp b/Telegram/SourceFiles/settings/settings_credits.cpp index 10ac6e011d..6509fe0a6d 100644 --- a/Telegram/SourceFiles/settings/settings_credits.cpp +++ b/Telegram/SourceFiles/settings/settings_credits.cpp @@ -13,7 +13,10 @@ https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL #include "info/settings/info_settings_widget.h" // SectionCustomTopBarData. #include "lang/lang_keys.h" #include "main/main_session.h" +#include "payments/payments_checkout_process.h" +#include "payments/payments_form.h" #include "settings/settings_common_session.h" +#include "ui/boxes/boost_box.h" // Ui::StartFireworks. #include "ui/effects/premium_graphics.h" #include "ui/effects/premium_top_bar.h" #include "ui/image/image_prepare.h" @@ -33,6 +36,8 @@ https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL #include "styles/style_layers.h" #include "styles/style_settings.h" +#include // XXH64. + #include namespace Settings { @@ -40,6 +45,16 @@ namespace { using SectionCustomTopBarData = Info::Settings::SectionCustomTopBarData; +[[nodiscard]] uint64 UniqueIdFromOption( + const Data::CreditTopupOption &d) { + const auto string = QString::number(d.credits) + + d.product + + d.currency + + QString::number(d.amount); + + return XXH64(string.data(), string.size() * sizeof(ushort), 0); +} + [[nodiscard]] QImage GenerateStarForLightTopBar(QRectF rect) { const auto strokeWidth = 3; @@ -177,6 +192,26 @@ void Credits::setupOptions(not_null container) { icon->moveToLeft(st.iconLeft, st.padding.top()); }, button->lifetime()); button->setClickedCallback([=] { + const auto invoice = Payments::InvoiceCredits{ + .session = &_controller->session(), + .randomId = UniqueIdFromOption(option), + .credits = option.credits, + .product = option.product, + .currency = option.currency, + .amount = option.amount, + }; + + const auto weak = Ui::MakeWeak(button); + const auto done = [=](Payments::CheckoutResult result) { + if (const auto strong = weak.data()) { + strong->window()->setFocus(); + if (result == Payments::CheckoutResult::Paid) { + Ui::StartFireworks(this); + } + } + }; + + Payments::CheckoutProcess::Start(std::move(invoice), done); }); Ui::ToggleChildrenVisibility(button, true); }