Fix: orders not being placed when paying with an Express payment method from the Cart block (https://github.com/woocommerce/woocommerce-blocks/pull/3403)
* Fix Express payment methods in Cart block * Create a draft order inside get_draft_order_object() if the ID doesn't match a draft order
This commit is contained in:
parent
a576ba8d67
commit
624a8601bc
|
@ -1,9 +1,7 @@
|
|||
/**
|
||||
* Internal dependencies
|
||||
*/
|
||||
import { ShippingDataProvider } from '../shipping';
|
||||
import { CheckoutStateProvider } from '../checkout-state';
|
||||
import { PaymentMethodDataProvider } from '../payment-methods';
|
||||
import { CheckoutProvider } from '../checkout';
|
||||
|
||||
/**
|
||||
* Cart provider
|
||||
|
@ -18,12 +16,8 @@ import { PaymentMethodDataProvider } from '../payment-methods';
|
|||
*/
|
||||
export const CartProvider = ( { children, redirectUrl } ) => {
|
||||
return (
|
||||
<CheckoutStateProvider redirectUrl={ redirectUrl } isCart={ true }>
|
||||
<ShippingDataProvider>
|
||||
<PaymentMethodDataProvider>
|
||||
{ children }
|
||||
</PaymentMethodDataProvider>
|
||||
</ShippingDataProvider>
|
||||
</CheckoutStateProvider>
|
||||
<CheckoutProvider isCart={ true } redirectUrl={ redirectUrl }>
|
||||
{ children }
|
||||
</CheckoutProvider>
|
||||
);
|
||||
};
|
||||
|
|
|
@ -14,13 +14,19 @@ import CheckoutProcessor from './processor';
|
|||
*
|
||||
* @param {Object} props Incoming props for the provider.
|
||||
* @param {Object} props.children The children being wrapped.
|
||||
* @param {boolean} [props.isCart] Whether it's rendered in the Cart
|
||||
* component.
|
||||
* @param {string} [props.redirectUrl] Initialize what the checkout will
|
||||
* redirect to after successful
|
||||
* submit.
|
||||
*/
|
||||
export const CheckoutProvider = ( { children, redirectUrl } ) => {
|
||||
export const CheckoutProvider = ( {
|
||||
children,
|
||||
isCart = false,
|
||||
redirectUrl,
|
||||
} ) => {
|
||||
return (
|
||||
<CheckoutStateProvider redirectUrl={ redirectUrl } isCart={ false }>
|
||||
<CheckoutStateProvider redirectUrl={ redirectUrl } isCart={ isCart }>
|
||||
<BillingDataProvider>
|
||||
<ShippingDataProvider>
|
||||
<PaymentMethodDataProvider>
|
||||
|
|
|
@ -6,10 +6,7 @@ import { dispatch } from '@wordpress/data';
|
|||
import { useStoreCart } from '@woocommerce/base-hooks';
|
||||
import { useEffect, RawHTML } from '@wordpress/element';
|
||||
import LoadingMask from '@woocommerce/base-components/loading-mask';
|
||||
import {
|
||||
ValidationContextProvider,
|
||||
CartProvider,
|
||||
} from '@woocommerce/base-context';
|
||||
import { ValidationContextProvider } from '@woocommerce/base-context';
|
||||
import {
|
||||
dispatchEvent,
|
||||
translateJQueryEventToNative,
|
||||
|
@ -82,9 +79,7 @@ const Block = ( { emptyCart, attributes, scrollToTop } ) => {
|
|||
) : (
|
||||
<LoadingMask showSpinner={ true } isLoading={ cartIsLoading }>
|
||||
<ValidationContextProvider>
|
||||
<CartProvider>
|
||||
<FullCart attributes={ attributes } />
|
||||
</CartProvider>
|
||||
<FullCart attributes={ attributes } />
|
||||
</ValidationContextProvider>
|
||||
</LoadingMask>
|
||||
) }
|
||||
|
|
|
@ -34,6 +34,7 @@ import Title from '@woocommerce/base-components/title';
|
|||
import { getSetting } from '@woocommerce/settings';
|
||||
import { useEffect } from '@wordpress/element';
|
||||
import { decodeEntities } from '@wordpress/html-entities';
|
||||
import { CartProvider } from '@woocommerce/base-context';
|
||||
|
||||
/**
|
||||
* Internal dependencies
|
||||
|
@ -44,6 +45,14 @@ import CartLineItemsTable from './cart-line-items-table';
|
|||
|
||||
import './style.scss';
|
||||
|
||||
const Block = ( props ) => {
|
||||
return (
|
||||
<CartProvider>
|
||||
<Cart { ...props } />
|
||||
</CartProvider>
|
||||
);
|
||||
};
|
||||
|
||||
/**
|
||||
* Component that renders the Cart block when user has something in cart aka "full".
|
||||
*
|
||||
|
@ -164,4 +173,4 @@ Cart.propTypes = {
|
|||
attributes: PropTypes.object.isRequired,
|
||||
};
|
||||
|
||||
export default Cart;
|
||||
export default Block;
|
||||
|
|
|
@ -271,6 +271,31 @@ class Checkout extends AbstractRoute {
|
|||
wc()->session->set( 'store_api_draft_order', $order_id );
|
||||
}
|
||||
|
||||
/**
|
||||
* Whether the passed argument is a draft order or an order that is
|
||||
* pending/failed and the cart hasn't changed.
|
||||
*
|
||||
* @param \WC_Order $order_object Order object to check.
|
||||
* @return boolean Whether the order is valid as a draft order.
|
||||
*/
|
||||
protected function is_valid_draft_order( $order_object ) {
|
||||
if ( ! $order_object instanceof \WC_Order ) {
|
||||
return false;
|
||||
}
|
||||
|
||||
// Draft orders are okay.
|
||||
if ( $order_object->has_status( 'checkout-draft' ) ) {
|
||||
return true;
|
||||
}
|
||||
|
||||
// Pending and failed orders can be retried if the cart hasn't changed.
|
||||
if ( $order_object->needs_payment() && $order_object->has_cart_hash( wc()->cart->get_cart_hash() ) ) {
|
||||
return true;
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get an order object, either using a current draft order, or returning a new one.
|
||||
*
|
||||
|
@ -278,23 +303,13 @@ class Checkout extends AbstractRoute {
|
|||
* @return \WC_Order|boolean Either the draft order, or false if one has not yet been created.
|
||||
*/
|
||||
protected function get_draft_order_object( $order_id ) {
|
||||
// If order ID doesn't exist or it doesn't match a draft order, create
|
||||
// a new draft order. That might happen when trying to checkout directly
|
||||
// from the Cart block with an express payment method and the draft
|
||||
// order hasn't been created yet.
|
||||
$draft_order_object = $order_id ? wc_get_order( $order_id ) : false;
|
||||
|
||||
if ( ! $draft_order_object instanceof \WC_Order ) {
|
||||
return false;
|
||||
}
|
||||
|
||||
// Draft orders are okay.
|
||||
if ( $draft_order_object->has_status( 'checkout-draft' ) ) {
|
||||
return $draft_order_object;
|
||||
}
|
||||
|
||||
// Pending and failed orders can be retried if the cart hasn't changed.
|
||||
if ( $draft_order_object->needs_payment() && $draft_order_object->has_cart_hash( wc()->cart->get_cart_hash() ) ) {
|
||||
return $draft_order_object;
|
||||
}
|
||||
|
||||
return false;
|
||||
return $this->is_valid_draft_order( $draft_order_object ) ? $draft_order_object : $this->create_or_update_draft_order();
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -308,14 +323,14 @@ class Checkout extends AbstractRoute {
|
|||
$cart_controller = new CartController();
|
||||
$order_controller = new OrderController();
|
||||
$reserve_stock = \class_exists( '\Automattic\WooCommerce\Checkout\Helpers\ReserveStock' ) ? new \Automattic\WooCommerce\Checkout\Helpers\ReserveStock() : new ReserveStock();
|
||||
$order_object = $this->get_draft_order_object( $this->get_draft_order_id() );
|
||||
$order_object = $this->get_draft_order_id() ? wc_get_order( $this->get_draft_order_id() ) : null;
|
||||
$created = false;
|
||||
|
||||
// Validate items etc are allowed in the order before it gets created.
|
||||
$cart_controller->validate_cart_items();
|
||||
$cart_controller->validate_cart_coupons();
|
||||
|
||||
if ( ! $order_object instanceof \WC_Order ) {
|
||||
if ( ! $this->is_valid_draft_order( $order_object ) ) {
|
||||
$order_object = $order_controller->create_order_from_cart();
|
||||
$created = true;
|
||||
} else {
|
||||
|
|
Loading…
Reference in New Issue