WooCommerce Refund Not Received? Fix Stuck Gateway Refunds
You click "Refund" in WooCommerce, the order status flips to "Refunded," and you move on. Then three days later the customer emails: the money never showed up on their card. This is one of the more confusing WooCommerce issues because WordPress itself looks perfectly happy — the bug lives in the handshake between WooCommerce and your payment gateway, and it fails silently more often than you'd think.
The symptom
WooCommerce shows the order as Refunded, sometimes with a green refund line item and the correct amount deducted from the order total. Everything in wp-admin looks correct. But when you check the actual gateway — Razorpay, Stripe, PayPal, or your payment aggregator's dashboard — one of two things is true: either there's no matching refund transaction at all, or there is one, but it's sitting in a "failed" or "pending" state that WooCommerce never checked back on.
The customer's bank statement is the source of truth here, not the WooCommerce order screen. If they say the money isn't back, believe them first and verify second.
Why this happens
1. The refund only updated the WordPress database
Some staff (or a plugin doing a bulk order edit) can change an order's status to "Refunded" or add a refund line item directly, without that action ever calling the gateway's API. WooCommerce lets you record a refund manually — useful for cash, bank transfer, or COD orders — but if the site owner didn't notice the "Restock refunded items" and "Refund via [Gateway]" checkbox was unchecked, no API call goes out. The record is entirely local.
2. The gateway API call fired but failed
When you do hit "Refund via Razorpay/Stripe," WooCommerce sends a real API request. That request can fail for reasons that have nothing to do with your store's code:
- The original payment already had a partial refund, and the new request exceeds the remaining refundable balance.
- The payment method doesn't support refunds at all — some UPI collect flows and certain wallet payments can only be refunded manually by the customer's bank or the aggregator's back office.
- API keys were rotated (a common Getwebup support ticket after a site migration) and the live keys in WooCommerce > Settings > Payments no longer match what's active on the gateway account.
- A firewall rule, ModSecurity, or an expired SSL certificate on the site blocked the gateway's outbound callback confirming the refund.
WooCommerce's UI doesn't always surface this failure clearly — sometimes it shows a red error banner, sometimes it silently marks the order refunded anyway because the local database update succeeded even though the remote API call errored out.
3. Refund window has closed
Most gateways only allow refunds within a fixed window after the original charge — commonly 6 months for cards, but as little as 24–48 hours for some UPI and wallet rails. Past that window, the API rejects the refund and it has to be processed manually by the payment provider's support team, which can take days.
4. Currency or amount mismatch
If the store changed its base currency, or a plugin rounds totals differently than the gateway does, WooCommerce can try to refund an amount that doesn't cleanly match the original charge in the gateway's minor units (paise/cents). Some APIs reject the whole request rather than adjust it, and again, WooCommerce may not relay that rejection back to the order notes clearly.
How to actually fix it
Step 1: Read the order notes, not just the status
Open the order in WooCommerce > Orders and scroll to the Order notes panel on the right. This is where the real error usually is, even when the top status looks fine. Look for lines like "Refund failed" or a raw gateway error message. If the notes only say "Order status changed to Refunded" with nothing about the gateway, that's your sign a manual/local refund was recorded without an API call.
Step 2: Cross-check the gateway dashboard directly
Log in to Razorpay, Stripe, or your gateway's dashboard and search for the original payment ID (it's usually stored on the order as a custom field, or visible in the order notes). Check its refund history there:
- No refund record exists — the API call never fired. Go to Step 3.
- Refund exists but shows "failed" — note the error code/reason shown and act on that specifically (insufficient balance in your payment account, expired card on the customer's end, etc.).
- Refund exists and shows "processed" — the money left your account. The delay is now on the customer's bank, not your site. Card refunds commonly take 5–10 business days to actually post; UPI/wallet refunds are usually same-day to 48 hours.
Step 3: Re-trigger the refund correctly
If no gateway-side refund exists yet:
- In the order, click Refund again.
- Confirm the "Refund via [Gateway name]" checkbox is ticked — if it's greyed out, your API keys or gateway connection are the problem, not the refund itself.
- Enter the exact remaining refundable amount, not a rounded figure.
- Submit, then immediately check the order notes for a success/failure message from the API response.
If the checkbox is missing or greyed out entirely, go to WooCommerce > Settings > Payments > [your gateway] and verify the API key/secret match what's live on the gateway account. A key mismatch after a site migration or a staging-to-live copy is one of the most common causes we see in support tickets.
Step 4: When the API genuinely can't refund it
Some payment methods (older UPI intent flows, certain net-banking transactions, expired refund windows) simply can't be refunded through the API. In that case, mark the order refunded in WooCommerce for your own bookkeeping, then process the refund manually through your gateway's dashboard or by contacting their support directly — and note the manual reference number in the order for future audits.
Refund behaviour by gateway
| Gateway | Typical refund window | Time to reach customer | Common failure cause |
|---|---|---|---|
| Razorpay | Up to 6 months (varies by method) | 5–7 business days (cards), same-day–48h (UPI) | Refund exceeds captured amount; UPI collect refund limits |
| Stripe | Up to 6 months | 5–10 business days | Insufficient balance in connected Stripe account |
| PayPal | Up to 180 days | 3–5 business days | Original transaction currency mismatch |
| Manual/COD | No fixed window | Depends on your process | Marked refunded in WooCommerce but never actually paid out |
Prevention
- Always leave "Refund via [Gateway]" checked when the original payment was online — reserve manual refund entries strictly for cash/COD/bank-transfer orders.
- After any site migration or staging clone, re-check that live API keys in WooCommerce > Settings > Payments match the gateway's live dashboard before processing any refunds.
- Keep a habit of screenshotting or noting the gateway refund ID on the order whenever a refund is issued — it saves a lot of back-and-forth if the customer disputes it later.
- Set a WooCommerce order note reminder (or use a support-ticket workflow) to check refund status again 7 days after issuing it, so failed refunds don't sit unnoticed.
- If you process a high volume of refunds, review your gateway's webhook logs periodically — a broken webhook endpoint (blocked by a firewall rule or an expired SSL cert) can quietly stop refund status updates from ever reaching your site, the same way it can stop payment confirmations.
Frequently asked questions
WooCommerce shows the order as Refunded but my customer says they never got the money. What do I check first?
Open the order and read the Order notes panel first, not just the status badge. If the notes don't mention the gateway (Razorpay, Stripe, PayPal) at all, the refund was likely recorded locally without an API call ever being made. Then cross-check the payment ID directly in your gateway's dashboard to see if a refund transaction exists there.
Why is the 'Refund via [Gateway]' checkbox greyed out when I try to refund an order?
This usually means WooCommerce can't authenticate with the gateway's API for that order — most often because the live API key/secret in WooCommerce > Settings > Payments no longer matches what's active on the gateway account, which commonly happens after a site migration or restoring a backup onto a new domain.
How long should a WooCommerce refund actually take to reach the customer?
Once the gateway confirms the refund as processed, card refunds typically take 5–10 business days to post on the customer's statement, while UPI and wallet refunds are usually same-day to 48 hours. If it's been longer than that and the gateway dashboard shows it as processed, the delay is on the customer's bank, not your site.
Can I just refund the customer manually outside WooCommerce and mark the order as refunded?
Yes, and for cash, COD, or direct bank-transfer orders that's the normal flow — just make sure you actually send the money through your bank or gateway's manual tools first, then record it in WooCommerce with a note including the reference number, so your bookkeeping matches reality.
What causes a refund to fail even when the original payment was captured successfully?
The most common causes are: the refund amount exceeds what's left refundable on a partially-refunded order, the payment method doesn't support API refunds at all (some UPI collect and net-banking flows), the refund window has closed, or there's a currency/rounding mismatch between WooCommerce's stored total and the gateway's minor-unit amount.