WooCommerce / Payments
WooCommerce Payment Failed but Customer Was Charged
Short answer
The payment and the order update are two separate steps. When the provider confirms a payment but WooCommerce never receives, accepts or finishes processing that confirmation, the money is taken and the order stays pending, failed or cancelled. Compare the provider's event log, the order notes and the gateway log for one affected order: the first point where they disagree is where the confirmation was lost.
Symptoms
- The provider's dashboard shows a successful charge; the WooCommerce order is Pending payment, Failed or Cancelled.
- The customer was charged but received no order confirmation email, or no order exists at all.
- Orders change to Processing hours later, or only after the customer contacts you.
- The customer was charged twice and two orders exist, only one of them paid.
Most common causes
- The notification never reached the store. The provider's server-to-server callback or webhook was blocked by a firewall, WAF, CDN bot protection, basic authentication, a maintenance-mode plugin or a geo-block.
- The notification was redirected. An HTTP→HTTPS or www/non-www redirect on the callback URL. Many providers treat a redirect as a failed delivery.
- The notification was rejected. A wrong webhook secret or signing key — for example after re-creating the webhook endpoint, or mixing test and live keys.
- The store failed while processing it. A PHP error in code that runs when an order is paid — stock, emails, an ERP sync — interrupted the update.
- The order was no longer pending. The hold-stock timeout cancelled it before a delayed confirmation arrived, or the customer paid on an old order tab.
- The redirect was the only confirmation. The customer closed the window after paying or after 3D Secure, and the store relied on the browser redirect instead of a server notification.
- The order could not be matched. Custom order numbers, multisite or a changed order reference prevent the gateway plugin from finding the order.
Diagnosis
1. Pick one affected order and build its timeline
From three sources, write down every event with its exact time:
| Source | What to note |
|---|---|
| Payment provider dashboard | Payment created, authorised, captured; notification/webhook attempts and their responses |
| WooCommerce order notes | Status changes and gateway messages, with timestamps |
| Gateway log (WooCommerce → Status → Logs) | Incoming notifications, validation results, errors |
The first event that appears in the provider but not in the store is where the confirmation was lost.
2. Check the provider's delivery log
Most providers show each notification or webhook attempt with its response code. Read them:
- Timeout or connection error — the store did not answer in time, or the request never reached it.
- 3xx — the callback URL redirects; update it to the final URL.
- 401 / 403 — authentication, a security plugin or a WAF blocked it.
- 400 — the gateway plugin rejected it, often a signature or secret mismatch.
- 500 — PHP failed while processing it. Look for a fatal error at that timestamp.
3. Confirm the request reached the server
Search the web server access log for requests to the callback URL at the times the provider reports. The URL depends on the gateway plugin — often a ?wc-api= URL or a REST endpoint. No entry at all means the request was blocked before PHP: CDN, WAF or firewall.
4. Look for errors during order processing
If the notification reached the store and was accepted, find out what happened next: a fatal-errors entry, a PHP error, or a failed scheduled action at the same minute. Code hooked to woocommerce_payment_complete or to order status changes runs inside the notification request; if it fails, the order may never be saved as paid.
Logs and technical checks
- Provider: event log and webhook/notification delivery history for the affected payments.
- WooCommerce → Status → Logs: the gateway's log source and
fatal-errors. - Web server access and error logs for the callback URL.
- WooCommerce → Settings → Products → Inventory: the Hold stock time that cancels unpaid orders.
- Tools → Scheduled Actions: failed or pending actions created around the payment time.
- Security plugin, CDN and WAF logs for blocked requests to the callback URL.
Solutions
- Make the callback URL reachable: exclude it from WAF challenges, bot protection, maintenance mode, basic authentication and caching. Use the final URL without redirects.
- Fix the webhook secret in the gateway settings to match the endpoint configured at the provider, separately for test and live mode.
- Fix the code that fails during payment processing, and move slow work — ERP syncs, external calls — to background jobs so the notification request finishes quickly.
- Make sure server notifications are enabled, so the order does not depend on the customer's browser returning to the store.
- Reconcile affected orders: for each successful payment without a paid order, verify amount, currency and customer, then complete or recreate the order through the gateway's or WooCommerce's normal tools, with an order note describing the verification.
What not to do
- Do not disable signature verification "to make it work". It lets anyone mark orders as paid.
- Do not delete failed or cancelled orders: they are the evidence and the link to the payment.
- Do not refund or charge customers again before reconciling both sides.
- Do not raise the hold-stock time as the fix. It hides late confirmations instead of fixing them.
When to contact an expert
Contact an engineer when charges without orders keep happening, when you cannot tell which orders are affected, when the gateway plugin's logs show nothing at all, or when the failure is inside custom code that runs after payment.
Related problems
- WooCommerce / Integrations WooCommerce Webhook Troubleshooting Delivery logs, response codes, signatures, and why WooCommerce disables a webhook after repeated failed deliveries.
- WooCommerce / Checkout WooCommerce Checkout Not Working: How to Diagnose the Root Cause First determine whether the failure happens before the checkout request, during it, or after the gateway response. The Network panel and PHP logs usually reveal which layer fails.
- WooCommerce / Orders WooCommerce Orders Missing or Incorrect Before assuming an order is lost, check every status, drafts and the payment provider. Incorrect totals usually come from tax settings, fees, coupons or recalculation.
- WooCommerce / Performance WooCommerce Action Scheduler Problems Past-due, failed and stuck scheduled actions: how the queue runs, why it stalls and how to fix it without losing pending work.
Frequently asked questions
Why does WooCommerce say payment failed when the customer was charged?
Because the store did not get or could not process the provider's confirmation. Common causes are a blocked or redirected notification URL, a wrong webhook secret, a PHP error while the order was being updated, or the order having been cancelled before the confirmation arrived.
Why was the order cancelled even though the customer paid?
With stock management enabled, WooCommerce cancels unpaid orders after the hold-stock time. If the confirmation arrives after that, it finds a cancelled order. Late confirmations are usually a symptom of webhooks or notifications failing on the first attempts.
Can I just mark the order as processing?
Only after confirming the payment in the provider's dashboard and matching amount, currency and customer. Add an order note explaining what was verified. Fix the cause too, or it will happen again.
How do I find all affected orders?
Export successful payments from the provider for the affected period and match them against WooCommerce orders by order number, transaction id or amount and email. Payments without a matching paid order are the ones to reconcile.