diff --git a/changelog/fix-8775-direct-checkout-shortcode-orders b/changelog/fix-8775-direct-checkout-shortcode-orders new file mode 100644 index 00000000000..28379f9ff19 --- /dev/null +++ b/changelog/fix-8775-direct-checkout-shortcode-orders @@ -0,0 +1,4 @@ +Significance: patch +Type: fix + +Fix shortcode orders when using WooPay Direct Checkout. diff --git a/includes/class-wc-payments-woopay-direct-checkout.php b/includes/class-wc-payments-woopay-direct-checkout.php index 4132801186b..012851bc002 100644 --- a/includes/class-wc-payments-woopay-direct-checkout.php +++ b/includes/class-wc-payments-woopay-direct-checkout.php @@ -27,7 +27,10 @@ public function init() { /** * This filter is used to ensure the session's store_api_draft_order is used, if it exists. * This prevents a bug where the store_api_draft_order is not used and instead, a new - * order_awaiting_payment is created during the checkout request. + * order_awaiting_payment is created during the checkout request. The bug being evident + * if a product had one remaining stock and the store_api_draft_order was reserving it, + * an order would fail to be placed since when order_awaiting_payment is created, it would + * not be able to reserve the one stock. * * @param int $order_id The order ID being used. * @return int|mixed The new order ID to use. @@ -39,11 +42,23 @@ public function maybe_use_store_api_draft_order_id( $order_id ) { $is_already_defined_order_id = ! empty( $order_id ); // Only apply this filter if the session doesn't already have an order_awaiting_payment. $is_order_awaiting_payment = isset( WC()->session->order_awaiting_payment ); - if ( ! $is_checkout || $is_already_defined_order_id || $is_order_awaiting_payment ) { + // Only apply this filter if draft order ID exists. + $has_draft_order = ! empty( WC()->session->get( 'store_api_draft_order' ) ); + if ( ! $is_checkout || $is_already_defined_order_id || $is_order_awaiting_payment || ! $has_draft_order ) { return $order_id; } - return absint( WC()->session->get( 'store_api_draft_order', $order_id ) ); + $draft_order_id = absint( WC()->session->get( 'store_api_draft_order' ) ); + // Set the order status to "pending" payment, so that it can be resumed. + $draft_order = wc_get_order( $draft_order_id ); + $draft_order->set_status( 'pending' ); + $draft_order->save(); + + // Move $draft_order_id in session, from store_api_draft_order to order_awaiting_payment. + WC()->session->set( 'store_api_draft_order', null ); + WC()->session->set( 'order_awaiting_payment', $draft_order_id ); + + return $order_id; } /**