Skip to content

Razorpay

Setup guide for the razorpay payments provider. The shared API (initiate_payment, verify_payment, refund_payment, webhooks, hooks, saved methods) is documented in Payments.

1. Get credentials. In the Razorpay Dashboard, under Settings -> API Keys, generate a Key ID and Key Secret.

2. Set environment variables:

Terminal window
KIRAK_PAYMENT_RAZORPAY_KEY_ID=rzp_test_...
KIRAK_PAYMENT_RAZORPAY_KEY_SECRET=...
KIRAK_PAYMENT_RAZORPAY_WEBHOOK_SECRET=... # from step 3

3. Configure the webhook. Under Settings -> Webhooks -> Add New Webhook, point it at https://your-domain.com/payments/webhook/razorpay and select at minimum: payment.captured, payment.failed, subscription.activated, subscription.charged, subscription.cancelled, refund.created. Set the webhook secret you enter there as KIRAK_PAYMENT_RAZORPAY_WEBHOOK_SECRET (Razorpay does not generate this for you – you choose it). For saved payment methods, also send payment.authorized, token.confirmed, token.rejected and token.cancelled – a registration link’s authorization payment reports through payment.captured (already selected above) or payment.authorized depending on the method; token.confirmed activates an e-mandate/NACH/UPI mandate once the bank confirms it (see below); token.rejected and token.cancelled keep payment_methods in sync when a mandate is rejected or cancelled at Razorpay.

4. Use it:

# One-time payment -- creates a Razorpay Payment Link
result = await kirak.payments.initiate_payment({
"provider": "razorpay",
"user_id": "42", "amount": 299900, "currency": "INR", # paise
"name": "Pro Plan", "type": "one_time",
"payment_email": "customer@example.com",
"customer_phone": "+919999999999", # optional, enables SMS notify
})
# Subscription -- subscription_plan_id is a Razorpay Plan ID
# (create the plan in the Razorpay Dashboard or via their API first --
# Kirak does not create plans for you)
result = await kirak.payments.initiate_payment({
"provider": "razorpay",
"user_id": "42", "amount": 0, "currency": "INR",
"name": "Pro Plan", "type": "subscription",
"subscription_plan_id": "plan_abc123",
"payment_email": "customer@example.com",
})

One Razorpay account, several Kirak databases: Razorpay sends every event to every webhook, and each app’s notes name its own numbered rows. The payment link, subscription and off-session order carry a random reference (kirak_ref in the notes, kept in the row’s payment_meta), and a payment.captured or payment.failed whose reference is not the row’s is acknowledged and left alone. Links made before this carry none and are matched by row id, but only to a row from before this too (one without a kirak_ref).

Known quirk: the default currency when a caller omits "currency" is INR (Stripe’s default is USD, Square’s is GBP) – always pass "currency" explicitly rather than relying on the per-provider default.

Saved payment methods and off-session charges need Recurring Payments enabled on the account (Settings -> Recurring Payments in the Razorpay Dashboard). setup_payment_method accepts method (card, upi, emandate or nach), max_amount (paise – the mandate’s per-charge ceiling), customer_name, customer_phone and payment_email. The registration link takes a small first payment for card/upi (REGISTRATION_FIRST_AMOUNT, currently 100 paise) to authorise the mandate – check your Razorpay Dashboard settings for whether this is refunded. emandate/nach methods only appear in list_payment_methods once the bank confirms the mandate (token.confirmed); until then the method is saved but pending, and unusable for charge_off_session. RBI’s rules for recurring payments (the mandate’s max_amount, pre-debit notification, and Additional Factor of Authentication limits) show up as failed off-session charges, not as an error Kirak can otherwise predict.

after_webhook receives these provider-neutral event names (see Webhook Hooks):

data["event"] Gateway events
payment_completed payment.captured
payment_failed payment.failed
subscription_renewed subscription.charged
subscription_updated subscription.activated, subscription.updated
subscription_past_due subscription.pending, subscription.halted
subscription_cancelled subscription.cancelled, subscription.completed
refund_completed refund.created
refund_pending – (reserved)
payment_method_saved payment.captured or payment.authorized (registration link’s first payment), token.confirmed (a pending e-mandate/NACH/UPI mandate confirmed by the bank)
payment_method_removed token.cancelled