How to Accept Razorpay Payments from Your Website

Full integration walkthrough — Standard Checkout, server-side order creation, signature verification, all the gotchas.

Razorpay Standard Checkout takes a day to integrate correctly. Here's the path that avoids the 5 most common bugs.

The 4 components

  1. Frontend — Razorpay's checkout.js opens the modal
  2. Backend (1) — server creates an Order with key_secret (NEVER on frontend)
  3. Backend (2) — server verifies the payment signature after success
  4. Webhook — Razorpay calls your endpoint to confirm capture

Step 1: Get keys

Razorpay dashboard → Settings → API Keys → generate test keys. Save key_id (safe for frontend) and key_secret (server-only).

Step 2: Create order (server-side)

// POST /api/create-order
const Razorpay = require('razorpay');
const rzp = new Razorpay({ key_id, key_secret });

const order = await rzp.orders.create({ amount: 50000, // in paise — ₹500 currency: 'INR', receipt: 'rcpt_' + Date.now(), }); res.json({ orderId: order.id }); ```

Step 3: Open checkout (frontend)

<script src="https://checkout.razorpay.com/v1/checkout.js"></script>
<script>
async function pay() {
  const { orderId } = await (await fetch('/api/create-order', { method:'POST' })).json();
  const rzp = new Razorpay({
    key: 'rzp_test_xxx',
    amount: 50000,
    currency: 'INR',
    order_id: orderId,
    handler: async (response) => {
      const verify = await fetch('/api/verify', {
        method: 'POST',
        body: JSON.stringify(response),
        headers: { 'Content-Type': 'application/json' }
      });
      const { ok } = await verify.json();
      if (ok) alert('Payment confirmed!');
    }
  });
  rzp.open();
}
</script>

Step 4: Verify signature (server-side)

const crypto = require('crypto');
const expected = crypto
  .createHmac('sha256', key_secret)
  .update(razorpay_order_id + '|' + razorpay_payment_id)
  .digest('hex');
if (expected !== razorpay_signature) return res.status(400).json({ ok: false });
res.json({ ok: true });

Common pitfalls

  1. Sending amount in rupees, not paise — Razorpay expects paise
  2. Forgetting to verify signature → security disaster
  3. Test mode card numbers — use 4111 1111 1111 1111, OTP 123456
  4. International cards on default account — needs separate approval

Hire a payment integration expert →

Need this built for you?

Hire a vetted Nexora expert. Escrow-protected. Fixed price. From $65.

Browse automation services →