WooCommerce: Allowing a Customer to Cancel an Order

July 12, 2021
Solutions, Wordpress
LinkedInTwitterFacebookEmail

In this slightly unusual case, we’re looking at allowing a customer to cancel an order for an extended period of time OR based on other specialized criteria. When building this out, the documentation can be a bit confusion on WooCommerce.

Below, we’ll use a filter in WooCommerce to set up specialized criteria for allowing customers to cancel their order.

The Basic Filter

First, let’s cover the basic filter. You’ll add this into your functions.php file on your theme (or child theme).

add_filter( 'woocommerce_valid_order_statuses_for_cancel', 'filter_valid_order_statuses_for_cancel', 20, 2 );
function filter_valid_order_statuses_for_cancel( $statuses, $order ){
    $custom_statuses = array( 'pending', 'processing', 'on-hold', 'failed' );
    $canChange = 1; //your custom criteria
    if ( $canChange == 1 ) {
        return $custom_statuses;
    } else { 
        return $statuses;
    }
}

A big thank you to LoicTheAztec for the basic setup.

The filter starts with calling the function “filter_valid_order_statuses_for_cancel”, just like other filters. There are two items being passed here: the $order variable which contains the order and the $statuses available.

Originally when I came across this filter, I thought it was talking about which statuses are SHOWN on the checkout page, but that’s not correct. This filter tells WooCommerce which order statuses it is allowed to cancel. Here’s how it thinks:

Person clicks Cancel button > WooCommerce checks order status > declines to cancel if the order status doesn’t match

We’re interrupting that process by changing which order statuses allow cancellation and possibly adding in our own criteria. 

Still confused? Keep reading our example cases below.

Example Cases

Allow WooCommerce orders to be cancelled regardless of status:

add_filter( 'woocommerce_valid_order_statuses_for_cancel', 'filter_valid_order_statuses_for_cancel', 20, 2 );
function filter_valid_order_statuses_for_cancel( $statuses, $order ){
    $custom_statuses = array( 'pending', 'processing', 'on-hold', 'failed' );
    return $custom_statuses;
}

Allow WooCommerce orders to be cancelled IF the order is on-hold only:

add_filter( 'woocommerce_valid_order_statuses_for_cancel', 'filter_valid_order_statuses_for_cancel', 20, 2 );
function filter_valid_order_statuses_for_cancel( $statuses, $order ){
    $custom_statuses = array('on-hold');
    return $custom_statuses;
}

Allow WooCommerce orders to be cancelled regardless of status, if it’s within 24 hours:

add_filter( 'woocommerce_valid_order_statuses_for_cancel', 'filter_valid_order_statuses_for_cancel', 20, 2 );
function filter_valid_order_statuses_for_cancel( $statuses, $order ){
    $custom_statuses = array( 'pending', 'processing', 'on-hold', 'failed' );
    $delay = 24*60*60; // (duration in seconds)
    $date_created_time = strtotime($order->get_date_created()); // Creation date time stamp
    $date_modified_time = strtotime($order->get_date_modified()); // Modified date time stamp
    $now = strtotime("now"); // Now time stamp
    if ( ( $date_created_time + $delay ) >= $now ){
        return $custom_statuses;
    } else { 
        return $statuses; //returns original statuses if the delay is over 24 hours.
    }
}

A big thank you to LoicTheAztec for this last example.

Summary

You can add in any criteria you’d like for your cancellation system using this filter. The sky’s the limit!

Join the Discussion

Your email address will not be published.

You may use these HTML tags and attributes: <a href="" title=""> <abbr title=""> <acronym title=""> <b> <blockquote cite=""> <cite> <code> <del datetime=""> <em> <i> <q cite=""> <s> <strike> <strong>