Ease local card expiry date check.

This commit is contained in:
John Preston 2023-02-07 19:13:07 +04:00
parent ddfcf9f1df
commit afd717b36e
8 changed files with 60 additions and 26 deletions

View file

@ -611,6 +611,10 @@ void CheckoutProcess::panelWebviewMessage(
}); });
} }
std::optional<QDate> CheckoutProcess::panelOverrideExpireDateThreshold() {
return _form->overrideExpireDateThreshold();
}
bool CheckoutProcess::panelWebviewNavigationAttempt(const QString &uri) { bool CheckoutProcess::panelWebviewNavigationAttempt(const QString &uri) {
if (Core::TryConvertUrlToLocal(uri) == uri) { if (Core::TryConvertUrlToLocal(uri) == uri) {
return true; return true;

View file

@ -151,6 +151,8 @@ private:
QString panelWebviewDataPath() override; QString panelWebviewDataPath() override;
std::optional<QDate> panelOverrideExpireDateThreshold() override;
const not_null<Main::Session*> _session; const not_null<Main::Session*> _session;
const std::unique_ptr<Form> _form; const std::unique_ptr<Form> _form;
const std::unique_ptr<Ui::Panel> _panel; const std::unique_ptr<Ui::Panel> _panel;

View file

@ -682,6 +682,13 @@ void Form::submit(const Core::CloudPasswordResult &result) {
}).send(); }).send();
} }
std::optional<QDate> Form::overrideExpireDateThreshold() const {
const auto phone = _session->user()->phone();
return phone.startsWith('7')
? QDate(2022, 2, 1)
: std::optional<QDate>();
}
void Form::validateInformation(const Ui::RequestedInformation &information) { void Form::validateInformation(const Ui::RequestedInformation &information) {
if (_validateRequestId) { if (_validateRequestId) {
if (_validatedInformation == information) { if (_validatedInformation == information) {
@ -795,7 +802,7 @@ void Form::validateCard(
bool saveInformation) { bool saveInformation) {
Expects(!v::is_null(_paymentMethod.native.data)); Expects(!v::is_null(_paymentMethod.native.data));
if (!validateCardLocal(details)) { if (!validateCardLocal(details, overrideExpireDateThreshold())) {
return; return;
} }
const auto &native = _paymentMethod.native.data; const auto &native = _paymentMethod.native.data;
@ -809,15 +816,19 @@ void Form::validateCard(
} }
} }
bool Form::validateCardLocal(const Ui::UncheckedCardDetails &details) const { bool Form::validateCardLocal(
if (auto error = cardErrorLocal(details)) { const Ui::UncheckedCardDetails &details,
const std::optional<QDate> &overrideExpireDateThreshold) const {
if (auto error = cardErrorLocal(details, overrideExpireDateThreshold)) {
_updates.fire(std::move(error)); _updates.fire(std::move(error));
return false; return false;
} }
return true; return true;
} }
Error Form::cardErrorLocal(const Ui::UncheckedCardDetails &details) const { Error Form::cardErrorLocal(
const Ui::UncheckedCardDetails &details,
const std::optional<QDate> &overrideExpireDateThreshold) const {
using namespace Stripe; using namespace Stripe;
auto errors = QStringList(); auto errors = QStringList();
@ -830,7 +841,8 @@ Error Form::cardErrorLocal(const Ui::UncheckedCardDetails &details) const {
} }
if (ValidateParsedExpireDate( if (ValidateParsedExpireDate(
details.expireMonth, details.expireMonth,
details.expireYear details.expireYear,
overrideExpireDateThreshold
) != kValid) { ) != kValid) {
push(u"LOCAL_CARD_EXPIRE_DATE_INVALID"_q); push(u"LOCAL_CARD_EXPIRE_DATE_INVALID"_q);
} }

View file

@ -218,6 +218,8 @@ public:
return _updates.events(); return _updates.events();
} }
[[nodiscard]] std::optional<QDate> overrideExpireDateThreshold() const;
void validateInformation(const Ui::RequestedInformation &information); void validateInformation(const Ui::RequestedInformation &information);
void validateCard( void validateCard(
const Ui::UncheckedCardDetails &details, const Ui::UncheckedCardDetails &details,
@ -284,9 +286,11 @@ private:
const Ui::RequestedInformation &information) const; const Ui::RequestedInformation &information) const;
bool validateCardLocal( bool validateCardLocal(
const Ui::UncheckedCardDetails &details) const; const Ui::UncheckedCardDetails &details,
const std::optional<QDate> &overrideExpireDateThreshold) const;
[[nodiscard]] Error cardErrorLocal( [[nodiscard]] Error cardErrorLocal(
const Ui::UncheckedCardDetails &details) const; const Ui::UncheckedCardDetails &details,
const std::optional<QDate> &overrideExpireDateThreshold) const;
const InvoiceId _id; const InvoiceId _id;
const not_null<Main::Session*> _session; const not_null<Main::Session*> _session;

View file

@ -207,7 +207,9 @@ CardValidationResult ValidateCard(const QString &number) {
}; };
} }
ExpireDateValidationResult ValidateExpireDate(const QString &date) { ExpireDateValidationResult ValidateExpireDate(
const QString &date,
const std::optional<QDate> &overrideExpireDateThreshold) {
const auto sanitized = RemoveWhitespaces(date).replace('/', QString()); const auto sanitized = RemoveWhitespaces(date).replace('/', QString());
if (!IsNumeric(sanitized)) { if (!IsNumeric(sanitized)) {
return { ValidationState::Invalid }; return { ValidationState::Invalid };
@ -225,12 +227,13 @@ ExpireDateValidationResult ValidateExpireDate(const QString &date) {
} }
const auto year = 2000 + normalized.mid(2).toInt(); const auto year = 2000 + normalized.mid(2).toInt();
const auto currentDate = QDate::currentDate(); const auto thresholdDate = overrideExpireDateThreshold.value_or(
const auto currentMonth = currentDate.month(); QDate::currentDate());
const auto currentYear = currentDate.year(); const auto thresholdMonth = thresholdDate.month();
if (year < currentYear) { const auto thresholdYear = thresholdDate.year();
if (year < thresholdYear) {
return { ValidationState::Invalid }; return { ValidationState::Invalid };
} else if (year == currentYear && month < currentMonth) { } else if (year == thresholdYear && month < thresholdMonth) {
return { ValidationState::Invalid }; return { ValidationState::Invalid };
} }
return { ValidationState::Valid, true }; return { ValidationState::Valid, true };
@ -238,15 +241,16 @@ ExpireDateValidationResult ValidateExpireDate(const QString &date) {
ValidationState ValidateParsedExpireDate( ValidationState ValidateParsedExpireDate(
quint32 month, quint32 month,
quint32 year) { quint32 year,
const std::optional<QDate> &overrideExpireDateThreshold) {
if ((year / 100) != 20) { if ((year / 100) != 20) {
return ValidationState::Invalid; return ValidationState::Invalid;
} }
return ValidateExpireDate( const auto date = QString("%1%2"
QString("%1%2" ).arg(month, 2, 10, QChar('0')
).arg(month, 2, 10, QChar('0') ).arg(year % 100, 2, 10, QChar('0'));
).arg(year % 100, 2, 10, QChar('0'))
).state; return ValidateExpireDate(date, overrideExpireDateThreshold).state;
} }
CvcValidationResult ValidateCvc( CvcValidationResult ValidateCvc(

View file

@ -10,6 +10,8 @@ https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL
#include "stripe/stripe_card.h" #include "stripe/stripe_card.h"
#include <vector> #include <vector>
class QDate;
namespace Stripe { namespace Stripe {
enum class ValidationState { enum class ValidationState {
@ -32,11 +34,13 @@ struct ExpireDateValidationResult {
}; };
[[nodiscard]] ExpireDateValidationResult ValidateExpireDate( [[nodiscard]] ExpireDateValidationResult ValidateExpireDate(
const QString &date); const QString &date,
const std::optional<QDate> &overrideExpireDateThreshold);
[[nodiscard]] ValidationState ValidateParsedExpireDate( [[nodiscard]] ValidationState ValidateParsedExpireDate(
quint32 month, quint32 month,
quint32 year); quint32 year,
const std::optional<QDate> &overrideExpireDateThreshold);
struct CvcValidationResult { struct CvcValidationResult {
ValidationState state = ValidationState::Invalid; ValidationState state = ValidationState::Invalid;

View file

@ -165,10 +165,11 @@ template <
PostprocessCardValidateResult); PostprocessCardValidateResult);
} }
[[nodiscard]] auto ExpireDateValidator() { [[nodiscard]] auto ExpireDateValidator(
return ComplexNumberValidator( const std::optional<QDate> &overrideExpireDateThreshold) {
Stripe::ValidateExpireDate, return ComplexNumberValidator([=](const QString &date) {
PostprocessExpireDateValidateResult); return Stripe::ValidateExpireDate(date, overrideExpireDateThreshold);
}, PostprocessExpireDateValidateResult);
} }
[[nodiscard]] auto CvcValidator(Fn<QString()> number) { [[nodiscard]] auto CvcValidator(Fn<QString()> number) {
@ -306,7 +307,8 @@ not_null<RpWidget*> EditCard::setupContent() {
_expire = make(container, { _expire = make(container, {
.type = FieldType::CardExpireDate, .type = FieldType::CardExpireDate,
.placeholder = tr::lng_payments_card_expire_date(), .placeholder = tr::lng_payments_card_expire_date(),
.validator = ExpireDateValidator(), .validator = ExpireDateValidator(
_delegate->panelOverrideExpireDateThreshold()),
}); });
_cvc = make(container, { _cvc = make(container, {
.type = FieldType::CardCVC, .type = FieldType::CardCVC,

View file

@ -56,6 +56,8 @@ public:
virtual QVariant panelClickHandlerContext() = 0; virtual QVariant panelClickHandlerContext() = 0;
virtual QString panelWebviewDataPath() = 0; virtual QString panelWebviewDataPath() = 0;
virtual std::optional<QDate> panelOverrideExpireDateThreshold() = 0;
}; };
} // namespace Payments::Ui } // namespace Payments::Ui