diff --git a/Telegram/SourceFiles/payments/payments_checkout_process.cpp b/Telegram/SourceFiles/payments/payments_checkout_process.cpp index efd2ffd39..ee6ef45e2 100644 --- a/Telegram/SourceFiles/payments/payments_checkout_process.cpp +++ b/Telegram/SourceFiles/payments/payments_checkout_process.cpp @@ -611,6 +611,10 @@ void CheckoutProcess::panelWebviewMessage( }); } +std::optional CheckoutProcess::panelOverrideExpireDateThreshold() { + return _form->overrideExpireDateThreshold(); +} + bool CheckoutProcess::panelWebviewNavigationAttempt(const QString &uri) { if (Core::TryConvertUrlToLocal(uri) == uri) { return true; diff --git a/Telegram/SourceFiles/payments/payments_checkout_process.h b/Telegram/SourceFiles/payments/payments_checkout_process.h index 9ad90c406..1e37c3d28 100644 --- a/Telegram/SourceFiles/payments/payments_checkout_process.h +++ b/Telegram/SourceFiles/payments/payments_checkout_process.h @@ -151,6 +151,8 @@ private: QString panelWebviewDataPath() override; + std::optional panelOverrideExpireDateThreshold() override; + const not_null _session; const std::unique_ptr
_form; const std::unique_ptr _panel; diff --git a/Telegram/SourceFiles/payments/payments_form.cpp b/Telegram/SourceFiles/payments/payments_form.cpp index 248f09caf..b10ee9b4a 100644 --- a/Telegram/SourceFiles/payments/payments_form.cpp +++ b/Telegram/SourceFiles/payments/payments_form.cpp @@ -682,6 +682,13 @@ void Form::submit(const Core::CloudPasswordResult &result) { }).send(); } +std::optional Form::overrideExpireDateThreshold() const { + const auto phone = _session->user()->phone(); + return phone.startsWith('7') + ? QDate(2022, 2, 1) + : std::optional(); +} + void Form::validateInformation(const Ui::RequestedInformation &information) { if (_validateRequestId) { if (_validatedInformation == information) { @@ -795,7 +802,7 @@ void Form::validateCard( bool saveInformation) { Expects(!v::is_null(_paymentMethod.native.data)); - if (!validateCardLocal(details)) { + if (!validateCardLocal(details, overrideExpireDateThreshold())) { return; } const auto &native = _paymentMethod.native.data; @@ -809,15 +816,19 @@ void Form::validateCard( } } -bool Form::validateCardLocal(const Ui::UncheckedCardDetails &details) const { - if (auto error = cardErrorLocal(details)) { +bool Form::validateCardLocal( + const Ui::UncheckedCardDetails &details, + const std::optional &overrideExpireDateThreshold) const { + if (auto error = cardErrorLocal(details, overrideExpireDateThreshold)) { _updates.fire(std::move(error)); return false; } return true; } -Error Form::cardErrorLocal(const Ui::UncheckedCardDetails &details) const { +Error Form::cardErrorLocal( + const Ui::UncheckedCardDetails &details, + const std::optional &overrideExpireDateThreshold) const { using namespace Stripe; auto errors = QStringList(); @@ -830,7 +841,8 @@ Error Form::cardErrorLocal(const Ui::UncheckedCardDetails &details) const { } if (ValidateParsedExpireDate( details.expireMonth, - details.expireYear + details.expireYear, + overrideExpireDateThreshold ) != kValid) { push(u"LOCAL_CARD_EXPIRE_DATE_INVALID"_q); } diff --git a/Telegram/SourceFiles/payments/payments_form.h b/Telegram/SourceFiles/payments/payments_form.h index 4290edee4..b1e1797c4 100644 --- a/Telegram/SourceFiles/payments/payments_form.h +++ b/Telegram/SourceFiles/payments/payments_form.h @@ -218,6 +218,8 @@ public: return _updates.events(); } + [[nodiscard]] std::optional overrideExpireDateThreshold() const; + void validateInformation(const Ui::RequestedInformation &information); void validateCard( const Ui::UncheckedCardDetails &details, @@ -284,9 +286,11 @@ private: const Ui::RequestedInformation &information) const; bool validateCardLocal( - const Ui::UncheckedCardDetails &details) const; + const Ui::UncheckedCardDetails &details, + const std::optional &overrideExpireDateThreshold) const; [[nodiscard]] Error cardErrorLocal( - const Ui::UncheckedCardDetails &details) const; + const Ui::UncheckedCardDetails &details, + const std::optional &overrideExpireDateThreshold) const; const InvoiceId _id; const not_null _session; diff --git a/Telegram/SourceFiles/payments/stripe/stripe_card_validator.cpp b/Telegram/SourceFiles/payments/stripe/stripe_card_validator.cpp index ee09add8d..139ab6b62 100644 --- a/Telegram/SourceFiles/payments/stripe/stripe_card_validator.cpp +++ b/Telegram/SourceFiles/payments/stripe/stripe_card_validator.cpp @@ -207,7 +207,9 @@ CardValidationResult ValidateCard(const QString &number) { }; } -ExpireDateValidationResult ValidateExpireDate(const QString &date) { +ExpireDateValidationResult ValidateExpireDate( + const QString &date, + const std::optional &overrideExpireDateThreshold) { const auto sanitized = RemoveWhitespaces(date).replace('/', QString()); if (!IsNumeric(sanitized)) { return { ValidationState::Invalid }; @@ -225,12 +227,13 @@ ExpireDateValidationResult ValidateExpireDate(const QString &date) { } const auto year = 2000 + normalized.mid(2).toInt(); - const auto currentDate = QDate::currentDate(); - const auto currentMonth = currentDate.month(); - const auto currentYear = currentDate.year(); - if (year < currentYear) { + const auto thresholdDate = overrideExpireDateThreshold.value_or( + QDate::currentDate()); + const auto thresholdMonth = thresholdDate.month(); + const auto thresholdYear = thresholdDate.year(); + if (year < thresholdYear) { return { ValidationState::Invalid }; - } else if (year == currentYear && month < currentMonth) { + } else if (year == thresholdYear && month < thresholdMonth) { return { ValidationState::Invalid }; } return { ValidationState::Valid, true }; @@ -238,15 +241,16 @@ ExpireDateValidationResult ValidateExpireDate(const QString &date) { ValidationState ValidateParsedExpireDate( quint32 month, - quint32 year) { + quint32 year, + const std::optional &overrideExpireDateThreshold) { if ((year / 100) != 20) { return ValidationState::Invalid; } - return ValidateExpireDate( - QString("%1%2" - ).arg(month, 2, 10, QChar('0') - ).arg(year % 100, 2, 10, QChar('0')) - ).state; + const auto date = QString("%1%2" + ).arg(month, 2, 10, QChar('0') + ).arg(year % 100, 2, 10, QChar('0')); + + return ValidateExpireDate(date, overrideExpireDateThreshold).state; } CvcValidationResult ValidateCvc( diff --git a/Telegram/SourceFiles/payments/stripe/stripe_card_validator.h b/Telegram/SourceFiles/payments/stripe/stripe_card_validator.h index 744af0814..0cc6e5013 100644 --- a/Telegram/SourceFiles/payments/stripe/stripe_card_validator.h +++ b/Telegram/SourceFiles/payments/stripe/stripe_card_validator.h @@ -10,6 +10,8 @@ https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL #include "stripe/stripe_card.h" #include +class QDate; + namespace Stripe { enum class ValidationState { @@ -32,11 +34,13 @@ struct ExpireDateValidationResult { }; [[nodiscard]] ExpireDateValidationResult ValidateExpireDate( - const QString &date); + const QString &date, + const std::optional &overrideExpireDateThreshold); [[nodiscard]] ValidationState ValidateParsedExpireDate( quint32 month, - quint32 year); + quint32 year, + const std::optional &overrideExpireDateThreshold); struct CvcValidationResult { ValidationState state = ValidationState::Invalid; diff --git a/Telegram/SourceFiles/payments/ui/payments_edit_card.cpp b/Telegram/SourceFiles/payments/ui/payments_edit_card.cpp index bfef08ae1..34efdc5cc 100644 --- a/Telegram/SourceFiles/payments/ui/payments_edit_card.cpp +++ b/Telegram/SourceFiles/payments/ui/payments_edit_card.cpp @@ -165,10 +165,11 @@ template < PostprocessCardValidateResult); } -[[nodiscard]] auto ExpireDateValidator() { - return ComplexNumberValidator( - Stripe::ValidateExpireDate, - PostprocessExpireDateValidateResult); +[[nodiscard]] auto ExpireDateValidator( + const std::optional &overrideExpireDateThreshold) { + return ComplexNumberValidator([=](const QString &date) { + return Stripe::ValidateExpireDate(date, overrideExpireDateThreshold); + }, PostprocessExpireDateValidateResult); } [[nodiscard]] auto CvcValidator(Fn number) { @@ -306,7 +307,8 @@ not_null EditCard::setupContent() { _expire = make(container, { .type = FieldType::CardExpireDate, .placeholder = tr::lng_payments_card_expire_date(), - .validator = ExpireDateValidator(), + .validator = ExpireDateValidator( + _delegate->panelOverrideExpireDateThreshold()), }); _cvc = make(container, { .type = FieldType::CardCVC, diff --git a/Telegram/SourceFiles/payments/ui/payments_panel_delegate.h b/Telegram/SourceFiles/payments/ui/payments_panel_delegate.h index d65bc81a7..ca0ed0caf 100644 --- a/Telegram/SourceFiles/payments/ui/payments_panel_delegate.h +++ b/Telegram/SourceFiles/payments/ui/payments_panel_delegate.h @@ -56,6 +56,8 @@ public: virtual QVariant panelClickHandlerContext() = 0; virtual QString panelWebviewDataPath() = 0; + + virtual std::optional panelOverrideExpireDateThreshold() = 0; }; } // namespace Payments::Ui