When WooCommerce Stripe payments fail, it's nearly always one of six things: a genuine card decline, a broken Stripe webhook, a 3D Secure step that never loads, a currency problem, a cached checkout page, or a conflict or bug in the WooCommerce Stripe plugin itself. Start in the Stripe Dashboard. If the payment shows as Declined there, the card issuer refused it. If it shows as Succeeded but the WooCommerce order says Pending payment or Failed, the problem is on your WordPress site.
That one check cuts the problem in half. Here's how I work through the rest, based on the WooCommerce stores I've built, like the Whitfield Service Station online ordering site and the Wow Vastra worldwide checkout, and the Stripe event bookings on the Ravens Ait venue site.
Are WooCommerce Stripe payments failing because of the card or the checkout?
The payment status in Stripe tells you. Declined means the card issuer or Stripe Radar said no. Succeeded with a Pending WooCommerce order means a webhook problem. Incomplete means 3D Secure didn't finish. Customers will tell you "payment failed" in every one of these cases, and each needs a different fix, so pin it down before you touch anything.
| Symptom | Most likely cause | Where to look |
|---|---|---|
| Stripe shows "Declined" with a decline code | Card issuer or Stripe Radar refused it | Stripe Dashboard > Payments |
| Stripe shows "Succeeded", order stuck on Pending payment | Webhook not reaching WooCommerce | Stripe Dashboard > Developers > Webhooks |
| Stripe shows "Incomplete" or "Requires action" | 3D Secure didn't load or finish | Browser console, Stripe logs |
| "Amount must convert to at least..." error | Total below Stripe's minimum for the currency | Stripe logs, currency settings |
| Card fields missing or the spinner never stops | JavaScript conflict, caching or an optimisation plugin | Browser console, staging copy |
| Worked last week, broke after an update | Plugin regression | Stripe plugin changelog and GitHub issues |
WooCommerce keeps its own record under WooCommerce > Status > Logs. The Stripe plugin only writes there if logging is switched on in its settings, so turn it on before you test.
Why are Stripe payments declined on my WooCommerce store?
If Stripe shows a decline, your checkout did its job and the customer's bank refused. Stripe's card declines guide says issuers label most declines as generic. So the real reason is often hidden, and only the cardholder can get it out of their bank.
There's still some of it you can control:
- Collect CVC and postcode. Stripe recommends both to cut fraud-related declines. Don't hide the postcode field to "simplify" checkout. It costs you more than it saves.
- Check your Stripe Radar rules. A custom rule that blocks by country or risk score can quietly reject good orders. Open a blocked payment in Stripe and it'll show which rule fired.
- Expect more declines on foreign cards. Stripe notes that cards issued outside your Stripe account's country see more declines. If you're a UK store selling worldwide, that's normal. It isn't a bug.
- Don't let customers hammer the button. Issuers can read repeated attempts as fraud, so limit retries.
Before you change any settings, look up the specific code in Stripe's decline codes list.
Why do WooCommerce orders stay pending after the customer paid?
Because Stripe's webhook isn't getting through to your site. This is the expensive one. The money lands in Stripe, WooCommerce never hears about it, and the order sits on Pending payment until WooCommerce may auto-cancel it as unpaid. The customer has paid and gets no confirmation. You get no order email.
Stripe sends payment events to your site, usually at https://yoursite.com/?wc-api=wc_stripe (WooCommerce's Stripe webhook docs). When that breaks, it's typically a missing endpoint, a test-mode signing secret on a live store, or a firewall blocking Stripe's requests. The response code in Stripe's webhook log narrows it down (Stripe's webhook docs explain how deliveries and retries work). A 403 points at a security plugin or firewall. A 500 points at a PHP error on your site.
On an ordering site it hurts twice. On a setup like Whitfield's, the kitchen receipt prints automatically through PrintNode. An order that never moves past Pending can mean food that's paid for and never made.
- 1
Find the endpoint
In Stripe, go to Developers > Webhooks and confirm an endpoint exists for your live domain, not a staging site or an old domain.
- 2
Read the response codes
Open recent events. A 200 is fine, a 403 means something is blocking Stripe, and a 500 means your site threw an error.
- 3
Match the secret to the mode
Paste the live signing secret into the Stripe settings in WooCommerce. Test and live mode have different secrets.
- 4
Let Stripe through
Allow the webhook URL in Wordfence, Cloudflare WAF or your host's firewall, and keep bot challenges off that path.
- 5
Resend and confirm
Resend a failed event from Stripe and check that the order moves to Processing.
Why does 3D Secure fail or never appear on WooCommerce?
In the UK and EU, Strong Customer Authentication rules mean many card payments need a second check from the bank, usually 3D Secure (Stripe's SCA guide covers the PSD2 and FCA background). The WooCommerce Stripe extension supports 3D Secure out of the box. When it breaks, the customer sees "This transaction requires authentication" and no bank pop-up.
You'll find plenty of threads on the WordPress.org forums about 3D Secure that works in test mode but not live. The usual causes are:
- An optimisation plugin delaying or combining JavaScript. Stripe's script then loads late or not at all. Exclude Stripe's scripts and the checkout page from JS delay, defer and minify.
- Two Stripe-based gateways active at the same time. WooCommerce support has flagged WooPayments and the Stripe plugin running together as a conflict. Pick one.
- A Content-Security-Policy header that doesn't allow Stripe's domains. I maintain a WordPress security headers plugin, and an over-strict CSP really will break payments. Run your checkout URL through my Security Headers Checker to see what you're sending, and read my guide to adding HTTP security headers to WordPress before you change anything.
- A theme or checkout plugin that re-renders the payment form and wipes out the Stripe card field in the process.
Can currency settings break Stripe checkout on WooCommerce?
Yes, and it's easy to miss because the store looks fine in your own currency. On Wow Vastra I added a currency switcher for worldwide checkout, and that's exactly the kind of setup where these bugs hide (I cover the setup in how to sell in multiple currencies on WooCommerce). What I check:
- The switcher passes the right currency to Stripe. Some multi-currency plugins show converted prices but still charge in the base currency, or round amounts oddly. Place a real test order in every currency you offer.
- Minimum amounts. Stripe's minimum charge is $0.50 US or the equivalent in the charge currency, which is £0.30 for GBP. A tiny order, or a coupon that leaves a few pence, fails with an "Amount must convert to at least" error.
- Zero totals. If you run 100% coupons or free trials, test those checkouts too.
- Payment methods beyond cards are offered based on the customer's location. A method one customer sees may simply not show for another.
Can caching break WooCommerce checkout?
Yes. A cached checkout can hand one visitor's session, nonce or cart to the next person. That shows up as "session expired" errors, wrong totals, or a Stripe form that won't submit. WooCommerce's docs say to exclude Cart, My Account and Checkout from caching, along with cart and session cookies such as woocommerce_cart_hash and wp_woocommerce_session_.
Most caching plugins handle this by default. The trouble tends to come from a second layer you forgot about: host-level caching, a Cloudflare "cache everything" rule, or settings someone added while chasing a speed score. I spend a lot of my time on Core Web Vitals, and my view is simple. Checkout is the one page you don't page-cache. Make it faster with lighter scripts instead.
Don't debug on the live checkout
Switching plugins off one by one on a live store breaks checkout for real customers. Clone the site to staging, put Stripe in test mode there and reproduce the failure first.
How do I find a plugin conflict or a Stripe plugin regression?
If payments worked and then stopped, ask what changed. A plugin update, a theme update, a PHP upgrade, a new caching rule. Check the Stripe plugin's GitHub issues first, then switch things off in batches on staging until payments work again.
The Stripe gateway does ship bugs now and then, and its public issue tracker is where they tend to show up first, often with a workaround from other merchants or the maintainers.
The order I work in, always on a staging copy:
- Check the Stripe plugin version against its GitHub issues and changelog.
- Turn off optimisation and caching plugins, then test.
- Switch to a default theme such as Storefront, then test.
- Turn off the remaining plugins in batches until the failure stops.
- If it's the gateway, roll back to the last good version or apply the documented workaround, then hold updates until a fix ships.
If the WooCommerce log gives you an error or a PHP stack trace, paste it into my free Error Message Explainer. It tells you in plain English what went wrong and the likely fix, which can save a round of back-and-forth before you open a support ticket.
How long does it take to fix a failing Stripe checkout?
Configuration problems like a wrong webhook secret, a firewall block or a cached checkout are usually quick once you've found them. Finding them is where the time goes, because you have to reproduce the failure first. Plugin conflicts take longer since you're testing combinations. A gateway regression depends on whether a workaround exists: you either apply it, or roll back and wait for a release.
Every hour in between costs orders, so limit the damage while it's being fixed:
- Switch on a backup gateway such as PayPal, so customers still have a way to pay.
- Reconcile pending orders. Compare Stripe's succeeded payments with WooCommerce orders on Pending payment, so nobody who paid gets cancelled or forgotten.
What should you ask a developer before they touch your checkout?
Mostly two things: how they'll protect live orders, and how they'll prove the fix works. These are the questions I'd want answered if it were my store:
- Will you work on a staging copy, not my live store?
- How will you confirm webhook delivery, not just a successful test payment?
- Will you test 3D Secure cards, every currency I sell in, coupons and zero totals?
- Which caching and optimisation exclusions will you set, and where?
- If it's a plugin bug, will you hold the version and tell me when it's safe to update?
- Who notices if webhooks start failing again next month?
The right answer to that last one is ongoing monitoring, usually as part of a maintenance retainer.
Need your Stripe checkout fixed fast?
If WooCommerce orders are failing right now, send me the symptoms, your Stripe plugin version and any log errors. I'll go through the Stripe webhook log, the checkout and your recent updates, find what's breaking payments and fix it on staging before it goes live. For bigger work, like a new ordering flow or a multi-currency store, have a look at my WooCommerce stores and online ordering service.



