WooCommerce Development

WooCommerce and WooCommerce Subscriptions – Automatically set order status to completed

This post is an update onWooCommerce – Automatically set order status after payment is received

WooCommerce is a great option to sell all type of goods, being it virtual or physical products you’ll quickly add them to your store and start selling to your visitors.

By default when WooCommerce system processes a payment it’ll set an order with only virtual and downloadable products to completed but sometimes this isn’t enough for your store.

In this case, the store sells physical products and subscriptions, that can be a physical product sent by mail each month or a virtual product that gives you access to restricted areas of the website, because of that we need to change WooCommerce default behavior and automatically set our virtual subscriptions as completed orders, after the payment is complete.

For doing this we’re going to use a hook “woocommerce_order_item_needs_processing” and check if the products on the order are only virtual and subscriptions.

 * Set Orders from Subscriptions marked as Virtual Products Completed Automatically.
 * @param  boolean $virtual_downloadable_item If item is virtual and downloadable.
 * @param  Object  $_product                  Product Object.
 * @param  int     $product_id                Product ID.
 * @return Boolean                            Should not be set to processing.
function rfvc_set_virtual_subscriptions_completed( $virtual_downloadable_item, $_product, $product_id ) {

	if ( $_product->is_virtual() && is_a( $_product, 'WC_Product_Subscription' ) ) {
		$virtual_downloadable_item = true;

	return $virtual_downloadable_item;
add_filter( 'woocommerce_order_item_needs_processing', 'rfvc_set_virtual_subscriptions_completed', 10, 3 );

You can also use this code to change the order status in virtual products, without them being subscriptions, removing the check for a subscription product object && is_a( $_product, 'WC_Product_Subscription' )

6 replies on “WooCommerce and WooCommerce Subscriptions – Automatically set order status to completed”

Hello and thank you for your post!

I have launch a subscription membership website(using woocommerce subscription and woocommerce membership plugins) and i sell only one virtual product (access to private content of the website).

I add in my functions.php your previous code
and this code too

2 questions:

Do you think i can get ride of this function

Do you think i need to upgrade your own function for the one provide in this upgrade post?

Thank you for your help

Hi, Raph if you update your code to this new version you won’t need the second function to set the order status as complete.
I would suggest you update it.

Another way to make this work, without any custom code, is setting you virtual product as “downloadable” too, WooCommerce automatically sets orders with only “virtual and downloadable” products to complete automatically.

Hello and thank you!

So basicly i just need to set my only virtual product as downloadable too and erase my 2 functions, get it

I need something a little tricky, maybe you can help.

I’m using a plugin called WooCommerce Order Status & Actions Manager to create a custom order status “Authentication” for one particular variable subscription product offering a free trial with a setup fee.

What I want is that when the first payment (the setup fee) is completed for this variable subscription product that the order status be set to “Authentication” and the subscription status be set to “Pending”.

Any idea how to do this??

Hi Ricardo,

Some of my products involve a bit of a process before the subscription becomes activated. Do you know if there is a way to automatically set a subscription status as pending for certain products or product categories.

Your help would be much appreciated!

Hi Sam,
For both this and your previous comment you can use the hook woocommerce_subscription_status_active, some documentation here: when the subscription is set to active, after successful payment, you can change it back to the status you want,using the inherited method from WooCommerce Orders (, $subscription->update_status( ‘on-hold’ );