From d0bb730ced2bbb509769a484f4f94bb082186a0d Mon Sep 17 00:00:00 2001 From: julianajlk Date: Wed, 1 May 2024 19:54:08 -0400 Subject: [PATCH 1/4] refactor: Reorder DPM succeeded loading to fix redirect to receipt --- src/payment/PaymentPage.jsx | 26 +++++++++++++------------- 1 file changed, 13 insertions(+), 13 deletions(-) diff --git a/src/payment/PaymentPage.jsx b/src/payment/PaymentPage.jsx index 816e3b48e..f0902f38e 100644 --- a/src/payment/PaymentPage.jsx +++ b/src/payment/PaymentPage.jsx @@ -108,6 +108,19 @@ class PaymentPage extends React.Component { const shouldRedirectToReceipt = paymentStatus === 'succeeded'; + // If this is a redirect from Stripe Dynamic Payment Methods with a successful payment, + // redirect to the receipt page. PageLoading render is required first otherwise there is a + // lag between when the paymentStatus is no longer null but the redirect hasn't happened yet. + if (shouldRedirectToReceipt) { + return ( + + ); + } + // If this is a redirect from Stripe Dynamic Payment Methods, show loading icon until getPaymentStatus is done. if (isPaymentRedirect && paymentStatus !== undefined && paymentStatus === null) { return ( @@ -134,19 +147,6 @@ class PaymentPage extends React.Component { ); } - // If this is a redirect from Stripe Dynamic Payment Methods with a successful payment, - // redirect to the receipt page. PageLoading render is required first otherwise there is a - // lag between when the paymentStatus is no longer null but the redirect hasn't happened yet. - if (shouldRedirectToReceipt) { - return ( - - ); - } - // In all other cases, we want to render the basket content. This is used before we've loaded // anything, during loading, and after we've loaded a basket with a product in it. From 30c45e6f5ae8097f4427276e64069c2faa6a4330 Mon Sep 17 00:00:00 2001 From: julianajlk Date: Wed, 1 May 2024 19:56:39 -0400 Subject: [PATCH 2/4] refactor: handleRequestError DPM country not compatible --- src/payment/data/handleRequestError.js | 10 +++++++--- 1 file changed, 7 insertions(+), 3 deletions(-) diff --git a/src/payment/data/handleRequestError.js b/src/payment/data/handleRequestError.js index 5a2a0a9bd..4ac221542 100644 --- a/src/payment/data/handleRequestError.js +++ b/src/payment/data/handleRequestError.js @@ -85,9 +85,13 @@ export default function handleRequestError(error) { } // Country not DPM compatible - if (error.type === 'invalid_request_error' && ( - error.param === 'payment_method_data[billing_details][address][country]' || error.param === 'billing_details[address][state]' || error.param === 'billing_details[address][postal_code]' - )) { + const billingAddressErrors = [ + 'payment_method_data[billing_details][address][country]', + 'billing_details[address][state]', + 'billing_details[address][postal_code]', + ]; + + if (error.type === 'invalid_request_error' && billingAddressErrors.includes(error.param)) { logInfo('Dynamic Payment Method Country Error', error.param); handleApiErrors([ { From eef052d8b1709fd8b9ec34d7f0d70d73d3414cf2 Mon Sep 17 00:00:00 2001 From: julianajlk Date: Thu, 2 May 2024 15:40:37 -0400 Subject: [PATCH 3/4] fix: Update comment on contry compatibility error --- src/payment/data/handleRequestError.js | 11 ++++++++++- 1 file changed, 10 insertions(+), 1 deletion(-) diff --git a/src/payment/data/handleRequestError.js b/src/payment/data/handleRequestError.js index 4ac221542..7777ae2ca 100644 --- a/src/payment/data/handleRequestError.js +++ b/src/payment/data/handleRequestError.js @@ -84,9 +84,18 @@ export default function handleRequestError(error) { ]); } - // Country not DPM compatible + // Country not DPM compatible Stripe error + // Note: with Affirm, if the billing country is not supported, it will not fail at the Stripe level, + // for which we have form validation in place to avoid that, instead of erroring at the Affirm payment environment. + // For other BNPL, Stripe will give the below error if the country is not compatible and/or + // if the state and/or postal code are missing. + // There is country and state validation at the form level, but the below error handling + // is a fallback if the form validation does not catch the country incompatibility. const billingAddressErrors = [ 'payment_method_data[billing_details][address][country]', + 'payment_method_data[billing_details][address][state]', + 'payment_method_data[billing_details][address][postal_code]', + 'billing_details[address][country]', 'billing_details[address][state]', 'billing_details[address][postal_code]', ]; From 7f2b37240ecf04e3d7bb133f76c2fcc951025e61 Mon Sep 17 00:00:00 2001 From: julianajlk Date: Thu, 2 May 2024 15:53:37 -0400 Subject: [PATCH 4/4] fix: Remove postal code validation for DPM countries --- .../payment-form/CardHolderInformation.jsx | 9 ++--- .../CardHolderInformation.test.jsx | 2 +- .../payment-form/StripePaymentForm.jsx | 1 - .../payment-form/utils/form-validators.js | 37 ++----------------- 4 files changed, 8 insertions(+), 41 deletions(-) diff --git a/src/payment/checkout/payment-form/CardHolderInformation.jsx b/src/payment/checkout/payment-form/CardHolderInformation.jsx index 7dbae32d0..92fe1342f 100644 --- a/src/payment/checkout/payment-form/CardHolderInformation.jsx +++ b/src/payment/checkout/payment-form/CardHolderInformation.jsx @@ -59,9 +59,10 @@ export class CardHolderInformationComponent extends React.Component { } render() { - const { disabled, showBulkEnrollmentFields, isDynamicPaymentMethodsEnabled } = this.props; - const shouldRequirePostalCode = isPostalCodeRequired(this.state.selectedCountry, isDynamicPaymentMethodsEnabled) - && this.props.enableStripePaymentProcessor; + const { disabled, showBulkEnrollmentFields } = this.props; + const shouldRequirePostalCode = isPostalCodeRequired( + this.state.selectedCountry, + ) && this.props.enableStripePaymentProcessor; return (
@@ -277,14 +278,12 @@ CardHolderInformationComponent.propTypes = { intl: intlShape.isRequired, disabled: PropTypes.bool, enableStripePaymentProcessor: PropTypes.bool, - isDynamicPaymentMethodsEnabled: PropTypes.bool, showBulkEnrollmentFields: PropTypes.bool, }; CardHolderInformationComponent.defaultProps = { disabled: false, enableStripePaymentProcessor: false, - isDynamicPaymentMethodsEnabled: false, showBulkEnrollmentFields: false, }; diff --git a/src/payment/checkout/payment-form/CardHolderInformation.test.jsx b/src/payment/checkout/payment-form/CardHolderInformation.test.jsx index 2677badf3..07481b214 100644 --- a/src/payment/checkout/payment-form/CardHolderInformation.test.jsx +++ b/src/payment/checkout/payment-form/CardHolderInformation.test.jsx @@ -74,7 +74,7 @@ describe('', () => { fireEvent.change(screen.getByLabelText('Country (required)'), { target: { value: 'US' } }); expect(getCountryStatesMap).toHaveBeenCalledWith('US'); - expect(isPostalCodeRequired).toHaveBeenCalledWith('US', false); // DPM enabled added to the call + expect(isPostalCodeRequired).toHaveBeenCalledWith('US'); }); }); describe('purchasedForOrganization field', () => { diff --git a/src/payment/checkout/payment-form/StripePaymentForm.jsx b/src/payment/checkout/payment-form/StripePaymentForm.jsx index ac18cdebe..0a8d88aab 100644 --- a/src/payment/checkout/payment-form/StripePaymentForm.jsx +++ b/src/payment/checkout/payment-form/StripePaymentForm.jsx @@ -198,7 +198,6 @@ const StripePaymentForm = ({ showBulkEnrollmentFields={isBulkOrder} disabled={submitting} enableStripePaymentProcessor={enableStripePaymentProcessor} - isDynamicPaymentMethodsEnabled={isDynamicPaymentMethodsEnabled} />
{ }; // eslint-disable-next-line import/prefer-default-export -export function isPostalCodeRequired(selectedCountry, isDynamicPaymentMethodsEnabled) { - // Stripe recommends to have state and zip code since it can have a material effect on +export function isPostalCodeRequired(selectedCountry) { + // Stripe recommends to have state and zip code required since it can have a material effect on // our card authorization rates and fees that the card networks and issuers charge. - // 'CA', 'GB' and 'US' were alreay required prior to implementing Dynamic Payment Methods. - // The Stripe API also requires state and zip code for BNPL options (Affirm, Afterpay, Klarna) - // for the countries that these payment methods are compatible with. - let countryListRequiredPostalCode = []; - if (isDynamicPaymentMethodsEnabled) { - countryListRequiredPostalCode = [ - 'CA', // Affirm, Afterpay, Klarna - 'GB', // Afterpay, Klarna - 'US', // Affirm, Afterpay, Klarna - 'AU', // Afterpay, Klarna - 'AT', // Klarna - 'BE', // Klarna - 'CH', // Klarna - 'CZ', // Klarna - 'DE', // Klarna - 'DK', // Klarna - 'ES', // Klarna - 'FI', // Klarna - 'FR', // Klarna - 'GR', // Klarna - 'IE', // Klarna - 'IT', // Klarna - 'NL', // Klarna - 'NO', // Klarna - 'NZ', // Afterpay, Klarna - 'PL', // Klarna - 'PT', // Klarna - 'SE', // Klarna - ]; - } else { - countryListRequiredPostalCode = ['CA', 'GB', 'US']; - } + const countryListRequiredPostalCode = ['CA', 'GB', 'US']; const postalCodeRequired = countryListRequiredPostalCode.includes(selectedCountry);