From f98f4f0d14961ebabcd214abb9fc3a65e8ee8c7f Mon Sep 17 00:00:00 2001 From: John Preston Date: Tue, 30 Mar 2021 10:01:31 +0400 Subject: Simple receipt viewing. --- Telegram/Resources/langs/lang.strings | 2 + .../payments/payments_checkout_process.cpp | 9 +-- Telegram/SourceFiles/payments/payments_form.cpp | 70 +++++++++++++++++++++- Telegram/SourceFiles/payments/payments_form.h | 4 ++ .../payments/ui/payments_form_summary.cpp | 34 ++++++++--- .../SourceFiles/payments/ui/payments_panel.cpp | 4 +- .../SourceFiles/payments/ui/payments_panel_data.h | 15 +++++ 7 files changed, 120 insertions(+), 18 deletions(-) diff --git a/Telegram/Resources/langs/lang.strings b/Telegram/Resources/langs/lang.strings index 3f49c3076d..1366dd31df 100644 --- a/Telegram/Resources/langs/lang.strings +++ b/Telegram/Resources/langs/lang.strings @@ -1861,7 +1861,9 @@ https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL "lng_payments_receipt_button" = "Receipt"; "lng_payments_checkout_title" = "Checkout"; +"lng_payments_receipt_title" = "Receipt"; "lng_payments_total_label" = "Total"; +"lng_payments_date_label" = "Date"; "lng_payments_pay_amount" = "Pay {amount}"; "lng_payments_payment_method" = "Payment Method"; "lng_payments_new_card" = "New Card..."; diff --git a/Telegram/SourceFiles/payments/payments_checkout_process.cpp b/Telegram/SourceFiles/payments/payments_checkout_process.cpp index 7d67fb94ef..f5508fb7f4 100644 --- a/Telegram/SourceFiles/payments/payments_checkout_process.cpp +++ b/Telegram/SourceFiles/payments/payments_checkout_process.cpp @@ -149,9 +149,7 @@ void CheckoutProcess::handleError(const Error &error) { const auto &id = error.id; switch (error.type) { case Error::Type::Form: - if (id == u"INVOICE_ALREADY_PAID"_q) { - showToast({ "Already Paid!" }); // #TODO payments errors message - } else if (true + if (true || id == u"PROVIDER_ACCOUNT_INVALID"_q || id == u"PROVIDER_ACCOUNT_TIMEOUT"_q) { showToast({ "Error: " + id }); @@ -232,8 +230,6 @@ void CheckoutProcess::handleError(const Error &error) { showToast({ "Error: Payment Failed. Your card has not been billed." }); // #TODO payments errors message } else if (id == u"BOT_PRECHECKOUT_FAILED"_q) { showToast({ "Error: PreCheckout Failed. Your card has not been billed." }); // #TODO payments errors message - } else if (id == u"INVOICE_ALREADY_PAID"_q) { - showToast({ "Already Paid!" }); // #TODO payments errors message } else if (id == u"REQUESTED_INFO_INVALID"_q || id == u"SHIPPING_OPTION_INVALID"_q || id == u"PAYMENT_CREDENTIALS_INVALID"_q @@ -448,7 +444,8 @@ void CheckoutProcess::panelShowBox(object_ptr box) { void CheckoutProcess::performInitialSilentValidation() { const auto &invoice = _form->invoice(); const auto &saved = _form->savedInformation(); - if ((invoice.isNameRequested && saved.name.isEmpty()) + if (invoice.receipt + || (invoice.isNameRequested && saved.name.isEmpty()) || (invoice.isEmailRequested && saved.email.isEmpty()) || (invoice.isPhoneRequested && saved.phone.isEmpty()) || (invoice.isShippingAddressRequested && !saved.shippingAddress)) { diff --git a/Telegram/SourceFiles/payments/payments_form.cpp b/Telegram/SourceFiles/payments/payments_form.cpp index 3cc62685e2..604bba091d 100644 --- a/Telegram/SourceFiles/payments/payments_form.cpp +++ b/Telegram/SourceFiles/payments/payments_form.cpp @@ -94,7 +94,11 @@ Form::Form(not_null session, FullMsgId itemId) , _api(&_session->mtp()) , _msgId(itemId) { fillInvoiceFromMessage(); - requestForm(); + if (_receiptMsgId) { + requestReceipt(); + } else { + requestForm(); + } } Form::~Form() = default; @@ -103,10 +107,16 @@ void Form::fillInvoiceFromMessage() { if (const auto item = _session->data().message(_msgId)) { if (const auto media = item->media()) { if (const auto invoice = media->invoice()) { + _receiptMsgId = FullMsgId( + _msgId.channel, + invoice->receiptMsgId); _invoice.cover = Ui::Cover{ .title = invoice->title, .description = invoice->description, }; + if (_receiptMsgId) { + _invoice.receipt.paid = true; + } if (const auto photo = invoice->photo) { loadThumbnail(photo); } @@ -205,6 +215,18 @@ void Form::requestForm() { }).send(); } +void Form::requestReceipt() { + _api.request(MTPpayments_GetPaymentReceipt( + MTP_int(_receiptMsgId.msg) + )).done([=](const MTPpayments_PaymentReceipt &result) { + result.match([&](const auto &data) { + processReceipt(data); + }); + }).fail([=](const MTP::Error &error) { + _updates.fire(Error{ Error::Type::Form, error.type() }); + }).send(); +} + void Form::processForm(const MTPDpayments_paymentForm &data) { _session->data().processUsers(data.vusers()); @@ -226,6 +248,32 @@ void Form::processForm(const MTPDpayments_paymentForm &data) { _updates.fire(FormReady{}); } +void Form::processReceipt(const MTPDpayments_paymentReceipt &data) { + _session->data().processUsers(data.vusers()); + + data.vinvoice().match([&](const auto &data) { + processInvoice(data); + }); + processDetails(data); + if (const auto info = data.vinfo()) { + info->match([&](const auto &data) { + processSavedInformation(data); + }); + } + if (const auto shipping = data.vshipping()) { + processShippingOptions({ *shipping }); + if (!_shippingOptions.list.empty()) { + _shippingOptions.selectedId = _shippingOptions.list.front().id; + } + } + _paymentMethod.savedCredentials = SavedCredentials{ + .id = "(used)", + .title = qs(data.vcredentials_title()), + }; + fillPaymentMethodInformation(); + _updates.fire(FormReady{}); +} + void Form::processInvoice(const MTPDinvoice &data) { _invoice = Ui::Invoice{ .cover = std::move(_invoice.cover), @@ -246,7 +294,6 @@ void Form::processInvoice(const MTPDinvoice &data) { } void Form::processDetails(const MTPDpayments_paymentForm &data) { - _session->data().processUsers(data.vusers()); const auto nativeParams = data.vnative_params(); auto nativeParamsJson = nativeParams ? nativeParams->match( @@ -268,6 +315,25 @@ void Form::processDetails(const MTPDpayments_paymentForm &data) { } } +void Form::processDetails(const MTPDpayments_paymentReceipt &data) { + _invoice.receipt = Ui::Receipt{ + .date = data.vdate().v, + .totalAmount = *reinterpret_cast( + &data.vtotal_amount().v), + .currency = qs(data.vcurrency()), + .paid = true, + }; + _details = FormDetails{ + .botId = data.vbot_id().v, + .providerId = data.vprovider_id().v, + }; + if (_details.botId) { + if (const auto bot = _session->data().userLoaded(_details.botId)) { + _invoice.cover.seller = bot->name; + } + } +} + void Form::processSavedInformation(const MTPDpaymentRequestedInfo &data) { const auto address = data.vshipping_address(); _savedInformation = Ui::RequestedInformation{ diff --git a/Telegram/SourceFiles/payments/payments_form.h b/Telegram/SourceFiles/payments/payments_form.h index c964a66836..d627df0200 100644 --- a/Telegram/SourceFiles/payments/payments_form.h +++ b/Telegram/SourceFiles/payments/payments_form.h @@ -186,9 +186,12 @@ private: [[nodiscard]] QImage prepareEmptyThumbnail() const; void requestForm(); + void requestReceipt(); void processForm(const MTPDpayments_paymentForm &data); + void processReceipt(const MTPDpayments_paymentReceipt &data); void processInvoice(const MTPDinvoice &data); void processDetails(const MTPDpayments_paymentForm &data); + void processDetails(const MTPDpayments_paymentReceipt &data); void processSavedInformation(const MTPDpaymentRequestedInfo &data); void processSavedCredentials( const MTPDpaymentSavedCredentialsCard &data); @@ -217,6 +220,7 @@ private: const not_null _session; MTP::Sender _api; FullMsgId _msgId; + FullMsgId _receiptMsgId; Ui::Invoice _invoice; std::unique_ptr _thumbnailLoadProcess; diff --git a/Telegram/SourceFiles/payments/ui/payments_form_summary.cpp b/Telegram/SourceFiles/payments/ui/payments_form_summary.cpp index aae6bd1af3..134ca52afb 100644 --- a/Telegram/SourceFiles/payments/ui/payments_form_summary.cpp +++ b/Telegram/SourceFiles/payments/ui/payments_form_summary.cpp @@ -17,6 +17,7 @@ https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL #include "ui/text/format_values.h" #include "data/data_countries.h" #include "lang/lang_keys.h" +#include "base/unixtime.h" #include "styles/style_payments.h" #include "styles/style_passport.h" @@ -187,17 +188,14 @@ void FormSummary::setupCover(not_null layout) { void FormSummary::setupPrices(not_null layout) { Settings::AddSkip(layout, st::paymentsPricesTopSkip); - const auto add = [&]( + const auto addRow = [&]( const QString &label, - int64 amount, + const QString &value, bool full = false) { const auto &st = full ? st::paymentsFullPriceAmount : st::paymentsPriceAmount; - const auto right = CreateChild( - layout.get(), - formatAmount(amount), - st); + const auto right = CreateChild(layout.get(), value, st); const auto &padding = st::paymentsPricePadding; const auto left = layout->add( object_ptr( @@ -220,6 +218,12 @@ void FormSummary::setupPrices(not_null layout) { right->moveToRight(st::paymentsPricePadding.right(), top, width); }, right->lifetime()); }; + const auto add = [&]( + const QString &label, + int64 amount, + bool full = false) { + addRow(label, formatAmount(amount), full); + }; for (const auto &price : _invoice.prices) { add(price.label, price.price); } @@ -234,6 +238,15 @@ void FormSummary::setupPrices(not_null layout) { } add(tr::lng_payments_total_label(tr::now), computeTotalAmount(), true); Settings::AddSkip(layout, st::paymentsPricesBottomSkip); + if (_invoice.receipt) { + Settings::AddDivider(layout); + Settings::AddSkip(layout, st::paymentsPricesBottomSkip); + addRow( + tr::lng_payments_date_label(tr::now), + langDateTime(base::unixtime::parse(_invoice.receipt.date)), + true); + Settings::AddSkip(layout, st::paymentsPricesBottomSkip); + } } void FormSummary::setupSections(not_null layout) { @@ -244,13 +257,16 @@ void FormSummary::setupSections(not_null layout) { const QString &label, const style::icon *icon, Fn handler) { - Settings::AddButtonWithLabel( + const auto button = Settings::AddButtonWithLabel( layout, std::move(title), rpl::single(label), st::paymentsSectionButton, - icon - )->addClickHandler(std::move(handler)); + icon); + button->addClickHandler(std::move(handler)); + if (_invoice.receipt) { + button->setAttribute(Qt::WA_TransparentForMouseEvents); + } }; add( tr::lng_payments_payment_method(), diff --git a/Telegram/SourceFiles/payments/ui/payments_panel.cpp b/Telegram/SourceFiles/payments/ui/payments_panel.cpp index d39a7ab697..f5c7015cc4 100644 --- a/Telegram/SourceFiles/payments/ui/payments_panel.cpp +++ b/Telegram/SourceFiles/payments/ui/payments_panel.cpp @@ -51,7 +51,9 @@ void Panel::showForm( const RequestedInformation ¤t, const PaymentMethodDetails &method, const ShippingOptions &options) { - _widget->setTitle(tr::lng_payments_checkout_title()); + _widget->setTitle(invoice.receipt + ? tr::lng_payments_receipt_title() + : tr::lng_payments_checkout_title()); auto form = base::make_unique_q( _widget.get(), invoice, diff --git a/Telegram/SourceFiles/payments/ui/payments_panel_data.h b/Telegram/SourceFiles/payments/ui/payments_panel_data.h index da920af39a..e530bf6b7c 100644 --- a/Telegram/SourceFiles/payments/ui/payments_panel_data.h +++ b/Telegram/SourceFiles/payments/ui/payments_panel_data.h @@ -21,11 +21,26 @@ struct Cover { QImage thumbnail; }; +struct Receipt { + TimeId date = 0; + int64 totalAmount = 0; + QString currency; + bool paid = false; + + [[nodiscard]] bool empty() const { + return !paid; + } + [[nodiscard]] explicit operator bool() const { + return !empty(); + } +}; + struct Invoice { Cover cover; std::vector prices; QString currency; + Receipt receipt; bool isNameRequested = false; bool isPhoneRequested = false; -- cgit v1.2.3