WooCommerce: Auto complete paid orders
The most accurate, effective and lightweight solution (For WooCommerce 3 and above) - 2019
This filter hook is located in:
WC_Order
Class insidepayment_complete()
method which is used by all payment methods when a payment is required in checkout.WC_Order_Data_Store_CPT
Class insideupdate()
method.
As you can see, by default the allowed paid order statuses are "processing" and "completed".
###Explanations:
- Lightweight and effective:
As it is a filter hook,
woocommerce_payment_complete_order_status
is only triggered when an online payment is required (not for "cheque", "bacs" or "cod" payment methods). Here we just change the allowed paid order statuses.
So no need to add conditions for the payment gateways or anything else.
- Accurate (avoid multiple notifications):
This is the only way to avoid sending 2 different customer notifications at the same time:
• One for "processing" orders status
• And one for "completed" orders status.
So customer is only notified once on "completed" order status.
Using the code below, will just change the paid order status (that is set by the payment gateway for paid orders) to "completed":
add_action( 'woocommerce_payment_complete_order_status', 'wc_auto_complete_paid_order', 10, 3 );
function wc_auto_complete_paid_order( $status, $order_id, $order ) {
return 'completed';
}
Code goes in function.php file of the active child theme (or active theme).
Related: WooCommerce: autocomplete paid orders based on shipping method
2018 - Improved version (For WooCommerce 3 and above)
Based on Woocommerce official hook, I found a solution to this problem *(Works with WC 3+).
In Woocommerce for all other payment gateways others than bacs
(Bank Wire), cheque
and cod
(Cash on delivery), the paid order statuses are "processing" and "completed".
So I target "processing" order status for all payment gateways like Paypal or credit card payment, updating the order status to complete.
The code:
add_action( 'woocommerce_thankyou', 'wc_auto_complete_paid_order', 20, 1 );
function wc_auto_complete_paid_order( $order_id ) {
if ( ! $order_id )
return;
// Get an instance of the WC_Product object
$order = wc_get_order( $order_id );
// No updated status for orders delivered with Bank wire, Cash on delivery and Cheque payment methods.
if ( in_array( $order->get_payment_method(), array( 'bacs', 'cod', 'cheque', '' ) ) ) {
return;
}
// For paid Orders with all others payment methods (paid order status "processing")
elseif( $order->has_status('processing') ) {
$order->update_status( 'completed' );
}
}
Code goes in function.php file of the active child theme (or active theme).
Original answer (For all woocommerce versions):
The code:
/**
* AUTO COMPLETE PAID ORDERS IN WOOCOMMERCE
*/
add_action( 'woocommerce_thankyou', 'custom_woocommerce_auto_complete_paid_order', 10, 1 );
function custom_woocommerce_auto_complete_paid_order( $order_id ) {
if ( ! $order_id )
return;
$order = wc_get_order( $order_id );
// No updated status for orders delivered with Bank wire, Cash on delivery and Cheque payment methods.
if ( ( 'bacs' == get_post_meta($order_id, '_payment_method', true) ) || ( 'cod' == get_post_meta($order_id, '_payment_method', true) ) || ( 'cheque' == get_post_meta($order_id, '_payment_method', true) ) ) {
return;
}
// For paid Orders with all others payment methods (with paid status "processing")
elseif( $order->get_status() === 'processing' ) {
$order->update_status( 'completed' );
}
}
Code goes in function.php file of the active child theme (or active theme).
With the help of this post: How to check payment method on a WooCommerce order by id?
with this : get_post_meta( $order_id, '_payment_method', true );
from helgatheviking
"Bank wire" (bacs), "Cash on delivery" (cod) and "Cheque" (cheque) payment methods are ignored and keep their original order status.
Updated the code for compatibility with WC 3.0+ (2017-06-10)
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
Auto-complete Paid Orders only for specific product IDs on Woocommerce
Here is a way to autocomplete paid orders for specific product IDS:
add_action( 'woocommerce_payment_complete_order_status', 'wc_auto_complete_paid_order', 10, 3 );
function wc_auto_complete_paid_order( $status, $order_id, $order ) {
// Below the targeted product Ids
$targeted_ids = array(37, 53);
// Loop through order line items
foreach( $order->get_items() as $item ) {
if ( in_array( $item->get_product_id(), $targeted_ids ) || in_array( $item->get_variation_id(), $targeted_ids ) ) {
return 'completed';
}
}
return $status;
}
Code goes in functions.php file of the active child theme (or active theme).
- WooCommerce: Auto complete paid orders
- Exclude specific products on auto-complete orders process in Woocommerce
Auto change order status to completed for specific products in WooCommerce
You can target specific product(s) Id(s) from order items, to make your code work only for them as follows:
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 );
$product_ids = array('23'); // Here set your targeted product(s) Id(s)
$product_found = false;
// Loop through order items
foreach ( $order->get_items() as $item ) {
if( array_intersect( $product_ids, array($item->get_product_id(), $item->get_variation_id()) ) ) {
$product_found = true;
break;
}
}
if( $order->has_status( 'processing' ) && $product_found ) {
$order->update_status( 'completed' );
}
}
If you want to target those products exclusively, then you will use the following instead:
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 );
$product_ids = array('23'); // Here set your targeted product(s) Id(s)
$product_found = true;
// Loop through order items
foreach ( $order->get_items() as $item ) {
if( ! array_intersect( $product_ids, array($item->get_product_id(), $item->get_variation_id()) ) ) {
$product_found = false;
break;
}
}
if( $order->has_status( 'processing' ) && $product_found ) {
$order->update_status( 'completed' );
}
}
Code goes in functions.php file of the active child theme (or active theme). It should works.
Addition: Avoid multiple notifications
You should better use
woocommerce_payment_complete_order_status
hook instead like in WooCommerce: Auto complete paid orders answer, to avoid multiple notifications.So the code is going to be:
add_action( 'woocommerce_payment_complete_order_status', 'wc_auto_complete_paid_order', 10, 3 );
function wc_auto_complete_paid_order( $status, $order_id, $order ) {
$product_ids = array('23'); // Here set your targeted product(s) Id(s)
$product_found = false;
// Loop through order items
foreach ( $order->get_items() as $item ) {
if( array_intersect( $product_ids, array($item->get_product_id(), $item->get_variation_id()) ) ) {
$product_found = true;
break;
}
}
return $product_found ? 'completed' : $status;
}Or targeting products exclusively:
add_action( 'woocommerce_payment_complete_order_status', 'wc_auto_complete_paid_order', 10, 3 );
function wc_auto_complete_paid_order( $status, $order_id, $order ) {
$product_ids = array('23'); // Here set your targeted product(s) Id(s)
$product_found = true;
// Loop through order items
foreach ( $order->get_items() as $item ) {
if( ! array_intersect( $product_ids, array($item->get_product_id(), $item->get_variation_id()) ) ) {
$product_found = false;
break;
}
}
return $product_found ? 'completed' : $status;
}It should work...
Auto process paid orders instead of auto complete in WooCommerce
Try to use the following, which will set paid orders status to processing by default:
add_action( 'woocommerce_payment_complete_order_status', 'wc_auto_complete_paid_order', 10, 3 );
function wc_auto_complete_paid_order( $status, $order_id, $order ) {
return 'processing';
}
Code goes in functions.php file of the active child theme (or active theme).
Related: WooCommerce: Auto complete paid orders
Related Topics
Is There a Use-Case For Singletons With Database Access in PHP
Is There a Function to Extract a 'Column' from an Array in PHP
Open_Basedir Restriction in Effect. File(/) Is Not Within the Allowed Path(S):
Matching Unicode Letter Characters in Pcre/PHP
Error Message "Strict Standards: Only Variables Should Be Passed by Reference"
PHP + MySQL Transactions Examples
Pdoexception "Could Not Find Driver"
PHP Method Chaining or Fluent Interface
How to Use Multiple Databases in Laravel
Target Class Controller Does Not Exist - Laravel 8
Difference Between Require, Include, Require_Once and Include_Once
How to Validate an Email Address in PHP
How to Get an Array of Specific "Key" in Multidimensional Array Without Looping
How to Convert Date to Timestamp in PHP
How to Repair a Serialized String Which Has Been Corrupted by an Incorrect Byte Count Length
Truncate a String to First N Characters of a String and Add Three Dots If Any Characters Are Removed