The Correct Razorpay Payment Flow (Explained Simply)

Published: (March 8, 2026 at 09:28 PM EDT)
3 min read
Source: Dev.to

Source: Dev.to

Many payment integration issues occur because developers misunderstand how the Razorpay payment lifecycle actually works. Following the correct flow ensures secure transactions, proper verification, and fewer bugs in production.

Below is the recommended Razorpay payment flow explained step‑by‑step.

1. User Clicks “Pay”

The payment process begins on the frontend when the user clicks the Pay button.

At this moment, the frontend should not attempt to process the payment directly. Instead, it should trigger an API request to your backend to create a payment order.

2. Backend Creates an Order

Your backend communicates with the Razorpay API to create an order. This step defines the payment amount and generates an order ID, which will later be used by the checkout.

const order = await razorpay.orders.create({
  amount: 10000, // Amount in paise (₹100)
  currency: "INR",
  receipt: "order_rcptid_11"
});

The response includes important details such as:

  • order.id
  • order.amount
  • order.currency

This order ID is essential because Razorpay uses it to track the transaction.

3. Frontend Opens Razorpay Checkout

Once the backend returns the order details, the frontend initializes the Razorpay checkout using the order ID.

var options = {
  key: "RAZORPAY_KEY_ID",
  amount: order.amount,
  order_id: order.id
};

This opens the Razorpay payment interface where the user can complete the transaction using UPI, cards, net banking, or wallets.

4. User Completes the Payment

After the payment is successfully completed, Razorpay returns the following values to the frontend:

razorpay_payment_id
razorpay_order_id
razorpay_signature

These values represent the payment details generated by Razorpay. However, this does not mean the payment should be trusted yet.

5. Backend Verifies the Signature (Critical Step)

The frontend must send the returned payment data to your backend.

Your backend then verifies the authenticity of the payment by generating a signature using your Razorpay secret key.

const crypto = require('crypto');
const generatedSignature = crypto
  .createHmac('sha256', secret)
  .update(`${razorpay_order_id}|${razorpay_payment_id}`)
  .digest('hex');

The backend compares the generated signature with the razorpay_signature returned by Razorpay.

  • If the signatures match, the payment is valid.
  • If they do not match, the payment must be rejected.

This verification step protects your system from payment tampering or fraud.

6. Store the Payment in the Database

Only after successful verification should the payment be stored in your database.

Typical fields to store include:

  • payment_id
  • order_id
  • amount
  • status
  • user_id
  • timestamp

Storing verified payment records ensures accurate accounting and helps with refunds or dispute resolution later.

7. Fulfill the Order

Once the payment is verified and stored, you can safely proceed with order fulfillment. Examples include:

  • Granting access to a digital product
  • Activating a subscription
  • Confirming an order
  • Sending a receipt or confirmation email

At this stage, the transaction can be considered complete.

Final Thoughts

A reliable Razorpay integration depends on following the correct lifecycle:

  • User initiates payment
  • Backend creates an order
  • Frontend launches checkout
  • User completes payment
  • Backend verifies the signature
  • Store the verified payment
  • Fulfill the order

If this flow is implemented correctly—especially the signature verification step—most Razorpay payment bugs and security issues can be avoided.

0 views
Back to Blog

Related posts

Read more »