type: architecture
status: active
timestamp: 2026-06-20
tags: [architecture, subscription, razorpay, firestore, webhook]

Subscription flow — Razorpay → webhook → Firestore → every site

One subscription unlocks everything via Razorpay webhook lands at api.oriz.in, Worker writes users/{uid}/subscription, every site and extension reads that doc to gate features.

Subscription flow — Razorpay → webhook → Firestore → every site

Concept

ONE subscription unlocks everything: every site, every extension, one account, one payment. Razorpay is the primary provider (Indian-first, supports UPI which Stripe still doesn’t). The flow uses the same webhook-to-Firestore pattern Stripe popularised.

How it works

  1. Checkout — user clicks Subscribe on any site, Razorpay Checkout opens client-side, payment completes
  2. Webhook — Razorpay POSTs to api.oriz.in/razorpay/webhook (one of the routes under api-routes-structure.md)
  3. Verify — the Worker validates the webhook signature against the Razorpay webhook secret (held in Cloudflare Secrets)
  4. Write — the Worker writes to users/{uid}/subscription in Firestore via firebase-rest-firestore (NOT firebase-admin — Workers gRPC limitation)
  5. Gate — every site and every extension reads users/{uid}/subscription via the Firebase web SDK, gated by App Check + Firestore security rules

Why this shape

Three properties matter:

If the privileged-blast-radius of holding the Razorpay webhook secret in the same Worker as everything else gets uncomfortable, the razorpay/ folder moves to a privileged Worker behind a Service Binding — see service-bindings-future.md.

Cross-refs


Edit on GitHub · Back to index