Initial assessment without passwords Quote before intervention One accountable specialist from start to finish

Payments Callbacks

WooCommerce Creates Duplicate Orders or Duplicate Charges

Stop duplicate WooCommerce orders or charges by distinguishing repeated clicks, retries, webhooks, custom code and non-idempotent payment processing.

Duplicate orders and duplicate charges are related but not identical. Two WooCommerce orders may point to one provider payment, one order may contain two charges, or both systems may contain duplicates. Each pattern has a different cause and refund risk.

Stop uncontrolled retesting. Reconcile every transaction before deleting, refunding or changing an order status.

Classify the duplicate pattern

Create a privacy-safe table containing WooCommerce order IDs, amounts, timestamps, customer reference, gateway transaction IDs and status. Determine whether product lines and addresses match.

Pattern A: two orders, one transaction
Pattern B: one order, two transactions
Pattern C: two orders, two transactions
Pattern D: one real charge plus one temporary authorisation

Confirm captured payment status in the provider dashboard. A pending bank hold is not necessarily a second completed charge.

Inspect customer submission behaviour

Slow checkout responses can encourage repeated taps, refreshes or opening another tab. Browser Network data may show multiple checkout requests seconds apart.

The button should become visibly busy after a valid submission, but a disabled button is only a user-interface safeguard. Server-side payment processing must remain safe when a request is retried.

Check mobile layouts and error visibility. Customers may press again because the first request completed invisibly.

Trace gateway idempotency

Many payment APIs accept an idempotency key so a retried request returns the original result instead of charging again. Review the gateway plugin’s logs and API request references.

One logical payment attempt should retain:
- one merchant/order reference
- one idempotency key where supported
- one stored provider transaction ID

Never print API secrets or full payment payloads. If custom code creates payment requests, verify the key remains stable across network retries but changes for a genuinely new order.

Check webhook replay

Providers retry webhooks when the store times out or returns a non-success status. The same event can therefore arrive several times. A handler must recognise the provider event or transaction already processed.

Inspect delivery history and WooCommerce order notes. If identical event IDs create repeated fulfilment, email or status effects, repair idempotency before replaying anything.

Respond promptly to the provider, then queue slow non-critical processing. A webhook that performs a long ERP export before responding invites retries.

Review custom hooks

Custom code may create an order on more than one lifecycle hook, call payment APIs from both browser and server, or run twice when checkout updates.

Search for wc_create_order(), gateway API calls and hooks attached to checkout or thank-you pages. The thank-you page can be refreshed and must not be treated as proof that payment should run again.

Do not edit WooCommerce core. Put corrected logic in maintained site code with logging and tests.

Check scheduled tasks and external systems

Failed scheduled actions may be retried, while an ERP or automation platform may resend order creation after a timeout. Compare correlation IDs across systems.

A timeout means “unknown outcome,” not “nothing happened.” Before a retry, the caller should query by stable reference or use an idempotent operation.

Reconcile customer impact

Identify which charge and order should remain. Refund confirmed duplicate captures through the gateway’s supported process and add private order notes linking all references.

Restore stock once where appropriate and prevent duplicate fulfilment. Do not simply trash an order: accounting, gateway, inventory and customer email records would diverge.

Communicate facts and refund timing without blaming the customer for pressing twice.

Verify the repair

Test a normal payment, a deliberate double click, a browser retry and a replayed sandbox webhook. Each logical attempt should result in one order, one captured charge and one fulfilment path.

Recurring monitoring should flag same-customer same-amount orders in a short interval, reused references and multiple captured payments per order. Detection complements idempotent design; it does not replace it.

BEFORE YOU SEND THE REQUEST

Frequently asked questions.

Do you ask for passwords in the form?+

No. The public form never requests access. Secure credentials are requested only after the scope and quote are approved.

Who reviews the incident?+

The request goes to Jordi Ensenyat, founder of Code Barcelona and a WordPress specialist with more than 15 years of experience.

Is anything changed before the quote?+

No. Visible symptoms and scope are reviewed first. Intervention begins after approval and with a rollback path prepared.

Do you work internationally?+

Yes. WP Repair handles WordPress and WooCommerce incidents in English and Spanish through a remote service.

Assess my incident