This project implements Razorpay payment gateway integration for token purchases in the CodeNearby API platform.
- ✅ Order creation via Razorpay API
- ✅ Payment verification with signature validation
- ✅ Webhook handling for payment status updates
- ✅ Database transaction logging
- ✅ React component for seamless payment flow
- ✅ Support for both USD and INR currencies
- ✅ Token balance updates post-payment
POST /api/v1/billing/buy-tokens
Request Body:
{
"packageId": "basic|standard|pro|enterprise",
"currency": "USD|INR"
}Response:
{
"success": true,
"orderId": "order_razorpay_id",
"amount": 99900,
"currency": "INR",
"key": "rzp_test_key",
"userEmail": "user@example.com",
"userName": "User Name",
"package": { ... },
"message": "Order created successfully"
}POST /api/v1/billing/verify-payment
Request Body:
{
"razorpay_order_id": "order_xxx",
"razorpay_payment_id": "pay_xxx",
"razorpay_signature": "signature_xxx"
}Response:
{
"success": true,
"paymentId": "pay_xxx",
"orderId": "order_xxx",
"tokensAdded": 1500,
"newBalance": 2000,
"newTier": "premium",
"message": "Payment verified and tokens added successfully!"
}POST /api/v1/billing/webhook
Handles Razorpay webhooks for:
payment.capturedpayment.failed- Other payment events
# Razorpay Test Credentials
RZP_PROD_KEY_ID=rzp_test_xxx
RZP_PROD_KEY_SECRET=xxx
# Optional: Webhook Secret
RZP_WEBHOOK_SECRET=webhook_secretimport RazorpayPayment from "@/components/razorpay-payment";
<RazorpayPayment
packageId="basic"
currency="INR"
amount={999}
packageName="Basic Package"
tokens={1000}
bonus={500}
onSuccess={() => {
toast.success("Payment successful!");
router.push("/dashboard");
}}
onError={(error) => {
toast.error(`Payment failed: ${error}`);
}}
/>Stores order information during payment process:
{
"orderId": "order_xxx",
"userId": "user_id",
"packageId": "basic",
"amount": 99900,
"currency": "INR",
"status": "created|completed",
"createdAt": "2025-01-15T...",
"expiresAt": "2025-01-15T..." // 15 minutes from creation
}Completed transaction records:
{
"userId": "user_id",
"orderId": "order_xxx",
"paymentId": "pay_xxx",
"packageId": "basic",
"amount": 99900,
"currency": "INR",
"tokensAdded": 1500,
"status": "completed",
"createdAt": "2025-01-15T..."
}Webhook event logs for debugging:
{
"event": "payment.captured",
"paymentId": "pay_xxx",
"orderId": "order_xxx",
"amount": 99900,
"currency": "INR",
"status": "captured",
"createdAt": "2025-01-15T..."
}- User clicks "Purchase" button
- Frontend calls
/api/v1/billing/buy-tokens - Backend creates Razorpay order and stores in
pending_orders - Frontend opens Razorpay checkout with order details
- User completes payment on Razorpay interface
- Razorpay returns payment details to frontend
- Frontend calls
/api/v1/billing/verify-payment - Backend verifies signature and payment status
- Backend updates user tokens and tier if successful
- Backend logs transaction and updates order status
- User redirected to dashboard with success message
- Signature Verification: All payments verified using HMAC-SHA256
- Order Expiration: Orders expire after 15 minutes
- Duplicate Prevention: Orders can only be processed once
- Webhook Validation: Webhook signatures verified before processing
- User Authorization: All endpoints require valid session
Use Razorpay test credentials:
- Test Card: 4111 1111 1111 1111
- Expiry: Any future date
- CVV: Any 3 digits
- OTP: 123456
The integration handles various error scenarios:
- Invalid package IDs
- Expired orders
- Failed signature verification
- Network timeouts
- Invalid payment status
All errors are logged and appropriate messages returned to frontend.
- Replace test credentials with live Razorpay keys
- Set up webhook URL in Razorpay dashboard
- Configure webhook secret for production
- Test with real payments in staging environment
- Monitor transaction logs and webhook events