Integrating Razorpay looks easy — until payments start failing in production.
Many developers successfully open the checkout page but still run into issues like:
- ❌ Payments not verifying
- ❌ Incorrect amounts being charged
- ❌ Successful payments not recorded
- ❌ Order status not updating
After fixing multiple Razorpay integrations, I noticed something interesting:
Most payment failures happen because of a few small mistakes.
In this guide, you'll learn the 5 most common Razorpay integration mistakes — and how to avoid them.
📚 Table of Contents
- Razorpay Payment Flow
- Mistake #1: Creating Orders on the Frontend
- Mistake #2: Using the Wrong Amount Format
- Mistake #3: Skipping Payment Verification
- Mistake #4: Not Implementing Webhooks
- Mistake #5: Using Test Keys in Production
- Final Thoughts
Razorpay Payment Flow (Overview)
Before looking at the mistakes, it's important to understand the correct payment flow.
User clicks Pay
↓
Frontend sends request to Backend
↓
Backend creates order using Razorpay API
↓
Order ID returned to Frontend
↓
Frontend opens Razorpay Checkout
↓
User completes payment
↓
Frontend sends payment details to Backend
↓
Backend verifies payment signature
↓
Payment confirmed
Key Principles
✔ Orders should be created on the backend
✔ Checkout runs on the frontend
✔ Payment verification must happen on the backend
This separation ensures security and reliability.
❌ Mistake #1: Creating Orders on the Frontend
A very common mistake is trying to create Razorpay orders directly from the frontend.
❌ Wrong Approach
// frontend
fetch("https://api.razorpay.com/v1/orders")
This exposes your secret API key, which is extremely dangerous.
Anyone could inspect your code and misuse it.
✅ Correct Approach
Orders should always be created on the backend.
const Razorpay = require("razorpay");
const razorpay = new Razorpay({
key_id: process.env.RAZORPAY_KEY_ID,
key_secret: process.env.RAZORPAY_KEY_SECRET
});
const order = await razorpay.orders.create({
amount: 50000,
currency: "INR",
receipt: "receipt_123"
});
Secure Order Creation Flow
User clicks Pay
↓
Frontend requests backend to create order
↓
Backend calls Razorpay API
↓
Razorpay returns Order ID
↓
Backend sends Order ID to frontend
↓
Checkout opens
❌ Mistake #2: Using the Wrong Amount Format
Razorpay expects the amount in paise, not rupees.
This small detail causes many integrations to fail.
❌ Incorrect Example
amount: 500
✅ Correct Example
amount: 500 * 100
If the customer needs to pay ₹500, Razorpay expects:
50000
Amount Conversion Flow
Customer payment: 500 INR
↓
Convert to paise
↓
500 × 100
↓
Send 50000 to Razorpay
💡 Rule to remember
Amount sent to Razorpay = Rupees × 100
❌ Mistake #3: Skipping Payment Verification
Many developers assume that if Razorpay checkout shows:
Payment Successful
then the payment is complete.
That is not enough proof.
You must verify the payment signature on your backend.
Payment Verification Flow
User completes payment
↓
Razorpay sends payment response to frontend
↓
Frontend sends payment_id, order_id, signature to backend
↓
Backend verifies signature using Razorpay secret key
↓
Backend confirms payment
Without verification, attackers could fake payment responses.
❌ Mistake #4: Not Implementing Webhooks
Some developers rely only on the frontend response.
This works during testing, but in production payments can be:
- delayed
- retried
- refunded
- partially captured
Webhooks notify your backend when these events happen.
Webhook Event Flow
Payment event occurs on Razorpay
↓
Razorpay sends webhook request
↓
Your backend webhook endpoint receives event
↓
Backend updates database
↓
Order status updated
Common webhook events include:
payment.captured
payment.failed
refund.processed
Without webhooks, your backend won't know the real payment state.
❌ Mistake #5: Using Test Keys in Production
This mistake happens more often than you think.
During development, Razorpay provides test API keys.
If those keys are deployed to production, real payments will fail.
Environment Variables
RAZORPAY_KEY_ID=
RAZORPAY_KEY_SECRET=
Deployment Flow
Development
↓
Use Razorpay Test Keys
↓
Testing completed
↓
Switch to Live Keys
↓
Deploy to Production
Always double-check this before deployment.
Final Thoughts
Payment integrations rarely fail because of complex code.
They fail because of small details developers overlook, such as:
- creating orders on the wrong layer
- sending incorrect amounts
- skipping payment verification
- ignoring webhooks
- deploying with test keys
Fixing these five mistakes will make your Razorpay integration:
✔ Secure
✔ Reliable
✔ Production-ready
💬 Discussion
Have you faced issues integrating Razorpay in production?
What was the hardest part of the payment integration?
Share your experience in the comments 👇
Top comments (0)