Skip to content

Commit 255fcfe

Browse files
feat(payment): Added BCP FL corresponding error for 422 payment status (#2941)
* feat(payment): Added corresponding error for 422 payment status * feat(payment): Added corresponding error for 422 payment status
1 parent e76117f commit 255fcfe

File tree

6 files changed

+104
-1
lines changed

6 files changed

+104
-1
lines changed

packages/bigcommerce-payments-integration/src/bigcommerce-payments-fastlane/bigcommerce-payments-fastlane-payment-initialize-options.ts

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -61,6 +61,11 @@ export default interface BigCommercePaymentsFastlanePaymentInitializeOptions {
6161
*/
6262
onChange?: (showPayPalCardSelector: () => Promise<CardInstrument | undefined>) => void;
6363

64+
/**
65+
* Callback that handles errors
66+
*/
67+
onError?: (error: unknown) => void;
68+
6469
/**
6570
* Is a stylisation options for customizing BigCommercePayments Fastlane components
6671
*

packages/bigcommerce-payments-integration/src/bigcommerce-payments-fastlane/bigcommerce-payments-fastlane-payment-strategy.spec.ts

Lines changed: 32 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -407,6 +407,10 @@ describe('BigCommercePaymentsFastlanePaymentStrategy', () => {
407407
});
408408

409409
describe('#execute()', () => {
410+
afterEach(() => {
411+
jest.clearAllMocks();
412+
});
413+
410414
const mockedInstrumentId = 'mockInstrumentId123';
411415

412416
const executeOptions = {
@@ -740,6 +744,34 @@ describe('BigCommercePaymentsFastlanePaymentStrategy', () => {
740744
}
741745
});
742746
});
747+
748+
it('throws specific error when get 422 error on payment request', async () => {
749+
const initOptions = {
750+
methodId,
751+
bigcommerce_payments_fastlane: {
752+
onInit: jest.fn(),
753+
onChange: jest.fn(),
754+
onError: jest.fn(),
755+
},
756+
};
757+
jest.spyOn(paymentIntegrationService, 'submitPayment').mockRejectedValue({
758+
name: 'Error',
759+
message: 'Payment request failed',
760+
response: {
761+
status: 422,
762+
name: 'INVALID_REQUEST',
763+
},
764+
});
765+
await strategy.initialize(initOptions);
766+
767+
try {
768+
await strategy.execute(executeOptions);
769+
} catch (error: unknown) {
770+
expect(initOptions.bigcommerce_payments_fastlane.onError).toHaveBeenCalledWith({
771+
translationKey: 'payment.errors.invalid_request_error',
772+
});
773+
}
774+
});
743775
});
744776

745777
describe('#onInit option callback', () => {

packages/bigcommerce-payments-integration/src/bigcommerce-payments-fastlane/bigcommerce-payments-fastlane-payment-strategy.ts

Lines changed: 29 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,7 @@ import {
22
BigCommercePaymentsFastlaneUtils,
33
BigCommercePaymentsInitializationData,
44
getFastlaneStyles,
5+
isBigcommerceFastlaneRequestError,
56
isPayPalFastlaneCustomer,
67
PayPalFastlaneAuthenticationState,
78
PayPalFastlaneCardComponentMethods,
@@ -32,14 +33,17 @@ import {
3233

3334
import BigCommercePaymentsRequestSender from '../bigcommerce-payments-request-sender';
3435

35-
import { WithBigCommercePaymentsFastlanePaymentInitializeOptions } from './bigcommerce-payments-fastlane-payment-initialize-options';
36+
import BigCommercePaymentsFastlanePaymentInitializeOptions, {
37+
WithBigCommercePaymentsFastlanePaymentInitializeOptions,
38+
} from './bigcommerce-payments-fastlane-payment-initialize-options';
3639
import { LiabilityShiftEnum } from '../bigcommerce-payments-types';
3740
import { isExperimentEnabled } from '@bigcommerce/checkout-sdk/utility';
3841

3942
export default class BigCommercePaymentsFastlanePaymentStrategy implements PaymentStrategy {
4043
private paypalComponentMethods?: PayPalFastlaneCardComponentMethods;
4144
private threeDSVerificationMethod?: string;
4245
private paypalFastlaneSdk?: PayPalFastlaneSdk;
46+
private bigcommerce_payments_fastlane?: BigCommercePaymentsFastlanePaymentInitializeOptions;
4347
private methodId?: string;
4448
private orderId?: string;
4549

@@ -74,6 +78,8 @@ export default class BigCommercePaymentsFastlanePaymentStrategy implements Payme
7478
);
7579
}
7680

81+
this.bigcommerce_payments_fastlane = bigcommerce_payments_fastlane;
82+
7783
if (
7884
!bigcommerce_payments_fastlane.onInit ||
7985
typeof bigcommerce_payments_fastlane.onInit !== 'function'
@@ -160,6 +166,19 @@ export default class BigCommercePaymentsFastlanePaymentStrategy implements Payme
160166
// TODO: we should probably update this method with removeStorageSessionId for better reading experience
161167
this.bigCommercePaymentsFastlaneUtils.updateStorageSessionId(true);
162168
} catch (error) {
169+
if (
170+
isBigcommerceFastlaneRequestError(error) &&
171+
error.response.name === 'INVALID_REQUEST'
172+
) {
173+
const invalidRequestError = {
174+
translationKey: 'payment.errors.invalid_request_error',
175+
};
176+
177+
this.handleError(invalidRequestError);
178+
179+
return Promise.reject();
180+
}
181+
163182
if (error instanceof Error && error.name !== 'FastlaneError') {
164183
throw error;
165184
}
@@ -510,4 +529,13 @@ export default class BigCommercePaymentsFastlanePaymentStrategy implements Payme
510529

511530
return isExperimentEnabled(features, 'PROJECT-7080.bcp_fastlane_three_ds');
512531
}
532+
533+
private handleError(error: unknown): void {
534+
if (
535+
this.bigcommerce_payments_fastlane?.onError &&
536+
typeof this.bigcommerce_payments_fastlane.onError === 'function'
537+
) {
538+
this.bigcommerce_payments_fastlane.onError(error);
539+
}
540+
}
513541
}

packages/bigcommerce-payments-utils/src/index.ts

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -21,3 +21,5 @@ export { default as PayPalSdkHelper } from './paypal-sdk-helper';
2121
*/
2222
export { default as createBigCommercePaymentsFastlaneUtils } from './create-bigcommerce-payments-fastlane-utils';
2323
export { default as BigCommercePaymentsFastlaneUtils } from './bigcommerce-payments-fastlane-utils';
24+
25+
export { default as isBigcommerceFastlaneRequestError } from './utils/is-bigcommerce-fastlane-request-error';
Lines changed: 17 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,17 @@
1+
import isBigcommerceFastlaneRequestError, {
2+
BigcommerceFastlaneRequestError,
3+
} from './is-bigcommerce-fastlane-request-error';
4+
5+
describe('isBigcommerceFastlaneRequestError', () => {
6+
it('should return true if paypal fastlane request is invalid', () => {
7+
const invalidRequestError: BigcommerceFastlaneRequestError = {
8+
name: 'Error',
9+
message: 'Invalid request',
10+
response: {
11+
name: 'INVALID_REQUEST',
12+
},
13+
};
14+
15+
expect(isBigcommerceFastlaneRequestError(invalidRequestError)).toBe(true);
16+
});
17+
});
Lines changed: 19 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,19 @@
1+
export interface BigcommerceFastlaneRequestError {
2+
name: string;
3+
message: string;
4+
response: {
5+
name: string;
6+
};
7+
}
8+
9+
export default function isBigcommerceFastlaneRequestError(
10+
error: unknown,
11+
): error is BigcommerceFastlaneRequestError {
12+
return (
13+
typeof error === 'object' &&
14+
error !== null &&
15+
'message' in error &&
16+
'response' in error &&
17+
'name' in (error as BigcommerceFastlaneRequestError).response
18+
);
19+
}

0 commit comments

Comments
 (0)