diff --git a/packages/braintree-integration/src/braintree-local-payment-methods/braintree-local-methods-payment-strategy.ts b/packages/braintree-integration/src/braintree-local-payment-methods/braintree-local-methods-payment-strategy.ts index 7ae6c452b4..84ef2fb579 100644 --- a/packages/braintree-integration/src/braintree-local-payment-methods/braintree-local-methods-payment-strategy.ts +++ b/packages/braintree-integration/src/braintree-local-payment-methods/braintree-local-methods-payment-strategy.ts @@ -3,6 +3,7 @@ import { BraintreeIntegrationService, LocalPaymentInstance, LocalPaymentsPayload, + NonInstantLocalPaymentMethods, onPaymentStartData, StartPaymentError, } from '@bigcommerce/checkout-sdk/braintree-utils'; @@ -18,6 +19,7 @@ import { PaymentMethodInvalidError, PaymentRequestOptions, PaymentStrategy, + isRequestError, } from '@bigcommerce/checkout-sdk/payment-integration-api'; import { LoadingIndicator } from '@bigcommerce/checkout-sdk/ui'; @@ -68,9 +70,14 @@ export default class BraintreeLocalMethodsPaymentStrategy implements PaymentStra await this.paymentIntegrationService.loadPaymentMethod(gatewayId); const state = this.paymentIntegrationService.getState(); - const storeConfig = state.getStoreConfigOrThrow(); const paymentMethod = state.getPaymentMethodOrThrow(gatewayId); + + if (this.isNonInstantPaymentMethod(paymentMethod.method)) { + return; + } + const { clientToken, config, initializationData } = paymentMethod; + const storeConfig = state.getStoreConfigOrThrow(); if (!clientToken || !initializationData) { throw new MissingDataError(MissingDataErrorType.MissingPaymentMethod); @@ -104,7 +111,7 @@ export default class BraintreeLocalMethodsPaymentStrategy implements PaymentStra const cart = state.getCartOrThrow(); const sessionId = await this.braintreeIntegrationService.getSessionId(); const billing = state.getBillingAddressOrThrow(); - const { firstName, lastName, countryCode } = billing; + const { firstName, lastName, countryCode, phone } = billing; const { currency, email, lineItems } = cart; const isShippingRequired = lineItems.physicalItems.length > 0; const grandTotal = state.getCheckoutOrThrow().outstandingBalance; @@ -115,6 +122,44 @@ export default class BraintreeLocalMethodsPaymentStrategy implements PaymentStra this.toggleLoadingIndicator(true); + if (this.isNonInstantPaymentMethod(payment.methodId)) { + const { methodId } = payment; + const paymentData = { + formattedPayload: { + vault_payment_instrument: null, + set_as_default_stored_instrument: null, + device_info: sessionId || null, + method_id: methodId, + [`${payment.methodId}_account`]: { + // take phone number from paymentData + phone + }, + }, + }; + + try { + await this.paymentIntegrationService.submitOrder(); + await this.paymentIntegrationService.submitPayment({ + methodId, + paymentData, + }); + } catch (error) { + if (isRequestError(error)) { + let redirectUrl = error.body.additional_action_required.data.redirect_url; + + if (redirectUrl) { + return new Promise(() => window.location.replace(redirectUrl)); + } + } + + this.toggleLoadingIndicator(false); + + return Promise.reject(error); + } + + return; + } + if (!this.localPaymentInstance) { throw new PaymentMethodInvalidError(); } @@ -216,4 +261,13 @@ export default class BraintreeLocalMethodsPaymentStrategy implements PaymentStra onError(error); } } + + /** + * + * Utils + * + * */ + private isNonInstantPaymentMethod(methodId: string): boolean { + return methodId.toUpperCase() in NonInstantLocalPaymentMethods; + } } diff --git a/packages/braintree-utils/src/types.ts b/packages/braintree-utils/src/types.ts index c16951adf3..b8cc549280 100644 --- a/packages/braintree-utils/src/types.ts +++ b/packages/braintree-utils/src/types.ts @@ -472,3 +472,13 @@ export interface BraintreeError extends Error { code: string | BraintreeErrorCode.KountNotEnabled; details?: unknown; } + +/** + * + * Braintree non-instant payment methods + * + */ + +export enum NonInstantLocalPaymentMethods { + TRUSTLY = 'trustly' +}