WooCommerce Virtual products - Autocomplete orders after payment

173 Views Asked by At

I have virtual products and I would like them to be auto-completed when purchased.

I found the code pasted below, added it to functions.php, and it did work, BUT with one caveat:
When people choose to pay by bank transfer (yep, they still do...), the order is set to on hold (OR maybe Pending payment, not sure, the developer set it up in Italian). In these cases the order should be manually updated when the payment is received and only then it can be completed.

However the code below sets every order as complete when the user lands on the Thank you page, that obviously doesn't work in these cases.

Any ideas? How can I solve this?

My code:

add_action('woocommerce_thankyou', 'wpd_autocomplete_virtual_orders', 10, 1 );
function wpd_autocomplete_virtual_orders( $order_id ) {
  
    if( ! $order_id ) return;
  
    // Get order
    $order = wc_get_order( $order_id );
  
    // get order items = each product in the order
    $items = $order->get_items();
  
    // Set variable
    $only_virtual = true;
  
    foreach ( $items as $item ) {
          
        // Get product object
        if ( isset($item['variation_id']) && ! empty($item['variation_id']) ) {
 
            $product = wc_get_product( $item['variation_id'] );
 
        } else {
 
            $product = wc_get_product( $item['product_id'] );
 
        }
 
        // Safety check
        if ( ! is_object($product) ) {
 
            return false;
 
        }
                 
        // Is virtual
        $is_virtual = $product->is_virtual();
  
        // Is_downloadable
        $is_downloadable = $product->is_downloadable();
  
        if ( ! $is_virtual && ! $is_downloadable  ) {
  
            $only_virtual = false;
  
        }
  
    }
  
    // true
    if ( $only_virtual ) {
  
        $order->update_status( 'completed' );
  
    }
 
}

In short: I tried to use some code, it didn't work as expected. I'd be grateful if you could advise on how to modify the code.

1

There are 1 best solutions below

1
LoicTheAztec On

Based on WooCommerce: Auto complete paid orders, try the following instead that will autocomplete paid orders if all items are virtual (but no bank transfer orders):

// Conditional function that check if order items are all virtual
function only_virtual_order_items( $order ) {
    $only_virtual_items = true; // Initializing

    // Loop through order items
    foreach( $order->get_items() as $item ) {
        $product = $item->get_product();
        // Check if there are items that are not virtual
        if ( ! ( $product->is_virtual() || $product->is_downloadable() ) ) {
            $only_virtual_items = false;
            break;
        }
    }
    return $only_virtual_items;
}

// Autocomplete paid orders
add_filter( 'woocommerce_payment_complete_order_status', 'wc_auto_complete_paid_order', 10, 3 );
function wc_auto_complete_paid_order( $status, $order_id, $order ) {
    // Check if all items are virtual
    if ( only_virtual_order_items( $order ) ) {
        $status = 'completed'; 
    }
    return $status;
}

If you want to autocomplete COD (Cash On Delivery Orders) use the following too:

add_action( 'woocommerce_cod_process_payment_order_status', 'wc_auto_complete_cod_order', 10, 2 );
function wc_auto_complete_cod_order( $status, $order ) {
    // Check if all items are virtual
    if ( only_virtual_order_items( $order ) ) {
        $status = 'completed'; 
    }
    return $status;
}

Code goes in functions.php file of your child theme (or in a plugin). Tested and works.