payments_non_panel_process.cpp 5.4 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176
  1. /*
  2. This file is part of Telegram Desktop,
  3. the official desktop application for the Telegram messaging service.
  4. For license and copyright information please follow this link:
  5. https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL
  6. */
  7. #include "payments/payments_non_panel_process.h"
  8. #include "api/api_credits.h"
  9. #include "base/unixtime.h"
  10. #include "boxes/send_credits_box.h"
  11. #include "data/components/credits.h"
  12. #include "data/data_credits.h"
  13. #include "data/data_photo.h"
  14. #include "data/data_user.h"
  15. #include "history/history_item.h"
  16. #include "history/history_item_components.h"
  17. #include "lang/lang_keys.h"
  18. #include "main/main_session.h"
  19. #include "mainwidget.h"
  20. #include "payments/payments_checkout_process.h" // NonPanelPaymentForm.
  21. #include "payments/payments_form.h"
  22. #include "settings/settings_credits_graphics.h"
  23. #include "ui/boxes/boost_box.h" // Ui::StartFireworks.
  24. #include "ui/layers/generic_box.h"
  25. #include "ui/text/format_values.h"
  26. #include "ui/text/text_utilities.h"
  27. #include "ui/toast/toast.h"
  28. #include "window/window_controller.h"
  29. #include "window/window_session_controller.h"
  30. namespace Payments {
  31. bool IsCreditsInvoice(not_null<HistoryItem*> item) {
  32. if (const auto payment = item->Get<HistoryServicePayment>()) {
  33. return payment->isCreditsCurrency;
  34. }
  35. const auto media = item->media();
  36. const auto invoice = media ? media->invoice() : nullptr;
  37. return invoice && (invoice->currency == Ui::kCreditsCurrency);
  38. }
  39. void ProcessCreditsPayment(
  40. std::shared_ptr<Main::SessionShow> show,
  41. QPointer<QWidget> fireworks,
  42. std::shared_ptr<CreditsFormData> form,
  43. Fn<void(CheckoutResult)> maybeReturnToBot) {
  44. const auto done = [=](Settings::SmallBalanceResult result) {
  45. if (result == Settings::SmallBalanceResult::Blocked) {
  46. if (const auto onstack = maybeReturnToBot) {
  47. onstack(CheckoutResult::Failed);
  48. }
  49. return;
  50. } else if (result == Settings::SmallBalanceResult::Cancelled) {
  51. if (const auto onstack = maybeReturnToBot) {
  52. onstack(CheckoutResult::Cancelled);
  53. }
  54. return;
  55. } else if (form->starGiftForm
  56. || IsPremiumForStarsInvoice(form->id)) {
  57. const auto done = [=](std::optional<QString> error) {
  58. const auto onstack = maybeReturnToBot;
  59. if (error) {
  60. if (*error == u"STARGIFT_USAGE_LIMITED"_q) {
  61. if (form->starGiftLimitedCount) {
  62. show->showToast({
  63. .title = tr::lng_gift_sold_out_title(
  64. tr::now),
  65. .text = tr::lng_gift_sold_out_text(
  66. tr::now,
  67. lt_count_decimal,
  68. form->starGiftLimitedCount,
  69. Ui::Text::RichLangValue),
  70. });
  71. } else {
  72. show->showToast(
  73. tr::lng_gift_sold_out_title(tr::now));
  74. }
  75. } else {
  76. show->showToast(*error);
  77. }
  78. if (onstack) {
  79. onstack(CheckoutResult::Failed);
  80. }
  81. } else if (onstack) {
  82. onstack(CheckoutResult::Paid);
  83. }
  84. };
  85. Ui::SendStarsForm(&show->session(), form, done);
  86. return;
  87. }
  88. const auto unsuccessful = std::make_shared<bool>(true);
  89. const auto box = show->show(Box(
  90. Ui::SendCreditsBox,
  91. form,
  92. [=] {
  93. *unsuccessful = false;
  94. if (const auto widget = fireworks.data()) {
  95. Ui::StartFireworks(widget);
  96. }
  97. if (const auto onstack = maybeReturnToBot) {
  98. onstack(CheckoutResult::Paid);
  99. }
  100. }));
  101. box->boxClosing() | rpl::start_with_next([=] {
  102. crl::on_main([=] {
  103. if (*unsuccessful) {
  104. if (const auto onstack = maybeReturnToBot) {
  105. onstack(CheckoutResult::Cancelled);
  106. }
  107. }
  108. });
  109. }, box->lifetime());
  110. };
  111. using namespace Settings;
  112. const auto starGift = std::get_if<InvoiceStarGift>(&form->id.value);
  113. auto source = !starGift
  114. ? SmallBalanceSource(SmallBalanceBot{ .botId = form->botId })
  115. : SmallBalanceSource(SmallBalanceStarGift{
  116. .recipientId = starGift->recipient->id,
  117. });
  118. MaybeRequestBalanceIncrease(show, form->invoice.credits, source, done);
  119. }
  120. void ProcessCreditsReceipt(
  121. not_null<Window::SessionController*> controller,
  122. std::shared_ptr<CreditsReceiptData> receipt,
  123. Fn<void(CheckoutResult)> maybeReturnToBot) {
  124. const auto entry = Data::CreditsHistoryEntry{
  125. .id = receipt->id,
  126. .title = receipt->title,
  127. .description = { receipt->description },
  128. .date = base::unixtime::parse(receipt->date),
  129. .photoId = receipt->photo ? receipt->photo->id : 0,
  130. .credits = receipt->credits,
  131. .bareMsgId = uint64(),
  132. .barePeerId = receipt->peerId.value,
  133. .peerType = Data::CreditsHistoryEntry::PeerType::Peer,
  134. };
  135. controller->uiShow()->show(Box(
  136. Settings::ReceiptCreditsBox,
  137. controller,
  138. entry,
  139. Data::SubscriptionEntry{}));
  140. controller->window().activate();
  141. }
  142. Fn<void(NonPanelPaymentForm)> ProcessNonPanelPaymentFormFactory(
  143. not_null<Window::SessionController*> controller,
  144. Fn<void(CheckoutResult)> maybeReturnToBot) {
  145. return [=](NonPanelPaymentForm form) {
  146. using CreditsFormDataPtr = std::shared_ptr<CreditsFormData>;
  147. using CreditsReceiptPtr = std::shared_ptr<CreditsReceiptData>;
  148. v::match(form, [&](const CreditsFormDataPtr &form) {
  149. ProcessCreditsPayment(
  150. controller->uiShow(),
  151. controller->content().get(),
  152. form,
  153. maybeReturnToBot);
  154. controller->window().activate();
  155. }, [&](const CreditsReceiptPtr &receipt) {
  156. ProcessCreditsReceipt(controller, receipt, maybeReturnToBot);
  157. }, [](RealFormPresentedNotification) {});
  158. };
  159. }
  160. Fn<void(NonPanelPaymentForm)> ProcessNonPanelPaymentFormFactory(
  161. not_null<Window::SessionController*> controller,
  162. not_null<HistoryItem*> item) {
  163. return IsCreditsInvoice(item)
  164. ? ProcessNonPanelPaymentFormFactory(controller)
  165. : nullptr;
  166. }
  167. } // namespace Payments