What matters first: Customers can be charged twice when checkout is resubmitted, a timeout encourages another attempt, or custom retry logic lacks idempotency.
What this symptom actually tells you
WooCommerce order status alone cannot prove the number of captures. Gateway transaction records, idempotency keys and timestamps are decisive.
Capture evidence before changing anything
- Collect every gateway charge, authorisation and refund reference.
- Map charges to WooCommerce orders, checkout sessions and customer attempts.
- Review timeout, retry and webhook logs around the incident.
- Disable the failing payment path if duplicate charging is ongoing.
Most common causes
- Customer retry: The first payment completed without a usable confirmation page.
- Gateway/client retry: A request was repeated without an idempotency key.
- Webhook and return race: Two code paths both capture or finalise payment.
- Custom payment code: The integration calls capture more than once.
Safe diagnostic and repair sequence
- Contain the issue and communicate with affected customers.
- Refund confirmed duplicate captures according to gateway and business process.
- Implement idempotency and one authoritative payment-completion path.
- Test timeout and repeated-webhook scenarios, not only the happy path.
How to choose between the likely causes
Do not treat Customer retry and Gateway/client retry as interchangeable. The first payment completed without a usable confirmation page. By contrast, a request was repeated without an idempotency key. Use two checks to separate them: Collect every gateway charge, authorisation and refund reference; and map charges to WooCommerce orders, checkout sessions and customer attempts. Those observations usually show whether the next safe move is to contain the issue and communicate with affected customers or to preserve the current state and widen the investigation.
On a live store, reproduce the issue with a controlled test order and follow the same payment, stock, tax and notification path used by customers. Avoid changing several checkout components at once because that changes the application state and can obscure the original sequence of events needed to attribute the failure. Record the exact timestamp, affected URL or transaction, last known good state and every change made during diagnosis. That handover is often what separates a repeatable repair from a temporary disappearance of the symptom.
What not to do
Do not refund from WooCommerce until you know whether the gateway supports and recorded that refund; otherwise records can diverge further.
How to verify the repair
- Each checkout session can produce at most one captured payment.
- Gateway and order refund records match.
- Timeouts and duplicate callbacks remain safe and idempotent.
A visible symptom disappearing is not enough. Close the incident only when the original failing action, the surrounding business journey and the relevant logs all agree that the fault is gone.
WP REPAIR INCIDENT STANDARD
Safe intervention sequence
WooCommerce order status alone cannot prove the number of captures. Gateway transaction records, idempotency keys and timestamps are decisive.
- Collect every gateway charge, authorisation and refund reference.
- Map charges to WooCommerce orders, checkout sessions and customer attempts.
- Review timeout, retry and webhook logs around the incident.
- Disable the failing payment path if duplicate charging is ongoing.
What must be verified
- Each checkout session can produce at most one captured payment.
- Gateway and order refund records match.
- Timeouts and duplicate callbacks remain safe and idempotent.
Official technical sources
Continue the diagnosis
This guide explains the diagnosis. If the site is affected now, the intervention should preserve a rollback path and verify the real business journey.
See the emergency repair service →ABOUT THIS SYMPTOM
Frequently asked questions about this guide.
Can WooCommerce's order status tell me how many times a customer was actually charged?+
No. Order status alone cannot prove the number of captures; gateway transaction records, idempotency keys and timestamps are the decisive evidence for determining whether a customer was charged once or multiple times.
Should I issue a refund directly from WooCommerce as soon as I spot a duplicate charge?+
Not until you confirm the gateway actually supports and has recorded that refund. Refunding from WooCommerce without that check can cause the gateway and order records to diverge further instead of reconciling them.
If duplicate charges are actively happening right now, what's the first move?+
Disable the failing payment path immediately if duplicate charging is ongoing, before working through root-cause analysis. Containing active harm to customers takes priority over diagnosing whether it's a customer retry, a gateway retry, or a race between webhook and return-page handling.
Does testing only the successful checkout flow catch this kind of bug?+
No. The guide specifically calls for testing timeout and repeated-webhook scenarios, not only the happy path, since duplicate payments typically emerge from retry and race conditions that never appear when everything completes on the first try.