AstroBaaS

Analytics & reporting

Stripe Billing (Subscriptions Setup)

Paid pluginsize Mplanned, not built

Indicative price, not an offer: €29/mo; credential: we configure Stripe Billing, webhook management

Generated from docs/plan/paid/stripe-billing/PLAN.md in the AstroBaaS repository. Nothing described below is implemented — it is the written plan for it.

A paid module integrating Stripe Billing platform for subscription management, handling recurring charges, usage-based billing, proration, and retry logic. Core provides order system; this pack configures Stripe Billing, manages webhook sync, and routes subscription events.

The problem

Merchant wants to offer subscriptions (€20/month) but building billing automation (retry on failed card, proration, tax calculation) is complex. Stripe Billing automates this, but setup requires credential, webhook configuration, and sync logic.

What it does

  • Stripe Billing configuration: set up Stripe Billing for shop (credentials stored securely)
  • Subscription creation: link AstroBaaS product to Stripe Billing product/price, handle monthly/annual billing
  • Billing cycles: automatic charge on billing date, retry failed payments (exponential backoff)
  • Proration: if customer upgrades mid-cycle, prorate charges fairly (credit for unused days)
  • Usage-based billing: track customer usage (API calls, storage), bill at month-end
  • Subscription management: pause/resume/cancel subscription from admin UI or API
  • Webhook sync: Stripe webhooks (charge.succeeded, charge.failed, customer.subscription.updated) sync to AstroBaaS orders/events

What it deliberately does NOT do

Each boundary carries its reason. A boundary without a reason gets crossed by the next person who reads this.

  • Tax calculation per region—owned by tax module (Stripe Tax or TaxJar integration)
  • Multi-currency billing—owned by currency module; Stripe handles, but AstroBaaS reports single currency
  • Fraud detection beyond Stripe’s built-in rules—owned by fraud module
  • Dunning management (retry logic for failed payments beyond Stripe’s defaults)—Stripe owns, this module configures only
  • Subscription analytics (churn, MRR, ARR)—owned by subscriptions analytics module

Data model

New entities: StripeAccount (id, merchantId, stripeAccountId, mode[test|live], createdAt); SubscriptionBinding (id, stripePriceId, productVariantId, billingCycle[monthly|annual], setupFee, createdAt). Links: StripeAccount.merchantId → Shop, SubscriptionBinding.productVariantId → ProductVariant. Migration: none (new data).

API

  • POST /api/v1/stripe/auth — OAuth flow to connect Stripe account (staff only, credential-gated)
  • GET /api/v1/stripe/account — fetch connected Stripe account details (staff only)
  • POST /api/v1/stripe/subscription-bindings — link product variant to Stripe price (staff only)
  • GET /api/v1/stripe/subscription-bindings — list product-to-price mappings (staff only)
  • POST /api/v1/stripe/webhooks — handle incoming Stripe webhooks (charge.succeeded, subscription.updated, etc.) (public, signature-verified)
  • POST /api/v1/stripe/sync — manual sync of Stripe customer data (staff only, for debugging)

Every route added here must also appear in src/pages/openapi.json.ts — a test fails the build if it does not.

Admin

Stripe settings page: button to connect Stripe account (OAuth flow), status indicator (connected/disconnected). Subscription bindings table: product variant name, linked Stripe price, billing cycle, edit/delete buttons. Webhook status card: last webhook received (timestamp), error rate (if any), retry backlog. Settings section: set Stripe mode (test/live), max retry attempts (default 3).

The seam — why this is paid

Core owns: order system (invoice, payment event recording), email infrastructure. Paid pack owns: Stripe Billing integration (OAuth, credential management), webhook handling, proration logic. Seam drawn here because Stripe Billing setup is credential-gated and requires Stripe partnership—support team manages Stripe account connectivity.

Credential: Stripe Billing setup, usage-based billing, proration logic

Dependencies

  • core:orders — Stripe charges create AstroBaaS orders/invoices
  • core:events — Stripe webhooks trigger AstroBaaS events (subscription.renewed, payment.failed)
  • core:authentication — Stripe OAuth flow requires session auth
  • assumption: Stripe account exists and is verified (merchant provides Stripe API keys or OAuth flow)

Acceptance checks

Each of these must be able to fail. Before claiming this is done, break the code deliberately and watch each one go red.

  • Merchant authorizes Stripe via OAuth; StripeAccount record is created with stripeAccountId, status is ‘connected’
  • A product variant (Monthly Subscription €20) is linked to Stripe price; SubscriptionBinding shows ‘productVariantId XYZ → stripePriceId price_ABC’
  • A customer subscribes via checkout (selects Monthly Subscription product); Stripe Billing creates subscription, first charge is scheduled, AstroBaaS records order with subscription reference
  • On billing date, Stripe charges customer €20; webhook charge.succeeded is received, AstroBaaS creates new order line item (Subscription Renewal €20) with audit timestamp
  • Customer upgrades mid-cycle (from €20/month to €50/month); Stripe prorates, credit is €10 (unused days), new charge is €40; AstroBaaS records both transactions
  • Charge fails (card declined); Stripe retries in 3 days, succeeds on second attempt; AstroBaaS records both attempt and success in audit log
  • Customer cancels subscription; Stripe subscription.canceled webhook is received, AstroBaaS marks subscription as canceled, no further charges
  • Merchant views Stripe status in admin; shows ‘Connected (test mode)’, webhook status ‘Last received 5 minutes ago’

Risks

Stripe credentials must be stored securely (encrypted, rotate regularly). Webhook signature validation is critical—unsigned webhooks can forge subscription events. If Stripe and AstroBaaS drift in sync, double-charging can occur—implement idempotency keys on all Stripe API calls. Proration logic must be transparent to customer—show in order/invoice. Test mode <-> live mode must be strictly separated (no mixing). If webhook delivery fails, Stripe retries; implement webhook event deduplication (idempotent processing).

Commercial context

Suggested price€29/mo; credential: we configure Stripe Billing, webhook management
Rival anchorStripe: free (native); Subbly: €99/mo; custom: €2000+

The anchor is what the nearest equivalent charges on Shopify or Magento today. It is context for a pricing decision, not the decision.


Generated from the commerce plan. See docs/COMMERCE-PLAN.md for the full catalogue and ../../AI-GUIDE.md for how to work on this repository.