简体   繁体   中英

Auto change order status to completed for specific products in WooCommerce

I have a virtual product and I want it to change status after payment is completed. The following code changes all purchases to "completed", but I want to change only one of my products, not all of them. My product is a variable product and has 4 items,

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' );
        }
    }

I searched a lot but did not find an answer. please help me. Thank You

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

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM