When WooCommerce PayPal payments stop working, it's almost always one of five things. The PayPal Payments plugin is in sandbox mode or has stale credentials, PayPal's webhooks can't reach your site, the order currency isn't supported for your account, the PayPal Smart Button script is being blocked by caching, minification or a Content Security Policy (CSP), or a checkout plugin is clashing with PayPal's scripts. Turn on PayPal Payments logging, open the browser console on your checkout page, and the error will usually point you at one of these pretty quickly.
Some failures, like INSTRUMENT_DECLINED, are the buyer's bank saying no. Those aren't your store's fault at all.
Here's the order I check things in when a store is losing PayPal sales and nobody can say why.
How do I find out why WooCommerce PayPal payments are not working?
Get the logs and the console open before you touch a single setting. If you start toggling things at random, the real error gets buried under the new ones you've just created.
- 1
Turn on logging
In the WooCommerce PayPal Payments settings, enable Logging. Every PayPal API request is then logged with a Debug ID.
- 2
Read the latest log
Go to WooCommerce > Status > Logs and open the newest woocommerce-paypal-payments file. Copy the error codes and Debug IDs.
- 3
Open the browser console
On the checkout page, press F12. Red Content Security Policy errors in Console, or failed js?client-id= or ppc-create-order requests in Network, show where it breaks.
- 4
Check failed order notes
WooCommerce records PayPal's reason on the order. Make sure it's really the error you think it is.
- 5
Test as a guest
Repeat the checkout in a private window while logged out. Page caching usually only affects visitors, not admins.
The Network tab tip comes from the plugin's own advanced troubleshooting guide. Grab your Debug IDs now if there's any chance you'll need PayPal support, because they expire after roughly 48 hours.
Once you've got an error message, match it to a likely cause here:
| Symptom or error | Most likely cause | First thing to try |
|---|---|---|
| No PayPal button at all | Script blocked by CSP, minification or page cache | Check the console, exclude PayPal scripts, purge cache |
| Popup opens, then closes | Checkout plugin refreshing the page, JavaScript conflict | Test with the checkout plugin switched off |
| "The payee does not have a PayPal account" | Invalid credentials or unverified PayPal account | Disconnect and reconnect via onboarding |
| "Something went wrong. Please try again…" | API rejection, plugin conflict or blocked REST endpoint | Read the log for the real PayPal error |
CANNOT_MIX_CURRENCIES or UNPROCESSABLE_ENTITY | Multi-currency plugin or unsupported currency | Check the order currency against PayPal's list |
DUPLICATE_INVOICE_ID | Restored backup or two sites sharing an invoice prefix | Give each site a unique invoice prefix |
| Paid at PayPal, order stuck on pending | Webhooks not arriving | Resubscribe webhooks, check firewall rules |
INSTRUMENT_DECLINED or PAYMENT_DENIED | Buyer's bank, card or PayPal account | Not a store fault; ask the buyer to use another method |
Most of that table comes from the plugin's common errors page. The rest is what I cover below.
Is PayPal connected in sandbox or live mode?
Check this first. It takes ten seconds, and a store left in sandbox mode takes no real money. The Connection tab of WooCommerce PayPal Payments has a Sandbox checkbox that switches the plugin between live and sandbox accounts. If someone tested the store and forgot to switch it back, buyers get an error or a test login page.
"The payee does not have a PayPal account" usually means, according to the WooCommerce PayPal team, that the API credentials are invalid or the merchant account isn't verified. Reconnecting through the onboarding wizard often sorts it. If it doesn't, only PayPal Merchant Support can confirm the account's verification status. And if you're not sure the credentials and webhooks are in sync, the plugin's support team suggests disconnecting and onboarding again from scratch with "Start over".
Staging sites cause their own trouble. Run a staging copy on the same PayPal account, or restore an older backup, and PayPal can reject orders with DUPLICATE_INVOICE_ID because it's seeing an invoice number it already knows. Don't turn off PayPal's duplicate protection. Give every site on your PayPal account a unique invoice prefix instead.
Are PayPal webhooks reaching my site?
If orders sit on pending after buyers have paid, the webhooks probably aren't getting through. WooCommerce PayPal Payments uses webhooks rather than the old IPN system, and for alternative payment methods the payment is only captured after a webhook confirmation arrives. No webhooks means money can leave the buyer's account while the order stays pending, and refunds you make in PayPal never show up in WooCommerce.
Click Resubscribe in the webhook section of the plugin settings. Don't trust the Simulate button to tell you it worked. A GitHub issue reports the Simulate button doing nothing since version 3.3.1, so don't rely on it: it may show a false failure, or a false success left over from an earlier run. A small real payment and refund with logging on is a much better test.
When webhooks keep failing, something is normally in the way:
- A firewall, Cloudflare WAF rule or security plugin blocking
/wp-json/requests. WooCommerce lists a blocked REST endpoint as a known cause. - Maintenance mode, password protection or HTTP basic auth on the live site.
- A domain or host change. Webhooks keep pointing at the old URL until you resubscribe.
If PayPal broke right after a host move or DNS change, rule that out before anything else. I do these moves as part of my hosting migration and maintenance work, and payment webhooks belong on any migration go-live checklist next to DNS and email.
Is my store currency supported by PayPal?
Not every currency works for every PayPal account, and an order in an unsupported or mixed currency gets rejected. PayPal's supported currencies reference says BRL, CNY and MYR only work for in-country accounts. HUF, JPY and TWD don't support decimals, so amounts in those have to be sent as whole numbers. WooCommerce's currency documentation also points out that PayPal supports merchants in some countries, India for example, without supporting the local currency. So if your Indian store prices in rupees, check that before anything else. For domestic Indian checkouts I'd usually make Razorpay the main gateway anyway.
Multi-currency plugins are the other usual suspect. PayPal rejects an order when the line items, shipping and total aren't all in the same currency. The error is CANNOT_MIX_CURRENCIES, and it tends to arrive wrapped in UNPROCESSABLE_ENTITY. WPML documented a case where PayPal Payments 2.9.1 failed every order placed in a non-default currency. I built Wow Vastra with a currency switcher and worldwide checkout, and on a store like that you need to test every gateway in every currency the switcher offers. No shortcuts.
Rounding causes smaller, sneakier failures. Tax or discount plugins can leave WooCommerce's total a penny off the sum of its line items. The plugin has a Subtotal Mismatch Behavior setting that sends PayPal an extra line to cover the difference.
Are caching, minification or a CSP blocking the PayPal buttons?
If the PayPal button has vanished completely, this is where I look first. WooCommerce's own docs say caching or JavaScript minification can break PayPal Payments. They recommend excluding at least /woocommerce-paypal-payments/modules/ppcp-button/assets/js/button.js from minification and purging the cache after every plugin update. If you use WP Rocket, its minify, combine and delay-JavaScript options are the first place PayPal exclusions should go. There are WordPress.org threads where WP Rocket stopped the button showing.
Full-page caching has a newer problem too. A GitHub issue reported in 4.2.0 says that with SDK v6, a cached page older than the WordPress nonce lifetime (12 to 24 hours) can fail its token request with "Could not validate nonce", and no buttons render. Until that's resolved, keep pages with PayPal buttons out of the page cache, or set the cache lifetime shorter than the nonce lifetime. The 4.2.0 changelog also fixed buttons disappearing after several page loads, so make sure you're on the current version.
Then there's CSP. A policy that doesn't list PayPal blocks its script outright. PayPal's button troubleshooting page shows the console error you'll get: "Refused to load the script https://www.paypal.com/sdk/js". Their suggested allow-list looks like this:
script-src 'unsafe-inline' https://*.paypal.com https://*.paypalobjects.com;
style-src 'unsafe-inline' https://*.paypal.com;
connect-src https://*.paypal.com;
frame-src https://*.paypal.com;
img-src https://*.paypal.com https://*.paypalobjects.com;
Be aware that 'unsafe-inline' in script-src weakens the policy, because it lets any inline script run. Where your site supports it, use nonces or hashes instead, and test in report-only mode before you enforce the policy.
Merge these into your existing policy rather than replacing it. I wrote and maintain HTTP Security Header, a WordPress.org plugin with 1,000+ active installs that adds CSP and other headers from a settings screen. That work has taught me a strict CSP written without payment providers in mind is one of the quickest ways to make checkout buttons disappear. Run your checkout URL through my free Security Headers Checker to see exactly what policy you're sending, and read my post on fixing a CSP that broke WordPress for how to test safely in report-only mode.
Don't just delete the CSP
Removing your security headers brings the PayPal button back, but it leaves the checkout exposed. Add the PayPal domains to the right directives instead, and test in report-only mode first.
Is a checkout plugin like Fluid Checkout clashing with PayPal?
It can be. Checkout plugins rebuild the page that PayPal's scripts expect to find. Fluid Checkout's changelog lists fixes for WooCommerce PayPal Payments, including switching to the classic checkout context so scripts work and removing a duplicate place-order button. Its developer has also described PayPal popups closing suddenly on mobile because the checkout refreshed parts of the page as the popup opened. The usual fix is to update both plugins and retest; you rarely need to remove either one.
To confirm a conflict without breaking checkout for real customers, use the Health Check & Troubleshooting plugin. WooCommerce's guide recommends it because it disables plugins only for you. Test with only WooCommerce and PayPal Payments active, then switch the others back on one at a time.
Custom checkout code can clash as well. If a required checkbox is validated on the woocommerce_checkout_process hook, the PayPal popup opens even when the box is empty, because that hook runs only after the PayPal order is created. Move the check to woocommerce_after_checkout_validation and it behaves. I built the optimised checkout for the Nortek LED store, and hook order is one of the details worth checking on any custom checkout.
Which PayPal errors are not my store's fault?
INSTRUMENT_DECLINED and PAYMENT_DENIED come from the buyer's bank or from PayPal, and no WooCommerce setting will change them. INSTRUMENT_DECLINED means the buyer's card, bank or credit line was refused, and the plugin sends the buyer back to pick another funding source. PAYMENT_DENIED is usually about the buyer's PayPal account or PayPal's risk review, and PayPal won't tell you why. A low background rate of both is normal. I'd only escalate if declines spike without a change in traffic, cluster on one method such as Pay Later, or if PayPal shows a payment as approved while WooCommerce marks the order failed.
What should I ask a developer to check?
Ask them to go through mode and verification, webhooks, currency, caching, CSP and plugin conflicts, in that order. Specifically:
- live or sandbox mode, and that the merchant account is verified
- webhook delivery, tested with a real payment and refund
- the store currency against PayPal's list, in every currency your switcher offers
- cache, minify and delay-JS exclusions for PayPal scripts
- your CSP on the cart, checkout and product pages
- conflicts, tested on staging or in Health Check mode, never on live customers
If Stripe is failing too, the cause is probably shared, and it's usually caching or CSP. My Stripe checkout fix guide covers that side.
Need your PayPal checkout fixed today?
If PayPal is failing right now, send me your store URL, the latest PayPal Payments log and a screenshot of the console error through my contact page. I'll look at the cause and tell you what it will take to fix. If you'd rather it didn't happen again, my WooCommerce store work and maintenance retainers cover updates, so plugin updates are tested before they reach your live checkout.



