How to create a new order with same details if the currrent checkout failed?

340 Views Asked by At

So currently when the payment fails, Woo-commerce puts the order to failed status. And if you reload or do a hard refresh and go-to checkout again without changing the cart you still have to do the payment for that failed order. I don't want that to happen. I want to create a new order with same cart and checkout details.(My invoice printing plugin makes 2 invoices with one failed and one completed if the payment approved which makes confusion on packaging dept.)

I tried few of the checkout hooks but none of them works.like

woocommerce_checkout_order_processed
woocommerce_review_order_after_payment
woocommerce_pay_order_before_submit

As the payment plugin makes a ajax call I am not sure which hook to use. Or how to do a hard reload so that it will skip the failed order and do a new order again. Thanks for reading and any info will be helpful. :)

1

There are 1 best solutions below

6
4efirrr On

You can use the woocommerce_checkout_order_created hook, which is starting when a new order is created, to create a new order when a payment fails. You will need to check if the current order is in an "Error" status, and if so, create a new order using the data from the previous order.

add_action( 'woocommerce_checkout_order_created', 'new_order_on_checkout_failed' );

function new_order_on_checkout_failed( $order_id ) {
  $order = wc_get_order( $order_id );
  if ( 'failed' === $order->get_status() ) {
    $new_order = wc_create_order( [
      'customer_id' => $order->get_customer_id(),
      'status' => 'pending', // status
    ] );

    // Copy data from previous order to new order
    foreach ( $order->get_items() as $item ) {
      $new_order->add_product(
        $item->get_product(),
        $item->get_quantity(),
        [
          'subtotal' => $item->get_subtotal(),
          'total' => $item->get_total(),
          'subtotal_tax' => $item->get_subtotal_tax(),
          'tax' => $item->get_tax(),
          'tax_data' => $item->get_tax_data(),
        ]
      );
    }

    // Copy shipping and billing information
    $new_order->set_address( $order->get_address( 'billing' ), 'billing' );
    $new_order->set_address( $order->get_address( 'shipping' ), 'shipping' );
    $new_order->set_payment_method( $order->get_payment_method() );
    $new_order->set_payment_method_title( $order->get_payment_method_title() );
    $new_order->set_total( $order->get_total() );

    $new_order->save();
  }
}

Or use woocommerce_payment_failed hook:

add_action( 'woocommerce_payment_failed', 'new_order_on_checkout_failed' );

function new_order_on_checkout_failed( $order_id ) {
    // Failed order
    $failed_order = wc_get_order( $order_id );
    
    // Create a new order with the same cart and checkout details
    $new_order = wc_create_order();
    $new_order->set_billing_address( $failed_order->get_billing() );
    $new_order->set_shipping_address( $failed_order->get_shipping() );
    $new_order->add_product( $failed_order->get_items() );
    $new_order->set_payment_method( $failed_order->get_payment_method() );

    $new_order->update_status( 'pending', 'New order created due to payment failure' );

    wp_redirect( $new_order->get_checkout_order_received_url() );
    exit;
}