Host it on Val Town ā this val is a ready-made receiver. It verifies the Stripe-Signature header against your webhook signing secret, stores each event (id, type, created, full JSON) in this val's SQLite database in a stripe_events table, and returns 200 immediately. Duplicate deliveries of the same event id are ignored.
- Remix this val.
- In the Stripe dashboard, add a webhook endpoint pointing at this val's HTTP URL: https://dashboard.stripe.com/webhooks/create
- Copy that endpoint's signing secret (starts with
whsec_) and set it as an env var:
š Add STRIPE_WEBHOOK_SECRET here: https://www.val.town/x/templates/stripe-webhook-receiver/environment-variables?key=STRIPE_WEBHOOK_SECRET
Send a correctly signed fake event with curl (uses the same HMAC-SHA256 scheme as Stripe):
URL="https://templates--019eb3e79454748cb661151a775d952d.web.val.run" SECRET="whsec_..." # your STRIPE_WEBHOOK_SECRET value TS=$(date +%s) BODY='{"id":"evt_test_123","object":"event","type":"payment_intent.succeeded","created":'$TS',"data":{"object":{}}}' SIG=$(printf '%s' "$TS.$BODY" | openssl dgst -sha256 -hmac "$SECRET" | awk '{print $2}') curl -i -X POST "$URL" \ -H "Content-Type: application/json" \ -H "Stripe-Signature: t=$TS,v1=$SIG" \ -d "$BODY"
Expect {"received":true} and a new row in stripe_events. A request with a missing or bad signature returns 400.
You can also send a real test event: with your endpoint configured in Stripe test mode, run stripe trigger payment_intent.succeeded with the Stripe CLI.
main.tsā HTTP handler: verifies the signature, saves the event, returns 200db.tsā SQLite table setup and insert