Autocomplete Orders in WooCommerce 3.0


Jun 14

There’s more than one way to autocomplete orders in WooCommerce 3.0. If the products in an order are all virtual and downloadable, the order will be marked completed once payment is received. Any other order will be marked processing to indicate some manual work is needed on the part of the shop owner to complete the transaction. Most articles I found on this topic use an action hooked to woocommerce_thankyou or a filter on woocommerce_payment_complete_order_status. There is another way. A better way.

The problem with hooking at either woocommerce_thankyou  or  woocommerce_payment_complete_order_status is that both require more code to examine the contents of an order when only certain products allow the order to be autocompleted. More opportunity for bugs and more opportunity for the hook to be incompatible with future versions of WooCommerce.

My use-case is for virtual subscriptions to skip the processing step once payment is received. While I was tempted to only check if the product is virtual, I decided to go the slightly more conservative route and also make sure the product is a subscription. There could be services, a virtual product, that would require manual work to perform before marking the order as completed.

How did I enable autocomplete for virtual subscriptions?

I try to get as close as I can to the driving function when I’m hooking or filtering in WordPress. Driving the result in this scenario (at least as of WC 3.0) is a function needs_processing() defined in class-wc-order.php. For each product in an order, this function is called to determine if that specific product requires processing. By default, it returns true unless the product is both virtual and downloadable.

The filter woocommerce_order_item_needs_processing can be used to modify the result of needs_processing().

add_filter( 'woocommerce_order_item_needs_processing' , 'filter_woo_item_needs_processing', 10, 3 );

function filter_woo_item_needs_processing( $needs_processing, $product, $order_ID ) {
	$product_type = $product->get_type();
	if ( $product->is_virtual() 
	&& ( 'subscription' == $product_type || 'subscription_variation' == $product_type || 'variable-subscription' == $product_type ) ) {
		return false;
	return $needs_processing;

A simple and direct solution that avoids more complicated logic to understand the structure of an order. This solution utilizes built-in WooCommerce methods to break an order into it’s component products and perform a simple test on the products contained in the order.


About the Author

Toastmaster, Woodworker, Craft Beer Enthusiast and dutiful supporter of three demanding house cats. I'm also an experienced Software Engineering Manager with a demonstrated history of working in the Information Technology and Services industry. Skilled in Operating System Development, Unix, SPARC Servers, Wordpress and PHP.

Leave a Comment:

(2) comments

Ian 8 months ago

Love this snippet, helped me a lot – thank you. FYI, you have an extra parenthesis towards the end of line 1.


    Ken 8 months ago

    Right you are! Not sure how that snuck in there, appreciate the notification. Fixed in the article.

Add Your Reply

Leave a Comment: