diff --git a/packages/bigcommerce-payments-integration/src/bigcommerce-payments-invoices/bigcommerce-payments-invoices-payment-initialize-options.ts b/packages/bigcommerce-payments-integration/src/bigcommerce-payments-invoices/bigcommerce-payments-invoices-payment-initialize-options.ts new file mode 100644 index 0000000000..2b314cc8e6 --- /dev/null +++ b/packages/bigcommerce-payments-integration/src/bigcommerce-payments-invoices/bigcommerce-payments-invoices-payment-initialize-options.ts @@ -0,0 +1,32 @@ +import { + PayPalButtonStyleOptions, + PayPalBuyNowInitializeOptions, +} from '../bigcommerce-payments-types'; + +export default interface BigCommercePaymentsInvoicesPaymentInitializeOptions { + /** + * A set of styling options for the checkout button. + */ + style?: PayPalButtonStyleOptions; + + /** + * The option that used to initialize a PayPal script with provided currency code. + */ + currencyCode?: string; + + /** + * The options that required to initialize Buy Now functionality. + */ + buyNowInitializeOptions?: PayPalBuyNowInitializeOptions; + + /** + * + * A callback that gets called when PayPal SDK restricts to render PayPal component. + * + */ + onEligibilityFailure?(): void; +} + +export interface WithBigCommercePaymentsInvoicesPaymentInitializeOptions { + bigcommerce_payments_invoices?: BigCommercePaymentsInvoicesPaymentInitializeOptions; +} diff --git a/packages/bigcommerce-payments-integration/src/bigcommerce-payments-invoices/bigcommerce-payments-invoices-payment-strategy.ts b/packages/bigcommerce-payments-integration/src/bigcommerce-payments-invoices/bigcommerce-payments-invoices-payment-strategy.ts new file mode 100644 index 0000000000..23e6edb9e2 --- /dev/null +++ b/packages/bigcommerce-payments-integration/src/bigcommerce-payments-invoices/bigcommerce-payments-invoices-payment-strategy.ts @@ -0,0 +1,59 @@ +import { + InvalidArgumentError, + OrderFinalizationNotRequiredError, + OrderRequestBody, + Payment, + PaymentArgumentInvalidError, + PaymentInitializeOptions, + PaymentIntegrationService, + PaymentRequestOptions, + PaymentStrategy, +} from '@bigcommerce/checkout-sdk/payment-integration-api'; + +import { WithBigCommercePaymentsInvoicesPaymentInitializeOptions } from './bigcommerce-payments-invoices-payment-initialize-options'; + +export default class BigCommercePaymentsInvoicesPaymentStrategy implements PaymentStrategy { + constructor(private paymentIntegrationService: PaymentIntegrationService) {} + + async initialize( + options?: PaymentInitializeOptions & + WithBigCommercePaymentsInvoicesPaymentInitializeOptions, + ): Promise { + const { methodId } = options || {}; + + if (!methodId) { + throw new InvalidArgumentError( + 'Unable to initialize payment because "options.methodId" argument is not provided.', + ); + } + + await this.paymentIntegrationService.loadPaymentMethods(); + } + + async execute(payload: OrderRequestBody, options?: PaymentRequestOptions): Promise { + const { payment, ...order } = payload; + const { methodId } = payment || {}; + + if (!payment || !methodId) { + throw new PaymentArgumentInvalidError(['payment']); + } + + const submitPaymentPayload: Payment = { + methodId, + paymentData: { + formattedPayload: {}, + }, + }; + + await this.paymentIntegrationService.submitOrder(order, options); + await this.paymentIntegrationService.submitPayment(submitPaymentPayload); + } + + finalize(): Promise { + return Promise.reject(new OrderFinalizationNotRequiredError()); + } + + deinitialize(): Promise { + return Promise.resolve(); + } +} diff --git a/packages/bigcommerce-payments-integration/src/bigcommerce-payments-invoices/create-bigcommerce-payments-invoices-payment-strategy.ts b/packages/bigcommerce-payments-integration/src/bigcommerce-payments-invoices/create-bigcommerce-payments-invoices-payment-strategy.ts new file mode 100644 index 0000000000..f2c3637b85 --- /dev/null +++ b/packages/bigcommerce-payments-integration/src/bigcommerce-payments-invoices/create-bigcommerce-payments-invoices-payment-strategy.ts @@ -0,0 +1,15 @@ +import { + PaymentStrategyFactory, + toResolvableModule, +} from '@bigcommerce/checkout-sdk/payment-integration-api'; + +import BigCommercePaymentsInvoicesPaymentStrategy from './bigcommerce-payments-invoices-payment-strategy'; + +const createBigCommercePaymentsInvoicesPaymentStrategy: PaymentStrategyFactory< + BigCommercePaymentsInvoicesPaymentStrategy +> = (paymentIntegrationService) => + new BigCommercePaymentsInvoicesPaymentStrategy(paymentIntegrationService); + +export default toResolvableModule(createBigCommercePaymentsInvoicesPaymentStrategy, [ + { id: 'bigcommerce_payments_invoices' }, +]); diff --git a/packages/bigcommerce-payments-integration/src/index.ts b/packages/bigcommerce-payments-integration/src/index.ts index 71073fc0ea..79249cad10 100644 --- a/packages/bigcommerce-payments-integration/src/index.ts +++ b/packages/bigcommerce-payments-integration/src/index.ts @@ -86,3 +86,11 @@ export { WithBigCommercePaymentsVenmoCustomerInitializeOptions } from './bigcomm export { default as createBigCommercePaymentsVenmoPaymentStrategy } from './bigcommerce-payments-venmo/create-bigcommerce-payments-venmo-payment-strategy'; export { WithBigCommercePaymentsVenmoPaymentInitializeOptions } from './bigcommerce-payments-venmo/bigcommerce-payments-venmo-payment-initialize-options'; + +/** + * + * BigCommercePayments Invoices strategies + * + */ +export { default as createBigCommercePaymentsInvoicesPaymentStrategy } from './bigcommerce-payments-invoices/create-bigcommerce-payments-invoices-payment-strategy'; +export { WithBigCommercePaymentsInvoicesPaymentInitializeOptions } from './bigcommerce-payments-invoices/bigcommerce-payments-invoices-payment-initialize-options'; diff --git a/packages/core/src/payment/payment-request-transformer.spec.ts b/packages/core/src/payment/payment-request-transformer.spec.ts index e9d619fc4d..fadb5f6f04 100644 --- a/packages/core/src/payment/payment-request-transformer.spec.ts +++ b/packages/core/src/payment/payment-request-transformer.spec.ts @@ -140,6 +140,19 @@ describe('PaymentRequestTransformer', () => { ); }); + it('remaps bigcommerce_payments_invoices id to the bigcommerce_payments provider gateway', () => { + const paymentMethod = { ...getAuthorizenet(), id: 'bigcommerce_payments_invoices' }; + + jest.spyOn(selectors.paymentMethods, 'getPaymentMethod').mockReturnValue(paymentMethod); + + const paymentRequestBodyResponse = paymentRequestTransformer.transform(payment, selectors); + + expect(paymentRequestBodyResponse.paymentMethod).toEqual({ + ...paymentMethod, + id: 'bigcommerce_payments', + }); + }); + it('transforms from hosted form data', () => { const result = paymentRequestTransformer.transformWithHostedFormData( { diff --git a/packages/core/src/payment/payment-request-transformer.ts b/packages/core/src/payment/payment-request-transformer.ts index fd04bea395..927a8e4acc 100644 --- a/packages/core/src/payment/payment-request-transformer.ts +++ b/packages/core/src/payment/payment-request-transformer.ts @@ -172,6 +172,15 @@ export default class PaymentRequestTransformer { return { ...paymentMethod, id: CheckoutButtonMethodType.BRAINTREE_PAYPAL }; } + // BigCommerce Payments Invoices: the method is registered as + // `bigcommerce_payments_invoices`, but BigPay expects the provider gateway + // `bigcommerce_payments` with `method: 'invoice'`. The BigPay client's id mapper + // doesn't recognise this method, so it would otherwise fall through and send the + // raw method id as the gateway. Remap the id to the provider here. + if (paymentMethod.id === 'bigcommerce_payments_invoices') { + return { ...paymentMethod, id: 'bigcommerce_payments' }; + } + return paymentMethod; }