Step-by-step Razorpay Dashboard configuration. Complete this before writing any code (Phase 0 of the implementation plan).
Current Payment Provider: Razorpay (India). For future international/Stripe setup see stripe_setup_guide.md.
Docs: user_journeys.md · architecture.md · api_specification.md
Prerequisites
- Razorpay account at dashboard.razorpay.com (you already have one ✅)
- Test Mode active (toggle in top-left of Dashboard)
- Access to LogicSpike
.env.localfile for storing keys - GST number (optional for invoices, required for GST on invoices)
Step 1: Collect API Keys
Dashboard → Settings → API Keys → Generate Test Key
| Key | Where to Store | Notes |
|---|---|---|
Key ID (rzp_test_...) |
RAZORPAY_KEY_ID in .env.local |
Sent to frontend for checkout modal |
| Key Secret | RAZORPAY_KEY_SECRET in .env.local |
Used on Manager backend only. Never expose to frontend. |
# .env.local
RAZORPAY_KEY_ID=rzp_test_...
RAZORPAY_KEY_SECRET=...
RAZORPAY_WEBHOOK_SECRET=... # Set in Step 5Security: The Key ID is safe to expose to the frontend (used to init the Razorpay checkout modal). The Key Secret MUST stay server-side only.
Step 2: Configure Business Profile
Dashboard → Settings → Business Profile
- Set Business Name (appears on payment page and invoices)
- Set Support email and Support URL
- Upload Business Logo (appears on Razorpay checkout modal)
- Set Business Category →
Software→SaaS
Step 3: Create Subscription Plans
Razorpay Subscriptions work with Plans that define billing interval and amount. You cannot use Checkout for recurring billing — you must use Razorpay Subscriptions API.
Dashboard → Subscriptions → Plans → + Create Plan
Create the following plans. Record every Plan ID — insert into the
planstable seed.
3a. Subscription Plans
LogicSpike Starter — Monthly
| Field | Value |
|---|---|
| Plan Name | LogicSpike Starter Monthly |
| Billing Amount | ₹999 / month (or USD equivalent if using international) |
| Interval | Monthly |
| Description | Starter plan — monthly billing |
→ Record: razorpay_plan_id_monthly = plan_...
LogicSpike Starter — Yearly
| Field | Value |
|---|---|
| Billing Amount | ₹9,990 / year (₹832/mo — 17% savings) |
| Interval | Yearly (set period: yearly, interval: 1) |
→ Record: razorpay_plan_id_yearly = plan_...
LogicSpike Pro — Monthly
| Field | Value |
|---|---|
| Billing Amount | ₹2,499 / month |
| Interval | Monthly |
→ Record: razorpay_plan_id_monthly = plan_...
LogicSpike Pro — Yearly
| Field | Value |
|---|---|
| Billing Amount | ₹24,990 / year (₹2,082/mo — 17% savings) |
| Interval | Yearly |
→ Record: razorpay_plan_id_yearly = plan_...
LogicSpike Business — Monthly
| Field | Value |
|---|---|
| Billing Amount | ₹6,799 / month |
| Interval | Monthly |
→ Record: razorpay_plan_id_monthly = plan_...
LogicSpike Business — Yearly
| Field | Value |
|---|---|
| Billing Amount | ₹67,990 / year (₹5,665/mo — 17% savings) |
| Interval | Yearly |
→ Record: razorpay_plan_id_yearly = plan_...
3b. Coin Pack One-Time Orders
Razorpay does not have a "one-time product catalog" like Stripe. Coin packs are handled via Razorpay Orders created dynamically by the backend. No dashboard setup needed — just store amounts in code/DB.
| Pack | Amount (INR paise) | Coins |
|---|---|---|
| Small | 41500 (₹415 ≈ $5) | 500 |
| Medium | 166000 (₹1,660 ≈ $20) | 2,200 (10% bonus) |
| Large | 415000 (₹4,150 ≈ $50) | 6,000 (20% bonus) |
Note: Amounts are stored in
coin_packsDB table (not Razorpay dashboard). The backend callsrazorpay.orders.create({ amount, currency: 'INR' })at checkout time.
Plan ID Reference Table
Fill in after creating all plans:
| Plan | Monthly Plan ID | Yearly Plan ID |
|---|---|---|
| Free | — (no subscription) | — |
| Starter | plan_... |
plan_... |
| Pro | plan_... |
plan_... |
| Business | plan_... |
plan_... |
Step 4: Configure Checkout Settings
Dashboard → Settings → Checkout Settings
- Enable Remember Customer (saves card for future payments)
- Set Brand Color to match LogicSpike theme
- Enable UPI payment method
- Enable Card (Visa, Mastercard, Rupay)
- Enable Net Banking
- Enable Wallets (Paytm, Mobikwik — optional)
- Upload Checkout Logo
Unlike Stripe, Razorpay checkout opens as a modal on your page — it does not redirect to a separate URL. The frontend initializes it via the Razorpay JS SDK.
Step 5: Register Webhook Endpoint
Dashboard → Settings → Webhooks → + Add New Webhook
Production
| Field | Value |
|---|---|
| Webhook URL | https://api.logicspike.com/webhooks/razorpay |
| Secret | Generate a strong random string (store as RAZORPAY_WEBHOOK_SECRET) |
| Active | ✅ |
Events to Subscribe
| Event | Why |
|---|---|
subscription.charged |
Recurring subscription payment succeeded → update subscriptions.current_period_end |
subscription.cancelled |
Subscription canceled → downgrade to Free |
subscription.activated |
Trial or new subscription activated → provision plan |
subscription.pending |
Subscription created, awaiting first payment |
payment.captured |
One-time payment (coin purchase) completed |
payment.failed |
Payment failed → set past_due |
Webhook Secret
# .env.local
RAZORPAY_WEBHOOK_SECRET=your_strong_random_secret_hereLocal Development
Use ngrok to forward webhook events locally:
# Install ngrok
# Expose local Manager service
ngrok http 8787
# Use the ngrok URL in Razorpay Dashboard webhook settings:
# https://abc123.ngrok.io/webhooks/razorpayRazorpay does not have a CLI equivalent to Stripe CLI. Use ngrok for local webhook testing.
Step 6: Subscription Trial Setup
Razorpay supports trials via Addons on the first invoice or via the trial_duration on the plan.
For the 1-month free trial:
- Create subscription with
trial_duration: 7(days — min 7 days), OR - Use
addonsto give a 100% discount on the first invoice - Razorpay does NOT require a card to start a trial (unlike Stripe)
LogicSpike specific: We want card-required trials (prevents abuse). Use Razorpay's
customer_notify: 1and collect card during subscription creation. The first charge is deferred bytrial_durationdays.
Step 7: Tax / GST Configuration
Dashboard → Settings → Tax Settings
- Enable GST
- Enter your GSTIN (if registered)
- Set HSN/SAC code for SaaS:
998314(software services)
Razorpay adds GST automatically to invoices if configured. No code changes needed.
Step 8: Smart Collect (for Failed Payments)
Dashboard → Settings → Smart Collect (if available on your plan)
- Enable automatic retry on payment failure
- Set retry interval: 3 retries, 2 days apart
- Enable Dunning emails (Razorpay sends payment failure emails)
Final Checklist
-
RAZORPAY_KEY_IDin.env.local -
RAZORPAY_KEY_SECRETin.env.local -
RAZORPAY_WEBHOOK_SECRETin.env.local - 6 subscription plans created (Starter/Pro/Business × Monthly/Yearly)
- All 6 Plan IDs recorded
- Webhook registered with 6 events
- Checkout settings configured with logo + brand color
- GST configured (if applicable)
- Test Mode active (not live!)
Environment Variables Summary
# Razorpay API
RAZORPAY_KEY_ID=rzp_test_...
RAZORPAY_KEY_SECRET=...
RAZORPAY_WEBHOOK_SECRET=...
# Razorpay Plan IDs (from Step 3)
RAZORPAY_PLAN_STARTER_MONTHLY=plan_...
RAZORPAY_PLAN_STARTER_YEARLY=plan_...
RAZORPAY_PLAN_PRO_MONTHLY=plan_...
RAZORPAY_PLAN_PRO_YEARLY=plan_...
RAZORPAY_PLAN_BUSINESS_MONTHLY=plan_...
RAZORPAY_PLAN_BUSINESS_YEARLY=plan_...
# Coin pack amounts are stored in coin_packs DB table (not env vars)Note: Plan IDs can also be stored directly in the
plansDB table seed instead of env vars.
Frontend Integration (Razorpay Checkout Modal)
Unlike Stripe (which redirects), Razorpay opens a modal on your page. The frontend flow:
// 1. Backend creates subscription/order, returns details
const { subscription_id, key_id } = await POST('/billing/checkout', { planId, cycle });
// 2. Frontend loads Razorpay script (add to _document.tsx or layout.tsx)
// <script src="https://checkout.razorpay.com/v1/checkout.js"></script>
// 3. Open Razorpay modal
const rzp = new window.Razorpay({
key: key_id,
subscription_id: subscription_id, // for subscriptions
// order_id: order_id, // for one-time coin purchases
name: 'LogicSpike',
description: 'Pro Plan — Monthly',
handler: function(response) {
// payment_id + subscription_id returned here
// Call POST /billing/payment/verify to verify server-side
await POST('/billing/payment/verify', {
razorpay_payment_id: response.razorpay_payment_id,
razorpay_subscription_id: response.razorpay_subscription_id,
razorpay_signature: response.razorpay_signature,
});
// Redirect to billing settings
},
prefill: { name: user.name, email: user.email },
theme: { color: '#your-brand-color' },
});
rzp.open();No redirect needed — the modal handles everything inline. Verification (
/billing/payment/verify) is an extra step not needed with Stripe.
Test Cards & UPI
| Method | Test Value | Scenario |
|---|---|---|
| Card | 4111 1111 1111 1111 |
Successful payment |
| Card | 5267 3181 8797 5449 |
Successful payment (Mastercard) |
| Card | 4000 0000 0000 0002 |
Payment declined |
| UPI | success@razorpay |
Successful UPI payment |
| UPI | failure@razorpay |
Failed UPI payment |
| Net Banking | Any bank | Use test credentials shown in modal |
CVV:
123· Expiry: any future date · OTP:1234for test
Going Live Checklist
- Switch to Live Mode in Razorpay Dashboard
- Generate Live API keys and update
.env(production) - Recreate all subscription plans in Live Mode
- Update Plan IDs in DB seed / env vars
- Register live webhook URL
- Update
RAZORPAY_WEBHOOK_SECRETwith live secret - Verify GST settings for live transactions
- Complete Razorpay KYC (required for live) — PAN + bank account
- Run a ₹1 test transaction and refund via Dashboard