Skip to content

Commit 7a52626

Browse files
feat(payment): PAYPAL-5723 add bcp button app switch
1 parent 3f3ebb7 commit 7a52626

File tree

2 files changed

+82
-6
lines changed

2 files changed

+82
-6
lines changed

packages/bigcommerce-payments-integration/src/bigcommerce-payments/bigcommerce-payments-button-strategy.spec.ts

Lines changed: 51 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -441,6 +441,57 @@ describe('BigCommercePaymentsButtonStrategy', () => {
441441
expect(bigCommercePaymentsSdkRenderMock).toHaveBeenCalled();
442442
});
443443

444+
it('render button with appSwitch flag', async () => {
445+
jest.spyOn(
446+
paymentIntegrationService.getState(),
447+
'getPaymentMethodOrThrow',
448+
).mockReturnValue({
449+
...paymentMethod,
450+
initializationData: {
451+
...paymentMethod.initializationData,
452+
isAppSwitchEnabled: true,
453+
},
454+
});
455+
456+
await strategy.initialize(initializationOptions);
457+
458+
expect(paypalSdk.Buttons).toHaveBeenCalledWith({
459+
appSwitchWhenAvailable: true,
460+
fundingSource: paypalSdk.FUNDING.PAYPAL,
461+
style: bigCommercePaymentsOptions.style,
462+
createOrder: expect.any(Function),
463+
onApprove: expect.any(Function),
464+
});
465+
});
466+
467+
it('calls resume when appSwitch enabled and returned from app', async () => {
468+
jest.spyOn(
469+
paymentIntegrationService.getState(),
470+
'getPaymentMethodOrThrow',
471+
).mockReturnValue({
472+
...paymentMethod,
473+
initializationData: {
474+
...paymentMethod.initializationData,
475+
isAppSwitchEnabled: true,
476+
},
477+
});
478+
479+
const resumeMock = jest.fn();
480+
const bigCommercePaymentsSdkRenderMock = jest.fn();
481+
482+
jest.spyOn(paypalSdk, 'Buttons').mockImplementation(() => ({
483+
close: jest.fn(),
484+
isEligible: jest.fn(() => true),
485+
render: bigCommercePaymentsSdkRenderMock,
486+
hasReturned: jest.fn(() => true),
487+
resume: resumeMock,
488+
}));
489+
490+
await strategy.initialize(initializationOptions);
491+
492+
expect(resumeMock).toHaveBeenCalled();
493+
});
494+
444495
it('does not render PayPal button if it is not eligible', async () => {
445496
const bigCommercePaymentsSdkRenderMock = jest.fn();
446497

packages/bigcommerce-payments-integration/src/bigcommerce-payments/bigcommerce-payments-button-strategy.ts

Lines changed: 31 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -99,6 +99,7 @@ export default class BigCommercePaymentsButtonStrategy implements CheckoutButton
9999
containerId: string,
100100
methodId: string,
101101
bigcommerce_payments: BigCommercePaymentsButtonInitializeOptions,
102+
isBuyNowFlow?: boolean,
102103
): void {
103104
const { buyNowInitializeOptions, style, onComplete, onEligibilityFailure } =
104105
bigcommerce_payments;
@@ -107,9 +108,14 @@ export default class BigCommercePaymentsButtonStrategy implements CheckoutButton
107108
const state = this.paymentIntegrationService.getState();
108109
const paymentMethod =
109110
state.getPaymentMethodOrThrow<BigCommercePaymentsInitializationData>(methodId);
110-
const { isHostedCheckoutEnabled } = paymentMethod.initializationData || {};
111+
const { isHostedCheckoutEnabled, isAppSwitchEnabled } =
112+
paymentMethod.initializationData || {};
111113

112114
const defaultCallbacks = {
115+
...(!isBuyNowFlow &&
116+
this.isPaypalCommerceAppSwitchEnabled(methodId) && {
117+
appSwitchWhenAvailable: true,
118+
}),
113119
createOrder: () =>
114120
this.bigCommercePaymentsIntegrationService.createOrder('bigcommerce_payments'),
115121
onApprove: ({ orderID }: ApproveCallbackPayload) =>
@@ -122,10 +128,12 @@ export default class BigCommercePaymentsButtonStrategy implements CheckoutButton
122128
};
123129

124130
const hostedCheckoutCallbacks = {
125-
onShippingAddressChange: (data: ShippingAddressChangeCallbackPayload) =>
126-
this.onShippingAddressChange(data),
127-
onShippingOptionsChange: (data: ShippingOptionChangeCallbackPayload) =>
128-
this.onShippingOptionsChange(data),
131+
...(!isAppSwitchEnabled && {
132+
onShippingAddressChange: (data: ShippingAddressChangeCallbackPayload) =>
133+
this.onShippingAddressChange(data),
134+
onShippingOptionsChange: (data: ShippingOptionChangeCallbackPayload) =>
135+
this.onShippingOptionsChange(data),
136+
}),
129137
onApprove: (data: ApproveCallbackPayload, actions: ApproveCallbackActions) =>
130138
this.onHostedCheckoutApprove(data, actions, methodId, onComplete),
131139
};
@@ -141,7 +149,11 @@ export default class BigCommercePaymentsButtonStrategy implements CheckoutButton
141149
const paypalButton = paypalSdk.Buttons(buttonRenderOptions);
142150

143151
if (paypalButton.isEligible()) {
144-
paypalButton.render(`#${containerId}`);
152+
if (paypalButton.hasReturned?.() && this.isPaypalCommerceAppSwitchEnabled(methodId)) {
153+
paypalButton.resume?.();
154+
} else {
155+
paypalButton.render(`#${containerId}`);
156+
}
145157
} else if (onEligibilityFailure && typeof onEligibilityFailure === 'function') {
146158
onEligibilityFailure();
147159
} else {
@@ -259,4 +271,17 @@ export default class BigCommercePaymentsButtonStrategy implements CheckoutButton
259271
throw error;
260272
}
261273
}
274+
275+
/**
276+
*
277+
* PayPal AppSwitch enabling handling
278+
*
279+
*/
280+
private isPaypalCommerceAppSwitchEnabled(methodId: string): boolean {
281+
const state = this.paymentIntegrationService.getState();
282+
const paymentMethod =
283+
state.getPaymentMethodOrThrow<BigCommercePaymentsInitializationData>(methodId);
284+
285+
return paymentMethod.initializationData?.isAppSwitchEnabled ?? false;
286+
}
262287
}

0 commit comments

Comments
 (0)