A payment integration is one of those features where 80% is easy and the last 20% — failures, retries, reconciliation — is what separates a demo from production. This is the path we follow to get Razorpay live, safely, in a few days.
1. Why create the order server-side?
Never trust the amount from the browser. The server creates a Razorpay order via the Orders API with the authoritative amount and currency, stores it against your own internal order record, and returns only the order ID to the client. The checkout widget then opens against that order.
2. How do you verify the Razorpay payment signature?
When checkout succeeds, the client sends back a payment ID, order ID, and signature. The server recomputes the HMAC-SHA256 signature with your key secret and compares it. If it doesn't match, the payment is not trusted — full stop. Only after verification do you mark the order paid. In pseudocode: expected = HMAC_SHA256(order_id + "|" + payment_id, key_secret); if expected != received_signature: reject().
3. Why treat webhooks as the source of truth?
Browsers close, networks drop. The reliable signal is the webhook: subscribe to payment.captured and payment.failed, verify the webhook signature (a separate secret from your API key), and update order state from there. Make the handler idempotent — check whether you've already processed that event ID before acting — so a webhook arriving twice (which Razorpay's own docs note can happen) doesn't double-process a refund or double-fulfil an order.
4. Handle the unhappy paths
Plan for pending payments, failed captures, and partial refunds from day one. Store the gateway's payment status alongside your own, and build a small reconciliation view so support can see exactly what happened to any transaction — this is usually the single most requested feature after the first month in production, once real customers start hitting real edge cases.
5. Keep compliance in mind
Let the gateway handle card data — never store full card details yourself. Use HTTPS everywhere, keep keys in secrets management, and log enough to audit without capturing sensitive fields, consistent with the PCI DSS scope-reduction principle: if you never touch card data, most of PCI DSS doesn't apply to your servers at all.
Need payments live quickly and correctly? We integrate Razorpay, Stripe, and PayU as a fixed-scope engagement.
See it in production: this exact flow runs in our Psychiatric Counselling & Scheduling Platform, On-Demand Ride & Driver Booking Platform, AI Résumé Optimizer, and Appointment Scheduling Portal.