App guides

The Razorpay app makes Razorpay the payment gateway for credit cards in your Swell store. Shoppers pay in Razorpay's window in Swell's hosted checkout, and Razorpay saves their card. The app captures payments when Swell takes them, charges the saved card for subscription renewals and later charges, and refunds payments from the order.

Card details stay with Razorpay. Swell keeps Razorpay's token for the card with its brand, last four digits and expiry date. Before the app takes any money, it checks the Razorpay payment against the Swell payment's amount, currency and card method, and it never takes the money twice for one Swell payment, even when a request is retried.

WhenWhat the app does
A shopper pays by card and clicks Complete orderCreates a Razorpay order for the total and opens the Razorpay window, with cards only. When the shopper pays, Razorpay authorizes the payment and saves the card, and the app checks the payment's signature before the order is placed.
The order is placedWith Charge automatically on under Settings > Orders, which is the default, captures the payment. With it off and Require payment authorization on, the payment is only authorized.
You click Charge order on an order with an authorized payment, within 5 daysCaptures the authorization for its full amount.
You charge an order that has no usable authorizationCharges the shopper's saved card with a new Razorpay payment. The payment shows Pending until a workflow records it as Paid, usually within seconds.
A subscription renewsCharges the saved card the same way, with no checkout for the customer.
You refund a paymentRefunds the amount, in full or in part, to the card through Razorpay.
Every 30 minutesFinishes saved card charges that are still pending 30 minutes after they started, up to 10 per run, for example when their workflow failed.
  • A Razorpay account and its API keys, from Account & Settings > API Keys in the Razorpay Dashboard. Test keys start with rzp_test_ and live keys with rzp_live_.
  • Recurring card payments enabled on your Razorpay account. The app saves every card at checkout so it can be charged again, and without recurring payments Razorpay can't save it.
  • Orders in a currency that Razorpay accepts for recurring card payments. The app sends the order's currency to Razorpay as it is, and Razorpay decides which cards and currencies can be saved and charged again.
  • An email address and a phone number for each shopper. Razorpay needs both to save the card. The app takes the phone number from the customer's account, or from the checkout's billing or shipping address.
  • Swell's hosted checkout. The app adds the Razorpay window to its card payment method.

Install Razorpay from the Swell App Store, and set it up in your test environment before the live one.

1
Copy your test API keys

In the Razorpay Dashboard, switch to test mode and go to Account & Settings > API Keys. Copy the Key ID, which starts with rzp_test_, and the Key secret of a test key.

2
Choose Razorpay as the card gateway

In Swell, go to Settings > Payments. Under Credit cards, click Edit settings, or Use a different gateway while the Swell test gateway is selected. In Credit card settings, choose Razorpay as the Payment gateway, enter the Key ID and Key secret, and click Save. Card payments go through Razorpay once you save.

If the toggle next to Credit cards is off, turn it on and click Save changes.

3
Ask for a phone number at checkout

Go to Settings > Checkout. Under Form fields, set Phone number to Required and click Save changes. Razorpay can't save a card without the shopper's phone number.

4
Choose when payments are captured

In Settings > Orders, Charge automatically and Require payment authorization are on by default, so payments are captured when the order is placed. To capture payments later from the order, turn off Charge automatically, keep Require payment authorization on, and click Save changes.

5
Place a test order

Place an order in the hosted checkout, pay by card and click Complete order. The Razorpay window opens. Pay with a Razorpay test card, such as 4111 1111 1111 1111 with any future expiry date and any CVV. In the order's Transactions, the payment shows Paid, or Authorized when Charge automatically is off.

To test a saved card charge, click Charge order on the order, enter an amount and charge it. The payment shows Pending, then Paid. To test a refund, click Refund order.

6
Go live

Settings are saved separately for each environment. In the live environment, repeat steps 2 to 4 with the Key ID and Key secret of a live key from Razorpay's live mode, which starts with rzp_live_.

In live mode, Razorpay charges a saved Indian card only after it notifies the cardholder, so saved card charges on those cards stay Pending for about 36 hours.

When a shopper chooses to pay by card, the checkout shows You will enter your card details in a secure Razorpay window. When they click Complete order, the app creates a Razorpay order for the cart's total and opens the Razorpay window, with the shopper's name, email address and phone number filled in. The window offers cards only. If a card is declined, the shopper can try again in the same window. If they close it, the order isn't placed, with the error Payment cancelled or the reason the last attempt failed.

When the shopper pays, Razorpay authorizes the payment and saves the card for later charges. The app checks the payment's signature with your Key secret, and the order is placed with the authorized payment and the saved card: Razorpay's token, the card brand, the last four digits and the expiry date. The Razorpay payment is set to manual capture, so Swell decides when it's captured.

The first time a customer pays, the app creates a Razorpay customer with their name, email address and phone number, and keeps it on their Swell account. Their later checkouts and charges use the same Razorpay customer, even if their phone number changes.

Swell decides when a payment is captured, with Charge automatically and Require payment authorization under Settings > Orders:

  • Both on, the default: the payment is authorized when the order is placed and captured right away.
  • Charge automatically off: the payment is only authorized, and shows Authorized in the order's Transactions. Capture it within 5 days.
  • Both off: no payment is taken when the order is placed. Charge the order later with Charge order.

To capture an authorized payment, open the order and click Charge order. Keep the amount at the authorized amount and click the Charge button. The app captures the Razorpay payment after checking that it's a card payment for the same amount and currency, and that no other Swell payment has used it.

Razorpay keeps an authorization from the checkout for 5 days. After that, the capture fails with The authorization is no longer valid; charge the saved card with a new payment. Click Charge order again to charge the saved card. To take a different amount than the authorization, enter it in Charge order: the app charges the saved card with a new payment, and Razorpay releases the authorization when it expires.

When Razorpay doesn't answer a capture, or answers with a server error, the capture fails, and the app doesn't charge the saved card instead, because the capture may still go through. Check the payment in the Razorpay Dashboard before you charge the order again: a new Charge order charges the saved card.

The app charges the shopper's saved card with a new Razorpay payment when a charge has no usable authorization, such as a subscription renewal, a Charge order after the authorization expired, or a different amount. The shopper doesn't need to be present.

Razorpay takes several seconds to charge a saved card, so the payment shows Pending in the order's Transactions, and a workflow finishes it, usually within seconds. It then shows Paid, or Error with the reason. The runs are listed under Apps > Razorpay > Workflows. Every 30 minutes, the app also finishes saved card charges that are still pending, for example after a workflow failed.

A saved card can be charged up to ₹10,000 at a time, or 10,000 in another currency with two decimals. The customer's account needs an email address, and a phone number unless the app already created their Razorpay customer.

In live mode, Razorpay charges a saved Indian card only after it notifies the cardholder, about 36 hours later. Until then, the payment stays Pending. The app checks it every 6 hours, for up to 8 days, and records it as Paid once Razorpay has charged the card. If the card still isn't charged after 8 days, the payment fails with Saved card payment … was not finalized: Payment is still pending (status: created) after 8 days. In test mode, saved cards are charged without the wait.

To refund a payment, open the order and click Refund order. Choose the payment, enter the Refund amount and an optional Reason, and click the Refund button. The app refunds the amount to the card through Razorpay. You can refund a payment in full or in parts, up to the amount paid. Refunds made in the Razorpay Dashboard aren't sent to Swell.

The app supports subscriptions, so the card payment method is offered at checkout for carts with subscription products. The first payment is taken at checkout. Renewals are charged on the saved card with no checkout, when Swell charges the subscription. With Charge automatically on under Settings > Subscriptions, that's when the renewal is due.

Each renewal payment shows Pending until its workflow finishes it, which on a live Indian card takes about 36 hours.

Every Razorpay order the app creates for a saved card charge carries the Swell payment's ID as its receipt. When a charge is retried, the app finds the earlier Razorpay payment by that receipt and finishes it instead of charging the card again. A new saved card payment is created at most once. If Razorpay's answer is lost, the app waits a minute and looks for the payment before it records anything.

A Razorpay payment the app captures is marked with its Swell payment, and the app never uses it for another one. If the app finds a Razorpay payment that was captured but not by the app, for example in the Razorpay Dashboard, it stops with Payment already captured but not recorded; contact support rather than charging again.

WhereWhat it's for
Settings > Payments, Credit cardsEdit settings: the Payment gateway, and the Key ID and Key secret while Razorpay is selected. The toggle turns card payments on or off.
Apps > Razorpay > SettingsThe Key ID and Key secret.
Apps > Razorpay > WorkflowsThe runs that finish saved card charges.
Settings > OrdersCharge automatically and Require payment authorization, which decide when payments are captured.
Settings > SubscriptionsCharge automatically for renewals, and the dunning and retry rules.
Settings > Checkout, Form fieldsPhone number, which Razorpay needs to save the card.
An order's TransactionsEach payment's status, Authorized, Pending, Paid or Error, and its refunds.
An order's Charge order buttonCaptures an authorized payment, or charges the saved card.
An order's Refund order buttonRefunds a payment in full or in part.
Developer > Console > LogsThe app's logs.

Settings are in Settings > Payments: under Credit cards, click Edit settings while Razorpay is the payment gateway. The same settings are in Apps > Razorpay > Settings. They're saved separately for each environment.

SettingDescriptionDefault
Key IDFrom Account & Settings > API Keys in the Razorpay Dashboard. Opens the Razorpay window in the checkout, so it's sent to the shopper's browser. Test keys start with rzp_test_, live keys with rzp_live_. Required.None
Key secretFrom the same page. Used only by the app's functions, never sent to the browser. Masked on the settings page. Required.None
  • Cards only. Razorpay's other payment methods, such as UPI, netbanking and wallets, aren't offered.
  • The Razorpay window is part of Swell's hosted checkout.
  • A charge on a saved card is limited to 1,000,000 in the currency's smallest unit: ₹10,000, or 10,000 in another currency with two decimals. The card is saved with that limit.
  • An authorization from the checkout can be captured for 5 days, and only for its full amount. A different amount is charged on the saved card as a new payment.
  • The app doesn't cancel authorizations in Razorpay, even when Swell voids the payment. Razorpay releases an authorization that isn't captured after 5 days.
  • In live mode, saved Indian cards are charged about 36 hours after Razorpay notifies the cardholder. The payment stays Pending until then, for up to 8 days.
  • Captures and refunds made in the Razorpay Dashboard aren't sent to Swell. A payment captured there can't be captured from Swell.
  • Each shopper needs an email address and a phone number.
  • Razorpay decides which cards and currencies can be saved and charged again.

Errors at checkout are shown to the shopper. A charge or refund that fails shows Error in the order's Transactions, with the reason when you point at it. The app also logs its errors. In the Swell dashboard, the logs are under Developer > Console > Logs, and saved card charges are under Apps > Razorpay > Workflows.

Razorpay is not configured means no Key ID is saved in this environment, and Razorpay keys are not configured that the Key ID or the Key secret is missing. Enter both under Settings > Payments and save. Razorpay checkout could not be loaded means the shopper's browser couldn't load Razorpay's checkout script from checkout.razorpay.com. The shopper can click Complete order again.

Razorpay needs the shopper's email address and phone number to save the card. Under Settings > Checkout > Form fields, set Phone number to Required. The same messages ending in to charge the saved card mean the customer's account is missing them. Add them to the account, then charge the order again.

Razorpay authorized the payment without saving the card, so the order isn't placed, and Razorpay releases the authorization after 5 days. Check that recurring card payments are enabled on your Razorpay account. Razorpay decides which cards can be saved, so the shopper can also try another card.

Razorpay's signature on the payment didn't match your Key secret, so the order isn't placed and the payment is left uncaptured. The shopper can pay again.

Razorpay refused the request, and the rest of the message is Razorpay's reason. Check the keys, that test keys are used in the test environment and live keys in the live one, and that recurring card payments are enabled on your Razorpay account.

A saved card charge shows Pending until its workflow finishes, usually within seconds. On a live Indian card it waits for Razorpay to notify the cardholder, about 36 hours. Open Apps > Razorpay > Workflows to see the run and its steps. If a run failed, the app finishes the charge within 30 minutes. If Razorpay has no payment for it by then, the payment fails with The saved card charge did not complete, and nothing was charged.

The authorization expired or was released before it was captured, for example after 5 days. Click Charge order again to charge the saved card.

The Razorpay payment was captured, but not by this Swell payment, for example in the Razorpay Dashboard. The app doesn't charge the card again. Check the payment in the Razorpay Dashboard, and email support@swell.is.

A saved card payment exists in Razorpay but couldn't be completed, and its money may be on hold or taken. The message names the Razorpay payment and the reason. Look it up in the Razorpay Dashboard before you charge the order again. Saved card payment … is still pending (status: created); contact support means a charge was retried while Razorpay was still waiting to charge the card.

No Razorpay payment to refund means the Swell payment has no Razorpay payment ID. Other reasons start with Razorpay: and come from Razorpay.

Uninstalling the app removes its functions, its workflow and its settings, including your API keys, and removes Razorpay from the Payment gateway options. Uninstalling applies to the environment you are in, so remove the app from the test and live environments separately.

Before you uninstall, choose another payment gateway for Credit cards under Settings > Payments. Uninstalling doesn't change the card method's gateway, and while it's still Razorpay, card payments stop working: Charge order and subscription renewals fail with an error that the payment app isn't installed.

Wait until no saved card charge shows Pending. After the app is removed, nothing finishes them: the Swell payment stays pending, and the Razorpay payment isn't captured.

Cards saved through the app are Razorpay tokens and can only be charged through Razorpay. Subscriptions paid with a saved card need a new card from the customer to renew on another gateway. Customers, saved cards, payments and refunds stay in your Razorpay account. The app isn't notified when it's uninstalled, so if you no longer need the API keys, regenerate them in the Razorpay Dashboard under Account & Settings > API Keys.

FunctionRuns onWhat it does
card-intent-createafter:payment.create_intent, for the card extensionCreates or reuses the Razorpay customer and creates the Razorpay order the checkout window pays.
card-intent-getafter:payment.get_intent, for the card extensionChecks the window's payment signature and returns the payment with its saved card token.
card-chargeafter:payment.charge, for the card extensionCaptures the shopper's authorization when it's valid, or creates an order for a saved card charge, starts card-charge-finish and answers async.
card-charge-finishA workflow, started by card-chargeCreates the recurring payment at most once, waits for live debits, captures it when the Swell payment asks for it, and records the result.
card-charge-sweepEvery 30 minutesFinishes pending saved card charges created between 30 minutes and 8 days ago, 10 per run.
card-refundafter:payment.refund, for the card extensionRefunds the amount on the Razorpay payment.

The app is the gateway of Swell's card method through a payment extension with subscriptions: true, so the gateway ID is app_<app id>_card. Its settings are key_id, which is public, and key_secret, in the card settings. The Razorpay customer is kept on the account under $app.razorpay as customer_id and contact, the phone it was created with.

The checkout component, components/Razorpay.tsx, is an @swell/apps-sdk component on the card extension and the checkout.payment.methods target. On submit it loads https://checkout.razorpay.com/v1/checkout.js, calls createIntent with the cart's capture_total in the currency's smallest unit, opens the window with recurring: '1' and a card-only display block, and passes the signed response to getIntent. It returns billing.card with the token, last4, brand, exp_month and exp_year, and billing.intent.razorpay.id.

The app calls the Razorpay API at https://api.razorpay.com/v1 with Basic auth: POST /customers with fail_existing: '0', POST /orders, GET /orders?receipt=…, GET /orders/{id}/payments, GET /payments/{id} with expand[]=token, POST /payments/create/recurring, PATCH /payments/{id} for notes, POST /payments/{id}/capture and POST /payments/{id}/refund. Errors are thrown as Razorpay: <description>. The checkout order has method: card, token.max_amount: 1000000 with frequency: as_presented, and manual capture with manual_expiry_period: 7200. Amounts are converted to the smallest unit in lib/amount.ts, with zero-decimal and three-decimal currencies.

get_intent checks the HMAC-SHA256 hex signature of order_id|payment_id with the key secret in constant time. card-charge takes the Razorpay payment from transaction_id or intent.razorpay.id, and uses it only when it's a card payment with the Swell payment's amount and currency, authorized, and not marked with another Swell payment in notes.swell_payment_id. After a capture it writes that note. A captured payment without the note fails closed. A capture that gets a network error, a 408, a 429 or a 5xx while the payment is still authorized fails the charge. Only another 4xx refusal falls back to the saved card.

A saved card charge reads the customer, looks up earlier attempts and creates an order with payment_capture: false, receipt set to the Swell payment ID, in parallel. An earlier payment is finished in the hook. Otherwise the hook starts card-charge-finish with identifiers only and answers async: true, because creating a recurring payment takes Razorpay longer than the hook can wait. While a Swell payment is async without success, a new charge of it answers async: true and creates nothing. A capture of a Swell payment that already has its result never starts a saved card charge.

The workflow's steps are check pending, charge saved card (never retried), wait for Razorpay and find by receipt after an unknown outcome, read payment and wait for debit 1 to wait for debit 32 at 6-hour intervals, capture, record and late capture. Each step that calls Razorpay reads the keys itself and doesn't return them. Step names are the step cache keys, so they mustn't change while runs sleep. The sweep reads the gateway from /settings/payments, reads up to 10 async, pending, non-void card payments of that gateway, newest first, works on 5 at a time and starts none after 6 seconds.

Swell builds and maintains the Razorpay app. For help with the app, email support@swell.is. For questions about your Razorpay account, API keys or recurring payments, contact Razorpay.