B2C Payments
A reusable billing framework for subscriptions, invoicing, prepaid credits and usage billing, dropped into any app.
- Role
- Founder and architect
- Areas
- AI, Tools, Apps, Pipelines

Once one of our web apps works and scales, turning it into a product should take days, not a rebuild. B2C Payments is the one billing integration every Big Blue Ceiling app uses for that, whether it sells to consumers or businesses, and whether it charges once, every month, or by what the customer uses.
The central idea is that apps don't care how a customer pays. An app asks billing what a customer is entitled to and reports what it spent. It never talks to a payment provider directly.
What it sells
- Subscriptions: flat or per seat, monthly or annual, with trials, plan changes and proration. The app sees features, limits and seats in a signed entitlement snapshot.
- One-time purchases: licenses, add-ons and credit packs, which arrive as a feature grant or a lot of credits in a wallet.
- Prepaid wallets: a balance of credits that running work draws down, such as an LLM call, a GPU job or a long pipeline.
- Usage billing with a cap: postpaid and metered, under a monthly spending limit the customer authorizes in advance. Billing never charges above it without a new authorization.
- Any mix: a plan with included usage, then credits, then overage, all through one spending call.
Spending and the Ledger covers how a running job pays for itself, and Screens and Console shows what customers and operators see.
A complete product, not a library
An app adopting B2C Payments writes configuration, not billing code. It's a backend API, a background worker, customer billing screens and an operator console, with client libraries for TypeScript and Python. Each app mounts it as a git submodule and describes its catalog, settings, copy and theme in one config file. A generator wires the services into the app's compose file, service registry, nginx and hosting config, so fixes and features land in one place and reach every app with a submodule bump.
It runs in two shapes from the same image: embedded in an app's own stack and database, or as one hub deployment that serves every app, with each app running only a thin proxy and the screens.
Rules it never bends
- Billing owns money; apps own people. Billing stores only opaque references to an app's organizations and users, never names, passwords or profiles. Every customer is an organization, and a consumer is a personal one.
- Money is whole numbers with a unit. Every amount is an integer in minor units with a currency or a declared credit unit. A lint rule rejects floating-point money anywhere in the schema or the contract.
- The provider is an event source, not the record. Provider webhooks update billing's own subscription, entitlement and ledger tables, and apps query billing, never the provider. Each provider is one adapter behind a single interface, starting with Stripe.
- No card data, ever. Checkout and payment-method changes use the provider's hosted pages.
- Every write is idempotent. Inbound webhooks are deduplicated by event id, every API change takes an idempotency key, and usage reports carry their own event ids, so a retry is always safe.
- Policy is a setting, never a constant. Tax posture, credit expiry and refunds, revenue recognition, dunning, proration, currencies and funding order are entries in a settings registry. Every value is implemented and tested, and settings are copied onto the objects they govern, so a later change never rewrites history.
How it's built
TypeScript throughout, on the same app anatomy as BigBlueBam: Fastify and Zod for the API, Drizzle over PostgreSQL with numbered append-only migrations, BullMQ on Redis for the worker, and React for the screens. One contract package declares every route, outbound webhook event, setting and config schema, and the OpenAPI description and other artifacts are generated from it and checked for drift in CI.
Before money moves, a scripted rehearsal runs end to end in the provider's sandbox: checkout, webhook, entitlement read, authorize, usage, an extension refused at the cap, settle, refund, the ledger invariants and a clean reconciliation.
Gallery

Usage by meter against the plan's included allowance. 
One overview for a business customer: plan, seats, spending and credits. 
At the spending cap the customer authorized. 
Payment failed, in grace: billing runs its own dunning. 
The app hits a plan limit and opens billing's upgrade prompt from its own code. 
Public pricing in the neutral fallback theme, built from the catalog. 
Out of credits: packs to buy and automatic top-up.



