Automatically cancel order after X days if no payment in WooCommerce
Update 4
Note: in WooCommerce, there is already a function hooked in woocommerce_cancel_unpaid_orders
action hook that cancel unpaid orders after 7 days.
I didn't find woocommerce_cancel_unpaid_submitted
action hook, so I don't know if it exist and if it is triggered.
Now there is some mistakes in your code and you can better use wc_get_orders() which give you directly the correct array of WC_Order
Objects instead…
Here are some different ways to make it (last ones are untested):
1) This last solution is tested and works When shop manager or administrator user roles browse the Admin orders list (only executed once a day):
add_action( 'restrict_manage_posts', 'cancel_unpaid_orders' );
function cancel_unpaid_orders() {
global $pagenow, $post_type;
// Enable the process to be executed daily when browsing Admin order list
if( 'shop_order' === $post_type && 'edit.php' === $pagenow
&& get_option( 'unpaid_orders_daily_process' ) < time() ) :
$days_delay = 5; // <=== SET the delay (number of days to wait before cancelation)
$one_day = 24 * 60 * 60;
$today = strtotime( date('Y-m-d') );
// Get unpaid orders (5 days old)
$unpaid_orders = (array) wc_get_orders( array(
'limit' => -1,
'status' => 'on-hold',
'date_created' => '<' . ( $today - ($days_delay * $one_day) ),
) );
if ( sizeof($unpaid_orders) > 0 ) {
$cancelled_text = __("The order was cancelled due to no payment from customer.", "woocommerce");
// Loop through orders
foreach ( $unpaid_orders as $unpaid_order ) {
$unpaid_order->update_status( 'cancelled', $cancelled_text );
}
}
// Schedule the process to the next day (executed once restriction)
update_option( 'unpaid_orders_daily_process', $today + $one_day );
endif;
}
Code goes in function.php file of your active child theme (or active theme).2) This third solution is tested and works: The function is triggered when any order change to "processing" or "completed" status (only executed once a day):
// Triggered on orders status change to "processing" or "completed"
add_action( 'woocommerce_order_status_changed', 'daily_cancel_unpaid_orders', 10, 4 );
function daily_cancel_unpaid_orders( $order_id, $old_status, $new_status, $order ) {
// Enable the process to be executed daily
if( in_array( $new_status, array('processing', 'completed') )
&& get_option( 'unpaid_orders_daily_process' ) < time() ) :
$days_delay = 5; // <=== SET the delay (number of days to wait before cancelation)
$one_day = 24 * 60 * 60;
$today = strtotime( date('Y-m-d') );
// Get unpaid orders (5 days old)
$unpaid_orders = (array) wc_get_orders( array(
'limit' => -1,
'status' => 'on-hold',
'date_created' => '<' . ( $today - ($days_delay * $one_day) ),
) );
if ( sizeof($unpaid_orders) > 0 ) {
$cancelled_text = __("The order was cancelled due to no payment from customer.", "woocommerce");
// Loop through WC_Order Objects
foreach ( $unpaid_orders as $order ) {
$order->update_status( 'cancelled', $cancelled_text );
}
}
// Schedule the process to the next day (executed once restriction)
update_option( 'unpaid_orders_daily_process', $today + $one_day );
endif;
}
Code goes in function.php file of your active child theme (or active theme).3) So you can try with
woocommerce_cancel_unpaid_submitted
action hook:add_action( 'woocommerce_cancel_unpaid_submitted', 'cancel_unpaid_orders' );
function cancel_unpaid_orders() {
$days_delay = 5; // <=== SET the delay (number of days to wait before cancelation)
$one_day = 24 * 60 * 60;
$today = strtotime( date('Y-m-d') );
// Get unpaid orders (5 days old here)
$unpaid_orders = (array) wc_get_orders( array(
'limit' => -1,
'status' => 'on-hold',
'date_created' => '<' . ( $today - ($days_delay * $one_day) ),
) );
if ( sizeof($unpaid_orders) > 0 ) {
$cancelled_text = __("The order was cancelled due to no payment from customer.", "woocommerce");
// Loop through orders
foreach ( $unpaid_orders as $order ) {
$order->update_status( 'cancelled', $cancelled_text );
}
}
}
Code goes in function.php file of your active child theme (or active theme).The function code should better works. For the hook I really don't know.
4) You can try also with
woocommerce_cancel_unpaid_orders
action hook instead. Auto complete order woocommerce
The reference you picked is ok
https://woocommerce.com/document/automatically-complete-orders/
Just needed a small adjustment:
/**
* Auto Complete Processing WooCommerce orders on Thankyou Page
*/
add_action( 'woocommerce_thankyou', 'custom_woocommerce_auto_complete_order' );
function custom_woocommerce_auto_complete_order( $order_id ) {
if ( ! $order_id ) {
return;
}
$order = wc_get_order( $order_id );
if ( $order->has_status('processing') ) {
$order->update_status( 'completed' );
}
}
What we are doing with this adjustment is checking if the order has status processing before updating it to completed. This will avoid failed orders to be turned into completed.Hope it works
Hide WooCommerce Subscriptions 'cancel' button after 90 days
function remove_cancel_button($actions, $subscription_id) {
// Gets the subscription object on subscription id
$subscription = new WC_Subscription($subscription_id);
$subscription_start_date = $subscription->get_date('start_date');
$subscription_start_date_obj = new \DateTime($subscription_start_date);
$now = new \DateTime();
if ($subscription_start_date_obj->diff($now)->days > 90) {
unset($actions['cancel']);
}
return $actions;
}
add_filter('wcs_view_subscription_actions', 'remove_cancel_button', 10, 2);
Tested OK
Related Topics
Setting Default Values (Conditional Assignment)
Best Way to Identify a User Uniquely
MySQL Int(11) Number Out of Range
Encoding Byte Data into Digits
Codeigniter 4 Problem Installing with Composer
Setting Max_Input_Vars PHP.Ini Directive Using Ini_Set
PHP Search Array Key and Get Value
How to Create a PHP Function That I Can Call Without Parentheses
PHP - Display a 404 Error Without Redirecting to Another Page
Make Woocommerce Checkout Phone Field Optional Based on Shipping Country
Custom Repository Class in Symfony2
How to Add Item to the JSON File Formatted Array
Base64 Over Http Post Losing Data (Objective-C)
How to Get Content of Remote HTML Page
Laravel 5 Auth Post Submit - Tokenmismatchexception in Verifycsrftoken.PHP Line 46