REST API & Integrations

Integrating Razorpay with WordPress and WooCommerce

Plan a Razorpay WordPress integration with order mapping, verified webhooks, refund handling and a test checklist for WooCommerce or custom forms.

Razorpay and WordPress — original abstract editorial illustration
In this article

A payment window saying “successful” is not the end of a WordPress payment integration. Your website still has to connect that payment to the right order, decide whether it is ready to fulfil, and show your team what happened if a notification arrives late.

That is the useful starting point for a Razorpay project: draw the route from an order to a verified payment and then to delivery. Only then choose the plugin or custom code that will maintain it.

This guide covers one-off payments. Recurring billing, marketplace transfers and partial-payment schedules need their own requirements. The examples below are proposed designs, not client results or a claim that a live store has been tested.

Choose the integration that fits the purchase

For an existing WooCommerce store, start by assessing Razorpay's maintained WooCommerce plugin against your actual WordPress, WooCommerce, PHP and checkout setup. A working gateway includes more than a pay button: your team needs a consistent order record and an understandable refund workflow. Razorpay documents the plugin's prerequisites and installation process. Plugin prerequisites, integration steps.

Without WooCommerce, compare the supported WordPress plugin or hosted payment option with a custom Checkout integration. A simple payment collection page may not need a new order-management system. A booking with availability, cancellation rules and a reference number probably needs more coordination. Check the supported workflow before promising that a plugin covers it. WordPress integration options.

If you are still choosing the provider, read the existing WooCommerce payment-gateway comparison. This article starts at the next decision: how your selected Razorpay integration should behave.

Keep the local order and payment records connected

For custom Checkout, create the Razorpay order on your server and pass its identifier to the browser. Calculate the price from trusted product or booking data; do not accept a price simply because the browser submitted it. Store the relationship to your local order before opening Checkout. Razorpay's integration guide requires server-side order creation and verification of the returned payment signature. Standard Checkout integration.

Here is a hypothetical mapping for a single ₹2,500 booking. These labels are illustrative, not valid API identifiers:

Record — Example value — Purpose

Local booking reference — BOOK-1042 — The reference the business uses for the booking

Expected amount — 250000 paise, INR — The server-approved amount for this example

Razorpay order reference — Stored API response ID — Connects Checkout to the local booking

Payment reference — Stored verified payment ID — Identifies a payment attempt

Fulfilment status — Awaiting verified payment — Prevents an unconfirmed booking from being delivered

Keep a separate place for payment attempts. If the first attempt fails and the customer tries again, support staff should be able to find both without creating two bookings. Decide what a retry does before implementation: reopen an eligible existing order, create a new payment attempt, or require staff review when the outcome is uncertain.

The public Key ID and a server secret serve different purposes. Keep API secrets and webhook secrets on the server, out of frontend bundles and ordinary enquiry messages.

Verify the return, then confirm the payment state

For a custom return handler, reconstruct the payment signature using the Razorpay order ID already stored on your server, the returned payment ID, and the API secret. The order value returned by the browser must not replace your trusted mapping. A valid signature establishes authenticity; your application still needs to match the payment to its expected order, amount and currency. Checkout verification.

Authorization and capture are different states. Agree on the capture policy and the condition that allows fulfilment. Do not translate every successful browser callback into “ship the order.” Razorpay documents capture settings, timeouts and cases where an authorized payment can remain uncaptured. Payment capture settings.

A useful customer message while reconciliation is pending is: “We are checking your payment. Keep this booking reference; please do not pay again yet.” Use that only when your application can actually reconcile the reference and provide a follow-up route. A reassuring message without an operational check merely hides the problem.

Give webhooks their own verification path

The browser can close before your return handler completes. A webhook gives your server another way to learn about the payment. It is a separate request with a different signature calculation: use the webhook secret and the exact raw request body, checking the X-Razorpay-Signature header. Do not parse and re-encode the body before checking it. Webhook validation.

In PHP, the core comparison can use hash_hmac('sha256', $rawBody, $webhookSecret) followed by hash_equals($expectedSignature, $receivedSignature). The trusted value goes first. This describes the verification step, not a complete WordPress endpoint: input validation, event handling, logging and order updates still need implementation. PHP's timing-safe comparison.

Razorpay may deliver an event again or out of order. Record its x-razorpay-event-id and make processing safe to repeat. Also protect the business action itself: two different valid events referring to one payment must not send two fulfilment requests. Webhook event handling.

For a custom implementation, a reasonable design is to durably record a validated event, acknowledge receipt, and let a worker apply the mapped state transition. The worker should refuse to downgrade a captured payment because an older authorization arrives later. Use a database transaction or an equivalent concurrency control where a payment changes fulfilment eligibility. This is an implementation recommendation, not a statement that a particular plugin uses this exact design.

Razorpay documents retries for unsuccessful webhook delivery and eventual webhook disabling after persistent failure. Monitor that condition and provide a reconciliation process; retries are not a substitute for operational ownership. Webhook delivery guidance.

Diagnose a paid-but-pending WooCommerce order

Start with identifiers and timestamps, not an immediate manual status change. Record the WooCommerce order, Razorpay order and payment references, the observed payment state, and the plugin version. Then check:

1. Does the payment belong to the expected account, environment and order?

2. Is it captured, merely authorized, failed, or still uncertain?

3. Does the installed plugin's documented webhook configuration point to this store?

4. Did the notification reach WordPress, or receive a firewall, login, redirect or application error?

5. Did the plugin process it, and do the order notes or relevant logs explain a delay?

Razorpay's current WooCommerce FAQ describes automatic configuration for payment.authorized and refund.created. Follow the instructions for the installed plugin instead of replacing its event setup with a custom integration's event list. Do not disable the site's firewall as a blanket fix; inspect the specific rejected request. WooCommerce troubleshooting.

For the broader architecture behind retries and observability, see WordPress webhooks and third-party API integration.

Reconcile refunds separately from settlements

A refund request, a recorded refund and money reaching the customer are different checkpoints. Decide who may request a refund, which system is the starting point, and how the other system learns about it. Full and partial refunds need explicit tests; partial refunds are not the same feature as allowing a customer to pay an order in instalments.

Razorpay supports refund operations through its dashboard and APIs. Its WooCommerce plugin source also contains order-refund handling. Confirm the installed version's supported path and inspect both systems after the test, especially when a refund starts outside WooCommerce. Refund documentation, official plugin source.

Settlement concerns the transfer to the merchant's bank account. A captured customer payment does not imply the merchant has already received that transfer. Use the account's actual settlement schedule and reports to reconcile amounts, deductions and refunds. Do not hard-code a universal arrival date or infer fees from an old tutorial. Settlement documentation.

Test the cases your support team will meet

Use a staging environment with test-mode configuration, clearly separated from production. A local simulation can exercise your own state machine, but it cannot prove that the provider reaches your webhook or that the installed gateway works. A controlled integration test needs the appropriate account and a reachable permitted endpoint. Webhook testing.

Prepare an acceptance sheet with an expected result and an observed result for each case:

Test — Expected business outcome

Successful payment for the expected order — One verified payment, one eligible fulfilment action

Customer cancels or closes Checkout — Order remains understandable and a safe retry is available

Payment completes but browser never returns — Server notification or reconciliation resolves the order

Same event delivered twice — Second delivery creates no duplicate business action

Older event arrives after a newer one — Final payment state is not incorrectly downgraded

Signature or amount does not match — No paid status or fulfilment is granted

Temporary webhook outage — Delivery/reconciliation can recover without losing the order

Full and partial refund — Intended amount and references agree across systems

Rehearse the customer's mobile journey as well as the admin view. If you need to test a live payment after staging, obtain the owner's explicit approval for the amount and refund handling. A successful test-mode run does not itself authorize a real charge.

Discuss your payment workflow

For an existing store, start with WooCommerce development. For a custom form or backend connection, see WordPress API integrations. Send the site URL, versions, purchase flow and a redacted description of the problem through the integration enquiry page. Keep API secrets and customer payment information out of that first message.

Frequently asked questions

Can I add Razorpay without WooCommerce?

Yes. Assess Razorpay's supported WordPress option, a hosted collection flow or a custom Checkout integration. Choose based on whether you need a catalog, inventory, bookings or only payment collection. A custom form still needs a reliable payment-to-record mapping.

Why did the customer pay while the order stayed pending?

The browser return, provider state and local order update may disagree. Inspect the mapped identifiers, capture state, webhook delivery and plugin logs. Do not assume a missing callback is the only cause or ask the customer to pay again before reconciling the first attempt.

How do I verify a Razorpay webhook signature in PHP?

Calculate the HMAC-SHA256 of the raw body with the webhook secret and compare it with the signature header using hash_equals, or use the official SDK verification helper. This is separate from the Checkout return-signature calculation.

Can I refund from the WordPress dashboard?

The supported WooCommerce plugin provides a refund path, but confirm it against your installed version and permissions. For a custom form, a refund interface is a separate feature. Always verify the resulting refund reference and status rather than relying only on the local button's success message.

Does adding Razorpay automatically enable every payment method?

No assumption of universal availability should be made. Confirm the methods enabled for the merchant account, supported checkout and relevant business market. Subscriptions and other specialized flows also need their own integration review.

Topics

  • Razorpay WordPress integration
  • Razorpay WooCommerce
  • Razorpay webhook WordPress
Share

Sources and further reading