Revert WooCommerce order status change from cancelled for specific payment methods

212 Views Asked by At

I am using WooCommerce to sell some digital products. Due to the nature of our business, we do not want the item stock to go lower than 0 (-1, -2, etc.)

We are currently accepting different payment methods, including Cryptocurrency and Stripe. As the transaction speed of Crypto is low, it sometimes takes up to 1 hour, so we are facing issues like this:

  1. When a user (User A) purchases an item and pays with Crypto, the item stock gets held (going from 1 to 0). As the blockchain is slow, it takes 2 hours to complete the payment. Since it's so slow, the item stock goes back from 0 to 1.

  2. While the blockchain payment is still pending, a different user (User B) comes to buy the same product. At this time, the item is not being held anymore. Thus, this user gets the product. Item stock goes from 1 to 0.

  3. The blockchain payment is finally confirmed. Woocommerce also gives the product to this user. Item stock goes from 0 to -1.

So 2 users get the same product.

I want to prevent for coinpayments and coinbase payment method Ids, changing order status from canceled to pending or from canceled to complete.

So I tried using the following code:

add_action('woocommerce_order_status_changed', 'prevent_status_change_after', 99, 4);

function prevent_status_change_after($order_id, $old_status, $new_status, $order) {
    $payment_method = $order->get_payment_method();
    
    if ($payment_method == 'coinbase' || $payment_method == 'coinpayments') {
        if ($old_status == 'cancelled' && ($new_status == 'completed' || $new_status == 'pending')) {
            // Optionally, add a note to the order
            $order->add_order_note('Attempt to change status from "cancelled" was prevented.');
            
            // Revert back to 'cancelled' status
            remove_action('woocommerce_order_status_changed', 'prevent_status_change_after', 99);
            $order->update_status('cancelled');
            add_action('woocommerce_order_status_changed', 'prevent_status_change_after', 99, 4);
        }
    }
}

But it doesn't seem to be working.

Any help is appreciated.

1

There are 1 best solutions below

1
On

Without any guaranty, try the following:

add_action('woocommerce_order_status_cancelled_to_pending', 'prevent_cryto_cancelled_status_change', 99, 2);
add_action('woocommerce_order_status_cancelled_to_completed', 'prevent_cryto_cancelled_status_change', 99, 2);
function prevent_cryto_cancelled_status_change( $order_id, $order ) {
    if ( in_array( $order->get_payment_method(), ['coinbase', 'coinpayments'] ) ) {
        // Revert back to 'cancelled' status
        $order->set_status('wc-cancelled', __('Attempt to change status from "cancelled" was prevented.')); 
        $order->save();
    }
}

Code goes in functions.php file of your child theme (or in a plugin). It should work.