Skip to content
Products
AI Website Builder New VPS Hosting Cloud Servers Web Hosting Dedicated Servers Domains
Company
About Documentation Support Center Contact Get Started Call +91 75795 45488
Login
Hosting Panel — cPanel & Billing Console Panel — VPS Management
ALL SYSTEMS OPERATIONAL
Troubleshooting

WooCommerce Order Stuck on Pending After Razorpay Payment

Getwebup 6 min read

Money leaves the customer's account, Razorpay shows the payment as "Captured," and yet WooCommerce still says the order is "Pending payment." No invoice email goes out, stock doesn't get deducted, and your customer is now emailing you asking where their order confirmation is. This isn't a payment problem — it's almost always a webhook that never made it to your server.

What's actually happening

WooCommerce doesn't know a payment succeeded just because the customer typed in a card or UPI PIN. After Razorpay processes the charge on its own servers, it sends a background HTTP POST — the webhook — to a specific URL on your site (something like /wc-api/wc_razorpay/ or /?wc-api=WC_Gateway_Razorpay depending on the plugin version). Your site is supposed to receive that POST, verify its signature, and flip the order status to "Processing" or "Completed."

If that single request gets blocked, redirected, or times out anywhere between Razorpay and your PHP process, WooCommerce never hears back. The charge is real and settled on Razorpay's side, but your store is stuck showing "Pending" forever — until someone manually marks the order paid.

Step 1: Check Razorpay's webhook logs first

Before touching your server, confirm the webhook actually fired and see what response it got:

  • Log in to the Razorpay DashboardAccount & SettingsWebhooks.
  • Click your site's webhook endpoint and open Recent Deliveries.
  • Look at the HTTP status code returned for the failed event.

That status code tells you almost everything you need to know:

Response seen in Razorpay logsMost likely cause
403 ForbiddenModSecurity, Wordfence, or a firewall rule is blocking the POST request
301 / 302 redirectURL trailing slash mismatch, or a forced HTTP→HTTPS redirect that drops the signature header
Connection timed outCSF/firewall dropping packets from Razorpay's IP range, or server under heavy load
SSL handshake failedOutdated cURL/OpenSSL on the server, or an expired/misconfigured SSL certificate
200 OK but order still PendingWebhook secret mismatch — signature verification failing silently inside the plugin

Cause 1: Your firewall or WAF is blocking the webhook

Symptom: Razorpay's dashboard shows 403 or "connection refused" on every delivery attempt.

Cause: ModSecurity (common on cPanel/WHM servers) and security plugins like Wordfence often treat an unauthenticated POST request hitting /wp-json/ or a custom wc-api endpoint as suspicious, especially if the payload looks like raw JSON with no cookies or nonce attached.

Fix:

  1. In WHM, go to Security → ModSecurity Tools and search the audit log for the timestamp of a failed delivery. Note the rule ID that triggered.
  2. Whitelist that specific rule ID for your domain only — don't disable ModSecurity globally:
SecRuleRemoveById 981173
  1. If you're on CSF, whitelist Razorpay's published webhook source IPs in ConfigServer Security & Firewall → Quick Allow. Razorpay documents its current IP list on their integrations page — don't guess, pull it fresh, since it does change.
  2. If Wordfence is installed, add the webhook path under Wordfence → Firewall → Rate Limiting → Whitelisted URLs, or exclude it from "Immediately block IPs that access these URLs."

Cause 2: A redirect is stripping the signature header

Symptom: Razorpay logs show a 301 or 302 instead of a 200.

Cause: If your webhook URL is registered as http://yoursite.com/wc-api/wc_razorpay but your site force-redirects everything to https://, or WordPress's canonical redirect adds/removes a trailing slash, the original POST body and headers can get lost in the redirect — most HTTP clients don't resend a POST body after a 301.

Fix: Update the webhook URL in the Razorpay dashboard to match your live URL exactly, including the protocol:

https://yourdomain.com/?wc-api=WC_Gateway_Razorpay

Test it directly with curl to confirm there's no redirect hop before you save it:

curl -I "https://yourdomain.com/?wc-api=WC_Gateway_Razorpay"

You want a single response, not a chain of 301s.

Cause 3: Webhook secret mismatch

Symptom: Razorpay shows 200 OK for every delivery, but the order still sits on Pending.

Cause: The Razorpay WooCommerce plugin verifies every webhook against a secret key you set in two places: the Razorpay dashboard and your plugin settings (WooCommerce → Settings → Payments → Razorpay). If these two values don't match — often because the site was cloned from staging, or the secret was regenerated on one side only — the plugin accepts the request, silently fails signature verification, and does nothing.

Fix: Regenerate the webhook secret in the Razorpay dashboard, then immediately paste the exact same value into the plugin's Webhook Secret field. Save both, then trigger a test event from the Razorpay dashboard's webhook page and confirm the order updates.

Cause 4: Outdated PHP/OpenSSL on the server

Symptom: Razorpay logs show SSL or TLS handshake errors, or your server's error log has entries like cURL error 60: SSL certificate problem.

Cause: Razorpay's API requires a reasonably current TLS stack. Servers still running PHP 7.2 or an old CA bundle sometimes fail to complete the handshake for outbound verification calls the plugin makes back to Razorpay to confirm the payment.

Fix: In cPanel, go to Software → MultiPHP Manager and confirm the domain is on PHP 8.1 or newer. If you're on a VPS managing PHP yourself, update the CA certificate bundle:

sudo apt update && sudo apt install ca-certificates --reinstall

Manually fixing orders already stuck

Once the webhook path is fixed, existing stuck orders won't auto-correct themselves — they already missed their one notification. For each affected order:

  • Confirm the payment actually captured in the Razorpay dashboard (search by order ID or amount).
  • In WooCommerce, open the order and manually change the status to Processing or Completed.
  • Add an order note referencing the Razorpay payment ID so support has a paper trail if the customer disputes it later.

For a handful of orders this is fine to do by hand. If you're finding dozens stuck at once, fix the webhook first — don't keep manually clearing new ones while the underlying block is still active.

Prevention checklist

  • Re-check your webhook URL and secret any time you migrate, clone, or move the site to a new server.
  • Keep a standing ModSecurity/CSF whitelist entry for your payment gateway's webhook path and IP range.
  • Set up an uptime or webhook-monitoring check that pings the webhook endpoint periodically so a silent block gets caught before customers notice.
  • Avoid stacking two security plugins that both filter incoming requests (e.g., Wordfence and a separate WAF) — they tend to duplicate and conflict on edge-case rules like this.

Prevention: if you're moving to Getwebup

If you're migrating a WooCommerce store to us, tell your onboarding engineer you're on Razorpay (or any gateway with webhooks) before cutover — we'll whitelist the webhook path in ModSecurity ahead of time so you don't lose a single order in the switch.

Frequently asked questions

Why does Razorpay show the payment as captured but WooCommerce still says Pending?

Razorpay processes the charge on its own servers and then sends a separate webhook notification to your site to confirm it. If that webhook is blocked, redirected, or fails signature verification, WooCommerce never finds out the payment succeeded, even though the money has already settled on Razorpay's side.

Is it safe to disable ModSecurity to fix this?

No. Disabling ModSecurity entirely removes protection for your whole site. Instead, find the specific rule ID blocking the webhook in the ModSecurity audit log (WHM → ModSecurity Tools) and whitelist just that rule for your domain.

How do I find Razorpay's current webhook IP addresses to whitelist?

Razorpay publishes its current server IP ranges on its official integration/developer documentation. Pull the list from there rather than an old blog post or forum answer, since it can change without notice.

Can I just manually mark stuck orders as paid instead of fixing the webhook?

You can for a handful of orders, but it's a workaround, not a fix. Every new order will keep getting stuck until the webhook actually reaches your server, so fix the underlying block (firewall rule, redirect, or secret mismatch) first.

Does this same issue happen with other payment gateways like Stripe or PayU?

Yes. Any gateway that relies on server-to-server webhooks (Stripe, PayU, Cashfree, Instamojo) can hit the identical failure modes: firewall blocks, redirect loops stripping headers, or a secret key mismatch after a migration.

#woocommerce #razorpay #webhook #payment-gateway #wordpress #cpanel

Keep reading

Chat with Support