WooCommerce fixes / duplicate renewal charge

WooCommerce Subscription Charged the Customer Twice? Causes & Fix

Two charges, same amount, same customer, same renewal. Before anything else: confirm it's genuinely a duplicate, then refund one today — a refund you make is a customer you keep; a chargeback they raise is a customer you lose plus a fee. Here's how to tell, and why it happened.

Last updated: 16 Jul 2026 · ~7 min read

Quick answer

The most common cause is the same renewal being processed twice at once, because the order-level payment lock was released before the second process started. The gateway's synchronous charge and the incoming payment_intent.succeeded webhook end up handling the same renewal, and two payment intents get confirmed instead of one. Refund the second charge from the duplicate renewal order — not directly in the gateway — so WooCommerce records it.

What a duplicate renewal charge actually is

A renewal is meant to be exactly one thing happening once: the scheduler fires a payment hook for a subscription, a renewal order is created, the gateway is asked for one charge. A duplicate means two processes both believed they owned that renewal at the same moment. WooCommerce guards against this with a short-lived lock on the order — if that lock is released, missing, or expires early, the guard is gone.

You'll usually see it as two paid renewal orders for one period, or one order with two "payment complete" notes and two charges against it at the gateway. Your customer sees two identical debits on their statement and, quite reasonably, assumes you're the problem. Speed matters more than elegance here.

The most common causes (most likely first)

  1. The order lock was released too early and two processes ran the same renewalTwo charges at the gateway seconds apart, same amount, same customer. The gateway's synchronous charge and the payment_intent.succeeded webhook both handled the renewal — each confirming its own intent, each calling payment_complete(). Look for two "payment complete" notes on the order within the same minute. The #1 cause.
  2. The store recorded a successful charge as failed, then retried itTwo charges hours or days apart, not seconds. The first one shows Succeeded at the gateway but its renewal order is marked Failed — the confirmation never came back, so the retry rules charged again. Check the webhook log around the first charge for a timeout or non-200.
  3. The same scheduled action ran twiceWooCommerce → Status → Scheduled Actions shows two scheduled_subscription_payment entries with identical arguments, or one action that ran twice. Overlapping queue runners — WP-Cron and a server cron both hitting wp-cron.php — will do this, as will a claim that was never released.
  4. Someone processed the renewal by hand while the automatic one was in flightOne charge lines up with the scheduled renewal time; the other lines up with an admin action, and an order note names a user. Common when a renewal looks stuck and gets "helped along".
  5. It isn't a duplicate — there are two subscriptionsThe two charges belong to two different subscription IDs. The customer checked out twice, or an old subscription was never cancelled when they resubscribed. Rule this out first: it takes thirty seconds and changes the whole answer.

Where to look first

Would you rather hear about the second charge from us or from the customer?

The hard part of a double charge isn't the refund — it's that you found out from an angry email a week later. DiagnosticIQ's free dashboard watches for the conditions behind duplicate renewals: overlapping queue runners, duplicated scheduled_subscription_payment actions, webhook deliveries failing around successful charges. It names the specific one on your store, and flags a repeat renewal charge while you can still refund it before the customer notices.

Get the free plugin

Made by Prima Digital — the team behind this guide. Free forever; no card to install.

How to know you fixed it

Verify

After the fix, the next renewal cycle produces one renewal order per subscription with one payment-complete note, and one matching charge at the gateway — with no duplicate scheduled_subscription_payment action left in the queue.

Frequently asked

Do I refund it?

If both charges are for the same period on the same subscription: yes, refund one, today, without waiting for the customer to ask. Refund the later charge in full through its renewal order so WooCommerce records it. A voluntary refund costs you the amount; a chargeback costs you the amount plus a fee plus the relationship.

Should I refund in Stripe or in WooCommerce?

In WooCommerce — open the duplicate renewal order and use the refund action so it goes through the gateway and gets recorded against the order. A refund issued only in the gateway dashboard leaves your order data and reports wrong.

Will cancelling the subscription stop it happening again?

No, and it'll cost you the customer. The duplicate comes from how the renewal is processed, not from the subscription itself. Fix the cause, keep the subscription, refund the extra charge.

Will it charge twice again next month?

Yes, if the cause is still there. Concurrent runners and duplicated scheduled actions repeat every cycle. Confirm at the next renewal that exactly one charge lands before you consider it closed.

>_
John O'Keane — Founder, Prima Digital · LinkedIn
Contributions by David Zhang · LinkedIn
I build DiagnosticIQ, the WooCommerce diagnostic plugin, and I've been on the wrong end of the email that starts "why have you charged me twice?" more than once.