Fix wrong keys being sent in `canMakePayment` and customer data showing in the Checkout block in the editor (https://github.com/woocommerce/woocommerce-blocks/pull/7434)
* Construct args for canMakePayment with correct keys * When the CheckoutEventsContext mounts, initialize payment store * Destructure useSelect correctly * Dispatch __internalInitializePaymentStore in selector tests * Update selector name to __internalUpdateAvailablePaymentMethods * Remove check for editor when registering checkout store * Add check for when express payment methods have updated too * Ensure billingAddress key exists in canMakePayment arg * Use editor context to know if we're in editor
This commit is contained in:
parent
48c450c469
commit
1eda6f8f3d
|
@ -16,6 +16,7 @@ import deprecated from '@wordpress/deprecated';
|
|||
import { useDispatch, useSelect } from '@wordpress/data';
|
||||
import {
|
||||
CHECKOUT_STORE_KEY,
|
||||
PAYMENT_STORE_KEY,
|
||||
VALIDATION_STORE_KEY,
|
||||
} from '@woocommerce/block-data';
|
||||
|
||||
|
@ -28,6 +29,11 @@ import { STATUS } from '../../../../../data/checkout/constants';
|
|||
import { useStoreEvents } from '../../../hooks/use-store-events';
|
||||
import { useCheckoutNotices } from '../../../hooks/use-checkout-notices';
|
||||
import { CheckoutState } from '../../../../../data/checkout/default-state';
|
||||
import {
|
||||
getExpressPaymentMethods,
|
||||
getPaymentMethods,
|
||||
} from '../../../../../blocks-registry/payment-methods/registry';
|
||||
import { useEditorContext } from '../../editor-context';
|
||||
|
||||
type CheckoutEventsContextType = {
|
||||
// Submits the checkout and begins processing.
|
||||
|
@ -69,6 +75,32 @@ export const CheckoutEventsProvider = ( {
|
|||
children: React.ReactChildren;
|
||||
redirectUrl: string;
|
||||
} ): JSX.Element => {
|
||||
const paymentMethods = getPaymentMethods();
|
||||
const expressPaymentMethods = getExpressPaymentMethods();
|
||||
const { isEditor } = useEditorContext();
|
||||
|
||||
const { __internalUpdateAvailablePaymentMethods } =
|
||||
useDispatch( PAYMENT_STORE_KEY );
|
||||
|
||||
// Update the payment method store when paymentMethods or expressPaymentMethods changes.
|
||||
// Ensure this happens in the editor even if paymentMethods is empty. This won't happen instantly when the objects
|
||||
// are updated, but on the next re-render.
|
||||
useEffect( () => {
|
||||
if (
|
||||
! isEditor &&
|
||||
Object.keys( paymentMethods ).length === 0 &&
|
||||
Object.keys( expressPaymentMethods ).length === 0
|
||||
) {
|
||||
return;
|
||||
}
|
||||
__internalUpdateAvailablePaymentMethods();
|
||||
}, [
|
||||
isEditor,
|
||||
paymentMethods,
|
||||
expressPaymentMethods,
|
||||
__internalUpdateAvailablePaymentMethods,
|
||||
] );
|
||||
|
||||
const checkoutActions = useDispatch( CHECKOUT_STORE_KEY );
|
||||
const checkoutState: CheckoutState = useSelect( ( select ) =>
|
||||
select( CHECKOUT_STORE_KEY ).getCheckoutState()
|
||||
|
|
|
@ -81,7 +81,7 @@ const registerMockPaymentMethods = () => {
|
|||
ariaLabel: name,
|
||||
} );
|
||||
} );
|
||||
dispatch( PAYMENT_STORE_KEY ).__internalInitializePaymentStore();
|
||||
dispatch( PAYMENT_STORE_KEY ).__internalUpdateAvailablePaymentMethods();
|
||||
};
|
||||
|
||||
const resetMockPaymentMethods = () => {
|
||||
|
|
|
@ -50,7 +50,7 @@ const unsubscribeInitializePaymentStore = registeredStore.subscribe(
|
|||
if ( cartLoaded ) {
|
||||
wpDataDispatch(
|
||||
'wc/store/payment'
|
||||
).__internalInitializePaymentStore();
|
||||
).__internalUpdateAvailablePaymentMethods();
|
||||
unsubscribeInitializePaymentStore();
|
||||
}
|
||||
}
|
||||
|
|
|
@ -1,13 +1,7 @@
|
|||
/**
|
||||
* External dependencies
|
||||
*/
|
||||
import {
|
||||
createReduxStore,
|
||||
register,
|
||||
subscribe,
|
||||
select as wpDataSelect,
|
||||
dispatch as wpDataDispatch,
|
||||
} from '@wordpress/data';
|
||||
import { createReduxStore, register } from '@wordpress/data';
|
||||
|
||||
/**
|
||||
* Internal dependencies
|
||||
|
@ -17,7 +11,6 @@ import * as selectors from './selectors';
|
|||
import * as actions from './actions';
|
||||
import reducer from './reducers';
|
||||
import { DispatchFromMap, SelectFromMap } from '../mapped-types';
|
||||
import { checkPaymentMethodsCanPay } from '../payment/check-payment-methods';
|
||||
|
||||
export const config = {
|
||||
reducer,
|
||||
|
@ -32,22 +25,6 @@ export const config = {
|
|||
const store = createReduxStore( STORE_KEY, config );
|
||||
register( store );
|
||||
|
||||
const isEditor = !! wpDataSelect( 'core/editor' );
|
||||
|
||||
// This is needed to ensure that the payment methods are displayed in the editor
|
||||
if ( isEditor ) {
|
||||
const unsubscribeEditor = subscribe( async () => {
|
||||
await checkPaymentMethodsCanPay();
|
||||
await checkPaymentMethodsCanPay( true );
|
||||
} );
|
||||
|
||||
const unsubscribeInitializePaymentStore = subscribe( async () => {
|
||||
wpDataDispatch( 'wc/store/payment' ).__internalInitializePaymentStore();
|
||||
unsubscribeEditor();
|
||||
unsubscribeInitializePaymentStore();
|
||||
} );
|
||||
}
|
||||
|
||||
export const CHECKOUT_STORE_KEY = STORE_KEY;
|
||||
declare module '@wordpress/data' {
|
||||
function dispatch(
|
||||
|
|
|
@ -158,13 +158,17 @@ export const __internalRemoveAvailableExpressPaymentMethod = (
|
|||
/**
|
||||
* The store is initialised once we have checked whether the payment methods registered can pay or not
|
||||
*/
|
||||
export function __internalInitializePaymentStore() {
|
||||
return async ( { dispatch } ) => {
|
||||
export function __internalUpdateAvailablePaymentMethods() {
|
||||
return async ( { select, dispatch } ) => {
|
||||
const expressRegistered = await checkPaymentMethodsCanPay( true );
|
||||
const registered = await checkPaymentMethodsCanPay( false );
|
||||
if ( registered && expressRegistered ) {
|
||||
dispatch( __internalSetExpressPaymentMethodsInitialized( true ) );
|
||||
const { paymentMethodsInitialized, expressPaymentMethodsInitialized } =
|
||||
select;
|
||||
if ( registered && paymentMethodsInitialized ) {
|
||||
dispatch( __internalSetPaymentMethodsInitialized( true ) );
|
||||
}
|
||||
if ( expressRegistered && expressPaymentMethodsInitialized ) {
|
||||
dispatch( __internalSetExpressPaymentMethodsInitialized( true ) );
|
||||
}
|
||||
};
|
||||
}
|
||||
|
|
|
@ -7,7 +7,10 @@ import {
|
|||
} from '@woocommerce/type-defs/payments';
|
||||
import { CURRENT_USER_IS_ADMIN, getSetting } from '@woocommerce/settings';
|
||||
import { dispatch, select } from '@wordpress/data';
|
||||
import { deriveSelectedShippingRates } from '@woocommerce/base-utils';
|
||||
import {
|
||||
deriveSelectedShippingRates,
|
||||
emptyHiddenAddressFields,
|
||||
} from '@woocommerce/base-utils';
|
||||
import { __, sprintf } from '@wordpress/i18n';
|
||||
import { store as noticesStore } from '@wordpress/notices';
|
||||
|
||||
|
@ -15,6 +18,7 @@ import {
|
|||
getExpressPaymentMethods,
|
||||
getPaymentMethods,
|
||||
} from '@woocommerce/blocks-registry';
|
||||
import { previewCart } from '@woocommerce/resource-previews';
|
||||
|
||||
/**
|
||||
* Internal dependencies
|
||||
|
@ -22,6 +26,15 @@ import {
|
|||
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' );
|
||||
|
@ -46,19 +59,95 @@ export const checkPaymentMethodsCanPay = async ( express = false ) => {
|
|||
const noticeContext = express
|
||||
? noticeContexts.EXPRESS_PAYMENTS
|
||||
: noticeContexts.PAYMENTS;
|
||||
const cart = select( CART_STORE_KEY ).getCartData();
|
||||
const selectedShippingMethods = deriveSelectedShippingRates(
|
||||
cart.shippingRates
|
||||
);
|
||||
const canPayArgument = {
|
||||
cart,
|
||||
cartTotals: cart.totals,
|
||||
cartNeedsShipping: cart.needsShipping,
|
||||
billingData: cart.billingAddress,
|
||||
shippingAddress: cart.shippingAddress,
|
||||
selectedShippingMethods,
|
||||
paymentRequirements: cart.paymentRequirements,
|
||||
};
|
||||
|
||||
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 ) {
|
||||
|
|
|
@ -24,7 +24,6 @@ import {
|
|||
CheckoutExpressPayment,
|
||||
SavedPaymentMethodOptions,
|
||||
} from '../../../blocks/cart-checkout-shared/payment-methods';
|
||||
import { checkPaymentMethodsCanPay } from '../check-payment-methods';
|
||||
import { defaultCartState } from '../../cart/default-state';
|
||||
|
||||
const originalSelect = jest.requireActual( '@wordpress/data' ).select;
|
||||
|
@ -132,8 +131,9 @@ const registerMockPaymentMethods = ( savedCards = true ) => {
|
|||
},
|
||||
} );
|
||||
} );
|
||||
checkPaymentMethodsCanPay();
|
||||
checkPaymentMethodsCanPay( true );
|
||||
wpDataFunctions
|
||||
.dispatch( PAYMENT_STORE_KEY )
|
||||
.__internalUpdateAvailablePaymentMethods();
|
||||
};
|
||||
|
||||
const resetMockPaymentMethods = () => {
|
||||
|
|
Loading…
Reference in New Issue