Payment providers
Manual and Stripe adapters, webhooks, and the integrations page.
Adapters live in features/integrations/payment. A PaymentProvider record has name, code, adapter (manual or stripe), isInstalled, isDefault, and config.
Manual
No credentials. Desk checkout, recorded deposits, and gift-card sales use the installed manual provider. A payment records tender taken at the desk.
Stripe
Needs STRIPE_SECRET_KEY and STRIPE_WEBHOOK_SECRET. Point the webhook at:
/api/payments/webhooks/pp_stripeThe route accepts only an installed Stripe provider, verifies the signature, logs each event once in PaymentWebhookEvent, rejects amount or currency mismatches, and handles:
payment_intent.succeededpayment_intent.payment_failedpayment_intent.canceledcharge.refundedrefund.updated
Set up
Run onboarding
It creates the manual provider (installed, default) and a Stripe record.
Set environment variables
Add the Stripe keys, then set isInstalled on the Stripe provider record in your seed or database. The webhook route only accepts an installed Stripe provider.
Register the webhook
Use the URL above and the signing secret as STRIPE_WEBHOOK_SECRET.
Integrations page
/dashboard/platform/integrations needs canManageIntegrations. It shows providers, recent webhook events, and DomainEvent rows still pending or in dead_letter.
Booking confirmations, gift-card emails, and password resets send through SMTP when SMTP_HOST and SMTP_FROM are set.