diff --git a/packages/bigcommerce-payments-integration/src/bigcommerce-payments/bigcommerce-payments-customer-strategy.spec.ts b/packages/bigcommerce-payments-integration/src/bigcommerce-payments/bigcommerce-payments-customer-strategy.spec.ts index eaacff08da..843806f05b 100644 --- a/packages/bigcommerce-payments-integration/src/bigcommerce-payments/bigcommerce-payments-customer-strategy.spec.ts +++ b/packages/bigcommerce-payments-integration/src/bigcommerce-payments/bigcommerce-payments-customer-strategy.spec.ts @@ -333,6 +333,62 @@ describe('BigCommercePaymentsCustomerStrategy', () => { expect(bigCommercePaymentsSdkRenderMock).toHaveBeenCalled(); }); + it('render button with appSwitch flag', async () => { + jest.spyOn( + paymentIntegrationService.getState(), + 'getPaymentMethodOrThrow', + ).mockReturnValue({ + ...paymentMethod, + initializationData: { + ...paymentMethod.initializationData, + isAppSwitchEnabled: true, + }, + }); + + await strategy.initialize(initializationOptions); + + expect(paypalSdk.Buttons).toHaveBeenCalledWith({ + appSwitchWhenAvailable: true, + fundingSource: paypalSdk.FUNDING.PAYPAL, + style: { + height: DefaultCheckoutButtonHeight, + color: StyleButtonColor.silver, + label: 'checkout', + }, + createOrder: expect.any(Function), + onApprove: expect.any(Function), + onClick: expect.any(Function), + }); + }); + + it('calls resume when appSwitch enabled and returned from app', async () => { + jest.spyOn( + paymentIntegrationService.getState(), + 'getPaymentMethodOrThrow', + ).mockReturnValue({ + ...paymentMethod, + initializationData: { + ...paymentMethod.initializationData, + isAppSwitchEnabled: true, + }, + }); + + const resumeMock = jest.fn(); + const bigCommercePaymentsSdkRenderMock = jest.fn(); + + jest.spyOn(paypalSdk, 'Buttons').mockImplementation(() => ({ + close: jest.fn(), + isEligible: jest.fn(() => true), + render: bigCommercePaymentsSdkRenderMock, + hasReturned: jest.fn(() => true), + resume: resumeMock, + })); + + await strategy.initialize(initializationOptions); + + expect(resumeMock).toHaveBeenCalled(); + }); + it('does not render PayPal button if it is not eligible', async () => { const bigCommercePaymentsSdkRenderMock = jest.fn(); diff --git a/packages/bigcommerce-payments-integration/src/bigcommerce-payments/bigcommerce-payments-customer-strategy.ts b/packages/bigcommerce-payments-integration/src/bigcommerce-payments/bigcommerce-payments-customer-strategy.ts index d8bdfaede1..e6dee9cdf3 100644 --- a/packages/bigcommerce-payments-integration/src/bigcommerce-payments/bigcommerce-payments-customer-strategy.ts +++ b/packages/bigcommerce-payments-integration/src/bigcommerce-payments/bigcommerce-payments-customer-strategy.ts @@ -119,11 +119,14 @@ export default class BigCommercePaymentsCustomerStrategy implements CustomerStra const state = this.paymentIntegrationService.getState(); const paymentMethod = state.getPaymentMethodOrThrow(methodId); - const { isHostedCheckoutEnabled, paymentButtonStyles } = + const { isHostedCheckoutEnabled, paymentButtonStyles, isAppSwitchEnabled } = paymentMethod.initializationData || {}; const { checkoutTopButtonStyles } = paymentButtonStyles || {}; const defaultCallbacks = { + ...(this.isPaypalCommerceAppSwitchEnabled(methodId) && { + appSwitchWhenAvailable: true, + }), createOrder: () => this.bigCommercePaymentsIntegrationService.createOrder('bigcommerce_payments'), onApprove: ({ orderID }: ApproveCallbackPayload) => @@ -132,10 +135,12 @@ export default class BigCommercePaymentsCustomerStrategy implements CustomerStra }; const hostedCheckoutCallbacks = { - onShippingAddressChange: (data: ShippingAddressChangeCallbackPayload) => - this.onShippingAddressChange(data), - onShippingOptionsChange: (data: ShippingOptionChangeCallbackPayload) => - this.onShippingOptionsChange(data), + ...(!isAppSwitchEnabled && { + onShippingAddressChange: (data: ShippingAddressChangeCallbackPayload) => + this.onShippingAddressChange(data), + onShippingOptionsChange: (data: ShippingOptionChangeCallbackPayload) => + this.onShippingOptionsChange(data), + }), onApprove: (data: ApproveCallbackPayload, actions: ApproveCallbackActions) => this.onHostedCheckoutApprove(data, actions, methodId, onComplete), }; @@ -153,7 +158,11 @@ export default class BigCommercePaymentsCustomerStrategy implements CustomerStra const paypalButton = paypalSdk.Buttons(buttonRenderOptions); if (paypalButton.isEligible()) { - paypalButton.render(`#${container}`); + if (paypalButton.hasReturned?.() && this.isPaypalCommerceAppSwitchEnabled(methodId)) { + paypalButton.resume?.(); + } else { + paypalButton.render(`#${container}`); + } } else { this.bigCommercePaymentsIntegrationService.removeElement(container); } @@ -249,4 +258,17 @@ export default class BigCommercePaymentsCustomerStrategy implements CustomerStra throw error; } } + + /** + * + * PayPal AppSwitch enabling handling + * + */ + private isPaypalCommerceAppSwitchEnabled(methodId: string): boolean { + const state = this.paymentIntegrationService.getState(); + const paymentMethod = + state.getPaymentMethodOrThrow(methodId); + + return paymentMethod.initializationData?.isAppSwitchEnabled ?? false; + } }