231 lines
7.2 KiB
TypeScript
231 lines
7.2 KiB
TypeScript
/**
|
|
* External dependencies
|
|
*/
|
|
import {
|
|
ExpressPaymentMethodConfigInstance,
|
|
PaymentMethodConfigInstance,
|
|
} from '@woocommerce/type-defs/payments';
|
|
import { CURRENT_USER_IS_ADMIN, getSetting } from '@woocommerce/settings';
|
|
import { dispatch, select } from '@wordpress/data';
|
|
import {
|
|
deriveSelectedShippingRates,
|
|
emptyHiddenAddressFields,
|
|
} from '@woocommerce/base-utils';
|
|
import { __, sprintf } from '@wordpress/i18n';
|
|
import { store as noticesStore } from '@wordpress/notices';
|
|
|
|
import {
|
|
getExpressPaymentMethods,
|
|
getPaymentMethods,
|
|
} from '@woocommerce/blocks-registry';
|
|
import { previewCart } from '@woocommerce/resource-previews';
|
|
|
|
/**
|
|
* Internal dependencies
|
|
*/
|
|
import { STORE_KEY as CART_STORE_KEY } from '../cart/constants';
|
|
import { STORE_KEY as PAYMENT_STORE_KEY } from './constants';
|
|
import { noticeContexts } from '../../base/context/event-emit';
|
|
import {
|
|
EMPTY_CART_ERRORS,
|
|
EMPTY_CART_ITEM_ERRORS,
|
|
EMPTY_EXTENSIONS,
|
|
} from '../../data/constants';
|
|
import {
|
|
defaultBillingAddress,
|
|
defaultShippingAddress,
|
|
} from '../../base/context/providers/cart-checkout/customer/constants';
|
|
|
|
export const checkPaymentMethodsCanPay = async ( express = false ) => {
|
|
const isEditor = !! select( 'core/editor' );
|
|
|
|
let availablePaymentMethods = {};
|
|
const paymentMethods = express
|
|
? getExpressPaymentMethods()
|
|
: getPaymentMethods();
|
|
|
|
const addAvailablePaymentMethod = (
|
|
paymentMethod:
|
|
| PaymentMethodConfigInstance
|
|
| ExpressPaymentMethodConfigInstance
|
|
) => {
|
|
const { name } = paymentMethod;
|
|
availablePaymentMethods = {
|
|
...availablePaymentMethods,
|
|
[ paymentMethod.name ]: { name },
|
|
};
|
|
};
|
|
|
|
const noticeContext = express
|
|
? noticeContexts.EXPRESS_PAYMENTS
|
|
: noticeContexts.PAYMENTS;
|
|
|
|
let cartForCanPayArgument: Record< string, unknown > = {};
|
|
let canPayArgument: Record< string, unknown > = {};
|
|
|
|
if ( ! isEditor ) {
|
|
const store = select( CART_STORE_KEY );
|
|
const cart = store.getCartData();
|
|
const cartErrors = store.getCartErrors();
|
|
const cartTotals = store.getCartTotals();
|
|
const cartIsLoading = ! store.hasFinishedResolution( 'getCartData' );
|
|
const isLoadingRates = store.isCustomerDataUpdating();
|
|
const selectedShippingMethods = deriveSelectedShippingRates(
|
|
cart.shippingRates
|
|
);
|
|
|
|
cartForCanPayArgument = {
|
|
cartCoupons: cart.coupons,
|
|
cartItems: cart.items,
|
|
crossSellsProducts: cart.crossSells,
|
|
cartFees: cart.fees,
|
|
cartItemsCount: cart.itemsCount,
|
|
cartItemsWeight: cart.itemsWeight,
|
|
cartNeedsPayment: cart.needsPayment,
|
|
cartNeedsShipping: cart.needsShipping,
|
|
cartItemErrors: cart.errors,
|
|
cartTotals,
|
|
cartIsLoading,
|
|
cartErrors,
|
|
billingData: emptyHiddenAddressFields( cart.billingAddress ),
|
|
billingAddress: emptyHiddenAddressFields( cart.billingAddress ),
|
|
shippingAddress: emptyHiddenAddressFields( cart.shippingAddress ),
|
|
extensions: cart.extensions,
|
|
shippingRates: cart.shippingRates,
|
|
isLoadingRates,
|
|
cartHasCalculatedShipping: cart.hasCalculatedShipping,
|
|
paymentRequirements: cart.paymentRequirements,
|
|
receiveCart: dispatch( CART_STORE_KEY ).receiveCart,
|
|
};
|
|
|
|
canPayArgument = {
|
|
cart: cartForCanPayArgument,
|
|
cartTotals: cart.totals,
|
|
cartNeedsShipping: cart.needsShipping,
|
|
billingData: cart.billingAddress,
|
|
billingAddress: cart.billingAddress,
|
|
shippingAddress: cart.shippingAddress,
|
|
selectedShippingMethods,
|
|
paymentRequirements: cart.paymentRequirements,
|
|
};
|
|
} else {
|
|
cartForCanPayArgument = {
|
|
cartCoupons: previewCart.coupons,
|
|
cartItems: previewCart.items,
|
|
crossSellsProducts: previewCart.cross_sells,
|
|
cartFees: previewCart.fees,
|
|
cartItemsCount: previewCart.items_count,
|
|
cartItemsWeight: previewCart.items_weight,
|
|
cartNeedsPayment: previewCart.needs_payment,
|
|
cartNeedsShipping: previewCart.needs_shipping,
|
|
cartItemErrors: EMPTY_CART_ITEM_ERRORS,
|
|
cartTotals: previewCart.totals,
|
|
cartIsLoading: false,
|
|
cartErrors: EMPTY_CART_ERRORS,
|
|
billingData: defaultBillingAddress,
|
|
billingAddress: defaultBillingAddress,
|
|
shippingAddress: defaultShippingAddress,
|
|
extensions: EMPTY_EXTENSIONS,
|
|
shippingRates: previewCart.shipping_rates,
|
|
isLoadingRates: false,
|
|
cartHasCalculatedShipping: previewCart.has_calculated_shipping,
|
|
paymentRequirements: previewCart.paymentRequirements,
|
|
receiveCart:
|
|
typeof previewCart?.receiveCart === 'function'
|
|
? previewCart.receiveCart
|
|
: () => undefined,
|
|
};
|
|
canPayArgument = {
|
|
cart: cartForCanPayArgument,
|
|
cartTotals: cartForCanPayArgument.totals,
|
|
cartNeedsShipping: cartForCanPayArgument.needsShipping,
|
|
billingData: cartForCanPayArgument.billingAddress,
|
|
billingAddress: cartForCanPayArgument.billingAddress,
|
|
shippingAddress: cartForCanPayArgument.shippingAddress,
|
|
selectedShippingMethods: deriveSelectedShippingRates(
|
|
cartForCanPayArgument.shippingRates
|
|
),
|
|
paymentRequirements: cartForCanPayArgument.paymentRequirements,
|
|
};
|
|
}
|
|
|
|
let paymentMethodsOrder;
|
|
if ( express ) {
|
|
paymentMethodsOrder = Object.keys( paymentMethods );
|
|
} else {
|
|
paymentMethodsOrder = Array.from(
|
|
new Set( [
|
|
...( getSetting( 'paymentGatewaySortOrder', [] ) as [] ),
|
|
...Object.keys( paymentMethods ),
|
|
] )
|
|
);
|
|
}
|
|
|
|
for ( let i = 0; i < paymentMethodsOrder.length; i++ ) {
|
|
const paymentMethodName = paymentMethodsOrder[ i ];
|
|
const paymentMethod = paymentMethods[ paymentMethodName ];
|
|
if ( ! paymentMethod ) {
|
|
continue;
|
|
}
|
|
|
|
// See if payment method should be available. This always evaluates to true in the editor context.
|
|
try {
|
|
const canPay = isEditor
|
|
? true
|
|
: await Promise.resolve(
|
|
paymentMethod.canMakePayment( canPayArgument )
|
|
);
|
|
|
|
if ( canPay ) {
|
|
if ( typeof canPay === 'object' && canPay.error ) {
|
|
throw new Error( canPay.error.message );
|
|
}
|
|
|
|
addAvailablePaymentMethod( paymentMethod );
|
|
}
|
|
} catch ( e ) {
|
|
if ( CURRENT_USER_IS_ADMIN || isEditor ) {
|
|
const { createErrorNotice } = dispatch( noticesStore );
|
|
const errorText = sprintf(
|
|
/* translators: %s the id of the payment method being registered (bank transfer, cheque...) */
|
|
__(
|
|
`There was an error registering the payment method with id '%s': `,
|
|
'woo-gutenberg-products-block'
|
|
),
|
|
paymentMethod.paymentMethodId
|
|
);
|
|
createErrorNotice( `${ errorText } ${ e }`, {
|
|
context: noticeContext,
|
|
id: `wc-${ paymentMethod.paymentMethodId }-registration-error`,
|
|
} );
|
|
}
|
|
}
|
|
}
|
|
const currentlyAvailablePaymentMethods = express
|
|
? select( PAYMENT_STORE_KEY ).getAvailableExpressPaymentMethods()
|
|
: select( PAYMENT_STORE_KEY ).getAvailablePaymentMethods();
|
|
|
|
const availablePaymentMethodNames = Object.keys( availablePaymentMethods );
|
|
if (
|
|
Object.keys( currentlyAvailablePaymentMethods ).length ===
|
|
availablePaymentMethodNames.length &&
|
|
Object.keys( currentlyAvailablePaymentMethods ).every( ( current ) =>
|
|
availablePaymentMethodNames.includes( current )
|
|
)
|
|
) {
|
|
// All the names are the same, no need to dispatch more actions.
|
|
return true;
|
|
}
|
|
|
|
const {
|
|
__internalSetAvailablePaymentMethods,
|
|
__internalSetAvailableExpressPaymentMethods,
|
|
} = dispatch( PAYMENT_STORE_KEY );
|
|
if ( express ) {
|
|
__internalSetAvailableExpressPaymentMethods( availablePaymentMethods );
|
|
return true;
|
|
}
|
|
__internalSetAvailablePaymentMethods( availablePaymentMethods );
|
|
return true;
|
|
};
|