Stripe webhook handler
Receives Stripe event webhooks and routes them to the appropriate
handler. Authentication is performed via HMAC-SHA256 signature
verification of the Stripe-Signature header against the stored
webhook secret (ss_stripe_webhook_secret).
Signature verification:
- Header format:
t={timestamp},v1={signature} - Signed payload:
{timestamp}.{raw_body} - Algorithm: HMAC-SHA256
- Tolerance: 300 seconds (5 minutes)
Handled event types:
checkout.session.completed— Creates council for new customers or adds credits for existinginvoice.paid— Handles renewal invoices, adds credits, fires renewal webhook, auto-creates renewal deal for E-SKUcharge.refunded— Deducts credits proportional to refund ratio (never below 0)customer.subscription.deleted— Marks council as cancelledcustomer.subscription.updated— Updates subscription SKUcheckout.session.async_payment_succeeded— Processes cleared async payments (ACH/bank)checkout.session.async_payment_failed— Cleans up failed async payment data
Unhandled event types are logged and acknowledged with {received: true}.
Authorizations
Stripe webhook signature header. Format: t={unix_timestamp},v1={hmac_sha256_hex}.
Verified against ss_stripe_webhook_secret with a 5-minute timestamp tolerance.
Body
Stripe event JSON object. The full Stripe event envelope is passed
through; only type and data.object are consumed by the handler.
Stripe event ID
"evt_1NqIAB2eZvKYlo2C5XFo8Dg6"
Stripe event types handled by the webhook
checkout.session.completed, invoice.paid, charge.refunded, customer.subscription.deleted, customer.subscription.updated, checkout.session.async_payment_succeeded, checkout.session.async_payment_failed "checkout.session.completed"
Response
Event received and processed
true