Skip to content

Commit

Permalink
refactor: Reorder DPM successful loading redirect (#8)
Browse files Browse the repository at this point in the history
REV-4009
  • Loading branch information
julianajlk authored May 2, 2024
1 parent 2c35546 commit 0de1892
Show file tree
Hide file tree
Showing 6 changed files with 38 additions and 58 deletions.
26 changes: 13 additions & 13 deletions src/payment/PaymentPage.jsx
Original file line number Diff line number Diff line change
Expand Up @@ -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 (
<PageLoading
srMessage={this.props.intl.formatMessage(messages['payment.loading.payment'])}
shouldRedirectToReceipt={shouldRedirectToReceipt}
orderNumber={orderNumber}
/>
);
}

// If this is a redirect from Stripe Dynamic Payment Methods, show loading icon until getPaymentStatus is done.
if (isPaymentRedirect && paymentStatus !== undefined && paymentStatus === null) {
return (
Expand All @@ -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 (
<PageLoading
srMessage={this.props.intl.formatMessage(messages['payment.loading.payment'])}
shouldRedirectToReceipt={shouldRedirectToReceipt}
orderNumber={orderNumber}
/>
);
}

// 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.

Expand Down
9 changes: 4 additions & 5 deletions src/payment/checkout/payment-form/CardHolderInformation.jsx
Original file line number Diff line number Diff line change
Expand Up @@ -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 (
<div className="basket-section">
Expand Down Expand Up @@ -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,
};

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -74,7 +74,7 @@ describe('<CardHolderInformation />', () => {
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', () => {
Expand Down
1 change: 0 additions & 1 deletion src/payment/checkout/payment-form/StripePaymentForm.jsx
Original file line number Diff line number Diff line change
Expand Up @@ -198,7 +198,6 @@ const StripePaymentForm = ({
showBulkEnrollmentFields={isBulkOrder}
disabled={submitting}
enableStripePaymentProcessor={enableStripePaymentProcessor}
isDynamicPaymentMethodsEnabled={isDynamicPaymentMethodsEnabled}
/>
<h5 aria-level="2">
<FormattedMessage
Expand Down
37 changes: 3 additions & 34 deletions src/payment/checkout/payment-form/utils/form-validators.js
Original file line number Diff line number Diff line change
Expand Up @@ -15,41 +15,10 @@ export const getCountryStatesMap = (country) => {
};

// 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);

Expand Down
21 changes: 17 additions & 4 deletions src/payment/data/handleRequestError.js
Original file line number Diff line number Diff line change
Expand Up @@ -84,10 +84,23 @@ 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]'
)) {
// 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]',
];

if (error.type === 'invalid_request_error' && billingAddressErrors.includes(error.param)) {
logInfo('Dynamic Payment Method Country Error', error.param);
handleApiErrors([
{
Expand Down

0 comments on commit 0de1892

Please sign in to comment.