The beauty of selling digital products—like eBooks, software licenses, or online courses—is automation. A customer buys a file, pays via credit card, and instantly receives a download link. However, a common WooCommerce bug causes orders containing purely digital, downloadable items to get stuck permanently in the "Processing" status rather than moving automatically to "Completed."
Because the order remains stuck in "Processing", WooCommerce refuses to release the download links to the customer's dashboard or email. This results in immediate customer complaints and manual overhead for the store manager. This issue happens because WooCommerce’s core logic treats all transactions as physical shipments by default. If a single product setting is misconfigured, or if the payment gateway fails to return an explicit "payment received and settled" signal via its webhook, WooCommerce leaves the order open, waiting for a human manager to manually confirm that the package was shipped.
The Solution
To fix this, you must adjust individual product attributes and implement an explicit snippet that forces auto-completion for virtual items.
-
Configure Product Attributes Correctly: Open your digital product edit screen. Under the Product Data dropdown, ensure that both the Virtual and Downloadable checkboxes are ticked. If "Virtual" is unchecked, the system expects a shipping routine.
-
Force Auto-Completion via Code: If your payment gateway approves transactions but leaves virtual orders processing, add this code to your child theme's
functions.phpfile to automate the transition:
add_action('woocommerce_order_status_processing', 'auto_complete_virtual_orders');
function auto_complete_virtual_orders($order_id) {
$order = wc_get_order($order_id);
if ('processing' === $order->get_status()) {
$is_virtual = true;
foreach ($order->get_items() as $item) {
$product = $item->get_product();
if (!$product || !$product->is_virtual()) {
$is_virtual = false;
break;
}
}
if ($is_virtual) {
$order->update_status('completed');
}
}
}
-
Verify Gateway Webhooks: Go to your payment processor dashboard (Stripe/PayPal) and ensure your webhook endpoints are functioning without
500errors, enabling them to send successful capture events instantly.
