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