@minotaurg/medusa-payment-razorpay
v1.0.0
Published
Razorpay payment provider for Medusa v2 — UPI, cards, net banking, wallets for Indian e-commerce
Maintainers
Readme
medusa-payment-razorpay
Razorpay payment provider for Medusa v2 — accept UPI, debit/credit cards, net banking, and wallets for Indian e-commerce stores.
Features
- UPI (Google Pay, PhonePe, Paytm)
- Debit & Credit Cards (Visa, Mastercard, RuPay)
- Net Banking (50+ banks)
- Wallets (Paytm, PhonePe, Amazon Pay)
- HMAC-SHA256 signature verification on authorize + webhooks
- Auto-capture for UPI payments
- Refund support
- Webhook handler for async payment events
Installation
npm install medusa-payment-razorpay razorpayConfiguration
Add to your medusa-config.ts:
module.exports = defineConfig({
// ...
modules: [
{
resolve: "@medusajs/payment",
options: {
providers: [
{
resolve: "medusa-payment-razorpay",
id: "razorpay",
options: {
key_id: process.env.RAZORPAY_KEY_ID,
key_secret: process.env.RAZORPAY_KEY_SECRET,
webhook_secret: process.env.RAZORPAY_WEBHOOK_SECRET,
},
},
],
},
},
],
})Environment Variables
RAZORPAY_KEY_ID=rzp_test_xxxxx # From Razorpay Dashboard → Settings → API Keys
RAZORPAY_KEY_SECRET=xxxxx # Secret key (never expose publicly)
RAZORPAY_WEBHOOK_SECRET=xxxxx # From Dashboard → Webhooks → SecretStorefront Integration
After the customer selects Razorpay at checkout:
- Call
initiatePaymentSession— creates a Razorpay order - Open Razorpay Checkout.js modal with the
order_idfrom session data - On success, push
razorpay_payment_id+razorpay_signatureback to the session - Call
cart.complete()— the provider verifies the HMAC signature
// Frontend: open Razorpay modal
const options = {
key: process.env.NEXT_PUBLIC_RAZORPAY_KEY_ID,
order_id: session.data.razorpay_order_id,
handler: async (response) => {
// Send payment_id + signature to backend to update session
await updatePaymentSession(session.id, {
razorpay_payment_id: response.razorpay_payment_id,
razorpay_signature: response.razorpay_signature,
})
// Then complete the cart
await completeCart(cartId)
},
}
const rzp = new Razorpay(options)
rzp.open()Webhook Setup
In your Razorpay Dashboard → Webhooks:
- URL:
https://your-domain.com/hooks/payment/razorpay_razorpay - Events:
payment.captured,payment.failed - Secret: Set the same value as
RAZORPAY_WEBHOOK_SECRET
How It Works
| Method | Action |
|--------|--------|
| initiatePayment | Creates Razorpay order, returns order_id |
| authorizePayment | Verifies HMAC-SHA256 signature |
| capturePayment | Captures authorized payment (auto for UPI) |
| refundPayment | Initiates refund via Razorpay API |
| cancelPayment | No-op (Razorpay orders auto-expire) |
| getWebhookActionAndData | Handles async events from Razorpay webhooks |
Notes
- All amounts are in paise (₹1 = 100 paise) — same as Razorpay's API
- In development mode, missing keys are allowed (skips validation)
- In production, all three env vars are required
License
MIT
