Razorpay Standard Checkout — live demo

Click Pay, complete the Razorpay test flow, and watch the three-step integration run end-to-end: create-order → Checkout.js modal → verify-payment signature check.

Ready. Click Pay to start.

How to test (test mode only)

Don't scan the QR with a real UPI app.Test-mode orders aren't registered on the live UPI network, so GPay / PhonePe / Paytm will say "invalid UPI id." Use the test credentials below inside the Razorpay modal instead.

Card tab

Razorpay test accounts have International Payments disabled by default. The old 4111 1111 1111 1111 number gets classified as international and rejected with "International cards are not supported." Use the domestic test cards below instead.

Card number   5267 3181 8797 5449   (Mastercard, domestic INR)
              4386 2894 0766 0153   (Visa, domestic INR)
Expiry        any future date (e.g. 12/30)
CVV           any 3 digits (e.g. 123)
Name          any
OTP           1111 (shown in the modal — NOT a real SMS)

If you get a real SMS OTP on your phone during test mode, that's a coincidental Razorpay account notification, not this payment — nothing is actually charged.

UPI tab

Typeone of these into the UPI ID field (don't scan):

success@razorpay   → payment.captured
failure@razorpay   → payment.failed

Nothing is actually charged. See Razorpay test card docs and test UPI IDs.

What happens when you click Pay

  1. Frontend calls POST /api/create-order with { amount: 100, currency: "INR", receipt: "..." }. Backend calls Razorpay API, returns { order_id, amount, currency }.
  2. Frontend opens Razorpay Checkout.js modal with the order_id + your NEXT_PUBLIC_RAZORPAY_KEY_ID.
  3. You complete the test payment. Razorpay calls the Checkout.js handler with razorpay_order_id, razorpay_payment_id, and razorpay_signature.
  4. Frontend forwards those three to POST /api/verify-payment. Backend recomputes HMAC-SHA256(order_id|payment_id, KEY_SECRET) and constant-time compares. Returns { ok: true, verified: true } or 400.
  5. In parallel, Razorpay fires the async webhook at /api/webhook (authoritative source for billing state — frontend verification is a UX gate, the webhook flips the DB).