diff --git a/plugins/woocommerce-blocks/assets/js/base/context/providers/cart-checkout/checkout-events/index.tsx b/plugins/woocommerce-blocks/assets/js/base/context/providers/cart-checkout/checkout-events/index.tsx index 5e3fac07013..c07a0325da0 100644 --- a/plugins/woocommerce-blocks/assets/js/base/context/providers/cart-checkout/checkout-events/index.tsx +++ b/plugins/woocommerce-blocks/assets/js/base/context/providers/cart-checkout/checkout-events/index.tsx @@ -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() diff --git a/plugins/woocommerce-blocks/assets/js/blocks/cart-checkout-shared/payment-methods/test/payment-methods.js b/plugins/woocommerce-blocks/assets/js/blocks/cart-checkout-shared/payment-methods/test/payment-methods.js index 55c5f2af94c..2d29dbb4dd2 100644 --- a/plugins/woocommerce-blocks/assets/js/blocks/cart-checkout-shared/payment-methods/test/payment-methods.js +++ b/plugins/woocommerce-blocks/assets/js/blocks/cart-checkout-shared/payment-methods/test/payment-methods.js @@ -81,7 +81,7 @@ const registerMockPaymentMethods = () => { ariaLabel: name, } ); } ); - dispatch( PAYMENT_STORE_KEY ).__internalInitializePaymentStore(); + dispatch( PAYMENT_STORE_KEY ).__internalUpdateAvailablePaymentMethods(); }; const resetMockPaymentMethods = () => { diff --git a/plugins/woocommerce-blocks/assets/js/data/cart/index.ts b/plugins/woocommerce-blocks/assets/js/data/cart/index.ts index 257752c9ec3..edb93516a56 100644 --- a/plugins/woocommerce-blocks/assets/js/data/cart/index.ts +++ b/plugins/woocommerce-blocks/assets/js/data/cart/index.ts @@ -50,7 +50,7 @@ const unsubscribeInitializePaymentStore = registeredStore.subscribe( if ( cartLoaded ) { wpDataDispatch( 'wc/store/payment' - ).__internalInitializePaymentStore(); + ).__internalUpdateAvailablePaymentMethods(); unsubscribeInitializePaymentStore(); } } diff --git a/plugins/woocommerce-blocks/assets/js/data/checkout/index.ts b/plugins/woocommerce-blocks/assets/js/data/checkout/index.ts index 53efeae667b..237664d645b 100644 --- a/plugins/woocommerce-blocks/assets/js/data/checkout/index.ts +++ b/plugins/woocommerce-blocks/assets/js/data/checkout/index.ts @@ -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( diff --git a/plugins/woocommerce-blocks/assets/js/data/payment/actions.ts b/plugins/woocommerce-blocks/assets/js/data/payment/actions.ts index 7fb2181c006..9981343f0a2 100644 --- a/plugins/woocommerce-blocks/assets/js/data/payment/actions.ts +++ b/plugins/woocommerce-blocks/assets/js/data/payment/actions.ts @@ -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 ) ); + } }; } diff --git a/plugins/woocommerce-blocks/assets/js/data/payment/check-payment-methods.ts b/plugins/woocommerce-blocks/assets/js/data/payment/check-payment-methods.ts index 842c3e1590f..a92ff91e43c 100644 --- a/plugins/woocommerce-blocks/assets/js/data/payment/check-payment-methods.ts +++ b/plugins/woocommerce-blocks/assets/js/data/payment/check-payment-methods.ts @@ -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 ) { diff --git a/plugins/woocommerce-blocks/assets/js/data/payment/test/selectors.js b/plugins/woocommerce-blocks/assets/js/data/payment/test/selectors.js index 23a1e2e231c..ceaf7089b7d 100644 --- a/plugins/woocommerce-blocks/assets/js/data/payment/test/selectors.js +++ b/plugins/woocommerce-blocks/assets/js/data/payment/test/selectors.js @@ -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 = () => { diff --git a/plugins/woocommerce-blocks/docs/internal-developers/testing/releases/873.md b/plugins/woocommerce-blocks/docs/internal-developers/testing/releases/873.md new file mode 100644 index 00000000000..ede5b310030 --- /dev/null +++ b/plugins/woocommerce-blocks/docs/internal-developers/testing/releases/873.md @@ -0,0 +1,14 @@ +# Testing notes and ZIP for release 8.7.3 + +Zip file for testing: [woocommerce-gutenberg-products-block.zip](https://github.com/woocommerce/woocommerce-blocks/files/9831749/woocommerce-gutenberg-products-block.zip) + +## Feature plugin and package inclusion in WooCommerce + +### Fix wrong keys being sent in canMakePayment and customer data showing in the Checkout block in the editor ([7434](https://github.com/woocommerce/woocommerce-blocks/pull/7434)) + +#### User Facing Testing + +1. Ensure you can check out using Stripe. Please also try various other payment gateways. +2. If you can, please check out with an express payment method. +3. Open the Checkout block in the editor. Ensure your customer details are not there. +4. Upload this extension [extension-for-testing.zip](https://github.com/woocommerce/woocommerce-blocks/files/9828874/extension-for-testing.zip) to your site and activate it. Ensure you see a payment method called `some-extension-name payment method` on your checkout. diff --git a/plugins/woocommerce-blocks/docs/internal-developers/testing/releases/README.md b/plugins/woocommerce-blocks/docs/internal-developers/testing/releases/README.md index a284009be12..9bb96e4b723 100644 --- a/plugins/woocommerce-blocks/docs/internal-developers/testing/releases/README.md +++ b/plugins/woocommerce-blocks/docs/internal-developers/testing/releases/README.md @@ -94,6 +94,7 @@ Every release includes specific testing instructions for new features and bug fi - [8.7.0](./870.md) - [8.7.1](./871.md) - [8.7.2](./872.md) + - [8.7.3](./873.md) diff --git a/plugins/woocommerce-blocks/package.json b/plugins/woocommerce-blocks/package.json index e49878a5574..c7b3cdd7da8 100644 --- a/plugins/woocommerce-blocks/package.json +++ b/plugins/woocommerce-blocks/package.json @@ -2,7 +2,7 @@ "name": "@woocommerce/block-library", "title": "WooCommerce Blocks", "author": "Automattic", - "version": "8.7.2", + "version": "8.7.3", "description": "WooCommerce blocks for the Gutenberg editor.", "homepage": "https://github.com/woocommerce/woocommerce-gutenberg-products-block/", "keywords": [ diff --git a/plugins/woocommerce-blocks/readme.txt b/plugins/woocommerce-blocks/readme.txt index 2850428c6be..014c8ef4734 100644 --- a/plugins/woocommerce-blocks/readme.txt +++ b/plugins/woocommerce-blocks/readme.txt @@ -4,7 +4,7 @@ Tags: gutenberg, woocommerce, woo commerce, products, blocks, woocommerce blocks Requires at least: 6.0 Tested up to: 6.0 Requires PHP: 7.0 -Stable tag: 8.7.2 +Stable tag: 8.7.3 License: GPLv3 License URI: https://www.gnu.org/licenses/gpl-3.0.html @@ -80,6 +80,11 @@ Release and roadmap notes available on the [WooCommerce Developers Blog](https:/ == Changelog == += 8.7.3 - 2022-10-20 = + +#### Bug fixes +- Fixed an issue where the argument passed to `canMakePayment` contained the incorrect keys. Also fixed the current user's customer data appearing in the editor when editing the Checkout block. + = 8.7.2 - 2022-10-13 = #### Bug Fixes diff --git a/plugins/woocommerce-blocks/src/Package.php b/plugins/woocommerce-blocks/src/Package.php index 7908c4049ca..597f82fd298 100644 --- a/plugins/woocommerce-blocks/src/Package.php +++ b/plugins/woocommerce-blocks/src/Package.php @@ -109,7 +109,7 @@ class Package { NewPackage::class, function ( $container ) { // leave for automated version bumping. - $version = '8.7.2'; + $version = '8.7.3'; return new NewPackage( $version, dirname( __DIR__ ), diff --git a/plugins/woocommerce-blocks/woocommerce-gutenberg-products-block.php b/plugins/woocommerce-blocks/woocommerce-gutenberg-products-block.php index 40d7321175d..0425713115b 100644 --- a/plugins/woocommerce-blocks/woocommerce-gutenberg-products-block.php +++ b/plugins/woocommerce-blocks/woocommerce-gutenberg-products-block.php @@ -3,7 +3,7 @@ * Plugin Name: WooCommerce Blocks * Plugin URI: https://github.com/woocommerce/woocommerce-gutenberg-products-block * Description: WooCommerce blocks for the Gutenberg editor. - * Version: 8.7.2 + * Version: 8.7.3 * Author: Automattic * Author URI: https://woocommerce.com * Text Domain: woo-gutenberg-products-block