Skip to content
Gaurav TiwariDocs

Set Up Razorpay Payments

Updated November 7, 2026

Indian buyers pay by UPI first and card second, and RBI rules don’t let you charge a saved card whenever a renewal comes due. Each renewal needs a mandate the customer approved, a notice before every debit and a cap on the amount. So most stores give up and email a pay link every cycle.

The Razorpay module takes UPI, cards, netbanking and wallets through Razorpay Checkout, and renews subscriptions automatically through card e-mandates, UPI Autopay and eNACH. Renewals start a few days early to cover Razorpay’s pre-debit notice, then settle through Razorpay’s signed webhook. Refunds work in both directions.

Turn On the Gateway

  1. Switch on the Razorpay module under Stackless → Dashboard.
  2. Go to WooCommerce → Settings → Payments → Razorpay (Stackless).
  3. Tick Enable (Accept payments with Razorpay).

Stackless → Settings → Razorpay only shows a link to that screen and your webhook URL. Razorpay stays off the checkout until the selected mode has a key id and secret.

Add Your API Keys

In the Razorpay Dashboard, open Account & Settings → API keys and generate keys once in Test mode and once in Live mode. The Open Razorpay API keys button on the settings screen goes straight there. Then fill in:

  • Test mode: on by default. Uses your test keys, so no real money moves.
  • Live key id, Live key secret and Live webhook secret
  • Test key id, Test key secret and Test webhook secret

When you save, Stackless checks each key pair with Razorpay and shows any error. A test key id must start with rzp_test_ and a live one with rzp_live_. With the gateway enabled, a missing key pair or webhook secret for the selected mode also shows an error.

You can also set these as wp-config.php constants, which win over saved settings and hide their fields: STACKLESS_RAZORPAY_LIVE_KEY_ID, STACKLESS_RAZORPAY_LIVE_KEY_SECRET, STACKLESS_RAZORPAY_LIVE_WEBHOOK_SECRET and the same three with TEST in place of LIVE.

Connect the Webhook

Razorpay has no API for adding webhooks to your own account, so you add it by hand, once in Test mode and once in Live mode. In Account & Settings → Webhooks, choose Add New Webhook and paste https://yoursite.com/wp-json/stackless/v1/razorpay/webhook. The settings screen shows your exact URL. Pick a secret, tick these events, and enter the same secret in the matching webhook secret field:

payment.authorized
payment.captured
payment.failed
order.paid
refund.processed
refund.failed
token.confirmed
token.rejected
token.cancelled
token.paused

The webhook confirms payments when a buyer closes the tab before coming back, settles every renewal debit, reports when a bank confirms or rejects a mandate, and brings refunds made in Razorpay into WooCommerce.

Each delivery’s X-Razorpay-Signature is checked against both secrets, and the one that matches decides whether it’s a test or live event. Each event is applied once, so Razorpay’s repeat deliveries change nothing.

What Buyers See

At checkout, Razorpay shows with the title “UPI, cards, netbanking and wallets” and the description “Pay securely with Razorpay.” It works on the classic and block checkout and on the order payment page.

  • Placing the order opens Razorpay Checkout on the order’s payment page, with the buyer’s name, email and phone filled in. If they close it, Pay now opens it again, next to Choose another payment method.
  • UPI shows as Intent or QR. UPI Collect, where the buyer types a UPI ID, is not offered.
  • After paying, Stackless checks Razorpay’s signature, reads the payment back from Razorpay and compares its amount and currency with the order. A payment that doesn’t match puts the order on hold with a note.
  • Checkout color sets the accent color of Razorpay Checkout.
  • Test mode adds “Test mode: no real payment will be taken.”

One-time orders can use any currency on Razorpay’s international payments list, as long as your Razorpay account has it switched on. Three-decimal currencies such as KWD and OMR are left out, and Razorpay hides itself for anything else. Orders in rupees must be ₹1 or more.

Turn On Recurring Payments

Automatic renewals use Razorpay recurring tokens. Razorpay switches the Recurring Payments feature on for an account on request, so ask Razorpay support before you sell subscriptions with it. Renewals and saved methods are in Indian rupees only.

The Subscriptions section of the gateway settings has three fields:

  • Renewal methods: Card, UPI Autopay and Bank account (eNACH), all on by default. These are the methods buyers can choose for subscriptions.
  • Plan-switch allowance (%): 0 to 500, default 50. The mandate covers the largest renewal plus this much, so upgrades keep renewing without a new mandate.
  • Start renewal charges early (days): 1 to 7, default 3.

A subscription checkout adds a Pay renewals with choice that lists only the methods whose ceiling covers the cart’s largest renewal. The buyer approves the mandate once in their bank or UPI app. If no method can cover the renewal, or the cart isn’t in rupees, Razorpay isn’t offered for that cart.

Mandate Maximum Amount

Every mandate has a maximum amount: the largest renewal on the order plus the plan-switch allowance, rounded up to whole rupees and held to the method’s ceiling. A ₹1,000 monthly plan with the default 50% allowance gets a ₹1,500 mandate.

MethodCeilingCharged at checkoutMandate lasts
Card₹15,000The order total, at least ₹1As long as the card
UPI Autopay₹99,999The order total, at least ₹110 years
Bank account (eNACH)₹1 crore₹0, the first payment follows separately10 years

₹15,000 is the RBI limit for card debits that don’t need the customer to approve each one. If Razorpay has approved your business for higher limits, raise the ceilings with a filter (see For Developers).

How Renewals Settle

Razorpay notifies the customer at least 24 hours before each debit, and the debit itself takes time: about a day for UPI, about 36 hours for cards and two working days for eNACH. So Stackless starts each renewal early, by the days in Start renewal charges early, and the webhook finishes it.

  1. On the early start date, Stackless creates the renewal order and asks Razorpay for a recurring debit on the saved mandate.
  2. Razorpay sends the customer its pre-debit notice. The order stays pending with a note that the debit was requested.
  3. When Razorpay captures the debit, the webhook marks the renewal paid. A failed debit marks it Failed with the reason, and your retry schedule takes over.
  • A debit is created once per attempt. If the same renewal runs again, Stackless reports the debit already in progress instead of asking for a second one.
  • If Razorpay can’t be reached, the debit is retried up to 3 more times, 15, 30 and 45 minutes apart.
  • A renewal above the mandate’s maximum, or on a mandate the customer paused or cancelled, fails without a debit. The customer gets the usual payment failed email with a link to pay.

Renewals, Failed Payments and Retries covers what happens after a failure.

Free Trials and eNACH First Payments

  • A checkout with nothing to pay today, such as a free trial, still sets up the mandate. Cards and UPI take a ₹1 authorization that’s refunded straight away, with an order note. eNACH authorizes ₹0.
  • An eNACH mandate takes the bank about two working days to confirm. When the order has something to pay, it goes on hold with a note, and the first payment is debited once the bank confirms. The payment page tells the buyer this before they approve.
  • If the bank rejects or cancels the eNACH mandate, that order is marked Failed and the saved method is removed.

Saved Methods

  • Customers can add a card, UPI Autopay or eNACH mandate from My Account → Payment methods. It takes the same ₹1 authorization (₹0 for eNACH), refunded once the method is saved.
  • A mandate still waiting for the bank shows “(awaiting bank confirmation)”, and a paused one shows “(paused)”.
  • Saved Razorpay methods aren’t offered at checkout, because a debit on them lands a day later. They pay renewals and Post-Purchase Offers, where the buyer is told the payment is being confirmed.
  • Customers can change a subscription’s payment method from My Account.
  • Removing a saved method in My Account cancels the mandate at Razorpay, so it’s never debited again.
  • Test and live mandates are kept apart, so a test mandate never shows in live mode.

Refunds

Refund from the WooCommerce order screen, in full or in part. The refund is made in Razorpay, and the order gets a note with the Razorpay refund id. Refunds made in the Razorpay Dashboard are recorded on the order through the webhook, and a refund Razorpay can’t complete adds a note. An order that only carried the ₹1 authorization has nothing to refund.

Billing Health

Razorpay reports to Billing Health: missing keys or webhook secret for the selected mode, test mode, renewal debits still pending after five days, and webhooks that failed recently. Razorpay retries a failing webhook for 24 hours and then disables it, so check a webhook warning the same day.

Limits

  • Automatic renewals need Razorpay’s Recurring Payments feature on your account.
  • Subscriptions, renewals and saved methods are in Indian rupees only.
  • Renewal orders stay pending for a day or more while Razorpay debits them.
  • A renewal above the mandate’s maximum fails. The customer pays it by hand or sets up a new mandate.
  • An eNACH subscription with a first payment stays on hold until the bank confirms the mandate, usually within two working days.
  • The webhook is added by hand, once per mode.
  • Saved methods aren’t offered at checkout.
  • A copy of your store, such as a staging site, never charges saved payment methods.
  • Turn on Debug log to write Razorpay activity to WooCommerce → Status → Logs (stackless-razorpay_gateway). Keys are never logged.

For Developers

stackless_razorpay_gateway_mandate_caps raises the per-method ceilings, in rupees, for businesses Razorpay has approved for higher limits:

add_filter('stackless_razorpay_gateway_mandate_caps', function ($caps) {
    $caps['card'] = 100000; // ₹1,00,000
    return $caps;
});

stackless_razorpay_gateway_currencies narrows the one-time currency list. stackless_razorpay_gateway_webhook runs after each webhook is applied, with the event type, the event and the mode. Copy any template from templates/razorpay_gateway/ to yourtheme/stackless/razorpay_gateway/ to change the payment fields or the payment page.

Share

Was this helpful?

Still stuck? Open a support ticket