2020-03-26 11:11:46 +00:00
|
|
|
/**
|
|
|
|
* External dependencies
|
|
|
|
*/
|
2020-04-15 15:15:56 +00:00
|
|
|
import { __, sprintf } from '@wordpress/i18n';
|
2020-03-26 11:11:46 +00:00
|
|
|
import {
|
|
|
|
getPaymentMethods,
|
|
|
|
getExpressPaymentMethods,
|
|
|
|
} from '@woocommerce/blocks-registry';
|
2020-05-12 16:40:08 +00:00
|
|
|
import { useState, useEffect, useRef, useCallback } from '@wordpress/element';
|
2020-04-09 11:44:29 +00:00
|
|
|
import {
|
|
|
|
useEditorContext,
|
|
|
|
useShippingDataContext,
|
|
|
|
} from '@woocommerce/base-context';
|
|
|
|
import { useStoreCart } from '@woocommerce/base-hooks';
|
2020-04-15 15:15:56 +00:00
|
|
|
import { CURRENT_USER_IS_ADMIN } from '@woocommerce/block-settings';
|
2020-03-26 11:11:46 +00:00
|
|
|
|
2020-05-12 16:40:08 +00:00
|
|
|
/**
|
|
|
|
* If there was an error registering a payment method, alert the admin.
|
|
|
|
*
|
|
|
|
* @param {Object} error Error object.
|
|
|
|
*/
|
|
|
|
const handleRegistrationError = ( error ) => {
|
|
|
|
if ( CURRENT_USER_IS_ADMIN ) {
|
|
|
|
throw new Error(
|
|
|
|
sprintf(
|
|
|
|
__(
|
|
|
|
// translators: %s is the error method returned by the payment method.
|
|
|
|
'Problem with payment method initialization: %s',
|
|
|
|
'woo-gutenberg-products-block'
|
|
|
|
),
|
|
|
|
error.message
|
|
|
|
)
|
|
|
|
);
|
|
|
|
}
|
|
|
|
};
|
|
|
|
|
2020-04-14 22:44:31 +00:00
|
|
|
/**
|
|
|
|
* This hook handles initializing registered payment methods and exposing all
|
|
|
|
* registered payment methods that can be used in the current environment (via
|
|
|
|
* the payment method's `canMakePayment` property).
|
|
|
|
*
|
|
|
|
* @param {function(Object):undefined} dispatcher A dispatcher for setting registered
|
|
|
|
* payment methods to an external
|
|
|
|
* state.
|
|
|
|
* @param {Object} registeredPaymentMethods Registered payment methods to
|
|
|
|
* process.
|
|
|
|
*
|
|
|
|
* @return {boolean} Whether the payment methods have been initialized or not. True when all payment
|
|
|
|
* methods have been initialized.
|
|
|
|
*/
|
2020-03-26 11:11:46 +00:00
|
|
|
const usePaymentMethodRegistration = (
|
|
|
|
dispatcher,
|
|
|
|
registeredPaymentMethods
|
|
|
|
) => {
|
|
|
|
const [ isInitialized, setIsInitialized ] = useState( false );
|
2020-05-12 16:40:08 +00:00
|
|
|
const { isEditor } = useEditorContext();
|
2020-04-09 11:44:29 +00:00
|
|
|
const { shippingAddress } = useShippingDataContext();
|
|
|
|
const { cartTotals, cartNeedsShipping } = useStoreCart();
|
|
|
|
const canPayArgument = useRef( {
|
|
|
|
cartTotals,
|
|
|
|
cartNeedsShipping,
|
|
|
|
shippingAddress,
|
|
|
|
} );
|
2020-04-14 22:44:31 +00:00
|
|
|
|
2020-04-09 11:44:29 +00:00
|
|
|
useEffect( () => {
|
|
|
|
canPayArgument.current = {
|
|
|
|
cartTotals,
|
|
|
|
cartNeedsShipping,
|
|
|
|
shippingAddress,
|
|
|
|
};
|
|
|
|
}, [ cartTotals, cartNeedsShipping, shippingAddress ] );
|
|
|
|
|
2020-05-12 16:40:08 +00:00
|
|
|
const resolveCanMakePayments = useCallback( async () => {
|
|
|
|
let initializedPaymentMethods = {},
|
|
|
|
canPay;
|
|
|
|
const setInitializedPaymentMethods = ( paymentMethod ) => {
|
|
|
|
initializedPaymentMethods = {
|
|
|
|
...initializedPaymentMethods,
|
|
|
|
[ paymentMethod.name ]: paymentMethod,
|
|
|
|
};
|
2020-03-26 11:11:46 +00:00
|
|
|
};
|
2020-04-14 22:44:31 +00:00
|
|
|
for ( const paymentMethodName in registeredPaymentMethods ) {
|
|
|
|
const current = registeredPaymentMethods[ paymentMethodName ];
|
2020-05-12 16:40:08 +00:00
|
|
|
|
2020-03-26 11:11:46 +00:00
|
|
|
if ( isEditor ) {
|
2020-05-12 16:40:08 +00:00
|
|
|
setInitializedPaymentMethods( current );
|
|
|
|
continue;
|
|
|
|
}
|
|
|
|
|
|
|
|
try {
|
|
|
|
canPay = await Promise.resolve(
|
2020-04-09 11:44:29 +00:00
|
|
|
current.canMakePayment( canPayArgument.current )
|
2020-05-12 16:40:08 +00:00
|
|
|
);
|
|
|
|
if ( canPay ) {
|
|
|
|
if ( canPay.error ) {
|
|
|
|
throw new Error( canPay.error.message );
|
|
|
|
}
|
|
|
|
setInitializedPaymentMethods( current );
|
|
|
|
}
|
|
|
|
} catch ( e ) {
|
|
|
|
handleRegistrationError( e );
|
2020-03-26 11:11:46 +00:00
|
|
|
}
|
|
|
|
}
|
2020-05-12 16:40:08 +00:00
|
|
|
// all payment methods have been initialized so dispatch and set
|
|
|
|
dispatcher( initializedPaymentMethods );
|
|
|
|
setIsInitialized( true );
|
|
|
|
}, [ dispatcher, isEditor, registeredPaymentMethods ] );
|
2020-03-26 11:11:46 +00:00
|
|
|
|
2020-05-12 16:40:08 +00:00
|
|
|
// if not initialized invoke the callback to kick off resolving the payments.
|
2020-04-14 22:44:31 +00:00
|
|
|
useEffect( () => {
|
2020-05-12 16:40:08 +00:00
|
|
|
if ( ! isInitialized ) {
|
|
|
|
resolveCanMakePayments();
|
2020-04-14 22:44:31 +00:00
|
|
|
}
|
2020-05-12 16:40:08 +00:00
|
|
|
}, [ resolveCanMakePayments, isInitialized ] );
|
2020-04-14 22:44:31 +00:00
|
|
|
|
2020-03-26 11:11:46 +00:00
|
|
|
return isInitialized;
|
|
|
|
};
|
|
|
|
|
|
|
|
export const usePaymentMethods = ( dispatcher ) =>
|
|
|
|
usePaymentMethodRegistration( dispatcher, getPaymentMethods() );
|
|
|
|
export const useExpressPaymentMethods = ( dispatcher ) =>
|
|
|
|
usePaymentMethodRegistration( dispatcher, getExpressPaymentMethods() );
|