Stripe / Cashier notes
Cashier remains installed on the Tenant billable model as the Stripe gateway driver — not the business source of truth.
Layering
| Layer | Source of truth |
|---|---|
| Licensing | workspace_module_subscriptions |
| Invoicing / payments | invoices, payments (Billing Engine ledger) |
| Stripe mirror | Cashier subscriptions / subscription_items on Tenant |
| Credentials | Encrypted payment_gateways.config (fallback: env STRIPE_*) |
See Billing Engine and Payment Gateway Architecture.
Current state
Tenantuses Cashier'sBillabletrait (stripe_id,pm_type,pm_last_fourare custom columns)StripeGatewayimplementsPaymentGatewayInterface(checkout, refunds, webhook normalization, testConnection)ManualGatewayis the default driver for synchronous settleGatewayManagerresolves drivers frompayment_gatewaystable +config/core-platform.php- Webhooks:
POST /stripe/webhook→ Cashier + Billing EnginePOST /webhooks/gateways/stripe→ Billing Engine only
Manual price mapping
Modules stay payment-provider agnostic (monthly_price, yearly_price, currency). Stripe Product/Price IDs live in payment_gateway_module_prices (managed under Payment Gateways → Product Mapping). The platform never auto-creates Stripe products/prices.
When Stripe is used
- Default gateway =
stripe: billable module installs return a Checkout redirect; webhook activates pending subscriptions and settles payments - Stripe supports recurring (
subscriptionscapability): provider renewals update the ledger via webhooks; those subscriptions are excluded from platformbilling:run-consolidatedcharge lines - Default gateway =
manual: purchases and consolidated runs mark payments succeeded immediately
Cashier subscription rows stay in sync for Stripe-backed workspaces but do not drive entitlements.