WooCommerce · Razorpay · Checkout

WooCommerce Razorpay payments failing: how to fix it

WooCommerce Razorpay payments failing? Check the webhook, Payment Action, caching and cron, and recover paid orders wrongly marked Failed.

Mohit Goyal 10 min read
WooCommerce Razorpay payments failing: how to fix it

Most WooCommerce orders that say a Razorpay payment failed aren't failed payments. The customer usually paid, Razorpay has the money, and WooCommerce just never recorded it. The cause is normally the Razorpay webhook, the Payment Action setting, a cached checkout page or a WP-Cron job that never ran. Look the payment up in your Razorpay Dashboard first, then work through the webhook, Payment Action, caching, WP-Cron and plugin conflicts, in that order.

This is general advice for store owners in India who are losing orders right now, based on Razorpay's own documentation and the open issues on the official plugin's GitHub repository. The Razorpay for WooCommerce plugin has 100,000+ active installs and was at version 4.8.8 at the time of writing. If your store takes UPI or cards through Razorpay, that's almost certainly the plugin you're running.

Are Razorpay payments actually failing on WooCommerce, or only the order status?

Usually it's only the WooCommerce order status that's wrong. The payment itself went through. To tell which, compare the payment's status in the Razorpay Dashboard with the WooCommerce order.

Start in the Razorpay Dashboard under Transactions, then Payments. A successful payment shows as captured there, according to Razorpay's integration guide. Search by the customer's email or phone and compare what you find with the WooCommerce order:

What you seeRazorpay DashboardWooCommerce orderLikely cause
Customer paid, order unpaidCapturedPending paymentThe callback and the webhook both missed it: webhook setup, firewall or cron
Customer paid, order failedAuthorizedFailedPayment Action set to Authorize (see below)
Money held, never settledAuthorizedProcessingAuthorize mode and nobody captured the payment
A real failureFailedFailed or PendingBank decline, UPI timeout or the customer cancelled
Nothing reached RazorpayNo payment IDPending paymentCheckout never opened: API keys, a JavaScript conflict or caching

Only the fourth row is a real payment failure, and there's usually nothing your site can do about it. The rest are sync problems between Razorpay and WooCommerce. Those you can fix.

How does Razorpay tell WooCommerce an order is paid?

Razorpay for WooCommerce marks an order paid in two ways: the browser callback when the customer returns to your store, and the payment.authorized webhook, which WP-Cron processes after a five-minute wait. If both fail, a paid order stays unpaid.

The callback is the easy path. The customer lands back on your site after paying, the plugin checks the signature and the order is marked paid. But people close tabs. They pay in a UPI app and never switch back. Some see an error even though the payment went through (issue #631). In all of those cases the payment.authorized webhook is the only thing left that can update the order.

And the webhook doesn't act the moment it arrives. Since version 3.9.4 the plugin waits five minutes before processing it, to avoid duplicate orders, and since version 4.7.2 a cron job does that processing (changelog). Razorpay's troubleshooting FAQ mentions the wait too. So a paid order depends on three things: the callback or the webhook arriving, the webhook passing its signature check, and the cron actually running.

Rendering diagram…

How do I check the Razorpay webhook URL and secret?

Open Account and Settings, then Webhooks, in the Razorpay Dashboard. The URL has to match your live WooCommerce domain exactly, with payment.authorized and refund.created enabled. If anything looks off, re-saving your API keys in WooCommerce re-registers the webhook against the current domain.

Since version 3.5.0 the plugin creates the webhook for you when you save your Key ID and Key Secret, subscribed to those two events (Razorpay FAQ). That's handy, but it still breaks after domain changes, host migrations and copied staging sites. Go through these:

  1. Confirm the keys. In WooCommerce, then Settings, then Payments, then Razorpay, check that the live site uses live keys and staging uses test keys. Razorpay's troubleshooting FAQ links "Authentication failed" and "API key provided is invalid" errors to keys that don't match the Dashboard.
  2. Save the settings again. This re-registers the webhook against the current domain.
  3. Check the URL in the Dashboard. Compare it character by character: https, and with or without www exactly as your site uses it.
  4. Remove stale webhooks. Delete any that still point at an old domain, an old host or a staging copy.
  5. Set an alert email. Razorpay sends webhook failure and deactivation notices to the address you set. Use one somebody actually reads.

If the webhook log shows Invalid signature, Razorpay's documented fix is blunt, but it works. Delete the Razorpay for WooCommerce plugin completely (deactivating isn't enough), delete the matching webhook in the Razorpay Dashboard, then install the latest version and save your keys so a fresh secret gets generated.

One trap catches a lot of stores: the same Razorpay account on two sites. Issue #213 describes webhooks returning server errors because each site gets notifications for orders it doesn't have. Keep staging on test mode. Always.

Should Payment Action be Authorize or Authorize and Capture?

Set Payment Action to Authorize and Capture. It's what Razorpay recommends, and it captures payments automatically. Only use Authorize if you check every order and capture it yourself from the Razorpay Dashboard, because Razorpay's integration guide warns that uncaptured payments are refunded automatically.

In version 4.8.8, the latest at the time of writing, Authorize mode also has a bug. Issue #670 shows that with Payment Action on Authorize, an order paid through the webhook route is marked Failed even though Razorpay has authorized the payment. The same payment coming back through the browser callback is marked Processing. And the webhook route is the one used by customers who paid in a UPI app and never came back, so these orders look exactly like lost sales.

Paid orders can turn into refunds

If an authorized Razorpay payment sits on a Failed WooCommerce order and nobody captures it, Razorpay refunds it when the capture window runs out. The customer paid and gets a refund instead of the goods. Check your capture settings in the Dashboard today.

The same report points to a related problem (issue #664). If Razorpay's API times out or returns an error while the cron is processing a webhook, the order stays Pending and later cron runs don't retry it. Until that's fixed, I'd switch to Authorize and Capture unless you have a real reason not to. If you have to stay on Authorize, check every Failed Razorpay order against the Dashboard every day.

Could caching or a firewall be breaking the checkout?

Yes. When no payment ID reaches Razorpay at all, or the webhook never arrives, page caching, JavaScript optimisation and firewalls are some of the first things I'd look at. Settings that are fine on blog pages can quietly break a WooCommerce payment flow. Check these:

  • Page cache. Exclude the cart, checkout, my-account, order-pay and order-received pages in every layer: your caching plugin, the server cache and Cloudflare. A cached checkout serves stale nonces, and Razorpay order creation then fails without any obvious error. My LiteSpeed Cache setup guide covers the exclusions.
  • JavaScript optimisation. Delaying, deferring or combining JavaScript can stop the Razorpay window from opening, or make it open late. Exclude the Razorpay checkout script and the plugin's own scripts.
  • Cloudflare cache rules. A "cache everything" rule overrides your plugin's exclusions unless you add bypass rules for the same paths.
  • Firewalls and bot protection. A security plugin, host firewall or Cloudflare bot setting can block Razorpay's server-to-server POST to your webhook URL. Allow the exact webhook URL shown in the plugin settings.

If the store is slow as well as dropping payments, fix both at once, and use speed fixes that never cache the checkout.

Why are Razorpay orders stuck on Pending payment?

Usually because WP-Cron isn't running, so the webhooks the plugin has queued never get processed. A misconfigured Cart or Checkout page in WooCommerce can also stop the payment from starting in the first place.

WP-Cron only fires when someone loads a page. On a quiet store, or on hosts that set DISABLE_WP_CRON without adding a real server cron, the webhook queue just sits there. Set a server cron to call wp-cron.php every few minutes, then use a plugin like WP Crontrol to confirm the Razorpay events run and aren't overdue.

If customers hit a 404 when they choose Razorpay, Razorpay's FAQ says to check the Cart and Checkout pages under WooCommerce, Settings, Advanced. The Pay endpoint should be order-pay and Order Received should be order-received.

Could a plugin, theme or PHP version be the cause?

Often. The plugin now needs PHP 7.4 or higher, and older versions threw fatal errors on newer PHP. So if the trouble started after a hosting change or a PHP upgrade, look at the PHP version and the error log before anything else. After that, the usual suspects are checkout field editors, side carts, one-page checkout plugins and heavily customised themes.

A standard conflict test is to deactivate everything except WooCommerce and Razorpay, then switch to a default theme. Do that on a staging copy. Never on a live store that's taking orders. The plugin's logs live under WooCommerce, then Status, then Logs. If a stack trace means nothing to you, paste it into my free Error Message Explainer and you'll get the likely cause and fix in plain English.

Two more things. The plugin only supports currencies with two decimal places, which matters if you run a currency switcher. And keep it updated: recent versions fixed security holes, including a security fix in 4.8.4.

How do I recover paid orders marked Failed?

Match every Failed and Pending WooCommerce order against the Razorpay Dashboard, capture the authorized payments you want to keep, and move those orders to Processing. Do this before you change any settings. Authorized payments get refunded once the capture window closes, and that clock is already running.

  1. Export the last 30 days of Failed and Pending Razorpay orders from WooCommerce.
  2. Match each one to its payment in the Razorpay Dashboard, using the Razorpay order ID in the order notes.
  3. Capture any authorized payment you want to keep.
  4. Change those orders to Processing, add a note with the payment ID, and send the customer a confirmation.
  5. If you can't fulfil an order, refund it yourself and tell the customer. Don't leave it to the automatic refund.

What should I ask a developer before they touch the checkout?

Ask how they'll test on staging, how they'll count the sales you've lost and how they'll stop it coming back after updates. A careless fix on a payment flow costs real money, so get answers to these first:

  • Will you reproduce the problem on staging with Razorpay test keys before changing live settings?
  • Will you reconcile Razorpay payments against WooCommerce orders, so we know how many sales we've lost?
  • Which cache, firewall and cron changes will you make, and how will you test a UPI payment where the customer closes the tab?
  • How will you stop it happening again after plugin updates?

The same questions work for other gateways. My Stripe checkout fix guide covers that side. If you're weighing a fix against a bigger rebuild, my guide to WooCommerce website cost in India covers what a Razorpay store typically involves.

If your store is losing Razorpay orders right now, I can reconcile your payments, fix the webhook, cron and caching setup, and test the whole checkout on staging. That's part of my WooCommerce stores service. If you'd rather someone checked payments after every update, a maintenance retainer covers that. Book a call and send me one order number that went wrong.

Frequently asked

Why does WooCommerce say an order failed when Razorpay says the payment is authorized?+

The likely cause is the Payment Action setting in Razorpay for WooCommerce. In plugin version 4.8.8, the latest at the time of writing, with Payment Action set to Authorize, orders updated through the webhook are marked Failed even though Razorpay has authorized the payment. Switch to Authorize and Capture, then capture any held payments in the Razorpay Dashboard before Razorpay refunds them automatically.

Why are my WooCommerce Razorpay orders stuck on Pending payment?+

The customer probably paid in Razorpay but never came back to the store, and the payment.authorized webhook didn't update the WooCommerce order. Check that the webhook is active in the Razorpay Dashboard, that your firewall lets Razorpay's requests through and that WP-Cron is actually running on your server.

How do I fix an Invalid signature error on the Razorpay webhook in WooCommerce?+

Razorpay's documented fix is to delete the Razorpay for WooCommerce plugin completely, delete the matching webhook in the Razorpay Dashboard, then install the latest plugin version and save your API keys again. Saving the keys recreates the webhook with a fresh secret.

Can I use my live Razorpay account on a WooCommerce staging site?+

No, use Razorpay test mode keys on staging. A GitHub issue on the official Razorpay for WooCommerce plugin describes webhooks returning server errors when one Razorpay account is used on two domains, because each site receives notifications for orders it doesn't have.

Can page caching break Razorpay payments on WooCommerce?+

Yes. A cached WooCommerce checkout can serve stale nonces or scripts, and delaying or combining JavaScript can stop the Razorpay payment window from opening. Exclude the cart, checkout, my-account, order-pay and order-received pages from every cache layer, including Cloudflare.

Should I update the Razorpay for WooCommerce plugin?+

Yes, but test the update on a staging site first. Recent releases fixed security vulnerabilities, including a security fix in version 4.8.4 listed in the plugin changelog, and Razorpay asks you to be on the latest version before you raise a support ticket.

Mohit Goyal

Written by Mohit Goyal

Senior Web Developer in Gurugram, India. 100+ fast, SEO-friendly sites shipped in 4+ years with Next.js, React and WordPress, including the procol.ai rebuild. Send me your next project.

Keep reading

Let's build

Have a site that needs to be fast, rank and convert?

Open to Work. Usually replies within a day.