Simple receipt viewing.

This commit is contained in:
John Preston 2021-03-30 10:01:31 +04:00
parent 78def16ced
commit f98f4f0d14
7 changed files with 120 additions and 18 deletions

View File

@ -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...";

View File

@ -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<Ui::BoxContent> 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)) {

View File

@ -94,7 +94,11 @@ Form::Form(not_null<Main::Session*> 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<const int64*>(
&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{

View File

@ -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<Main::Session*> _session;
MTP::Sender _api;
FullMsgId _msgId;
FullMsgId _receiptMsgId;
Ui::Invoice _invoice;
std::unique_ptr<ThumbnailLoadProcess> _thumbnailLoadProcess;

View File

@ -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<VerticalLayout*> layout) {
void FormSummary::setupPrices(not_null<VerticalLayout*> 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<FlatLabel>(
layout.get(),
formatAmount(amount),
st);
const auto right = CreateChild<FlatLabel>(layout.get(), value, st);
const auto &padding = st::paymentsPricePadding;
const auto left = layout->add(
object_ptr<FlatLabel>(
@ -220,6 +218,12 @@ void FormSummary::setupPrices(not_null<VerticalLayout*> 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<VerticalLayout*> 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<VerticalLayout*> layout) {
@ -244,13 +257,16 @@ void FormSummary::setupSections(not_null<VerticalLayout*> layout) {
const QString &label,
const style::icon *icon,
Fn<void()> 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(),

View File

@ -51,7 +51,9 @@ void Panel::showForm(
const RequestedInformation &current,
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<FormSummary>(
_widget.get(),
invoice,

View File

@ -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<LabeledPrice> prices;
QString currency;
Receipt receipt;
bool isNameRequested = false;
bool isPhoneRequested = false;