Introduction
This guide provides a comprehensive walkthrough for integrating Razorpay payment gateway into your Node.js backend application. Razorpay is a popular payment solution that enables businesses to accept online payments securely and efficiently.
Quick Setup
Prerequisites
- Node.js (v14+ recommended)
- npm or Yarn
- Razorpay Account
Installation
npm install razorpay
# or
yarn add razorpay
Configuration
- Obtain your API keys from the Razorpay Dashboard
- Set up environment variables:
RAZORPAY_KEY_ID=your_key_id
RAZORPAY_KEY_SECRET=your_key_secret
Deep Dive: Integration Workflow
1. Initializing Razorpay Client
const Razorpay = require('razorpay');
const razorpay = new Razorpay({
key_id: process.env.RAZORPAY_KEY_ID,
key_secret: process.env.RAZORPAY_KEY_SECRET
});
2. Order Creation Process
Understanding Razorpay Orders
In Razorpay, an Order is a crucial component of the payment lifecycle. It serves several important purposes:
- Unique Identification: Each order gets a unique
order_id - Amount Protection: Prevents tampering with transaction amounts
- Payment Tracking: Consolidates multiple payment attempts
- Fraud Prevention: Provides an additional layer of transaction security
Orders go through different states:
created: Initial order stateattempted: First payment attempt madepaid: Successful payment completed
Order Creation Requirements
Mandatory Parameters
- Amount
- Required: Always specify the payment amount
- Format: Smallest currency unit (paisa for INR, cents for USD)
- Examples:
- ₹100 = 10000 (in paisa)
- $50 = 5000 (in cents)
- Validation: Must be a positive integer
- Currency
- Required: Specify the transaction currency
- Supported Currencies:
- INR (Indian Rupees)
- USD (US Dollars)
- EUR (Euros)
- Other supported Razorpay currencies
- Format: 3-letter ISO currency code
Order Creation Example
const orderOptions = {
amount: 10000, // Required: 100 INR in paisa
currency: 'INR', // Required: Currency type
receipt: 'order_rcptid_' + Date.now(), // Recommended: Unique internal reference
payment_capture: 1 // Optional: Auto-capture payment
};
const order = await razorpay.orders.create(orderOptions);
Additional Recommended Parameters
- Receipt
- Unique identifier for your internal tracking
- Helps in reconciliation
- Typically uses timestamp or unique order number
- Notes
- Optional metadata
- Can include additional order details
- Maximum 15 key-value pairs allowed
Validation Checks
- Ensure amount is a valid number
- Verify currency support
- Generate unique receipt identifier
- Protect against duplicate orders
Common Mistakes to Avoid
- Incorrect amount conversion
- Using unsupported currencies
- Omitting required parameters
- Generating non-unique receipts
3. Passing Order ID to Frontend Razorpay Checkout
Purpose of Sending Order ID
When creating a Razorpay order, the backend generates a unique order_id that serves critical functions:
- Transaction Uniqueness: Provides a distinct identifier for each payment attempt
- Amount Protection: Prevents client-side manipulation of payment amounts
- Payment Tracking: Allows Razorpay to link frontend payment attempts to the original order
Backend Response
res.json({
success: true,
order_id: order.id,
amount: order.amount,
});
What Frontend Will Do with This Data
- Use
orderIdto initiate Razorpay checkout - Validate transaction amount
- Complete payment process
4. Webhook Implementation
Why Webhooks are Crucial
Webhooks are essential for real-time payment status updates. They provide several key benefits:
- Instant notification of payment events
- Reliable tracking of transaction statuses
- Reduced need for manual payment reconciliation
Webhook Event Types
Razorpay supports multiple webhook events:
payment.captured: Successful paymentpayment.failed: Payment unsuccessfulrefund.processed: Refund completeddispute.created: Payment dispute initiated
Webhook Handler Implementation
const crypto = require('crypto');
function handleWebhook(req, res) {
const secret = process.env.RAZORPAY_WEBHOOK_SECRET;
const signature = req.headers['x-razorpay-signature'];
// Verify webhook signature
const expectedSignature = crypto
.createHmac('sha256', secret)
.update(req.rawBody)
.digest('hex');
// Signature validation
if (signature !== expectedSignature) {
return res.status(400).send('Invalid signature');
}
const event = req.body;
// Handle different payment events
switch (event.event) {
case 'payment.captured':
// Update order status to paid
updateOrderStatus(event.payload.payment.entity, 'PAID');
break;
case 'payment.failed':
// Handle failed payment
updateOrderStatus(event.payload.payment.entity, 'FAILED');
break;
case 'refund.processed':
// Process refund
handleRefund(event.payload.payment.entity);
break;
}
res.status(200).send('Webhook processed');
}
// Update order status in database
async function updateOrderStatus(paymentDetails, status) {
try {
const order = await Order.findOne({
razorpayOrderId: paymentDetails.order_id
});
if (order) {
order.status = status;
order.paymentDetails = paymentDetails;
await order.save();
}
} catch (error) {
console.error('Error updating order status', error);
}
}
Best Practices
Amount Handling
- Always convert amounts to the smallest currency unit
- Examples:
- ₹299.00 →
29900 - $50.25 →
5025
- ₹299.00 →
Security Considerations
- Use environment variables for sensitive information
- Implement webhook signature verification
- Use HTTPS for all transactions
- Store API keys securely
Error Handling
async function processPayment(order) {
try {
// Payment processing logic
} catch (error) {
// Categorize and handle different types of errors
if (error.code === 'BAD_REQUEST_ERROR') {
// Handle specific Razorpay errors
} else {
// Generic error handling
logger.error('Payment processing failed', error);
}
}
}
Testing Strategies
Test Mode
- Use Razorpay test credentials
- Simulate various payment scenarios
- Test different payment methods
Test Card & UPI ID Details
Razorpay offers dedicated test payment details to validate different scenarios.
Test Card Details
- Use Razorpay test card numbers to simulate payments.
- Test transactions with different card networks (Visa, MasterCard, etc.).
- Validate success, failure, and insufficient funds scenarios.
Refer to Test Card Details for more information.
Test UPI ID Details
- Utilize test UPI IDs to simulate domestic (Indian) UPI payments.
- Test both successful and failed transactions for one-time payments.
Refer to Test UPI ID Details for UPI-specific test cases.
Transitioning to Live Mode
Pre-Live Preparation Checklist
- Complete comprehensive testing of all payment flows
- Verify all integration points
- Obtain live Razorpay account credentials
- Replace test API keys with live credentials
- Secure production environment
Deployment Checklist
- Replace test API keys with live keys
- Verify webhook endpoints
- Implement comprehensive logging
- Set up monitoring for payment flows
Additional Resources
Troubleshooting
- Check API key permissions
- Verify webhook configurations
- Monitor error logs
- Use Razorpay dashboard for transaction insights
Conclusion
Integrating Razorpay with your Node.js backend is straightforward when following these guidelines. Always prioritize security, handle edge cases, and provide a smooth payment experience for your users.