/** * External dependencies */ import type { CanMakePaymentCallback, CanMakePaymentExtensionCallback, } from '@woocommerce/type-defs/payments'; /** * Internal dependencies */ import { NamespacedCanMakePaymentExtensionsCallbacks, PaymentMethodName, ExtensionNamespace, extensionsConfig, } from './extensions-config'; // Filter out payment methods by supported features and cart requirement. export const canMakePaymentWithFeaturesCheck = ( canMakePayment: CanMakePaymentCallback, features: string[] ): CanMakePaymentCallback => ( canPayArgument ) => { const requirements = canPayArgument?.paymentRequirements || []; const featuresSupportRequirements = requirements.every( ( requirement ) => features.includes( requirement ) ); return featuresSupportRequirements && canMakePayment( canPayArgument ); }; // Filter out payment methods by callbacks registered by extensions. export const canMakePaymentWithExtensions = ( canMakePayment: CanMakePaymentCallback, extensionsCallbacks: NamespacedCanMakePaymentExtensionsCallbacks, paymentMethodName: PaymentMethodName ): CanMakePaymentCallback => ( canPayArgument ) => { // Validate whether the payment method is available based on its own criteria first. let canPay = canMakePayment( canPayArgument ); if ( canPay ) { // Gather all callbacks for paymentMethodName. const namespacedCallbacks: Record< ExtensionNamespace, CanMakePaymentExtensionCallback > = {}; Object.entries( extensionsCallbacks ).forEach( ( [ namespace, callbacks ] ) => { namespacedCallbacks[ namespace ] = callbacks[ paymentMethodName ]; } ); canPay = Object.keys( namespacedCallbacks ).every( ( namespace ) => { try { return namespacedCallbacks[ namespace ]( canPayArgument ); } catch ( err ) { // eslint-disable-next-line no-console console.error( `Error when executing callback for ${ paymentMethodName } in ${ namespace }`, err ); // .every() expects a return value at the end of every arrow function and // this ensures that the error is ignored when computing the whole result. return true; } } ); } return canPay; }; export const getCanMakePayment = ( canMakePayment: CanMakePaymentCallback, features: string[], paymentMethodName: string ): CanMakePaymentCallback => { const canPay = canMakePaymentWithFeaturesCheck( canMakePayment, features ); // Loop through all callbacks to check if there are any registered for this payment method. return ( Object.values( extensionsConfig.canMakePayment ) as Record< PaymentMethodName, CanMakePaymentCallback >[] ).some( ( callbacks ) => paymentMethodName in callbacks ) ? canMakePaymentWithExtensions( canPay, extensionsConfig.canMakePayment, paymentMethodName ) : canPay; };