7

In WooCommerce any order placed with the BACS (direct bank transfer) is set to "on-hold".

How would one go about changing this automatically to processing?

I wan't it to work inside the functions.php

I have the following code but that doesn't work:

add_filter( 'woocommerce_payment_complete_order_status', 'rfvc_update_order_status', 10, 2 );

function rfvc_update_order_status( $order_status, $order_id ) {
    $order = new WC_Order( $order_id );
    if ( 'on-hold' == $order_status && 'on-hold' == $order->status ) {
        return 'processing';
    }
    return $order_status;
}

Any help would be great!

LoicTheAztec
  • 229,944
  • 23
  • 356
  • 399
Tristan .L
  • 829
  • 3
  • 9
  • 20
  • 1
    I decided to go for the second approach as it seems the first filter does not trigger with the BACS payment. – Tristan .L Apr 14 '16 at 15:25

3 Answers3

14

New 2020 update

WooCommerce version 3.4 has introduced a much better hook than woocommerce_thankyou or woocommerce_thankyou_bacs, that allows to change the default order status for BACS payment method.

Using this hook will:

  • clearly lighten the necessary code,
  • avoid "on-hold" notification to the customer when a BACS order is placed.

So use instead the following:

add_filter( 'woocommerce_bacs_process_payment_order_status','filter_bacs_process_payment_order_status_callback', 10, 2 );
function filter_bacs_process_payment_order_status_callback( $status, $order ) {
    return 'processing';
}

Code goes in functions.php file of the active child theme (or active theme). Tested and works.


Original answer:

Update (added a version for woocommerce 3+ at the end)

It seems that woocommerce_payment_complete_order_status action hook doesn't trigger with BACS payment method.

Based on this thread, 'woocommerce_thankyou' action hook does the job:

add_action( 'woocommerce_thankyou', 'bacs_order_payment_processing_order_status', 10, 1 );
 
function bacs_order_payment_processing_order_status( $order_id ) {
    if ( ! $order_id ) {
        return;
    }

    // Get an instance of the WC_Order object
    $order = new WC_Order( $order_id );
 
    if ( ( get_post_meta($order->id, '_payment_method', true) == 'bacs' ) && ('on-hold' == $order->status || 'pending' == $order->status) ) {
        $order->update_status('processing');
    } else {
        return;
    }
}

Code goes in function.php file of your active child theme (or active theme). tested and works.


For woocommerce 3+ versions:

Here we use the similar composite hook woocommerce_thankyou_{$order->get_payment_method()}:

add_action( 'woocommerce_thankyou_bacs', 'bacs_order_payment_processing_order_status', 10, 1 );
function bacs_order_payment_processing_order_status( $order_id ) {
    if ( ! $order_id ) {
        return;
    }

    // Get an instance of the WC_Order object
    $order = wc_get_order( $order_id );
 
    if ( in_array( $order->get_status(), array('on-hold', 'pending') ) ) {
        $order->update_status('processing');
    } else {
        return;
    }
}

Code goes in function.php file of your active child theme (or active theme). tested and works.

LoicTheAztec
  • 229,944
  • 23
  • 356
  • 399
  • This is perfect! :) Thank you! – Tristan .L Apr 14 '16 at 07:38
  • @LoicTheAztec: Are you sure the latter code works? I am getting a syntax error in my functions.php – Madita von Birkenlund Sep 05 '18 at 13:09
  • @MaditavonBirkenlund Sorry there was a missing bracket in WC 3+ updated code – LoicTheAztec Sep 05 '18 at 14:50
  • @LoicTheAztec Okay, but now both emails - on hold AND processing are sent at at the same time, and only in the on hold email the pament instructions are shown. Only the processing email should be sent though, shouldn't it? – Madita von Birkenlund Sep 05 '18 at 15:24
  • 1
    @MaditavonBirkenlund Anyway to auto "process" BACS or CHEQUE Orders is not a good idea, as the shop owner needs to wait his bank confirmation, before passing an order to "processing" or "complete" orders status. So if you want, you can make some changes in BACS using something like: http://www.remicorson.com/change-the-orders-default-status-by-gateway-in-woocommerce/ … Or you can also use a clone of BACS gateway for specific "Trusted customers" that has "processing" status in [`process_payment()` own function](https://docs.woocommerce.com/wc-apidocs/source-class-WC_Gateway_BACS.html#335-364) – LoicTheAztec Sep 05 '18 at 15:42
  • In Thank you page order status is still on hold how to change that? – kasper Aug 02 '23 at 13:12
  • For BACS? Are you using the first code snippet? – LoicTheAztec Aug 02 '23 at 14:54
6

There is a new filter which will allow you to set the status when BACS 'payment' is processed.

/**
 * Change the default status when BACS 'payment' is processed.
 * 
 * @see WC_Gateway_BACS::process_payment()
 * woocommerce/includes/gateways/bacs/class-wc-gateway-bacs.php:362
 * @since Mar 8, 2018
 * @link https://github.com/woocommerce/woocommerce/blob/750fda3b1b55c55645f626d3873d956282e3ac1b/includes/gateways/bacs/class-wc-gateway-bacs.php#L364
 * 
 * @filter woocommerce_bacs_process_payment_order_status
 * @priority 10
 * @args 2
 * 
 * @param string $status Status to filter. Default 'on-hold'.
 * @param WC_Order $order
 * @return string New status 'processing'.
 */
add_filter( 'woocommerce_bacs_process_payment_order_status', function( $status = 'on_hold', $order = null ) {
    return 'processing';
}, 10, 2 );
Shaun Cockerill
  • 800
  • 8
  • 11
  • This is best solution, it change default behavior and doesnt trigger multiple order status actions. – hexcross Jun 24 '20 at 08:43
  • Someone asked me about situations where the stock levels aren't reduced. I double checked the code, and since 3.0.0, WooCommerce will attempt to reduce stock automatically when the payment complete action is triggered, as well as when the order status moves to either on-hold, processing or completed. – Shaun Cockerill Oct 28 '20 at 01:16
1

Try changing the code to this:

function rfvc_update_order_status( $order_status, $order_id ) {
    $order = new WC_Order( $order_id );
    if ( 'on-hold' == $order_status && 'on-hold' == $order->status ) {
        $order->update_status('processing', 'order_note');
    }
    return $order_status;
}

The key change here is this:

$order->update_status('processing', 'order_note');

You can add order note too if you prefer.

Nerijus Masikonis
  • 1,954
  • 1
  • 14
  • 14
  • Ah great stuff, that should do the job, however I'm hooking into `woocommerce_payment_complete_order_status` does this even trigger when using BACS? As that payment option just sends people an invoice.. – Tristan .L Apr 13 '16 at 13:24
  • Can you try? Normally it should. – Nerijus Masikonis Apr 13 '16 at 13:50
  • It turns out `woocommerce_payment_complete_order_status` is indeed triggering after the payment is received. So it will not trigger when just ordering. – Tristan .L Apr 13 '16 at 15:19
  • In this case you should use another trigger but the key thing here is that you can use $order->update_status('processing', 'order_note'); to change the status of the order. – Nerijus Masikonis Apr 14 '16 at 05:05
  • I tried, but until I have a rep of 15 that won't have any effect. If you give me one vote up I can give you one since I am on rep 14. – Tristan .L Apr 15 '16 at 07:24