Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

WooCommerce: Auto complete paid orders

Normally wooCommerce should autocomplete orders for virtual products. But it doesn't and this is a real problem, even a BUG like.

So at this point you can find somme helpful things(but not really convenient):

1) A snippet code (that you can find in wooCommerce docs):

/**  * Auto Complete all WooCommerce orders.  */ 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 );     $order->update_status( 'completed' ); } 

But this snippet does not work for BACS*, Pay on delivery and Cheque payment methods. It's ok for Paypal and Credit Card gateways payment methods.

*BACS is a Direct Bank transfer payment method

And …

2) A plugin: WooCommerce Autocomplete Orders

This plugin works for all payment methods, but not for other Credit Card gateways payment methods.

My question:

Using (as a base) the wooCommerce snippet in point 1:

How can I implement conditional code based on woocommerce payment methods?

I mean something like: if the payment methods aren't "BACS", "Pay on delivery" and "Cheque" then apply the snippet code (update status to "completed" for paid orders concerning virtual products).

Some help will be very nice.

like image 306
LoicTheAztec Avatar asked Feb 28 '16 18:02

LoicTheAztec


People also ask

How do I change my order status automatically in WooCommerce?

Setup. To setup Order Status Control, go to WooCommerce > Settings > General and update the Orders to Auto-Complete setting to determine which paid orders should skip the Processing status and go directly to Completed status: None: No orders will be automatically completed.

Do you need to complete WooCommerce orders?

All product orders require processing, except those with only products that are both digital and downloadable. If the payment has been successful and the order does not contain Digital or Downloadable products, the order will be set to Processing.

How do I print all orders in WooCommerce?

Go to WooCommerce => Orders. From the list of orders, tick on the order checkboxes you want to generate and print PDF invoices and packing slips for. From the bulk actions menu, select either “Make PDF Invoice” or “Make Packing Slip”. Once you've selected one, click on the “Apply” button.


2 Answers

The most accurate, effective and lightweight solution (For WooCommerce 3 and above) - 2019

This filter hook is located in:

  • WC_Order Class inside payment_complete() method which is used by all payment methods when a payment is required in checkout.
  • WC_Order_Data_Store_CPT Class inside update() method.

As you can see, by default the allowed paid order statuses are "processing" and "completed".

###Explanations:

  1. 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.

  1. 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)

like image 50
LoicTheAztec Avatar answered Oct 09 '22 03:10

LoicTheAztec


For me this hook was called even if the payment did not go through or failed, and this resulted to completed failed payments. After some research I changed it to use 'woocommerce_payment_complete' because it's called only when payment is complete and it covers the issue that @LoicTheAztec mentions above –

add_action( 'woocommerce_payment_complete', '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;     // Updated status to "completed" for paid Orders with all others payment methods     } else {         $order->update_status( 'completed' );     } } 
like image 26
Motaz Homsi Avatar answered Oct 09 '22 02:10

Motaz Homsi