I built Wallxy's production Razorpay integration: the full subscription lifecycle, mandate verification, proration, add-ons, webhook handling, a wallet with credits, and invoice generation, backed by asynchronous workers for expiry and usage-based billing.
- lifecycle states: trial → active → expired
- 3
- mandate verification before billing
- ₹1
- billing lifecycle covered end-to-end in Playwright
- 21-day
- async billing workers: expiry & usage
- 2
The problem
Wallxy is a SaaS for design professionals, so subscriptions are the business. Billing has to be right in every edge case: upgrades mid-cycle, add-ons, trials that convert or lapse, and payment events that arrive asynchronously from Razorpay.
Architecture
A simplified view of how the pieces fit together.
Customer
Plans & checkout
Next.js UI
₹1 mandate
payment method verified
Billing core
Razorpay
subscriptions & payments
Webhook handling
payment events → subscription state
MongoDB
subscriptions · wallet · invoices
Async workers
GCP Pub/Sub
billing events
Cloud Run
subscription expiry · usage billing
What it covers
- Full subscription lifecycle: trial → active → expired.
- ₹1 mandate verification before recurring billing starts.
- Proration when plans change, and add-ons on top of a plan.
- Webhook handling for Razorpay payment and subscription events.
- A wallet with credits, and invoice generation.
- Subscription plans wired into the Brand Marketplace module.
Asynchronous by design
Time-based work, like expiring subscriptions and usage-based billing, runs outside the request path as workers on Google Cloud Pub/Sub and Cloud Run, so users never wait on it and it doesn't depend on someone visiting the app.
Tested like money depends on it
Jest unit and integration tests cover the payment scenarios, and Playwright end-to-end tests walk through auth flows and a full 21-day subscription billing lifecycle.
Key decisions
Verify before you bill
A ₹1 mandate confirms the payment method up front, before a trial converts into a paid subscription.
Events over polling
Razorpay webhooks drive state changes, and Pub/Sub workers handle the time-based transitions: expiry and usage billing.
Test the calendar, not just the function
Billing bugs hide in time. The E2E suite follows a subscription across a 21-day cycle instead of testing each step alone.
Want something like this built, or someone who builds it?
Tell me about your project, or grab my résumé if you're hiring. The code is private; I'm happy to walk through it in an interview.