Skip to main content

Test Razorpay Payments — Orders API, Paise and HMAC

Test Razorpay
in paise — not rupees

Razorpay's Orders API works in paise — India's smallest currency unit. ₹1 = 100 paise, ₹500 = 50000 paise, integer only. This mock handles the full order → redirect → signature verification flow without any Razorpay account or dashboard access.

Paise amounts

integer only, no decimals

HMAC sig

mandatory verification

0 credentials

to get started

Razorpay is the dominant payment gateway in India. The integration uses an Orders API: you create an order on your server, open the Razorpay checkout in the browser, and after the customer pays, verify the payment signature before fulfilling. All amounts are in paise — the smallest Indian currency unit. ₹1 = 100 paise. If you send 500 instead of 50000, the customer gets charged ₹5 instead of ₹500.

Signature verification is mandatory and often skipped in tutorials. After payment, Razorpay sends razorpay_order_id, razorpay_payment_id, and razorpay_signature to your frontend. Your server must compute HMAC-SHA256(order_id + '|' + payment_id, key_secret) and compare it against the signature. Skip this check and anyone can send a fake payment callback to your server.

Razorpay supports cards, UPI, netbanking, wallets, and EMI — all from the same checkout. UPI accounts for over 70% of digital transactions in India and is instant 24/7. The payment.captured webhook fires after the payment is finalized — that's the right place to fulfill orders, not the frontend callback. This mock delivers the full Orders API flow with signature verification and webhook events.

How do paise amounts work in Razorpay?

₹1 = 100 paise
₹500 = 50000
Integer only. No decimals.

Razorpay — like Stripe, Checkout.com, and most modern gateways — works in the smallest indivisible currency unit. For INR, that is paise. Floating point numbers are unreliable for money: 0.1 + 0.2 !== 0.3 in most languages. Integers never have this problem.

Watch out

If you send 500 instead of 50000, the customer pays ₹5 not ₹500. Razorpay applies no conversion — the number you send is interpreted directly as paise.

Rupees to paise conversion
Rupees (₹)Send as (paise)
₹1100
₹101,000
₹10010,000
₹50050,000
₹99999,900
₹1,4991,49,900

Conversion is always: rupee_amount × 100. No rounding needed — paise is already the smallest unit.

How do you verify a Razorpay payment signature?

After the customer pays, Razorpay sends three values back to your callback. You must verify them with HMAC-SHA256 before fulfilling the order.

HMAC-SHA256(
razorpay_order_id + "|" + razorpay_payment_id,
key_secret
)

The resulting hex string must match razorpay_signature exactly. If it does not, reject the callback with a 400.

Without this check, an attacker who knows your order_id can send a fake payment_id to your callback and get their order fulfilled without paying. This has happened to real apps.

razorpay_order_id

The order ID you created in step 1. Starts with order_

razorpay_payment_id

The unique ID for this payment attempt. Starts with pay_

razorpay_signature

HMAC hex string. Verify this against your own calculation. Must match exactly.

Which Razorpay payment methods use the same webhook shape?

Razorpay's checkout supports all major Indian payment methods through a single integration. Every method fires the same payment.captured webhook format.

💳

Cards

Visa, Mastercard, Rupay

📱

UPI

GPay, PhonePe, BHIM

🏦

Netbanking

50+ banks supported

👛

Wallets

Paytm, MobiKwik, Freecharge

📦

EMI

Bank and No-cost EMI

💵

Pay Later

Simpl, LazyPay, HDFC PayLater

Unified response: Whether the customer pays with a Visa card, UPI, or a wallet, your webhook handler receives the same payment.captured event shape with method indicating which rail was used. You do not need separate handlers per method.

Integration code

curl -X POST https://mockgateway.com/api/base/razorpay/v1/orders \
  -H "Authorization: Bearer YOUR_MOCK_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{
    "amount": 50000,
    "currency": "INR",
    "receipt": "receipt#ORD-0042",
    "notes": {
      "order_id": "ORD-0042",
      "customer": "Priya Sharma"
    }
  }'

// amount = 50000 paise = ₹500.00
// INR is the only supported currency in this mock

Request parameters

Sent to POST /api/base/razorpay/v1/orders

Request parameters
ParameterTypeRequiredDescription
amountintegerrequired

Amount in smallest currency unit (paise for INR)

e.g. 50000
currencystringrequired

ISO 4217 currency (e.g. INR)

e.g. INR
descriptionstringoptional

Payment description

order_idstringoptional

Your order reference

e.g. ORD-12345

Response fields

Response fields
FieldTypeDescription
idstringRazorpay payment ID
statusenumPayment status
order_idstringRazorpay order ID
created_atinteger
payment_link_idstringRazorpay payment link identifier

Questions about Razorpay

Other gateway templates

Looking for a different provider?