mirror of
https://github.com/AyuGram/AyuGramDesktop.git
synced 2025-04-15 21:57:10 +02:00
Support additional saved payment methods.
This commit is contained in:
parent
e492a18194
commit
f7885da7dd
9 changed files with 155 additions and 77 deletions
|
@ -2397,7 +2397,6 @@ https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL
|
|||
"lng_theme_editor_menu_show" = "Show palette file";
|
||||
|
||||
"lng_payments_not_supported" = "Sorry, Telegram Desktop doesn't support payments yet. Please use one of our mobile apps to do this.";
|
||||
"lng_payments_webview_no_card" = "Unfortunately, you can't add a new card with current system configuration.";
|
||||
"lng_payments_webview_no_use" = "Unfortunately, you can't use payments with current system configuration.";
|
||||
"lng_payments_webview_install_edge" = "Please install {link}.";
|
||||
"lng_payments_webview_install_webkit" = "Please install WebKitGTK (webkit2gtk-5.0/webkit2gtk-4.1/webkit2gtk-4.0) using your package manager.";
|
||||
|
|
|
@ -853,7 +853,7 @@ inputWebFileGeoPointLocation#9f2221c9 geo_point:InputGeoPoint access_hash:long w
|
|||
|
||||
upload.webFile#21e753bc size:int mime_type:string file_type:storage.FileType mtime:int bytes:bytes = upload.WebFile;
|
||||
|
||||
payments.paymentForm#4cc5563f flags:# can_save_credentials:flags.2?true password_missing:flags.3?true form_id:long bot_id:long title:string description:string photo:flags.5?WebDocument invoice:Invoice provider_id:long url:string native_provider:flags.4?string native_params:flags.4?DataJSON additional_methods:flags.6?Vector<PaymentFormMethod> saved_info:flags.0?PaymentRequestedInfo saved_credentials:flags.1?PaymentSavedCredentials users:Vector<User> = payments.PaymentForm;
|
||||
payments.paymentForm#a0058751 flags:# can_save_credentials:flags.2?true password_missing:flags.3?true form_id:long bot_id:long title:string description:string photo:flags.5?WebDocument invoice:Invoice provider_id:long url:string native_provider:flags.4?string native_params:flags.4?DataJSON additional_methods:flags.6?Vector<PaymentFormMethod> saved_info:flags.0?PaymentRequestedInfo saved_credentials:flags.1?Vector<PaymentSavedCredentials> users:Vector<User> = payments.PaymentForm;
|
||||
|
||||
payments.validatedRequestedInfo#d1451883 flags:# id:flags.0?string shipping_options:flags.1?Vector<ShippingOption> = payments.ValidatedRequestedInfo;
|
||||
|
||||
|
|
|
@ -234,6 +234,11 @@ CheckoutProcess::CheckoutProcess(
|
|||
handleFormUpdate(update);
|
||||
}, _lifetime);
|
||||
|
||||
_panel->savedMethodChosen(
|
||||
) | rpl::start_with_next([=](QString id) {
|
||||
_form->chooseSavedMethod(id);
|
||||
}, _panel->lifetime());
|
||||
|
||||
_panel->backRequests(
|
||||
) | rpl::start_with_next([=] {
|
||||
panelCancelEdit();
|
||||
|
@ -284,7 +289,7 @@ void CheckoutProcess::handleFormUpdate(const FormUpdate &update) {
|
|||
if (!_initialSilentValidation) {
|
||||
showForm();
|
||||
}
|
||||
if (_form->paymentMethod().savedCredentials) {
|
||||
if (!_form->paymentMethod().savedCredentials.empty()) {
|
||||
_session->api().cloudPassword().reload();
|
||||
}
|
||||
}, [&](const ThumbnailUpdated &data) {
|
||||
|
@ -532,7 +537,8 @@ void CheckoutProcess::panelSubmit() {
|
|||
|| invoice.isPhoneRequested)) {
|
||||
_submitState = SubmitState::Validating;
|
||||
_form->validateInformation(_form->information());
|
||||
} else if (!method.newCredentials && !method.savedCredentials) {
|
||||
} else if (!method.newCredentials
|
||||
&& method.savedCredentialsIndex >= method.savedCredentials.size()) {
|
||||
editPaymentMethod();
|
||||
} else if (invoice.isRecurring && !_form->details().termsAccepted) {
|
||||
_panel->requestTermsAcceptance(
|
||||
|
@ -712,10 +718,13 @@ void CheckoutProcess::requestPassword() {
|
|||
getPasswordState([=](const Core::CloudPasswordState &state) {
|
||||
auto fields = PasscodeBox::CloudFields::From(state);
|
||||
fields.customTitle = tr::lng_payments_password_title();
|
||||
const auto &method = _form->paymentMethod();
|
||||
const auto &list = method.savedCredentials;
|
||||
const auto index = method.savedCredentialsIndex;
|
||||
fields.customDescription = tr::lng_payments_password_description(
|
||||
tr::now,
|
||||
lt_card,
|
||||
_form->paymentMethod().savedCredentials.title);
|
||||
(index < list.size()) ? list[index].title : QString());
|
||||
fields.customSubmitButton = tr::lng_payments_password_submit();
|
||||
fields.customCheckCallback = [=](
|
||||
const Core::CloudPasswordResult &result) {
|
||||
|
|
|
@ -314,10 +314,15 @@ void Form::processForm(const MTPDpayments_paymentForm &data) {
|
|||
processSavedInformation(data);
|
||||
});
|
||||
}
|
||||
_paymentMethod.savedCredentials.clear();
|
||||
_paymentMethod.savedCredentialsIndex = 0;
|
||||
if (const auto credentials = data.vsaved_credentials()) {
|
||||
credentials->match([&](const auto &data) {
|
||||
processSavedCredentials(data);
|
||||
});
|
||||
_paymentMethod.savedCredentials.reserve(credentials->v.size());
|
||||
for (const auto &saved : credentials->v) {
|
||||
saved.match([&](const auto &data) {
|
||||
addSavedCredentials(data);
|
||||
});
|
||||
}
|
||||
}
|
||||
if (const auto additional = data.vadditional_methods()) {
|
||||
processAdditionalPaymentMethods(additional->v);
|
||||
|
@ -344,10 +349,11 @@ void Form::processReceipt(const MTPDpayments_paymentReceipt &data) {
|
|||
_shippingOptions.selectedId = _shippingOptions.list.front().id;
|
||||
}
|
||||
}
|
||||
_paymentMethod.savedCredentials = SavedCredentials{
|
||||
_paymentMethod.savedCredentials = { {
|
||||
.id = "(used)",
|
||||
.title = qs(data.vcredentials_title()),
|
||||
};
|
||||
} };
|
||||
_paymentMethod.savedCredentialsIndex = 0;
|
||||
fillPaymentMethodInformation();
|
||||
_updates.fire(FormReady{});
|
||||
}
|
||||
|
@ -467,12 +473,12 @@ void Form::processSavedInformation(const MTPDpaymentRequestedInfo &data) {
|
|||
};
|
||||
}
|
||||
|
||||
void Form::processSavedCredentials(
|
||||
void Form::addSavedCredentials(
|
||||
const MTPDpaymentSavedCredentialsCard &data) {
|
||||
_paymentMethod.savedCredentials = SavedCredentials{
|
||||
_paymentMethod.savedCredentials.push_back({
|
||||
.id = qs(data.vid()),
|
||||
.title = qs(data.vtitle()),
|
||||
};
|
||||
});
|
||||
refreshPaymentMethodDetails();
|
||||
}
|
||||
|
||||
|
@ -489,17 +495,33 @@ void Form::processAdditionalPaymentMethods(
|
|||
}
|
||||
|
||||
void Form::refreshPaymentMethodDetails() {
|
||||
const auto &saved = _paymentMethod.savedCredentials;
|
||||
const auto &entered = _paymentMethod.newCredentials;
|
||||
_paymentMethod.ui.title = entered ? entered.title : saved.title;
|
||||
refreshSavedPaymentMethodDetails();
|
||||
_paymentMethod.ui.provider = _invoice.provider;
|
||||
_paymentMethod.ui.ready = entered || saved;
|
||||
_paymentMethod.ui.native.defaultCountry = defaultCountry();
|
||||
_paymentMethod.ui.canSaveInformation
|
||||
= _paymentMethod.ui.native.canSaveInformation
|
||||
= _details.canSaveCredentials || _details.passwordMissing;
|
||||
}
|
||||
|
||||
void Form::refreshSavedPaymentMethodDetails() {
|
||||
const auto &list = _paymentMethod.savedCredentials;
|
||||
const auto index = _paymentMethod.savedCredentialsIndex;
|
||||
const auto &entered = _paymentMethod.newCredentials;
|
||||
_paymentMethod.ui.savedMethods.clear();
|
||||
if (entered) {
|
||||
_paymentMethod.ui.savedMethods.push_back({ .title = entered.title });
|
||||
}
|
||||
for (const auto &item : list) {
|
||||
_paymentMethod.ui.savedMethods.push_back({
|
||||
.id = item.id,
|
||||
.title = item.title,
|
||||
});
|
||||
}
|
||||
_paymentMethod.ui.savedMethodIndex = (index < list.size())
|
||||
? (index + (entered ? 1 : 0))
|
||||
: 0;
|
||||
}
|
||||
|
||||
QString Form::defaultPhone() const {
|
||||
return _session->user()->phone();
|
||||
}
|
||||
|
@ -588,12 +610,16 @@ void Form::fillSmartGlocalNativeMethod(QJsonObject object) {
|
|||
|
||||
void Form::submit() {
|
||||
Expects(_paymentMethod.newCredentials
|
||||
|| _paymentMethod.savedCredentials);
|
||||
|| (_paymentMethod.savedCredentialsIndex
|
||||
< _paymentMethod.savedCredentials.size()));
|
||||
|
||||
const auto password = _paymentMethod.newCredentials
|
||||
? QByteArray()
|
||||
: _session->validTmpPassword();
|
||||
if (!_paymentMethod.newCredentials && password.isEmpty()) {
|
||||
const auto index = _paymentMethod.savedCredentialsIndex;
|
||||
const auto &list = _paymentMethod.savedCredentials;
|
||||
|
||||
const auto password = (index < list.size())
|
||||
? _session->validTmpPassword()
|
||||
: QByteArray();
|
||||
if (index < list.size() && password.isEmpty()) {
|
||||
_updates.fire(TmpPasswordRequired{});
|
||||
return;
|
||||
} else if (!_session->local().isBotTrustedPayment(_details.botId)) {
|
||||
|
@ -618,16 +644,16 @@ void Form::submit() {
|
|||
inputInvoice(),
|
||||
MTP_string(_requestedInformationId),
|
||||
MTP_string(_shippingOptions.selectedId),
|
||||
(_paymentMethod.newCredentials
|
||||
? MTP_inputPaymentCredentials(
|
||||
(index < list.size()
|
||||
? MTP_inputPaymentCredentialsSaved(
|
||||
MTP_string(list[index].id),
|
||||
MTP_bytes(password))
|
||||
: MTP_inputPaymentCredentials(
|
||||
MTP_flags((_paymentMethod.newCredentials.saveOnServer
|
||||
&& _details.canSaveCredentials)
|
||||
? MTPDinputPaymentCredentials::Flag::f_save
|
||||
: MTPDinputPaymentCredentials::Flag(0)),
|
||||
MTP_dataJSON(MTP_bytes(_paymentMethod.newCredentials.data)))
|
||||
: MTP_inputPaymentCredentialsSaved(
|
||||
MTP_string(_paymentMethod.savedCredentials.id),
|
||||
MTP_bytes(password))),
|
||||
MTP_dataJSON(MTP_bytes(_paymentMethod.newCredentials.data)))),
|
||||
MTP_long(_invoice.tipsSelected)
|
||||
)).done([=](const MTPpayments_PaymentResult &result) {
|
||||
hideProgress();
|
||||
|
@ -725,7 +751,9 @@ bool Form::hasChanges() const {
|
|||
return (information != _savedInformation)
|
||||
|| (_stripe != nullptr)
|
||||
|| (_smartglocal != nullptr)
|
||||
|| !_paymentMethod.newCredentials.empty();
|
||||
|| (!_paymentMethod.newCredentials.empty()
|
||||
&& (_paymentMethod.savedCredentialsIndex
|
||||
>= _paymentMethod.savedCredentials.size()));
|
||||
}
|
||||
|
||||
bool Form::validateInformationLocal(
|
||||
|
@ -940,10 +968,30 @@ void Form::setPaymentCredentials(const NewCredentials &credentials) {
|
|||
Expects(!credentials.empty());
|
||||
|
||||
_paymentMethod.newCredentials = credentials;
|
||||
_paymentMethod.savedCredentialsIndex
|
||||
= _paymentMethod.savedCredentials.size();
|
||||
refreshSavedPaymentMethodDetails();
|
||||
const auto requestNewPassword = credentials.saveOnServer
|
||||
&& !_details.canSaveCredentials
|
||||
&& _details.passwordMissing;
|
||||
refreshPaymentMethodDetails();
|
||||
_updates.fire(PaymentMethodUpdate{ requestNewPassword });
|
||||
}
|
||||
|
||||
void Form::chooseSavedMethod(const QString &id) {
|
||||
auto &index = _paymentMethod.savedCredentialsIndex;
|
||||
const auto &list = _paymentMethod.savedCredentials;
|
||||
if (id.isEmpty() && _paymentMethod.newCredentials) {
|
||||
index = list.size();
|
||||
} else {
|
||||
const auto i = ranges::find(list, id, &SavedCredentials::id);
|
||||
index = (i != end(list)) ? (i - begin(list)) : 0;
|
||||
}
|
||||
refreshSavedPaymentMethodDetails();
|
||||
const auto requestNewPassword = (index == list.size())
|
||||
&& _paymentMethod.newCredentials
|
||||
&& _paymentMethod.newCredentials.saveOnServer
|
||||
&& !_details.canSaveCredentials
|
||||
&& _details.passwordMissing;
|
||||
_updates.fire(PaymentMethodUpdate{ requestNewPassword });
|
||||
}
|
||||
|
||||
|
|
|
@ -113,7 +113,8 @@ struct NativePaymentMethod {
|
|||
|
||||
struct PaymentMethod {
|
||||
NativePaymentMethod native;
|
||||
SavedCredentials savedCredentials;
|
||||
std::vector<SavedCredentials> savedCredentials;
|
||||
int savedCredentialsIndex = 0;
|
||||
NewCredentials newCredentials;
|
||||
Ui::PaymentMethodDetails ui;
|
||||
};
|
||||
|
@ -222,6 +223,7 @@ public:
|
|||
const Ui::UncheckedCardDetails &details,
|
||||
bool saveInformation);
|
||||
void setPaymentCredentials(const NewCredentials &credentials);
|
||||
void chooseSavedMethod(const QString &id);
|
||||
void setHasPassword(bool has);
|
||||
void setShippingOption(const QString &id);
|
||||
void setTips(int64 value);
|
||||
|
@ -254,7 +256,7 @@ private:
|
|||
void processDetails(const MTPDpayments_paymentForm &data);
|
||||
void processDetails(const MTPDpayments_paymentReceipt &data);
|
||||
void processSavedInformation(const MTPDpaymentRequestedInfo &data);
|
||||
void processSavedCredentials(
|
||||
void addSavedCredentials(
|
||||
const MTPDpaymentSavedCredentialsCard &data);
|
||||
void processAdditionalPaymentMethods(
|
||||
const QVector<MTPPaymentFormMethod> &list);
|
||||
|
@ -263,6 +265,7 @@ private:
|
|||
void fillStripeNativeMethod(QJsonObject object);
|
||||
void fillSmartGlocalNativeMethod(QJsonObject object);
|
||||
void refreshPaymentMethodDetails();
|
||||
void refreshSavedPaymentMethodDetails();
|
||||
[[nodiscard]] QString defaultPhone() const;
|
||||
[[nodiscard]] QString defaultCountry() const;
|
||||
|
||||
|
|
|
@ -500,7 +500,9 @@ void FormSummary::setupSections(not_null<VerticalLayout*> layout) {
|
|||
};
|
||||
add(
|
||||
tr::lng_payments_payment_method(),
|
||||
_method.title,
|
||||
(_method.savedMethods.empty()
|
||||
? QString()
|
||||
: _method.savedMethods[_method.savedMethodIndex].title),
|
||||
&st::paymentsIconPaymentMethod,
|
||||
[=] { _delegate->panelEditPaymentMethod(); });
|
||||
if (_invoice.isShippingAddressRequested) {
|
||||
|
|
|
@ -227,7 +227,9 @@ void Panel::showForm(
|
|||
const RequestedInformation ¤t,
|
||||
const PaymentMethodDetails &method,
|
||||
const ShippingOptions &options) {
|
||||
if (invoice && !method.ready && !method.native.supported) {
|
||||
if (invoice
|
||||
&& method.savedMethods.empty()
|
||||
&& !method.native.supported) {
|
||||
const auto available = Webview::Availability();
|
||||
if (available.error != Webview::Available::Error::None) {
|
||||
showWebviewError(
|
||||
|
@ -410,25 +412,35 @@ void Panel::chooseTips(const Invoice &invoice) {
|
|||
}
|
||||
|
||||
void Panel::showEditPaymentMethod(const PaymentMethodDetails &method) {
|
||||
auto bottomText = method.canSaveInformation
|
||||
? rpl::producer<QString>()
|
||||
: tr::lng_payments_processed_by(
|
||||
lt_provider,
|
||||
rpl::single(method.provider));
|
||||
setTitle(tr::lng_payments_card_title());
|
||||
if (method.native.supported) {
|
||||
showEditCard(method.native, CardField::Number);
|
||||
} else if (!showWebview(method.url, true, std::move(bottomText))) {
|
||||
} else {
|
||||
showEditCardByUrl(
|
||||
method.url,
|
||||
method.provider,
|
||||
method.canSaveInformation);
|
||||
}
|
||||
}
|
||||
|
||||
void Panel::showEditCardByUrl(
|
||||
const QString &url,
|
||||
const QString &provider,
|
||||
bool canSaveInformation) {
|
||||
auto bottomText = canSaveInformation
|
||||
? rpl::producer<QString>()
|
||||
: tr::lng_payments_processed_by(lt_provider, rpl::single(provider));
|
||||
if (!showWebview(url, true, std::move(bottomText))) {
|
||||
const auto available = Webview::Availability();
|
||||
if (available.error != Webview::Available::Error::None) {
|
||||
showWebviewError(
|
||||
tr::lng_payments_webview_no_card(tr::now),
|
||||
tr::lng_payments_webview_no_use(tr::now),
|
||||
available);
|
||||
} else {
|
||||
showCriticalError({ "Error: Could not initialize WebView." });
|
||||
}
|
||||
_widget->setBackAllowed(true);
|
||||
} else if (method.canSaveInformation) {
|
||||
} else if (canSaveInformation) {
|
||||
const auto &padding = st::paymentsPanelPadding;
|
||||
_saveWebviewInformation = CreateChild<Checkbox>(
|
||||
_webviewBottom.get(),
|
||||
|
@ -444,23 +456,11 @@ void Panel::showEditPaymentMethod(const PaymentMethodDetails &method) {
|
|||
}
|
||||
|
||||
void Panel::showAdditionalMethod(
|
||||
const PaymentMethodAdditional &method,
|
||||
const QString &provider,
|
||||
const PaymentMethodAdditional &method) {
|
||||
auto bottomText = tr::lng_payments_processed_by(
|
||||
lt_provider,
|
||||
rpl::single(provider));
|
||||
bool canSaveInformation) {
|
||||
setTitle(rpl::single(method.title));
|
||||
if (!showWebview(method.url, true, std::move(bottomText))) {
|
||||
const auto available = Webview::Availability();
|
||||
if (available.error != Webview::Available::Error::None) {
|
||||
showWebviewError(
|
||||
tr::lng_payments_webview_no_use(tr::now),
|
||||
available);
|
||||
} else {
|
||||
showCriticalError({ "Error: Could not initialize WebView." });
|
||||
}
|
||||
_widget->setBackAllowed(true);
|
||||
}
|
||||
showEditCardByUrl(method.url, provider, canSaveInformation);
|
||||
}
|
||||
|
||||
void Panel::showWebviewProgress() {
|
||||
|
@ -592,29 +592,32 @@ postEvent: function(eventType, eventData) {
|
|||
}
|
||||
|
||||
void Panel::choosePaymentMethod(const PaymentMethodDetails &method) {
|
||||
const auto hasSaved = method.ready;
|
||||
if (!hasSaved && method.additionalMethods.empty()) {
|
||||
if (method.savedMethods.empty() && method.additionalMethods.empty()) {
|
||||
showEditPaymentMethod(method);
|
||||
return;
|
||||
}
|
||||
showBox(Box([=](not_null<GenericBox*> box) {
|
||||
const auto save = [=](int option) {
|
||||
const auto basic = hasSaved ? 1 : 0;
|
||||
if (option > basic) {
|
||||
const auto index = option - basic - 1;
|
||||
const auto saved = int(method.savedMethods.size());
|
||||
if (!option) {
|
||||
showEditPaymentMethod(method);
|
||||
} else if (option > saved) {
|
||||
const auto index = option - saved - 1;
|
||||
Assert(index < method.additionalMethods.size());
|
||||
showAdditionalMethod(
|
||||
method.additionalMethods[index],
|
||||
method.provider,
|
||||
method.additionalMethods[index]);
|
||||
} else if (!option) {
|
||||
showEditPaymentMethod(method);
|
||||
method.canSaveInformation);
|
||||
} else {
|
||||
const auto index = option - 1;
|
||||
_savedMethodChosen.fire_copy(method.savedMethods[index].id);
|
||||
}
|
||||
};
|
||||
auto options = std::vector{
|
||||
tr::lng_payments_new_card(tr::now),
|
||||
};
|
||||
if (hasSaved) {
|
||||
options.push_back(method.title);
|
||||
for (const auto &saved : method.savedMethods) {
|
||||
options.push_back(saved.title);
|
||||
}
|
||||
for (const auto &additional : method.additionalMethods) {
|
||||
options.push_back(additional.title);
|
||||
|
@ -622,7 +625,9 @@ void Panel::choosePaymentMethod(const PaymentMethodDetails &method) {
|
|||
SingleChoiceBox(box, {
|
||||
.title = tr::lng_payments_payment_method(),
|
||||
.options = std::move(options),
|
||||
.initialSelection = hasSaved ? 1 : -1,
|
||||
.initialSelection = (method.savedMethods.empty()
|
||||
? -1
|
||||
: (method.savedMethodIndex + 1)),
|
||||
.callback = save,
|
||||
});
|
||||
}));
|
||||
|
@ -823,6 +828,10 @@ rpl::producer<> Panel::backRequests() const {
|
|||
return _widget->backRequests();
|
||||
}
|
||||
|
||||
rpl::producer<QString> Panel::savedMethodChosen() const {
|
||||
return _savedMethodChosen.events();
|
||||
}
|
||||
|
||||
void Panel::showBox(object_ptr<BoxContent> box) {
|
||||
if (const auto widget = _webview ? _webview->window.widget() : nullptr) {
|
||||
const auto hideNow = !widget->isHidden();
|
||||
|
|
|
@ -63,14 +63,15 @@ public:
|
|||
InformationField field);
|
||||
void showEditPaymentMethod(const PaymentMethodDetails &method);
|
||||
void showAdditionalMethod(
|
||||
const PaymentMethodAdditional &method,
|
||||
const QString &provider,
|
||||
const PaymentMethodAdditional &method);
|
||||
void showEditCard(
|
||||
const NativeMethodDetails &native,
|
||||
CardField field);
|
||||
void showCardError(
|
||||
const NativeMethodDetails &native,
|
||||
CardField field);
|
||||
bool canSaveInformation);
|
||||
void showEditCard(const NativeMethodDetails &native, CardField field);
|
||||
void showEditCardByUrl(
|
||||
const QString &url,
|
||||
const QString &provider,
|
||||
bool canSaveInformation);
|
||||
void showCardError(const NativeMethodDetails &native, CardField field);
|
||||
void chooseShippingOption(const ShippingOptions &options);
|
||||
void chooseTips(const Invoice &invoice);
|
||||
void choosePaymentMethod(const PaymentMethodDetails &method);
|
||||
|
@ -86,6 +87,7 @@ public:
|
|||
void updateThemeParams(const Webview::ThemeParams ¶ms);
|
||||
|
||||
[[nodiscard]] rpl::producer<> backRequests() const;
|
||||
[[nodiscard]] rpl::producer<QString> savedMethodChosen() const;
|
||||
|
||||
void showBox(object_ptr<Ui::BoxContent> box);
|
||||
void showToast(const TextWithEntities &text);
|
||||
|
@ -120,6 +122,7 @@ private:
|
|||
rpl::variable<int> _formScrollTop;
|
||||
QPointer<EditInformation> _weakEditInformation;
|
||||
QPointer<EditCard> _weakEditCard;
|
||||
rpl::event_stream<QString> _savedMethodChosen;
|
||||
bool _webviewProgress = false;
|
||||
bool _testMode = false;
|
||||
|
||||
|
|
|
@ -167,13 +167,18 @@ struct PaymentMethodAdditional {
|
|||
QString url;
|
||||
};
|
||||
|
||||
struct PaymentMethodDetails {
|
||||
struct PaymentMethodSaved {
|
||||
QString id;
|
||||
QString title;
|
||||
};
|
||||
|
||||
struct PaymentMethodDetails {
|
||||
NativeMethodDetails native;
|
||||
std::vector<PaymentMethodSaved> savedMethods;
|
||||
std::vector<PaymentMethodAdditional> additionalMethods;
|
||||
QString url;
|
||||
QString provider;
|
||||
bool ready = false;
|
||||
int savedMethodIndex = 0;
|
||||
bool canSaveInformation = false;
|
||||
};
|
||||
|
||||
|
|
Loading…
Add table
Reference in a new issue