By default, WooCommerce automatically marks virtual downloadable products as “completed” after the customer pays successfully. But if our virtual product is not downloadable, such as a coupon or an online recharge code, the order will not be marked as completed automatically after payment. That is clearly not a great user experience. The following adjustment makes WooCommerce support automatic completion for non-downloadable virtual products as well.
Just copy the code below into the theme’s functions.php file.
add_filter( 'woocommerce_payment_complete_order_status', 'virtual_order_payment_complete_order_status', 10, 2 );
function virtual_order_payment_complete_order_status( $order_status, $order_id ) {
$order = new WC_Order( $order_id );
if ( 'processing' == $order_status &&
( 'on-hold' == $order->status || 'pending' == $order->status || 'failed' == $order->status ) ) {
$virtual_order = null;
if ( count( $order->get_items() ) > 0 ) {
foreach( $order->get_items() as $item ) {
if ( 'line_item' == $item['type'] ) {
$_product = $order->get_product_from_item( $item );
if ( ! $_product->is_virtual() ) {
// If it is not a virtual product, stop checking and break out.
$virtual_order = false;
break;
} else {
$virtual_order = true;
}
}
}
}
// If it is a virtual product, return completed.
if ( $virtual_order ) {
return 'completed';
}
}
// For non-virtual products, return the existing order status.
return $order_status;
}
This is actually a very common requirement. It is hard to understand why WooCommerce does not provide a built-in option for it and instead leaves us to implement it ourselves.
