TransactKit-Litev1.0.0
TransactKit-Lite webhooks
Configure and operate TransactKit-Lite Stripe webhook verification, event handling, durable deduplication, retries, and local synchronization.
Updated
Webhook endpoint and signature
Stripe sends POST /api/stripe/webhook with Content-Type application/json and the Stripe-Signature header. The controller passes the exact request body string to Stripe's Webhook.constructEvent together with STRIPE_WEBHOOK_SECRET.
Do not parse, normalize, reconstruct, or log the payload before verification. A missing secret returns 503; a missing/invalid signature or malformed signed JSON returns 400.
Handled Stripe events
| Event | Local behavior |
|---|---|
| checkout.session.completed | Marks the Payment paid when payment_status is paid; otherwise records a completed Checkout that is still processing |
| checkout.session.async_payment_succeeded | Marks the matching Payment paid |
| checkout.session.async_payment_failed | Marks only the latest matching Checkout attempt failed |
| checkout.session.expired | Marks only the latest matching attempt expired so a new attempt can start |
| refund.created | Upserts the local refund projection and recalculates successful cumulative refunds |
| refund.updated | Upserts current refund state and recalculates successful cumulative refunds |
| refund.failed | Upserts the failed refund state without adding it to the successful refunded total |
| Any other verified event | Records the event as IGNORED |
Durable claiming and transaction flow
The database unique constraint on stripe_event_id is the deduplication boundary. After claiming or losing a concurrent claim race, the handler locks the existing event row before deciding whether to process, retry, or acknowledge it.
Raw body + Stripe-Signature
-> Stripe SDK signature and event verification
-> REQUIRES_NEW insert of unique Stripe event ID as RECEIVED
-> lock event row
-> dispatch supported event inside one business transaction
-> PROCESSED or IGNORED
On handler failure
-> roll back business writes
-> REQUIRES_NEW update of the event claim to FAILED
-> return an error so Stripe can retryDeduplication and retry behavior
Stripe may deliver an event more than once. Stripe controls delivery and retry timing; TransactKit-Lite controls only its local claim, deduplication, transaction, and response behavior.
| State | Terminal | Behavior on redelivery |
|---|---|---|
| RECEIVED | No | Retry business processing; covers work interrupted after the durable claim |
| FAILED | No | Retry business processing after the prior failure |
| PROCESSED | Yes | Acknowledge with duplicate=true without applying state again |
| IGNORED | Yes | Acknowledge with duplicate=true without dispatching again |
Local synchronization rules
- Checkout lookup uses the Stripe Session ID first and client_reference_id/businessReference as a fallback.
- Old failed or expired Session events cannot replace the latest attempt state.
- A completed unpaid Session stays PENDING with Checkout status COMPLETE until an asynchronous success or failure event arrives.
- Refund rows are unique by Stripe Refund ID, so created/updated delivery does not double-count one successful refund.
- Only Refund records with status succeeded contribute to Payment.refundedAmount.
- A business-processing failure rolls back Payment/Refund changes before FAILED is stored independently.
Test locally with Stripe CLI
Restart the application after setting the CLI signing secret. Keep the Stripe CLI process running while completing Test Mode Checkout and refund flows.
stripe listen --events checkout.session.completed,checkout.session.async_payment_succeeded,checkout.session.async_payment_failed,checkout.session.expired,refund.created,refund.updated,refund.failed --forward-to localhost:8080/api/stripe/webhookSTRIPE_SECRET_KEY=sk_test_replace_me
STRIPE_WEBHOOK_SECRET=whsec_value_from_stripe_listenProduction webhook checklist
- Expose only the HTTPS webhook route required by Stripe.
- Store STRIPE_WEBHOOK_SECRET in managed secret configuration and rotate it through an intentional deployment process.
- Configure API version 2026-08-26.dahlia for the Stripe endpoint.
- Subscribe only to the seven event types the application handles unless the host adds another verified handler.
- Return errors for retryable processing failures; do not acknowledge work that was not committed.
- Monitor delivery failures, FAILED/stranded RECEIVED claims, projection drift, and database health.
- Keep sensitive payloads and secrets out of logs.
- Back up the local database and define reconciliation and fulfillment procedures.