/** * External dependencies */ import { useEffect, useCallback, useState } from '@wordpress/element'; /** * Internal dependencies */ import { getErrorMessageForTypeAndCode } from '../stripe-utils'; import { usePaymentIntents } from './use-payment-intents'; import { usePaymentProcessing } from './use-payment-processing'; /** * @typedef {import('@woocommerce/type-defs/registered-payment-method-props').EventRegistrationProps} EventRegistrationProps * @typedef {import('@woocommerce/type-defs/registered-payment-method-props').BillingDataProps} BillingDataProps * @typedef {import('@woocommerce/type-defs/registered-payment-method-props').EmitResponseProps} EmitResponseProps * @typedef {import('../stripe-utils/type-defs').Stripe} Stripe * @typedef {import('react').Dispatch} SourceIdDispatch */ /** * A custom hook for the Stripe processing and event observer logic. * * @param {EventRegistrationProps} eventRegistration Event registration functions. * @param {BillingDataProps} billing Various billing data items. * @param {string} sourceId Current set stripe source id. * @param {SourceIdDispatch} setSourceId Setter for stripe source id. * @param {EmitResponseProps} emitResponse Various helpers for usage with observer * response objects. * @param {Stripe} stripe The stripe.js object. * * @return {function(Object):Object} Returns a function for handling stripe error. */ export const useCheckoutSubscriptions = ( eventRegistration, billing, sourceId, setSourceId, emitResponse, stripe ) => { const [ error, setError ] = useState( '' ); const onStripeError = useCallback( ( event ) => { const type = event.error.type; const code = event.error.code || ''; const message = getErrorMessageForTypeAndCode( type, code ) ?? event.error.message; setError( message ); return message; }, [] ); const { onCheckoutAfterProcessingWithSuccess, onPaymentProcessing, onCheckoutAfterProcessingWithError, } = eventRegistration; usePaymentIntents( stripe, onCheckoutAfterProcessingWithSuccess, emitResponse ); usePaymentProcessing( onStripeError, error, stripe, billing, emitResponse, sourceId, setSourceId, onPaymentProcessing ); // hook into and register callbacks for events. useEffect( () => { const onError = ( { processingResponse } ) => { if ( processingResponse?.paymentDetails?.errorMessage ) { return { type: emitResponse.responseTypes.ERROR, message: processingResponse.paymentDetails.errorMessage, messageContext: emitResponse.noticeContexts.PAYMENTS, }; } // so we don't break the observers. return true; }; const unsubscribeAfterProcessing = onCheckoutAfterProcessingWithError( onError ); return () => { unsubscribeAfterProcessing(); }; }, [ onCheckoutAfterProcessingWithError, emitResponse.noticeContexts.PAYMENTS, emitResponse.responseTypes.ERROR, ] ); return onStripeError; };