If you’re running an e-commerce business, you know that managing customer orders is super important. One crucial step in the customer journey is order cancellation, which may vary depending on your business needs. You might even have specific conditions under which an order can be canceled. By default, WooCommerce allows customers to cancel an order if it’s in a pending payment or failed status. Also, pending orders are canceled based on store settings. However, if you’re looking to customize these default settings, WooCommerce has got you covered. In this article, we’ll explore various case scenarios and recommend different solutions based on our experience working with several clients over the years. Hope it helps!
Completely remove the order cancellation
According to the business requirements, customers should not be able to cancel their orders at any stage. However, WooCommerce provides an option for customers to cancel their orders through the “My Account” section. To remove this option, we can use the woocommerce_my_account_my_orders_actions filter hook. Using this hook, we can add or remove actions for customer orders under their account. In our case, we need to remove the cancel action.
This can be achieved using the woocommerce_my_account_my_orders_actions filter
add_filter('woocommerce_my_account_my_orders_actions', 'remove_myaccount_orders_cancel_button', 10, 2);
function remove_myaccount_orders_cancel_button( $actions, $order ){
unset($actions['cancel']);
return $actions;
}
Conditionally prevent order cancellation
The code mentioned above completely removes the cancel action. However, what if we want to remove it based on the order status? Many businesses want to allow their customers to cancel the order, but only until it’s in processing. Once it’s dispatched (custom order status), cancellation is no longer required. This can be easily achieved by accessing the order status.
We can update the code as below:
add_filter('woocommerce_my_account_my_orders_actions', 'remove_myaccount_orders_cancel_button', 10, 2);
function remove_myaccount_orders_cancel_button( $actions, $order ){
if ( $order->has_status( 'processing' ) ) {
unset($actions['cancel']);
}
return $actions;
}
Preventing cancellation from URL requests
While the above code removes the actions, some geek customers may still end up doing that by directly accessing the cancel URL. For someone familiar with WooCommerce, internally can craft the URL internally.
TODO: Add a URL that some geek can use to cancel the order
To handle this, we will need to sniff the incoming request, and if it’s an order cancellation, we will redirect the customer to my account.
add_filter( 'parse_request', 'sniff_cancel_url');
function sniff_cancel_url() {
global $wp;
if (
isset( $_GET['cancel_order'] ) &&
isset( $_GET['order'] ) &&
isset( $_GET['order_id'] ) &&
( isset( $_GET['_wpnonce'] ) && wp_verify_nonce( wp_unslash( $_GET['_wpnonce'] ), 'woocommerce-cancel_order' ) ) // phpcs:ignore WordPress.Security.ValidatedSanitizedInput.InputNotSanitized
) {
wp_safe_redirect( 'my-account' );
exit;
}
}
Modifying the default valid status for cancellation
While the above code solves the problems, it’s still too much code. WordPress’s core philosophy is extensibility, which is inherited by Woo. The same can be achieved by leveraging core filters that handle both scenarios. WooCommerce core defines a valid status for the cancel action and handles the request accordingly. These default statuses can be customized as needed.
This can be accomplished with woocommerce_valid_order_statuses_for_cancel filter:
apply_filters( 'woocommerce_valid_order_statuses_for_cancel', array( 'pending', 'failed' ), $order);
Let’s look at code examples to achieve the above solution with as little code.
To completely disable cancel:
add_filter( 'woocommerce_valid_order_statuses_for_cancel', 'valid_cancel_status');
function valid_cancel_status ($status, $order) {
return [];
}
We are returning an empty array to completely remove the cancel action.
To allow cancellation till it’s in processing
add_filter( 'woocommerce_valid_order_statuses_for_cancel', 'valid_cancel_status');
function valid_cancel_status ($status, $order) {
$status[] = 'processing';
return $status;
}
We are adding a new array item ‘processing’ to the default statuses.
Transform your WooCommerce store to perfectly match your business vision. We are here to help you customize and adapt it to your unique needs. Schedule a call and let’s explore how we can elevate your store together!


Leave a Reply