Payment Gateway Webhooks
Ingress points
| URL | Controller | Notes |
|---|---|---|
POST /webhooks/gateways/{code} | GatewayWebhookController | Gateway-agnostic extension point |
POST /stripe/webhook | StripeWebhookController | Extends Cashier; also dispatches Billing Engine |
Flow
mermaid
sequenceDiagram
participant P as Provider
participant WH as Webhook Controller
participant D as Driver parseWebhook
participant LOG as webhook_logs
participant BE as BillingEngine
P->>WH: POST payload + signature headers
WH->>LOG: status=received
WH->>D: parseWebhook(payload, signature)
D-->>WH: GatewayEvent
WH->>BE: handleGatewayEvent(event)
WH->>LOG: status=processed|ignored|failedNormalized events
GatewayEvent types:
payment_succeeded/payment_failedsubscription_created/subscription_updated/subscription_cancelledunsupported(logged as ignored)
Drivers should populate tenantId when resolvable so BillingEngine stays provider-agnostic. If not, include meta.payment_id (and/or providerSubscriptionId) so the engine can still resolve the workspace for payment_failed without a customer map.
Stripe events handled for billing activation
invoice.payment_succeededinvoice.payment_failedcustomer.subscription.*(cancel → deactivate licensing)
Cashier still handles its own mirror tables on /stripe/webhook.
Creem events handled for billing activation
Signature header: creem-signature (HMAC-SHA256 of raw body).
subscription.paid/checkout.completed→ activate pending modulessubscription.active/subscription.update→ link provider subscription idsubscription.canceled/subscription.expired→ cancel module licensingsubscription.past_due→payment_failedrefund.created→ ignored (unsupported) after signature verification
See Creem gateway for the full event matrix.
Local development
bash
stripe listen --forward-to https://your-app.test/stripe/webhook
# or
stripe listen --forward-to https://your-app.test/webhooks/gateways/stripe
# Creem: forward sandbox webhooks (ngrok / Herd) to:
# https://your-app.test/webhooks/gateways/creemUse the CLI webhook signing secret for local verification (whsec_… for Stripe; Creem dashboard webhook secret for Creem).