skip to Main Content

I get several orders where a customer selects "Direct Bank Transfer" and then they change their mind and want to pay by Credit Card. This is quite annoying because I have to manually change the order from "On Hold" to "Pending Payment" so they can pay by card via the "order-pay" endpoint which is found in "My Account" under "Orders".

I’ve been using the WooCommerce change order status BACS processing to automatically change the order status from "On Hold" to "Pending Payment".

// WooCommerce Change Order Status BACS Pending

add_action( 'woocommerce_thankyou', 'bacs_order_payment_pending_order_status', 10, 1 );

function bacs_order_payment_pending_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 ) ) {
        $order->update_status('pending');
    } else {
        return;
    }
}

But since I have several user profiles (I sell B2B as well), this is not practical for my shop. I’m trying to expand this snippet to also check for the user role. I’ve used the following in my other snippets. Is it possible to add the below logic to the snippet above?

    $user = wp_get_current_user();
    $roles = (array) $user->roles;
    $roles_to_check = array('administrator', 'customer', 'shop_manager');
    $compare = array_diff($roles, $roles_to_check);

    if (empty($compare)){

This is my attempt.

// WooCommerce Change Order Status BACS Pending

add_action( 'woocommerce_thankyou', 'bacs_order_payment_pending_order_status', 10, 1 );

function bacs_order_payment_pending_order_status( $order_id ) {
    if ( ! $order_id ) {
        return;
    }

    // Get an instance of the WC_Order object
    $order = new WC_Order( $order_id );

    $user = wp_get_current_user();
    $roles = (array) $user->roles;
    $roles_to_check = array('administrator', 'customer', 'shop_manager');
    $compare = array_diff($roles, $roles_to_check);

    if (empty($compare)){

    if ( ( get_post_meta($order->id, '_payment_method', true) == 'bacs' ) && ('on-hold' == $order->status ) ) {
        $order->update_status('pending');
    } else {
        return;
    }
}

2

Answers


  1. You can use this as follows, comment with explanation added in the code

    function bacs_order_payment_pending_order_status( $order_id ) {
        // Get $order object
        $order = wc_get_order( $order_id );
        
        // Is a WC_Order
        if ( is_a( $order, 'WC_Order' ) ) {
            // Get user
            $user = $order->get_user();
            
            // Roles
            $roles = (array) $user->roles;
            
            // Roles to check
            $roles_to_check = array( 'administrator', 'customer', 'shop_manager' );
            
            // Compare
            $compare = array_diff( $roles, $roles_to_check );
            
            // Result is empty
            if ( empty ( $compare ) ) {
                if ( $order->get_payment_method() == 'bacs' && $order->has_status( 'on-hold' ) ) {
                    $order->update_status( 'pending' );
                }
            }
        }
    }
    add_action( 'woocommerce_thankyou', 'bacs_order_payment_pending_order_status', 10, 1 );
    

    Might Come in handy: WooCommerce: Get Order Info (total, items, etc) From $order Object

    Login or Signup to reply.
  2. Woocommerce version 3.4.0 has introduced a much better hook that allows to change the default status for BACS payment gateway which is set to "on-hold".

    Using this hook will:

    • Lighten your code,
    • Avoid "on-hold" notification to the customer when a BACS order is placed.

    Here is that code:

    add_filter( 'woocommerce_bacs_process_payment_order_status','filter_process_payment_order_status_callback', 10, 2 );
    function filter_process_payment_order_status_callback( $status, $order ) {
        // Here set the user roles to check
        $roles_to_check = array( 'administrator', 'customer', 'shop_manager' ); 
        
        $user = $order->get_user(); // Get the WP_User Object
            
        $compare = array_diff( $user->roles, $roles_to_check ); // compare
            
        if ( empty ( $compare ) ) {
            return 'pending';
        }
        return $status;
    }
    

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

    Since WooCommerce 5+: Allow re-sending New Order Notification in WooCommerce 5+


    Enabling New Order email notification (sent to the admin) for BACS payments:

    As pending Orders doesn’t send email notifications, you can enable that with the following

    add_action( 'woocommerce_checkout_order_processed', 'pending_new_order_notification', 20, 1 );
    function pending_new_order_notification( $order_id ) {
        // Get an instance of the WC_Order object
        $order = wc_get_order( $order_id );
    
        // Only for "pending" order status and BACS payments
        if( $order->has_status( 'pending' ) && $order->get_payment_method() === 'bacs' ) 
        {
            // Send "New Email" notification (to admin)
            WC()->mailer()->get_emails()['WC_Email_New_Order']->trigger( $order_id );
        }
    }
    

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

    Related: Send an Email notification to the admin for pending order status in WooCommerce


    Useful: How to get WooCommerce order details

    Related: Change default WooCommerce order status to processing for cheque and bacs payments

    Freshly updated answer thread: WooCommerce change order status BACS processing

    Login or Signup to reply.
Please signup or login to give your own answer.
Back To Top
Search