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) {
if (Core::TryConvertUrlToLocal(uri) == uri) {
return true;

View file

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

View file

@ -682,6 +682,13 @@ void Form::submit(const Core::CloudPasswordResult &result) {
}).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) {
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<QDate> &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<QDate> &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);
}

View file

@ -218,6 +218,8 @@ public:
return _updates.events();
}
[[nodiscard]] std::optional<QDate> 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<QDate> &overrideExpireDateThreshold) const;
[[nodiscard]] Error cardErrorLocal(
const Ui::UncheckedCardDetails &details) const;
const Ui::UncheckedCardDetails &details,
const std::optional<QDate> &overrideExpireDateThreshold) const;
const InvoiceId _id;
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());
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<QDate> &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(

View file

@ -10,6 +10,8 @@ https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL
#include "stripe/stripe_card.h"
#include <vector>
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<QDate> &overrideExpireDateThreshold);
[[nodiscard]] ValidationState ValidateParsedExpireDate(
quint32 month,
quint32 year);
quint32 year,
const std::optional<QDate> &overrideExpireDateThreshold);
struct CvcValidationResult {
ValidationState state = ValidationState::Invalid;

View file

@ -165,10 +165,11 @@ template <
PostprocessCardValidateResult);
}
[[nodiscard]] auto ExpireDateValidator() {
return ComplexNumberValidator(
Stripe::ValidateExpireDate,
PostprocessExpireDateValidateResult);
[[nodiscard]] auto ExpireDateValidator(
const std::optional<QDate> &overrideExpireDateThreshold) {
return ComplexNumberValidator([=](const QString &date) {
return Stripe::ValidateExpireDate(date, overrideExpireDateThreshold);
}, PostprocessExpireDateValidateResult);
}
[[nodiscard]] auto CvcValidator(Fn<QString()> number) {
@ -306,7 +307,8 @@ not_null<RpWidget*> 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,

View file

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