A paid order marked Failed or Cancelled can stop fulfilment, return stock and send the wrong email even though the provider holds the money. The status may come from an out-of-order webhook, WooCommerce’s unpaid-order cleanup, a gateway timeout or custom automation.
Do not change every affected order to Processing in bulk. First prove the payment state and identify which actor changed the status.
Reconcile provider and store records
For each order, match amount, currency, payment reference and timestamp. Confirm whether the provider shows captured, authorised, reversed, disputed or refunded.
Create a privacy-safe incident table. Keep transaction IDs and order IDs, but exclude card and full customer data.
If the provider status is uncertain, pause fulfilment and investigate. WooCommerce’s label alone is not sufficient evidence of payment.
Read the order-note timeline
Private order notes normally show payment attempts, stock changes, webhook processing and status transitions. Read them in timestamp order and identify the last known correct state.
Useful sequence:
order created
payment initiated
payment confirmed
status changed by gateway or scheduled task
stock/email/fulfilment effects
Compare timezones before concluding that events arrived in the wrong order.
Check webhook ordering and retries
Networks do not guarantee that webhook events arrive in creation order. A delayed “payment failed” event can appear after a later successful capture unless the handler checks the current provider object and event sequence.
Inspect provider delivery history, event IDs and API object status. Repeated delivery must not repeat stock or fulfilment effects.
Do not replay events until you know how the integration handles an already-paid order.
Review unpaid-order cancellation
WooCommerce can cancel unpaid orders after the configured stock-hold period. If confirmation is delayed beyond that window, cleanup may cancel the order before the successful webhook arrives.
Check WooCommerce inventory settings and Scheduled Actions around the transition. Increasing the hold time may help asynchronous methods, but it also reserves stock longer. Choose a value based on actual payment behaviour.
The gateway should recover a genuinely paid order safely when confirmation arrives.
Inspect gateway and PHP failures
Match the incorrect transition with gateway, WooCommerce and PHP logs. An API timeout can make the plugin interpret an unknown result as failure, while the provider later captures payment.
Avoid treating timeout as a definite decline. Custom integrations should query a stable provider reference before creating another charge or final failure.
Fix fatal errors and scheduled-action backlogs before rerunning processing.
Find external status writers
ERP, fulfilment, subscription, fraud and custom code can update order status. Search notes for the integration name, then review hooks attached to payment completion, cancellation and failed status.
Use WooCommerce order methods and conditional checks:
$order = wc_get_order( $order_id );
if ( $order && $order->is_paid() ) {
// Do not downgrade solely from a stale local event.
}
Provider evidence and business rules still determine the correct action; the snippet is only a defensive pattern.
Correct affected orders safely
After verifying capture, restore the appropriate paid status through WooCommerce or the gateway’s supported reconciliation tool. Add a private note containing the provider reference and reason.
Check whether stock was returned, emails sent or fulfilment cancelled. Correct each downstream effect once. Never create a second payment to make the status look normal.
Verify the repaired lifecycle
Test success, decline, delayed confirmation and webhook retry in sandbox. Confirm a captured payment reaches the intended paid status and cannot be downgraded by a stale event.
Recurring monitoring should compare captured provider payments with Failed, Cancelled and old Pending orders. Alerting on these contradictions prevents a status defect from becoming a fulfilment or customer-service failure.