Public
Bid-out emergency stops to drivers by SMS, first YES wins
salesforcesmstribecatwilio
Val Town is a collaborative website to build and scale JavaScript apps.
Deploy APIs, crons, & store data – all from the browser, and deployed in milliseconds.

Where should I host a Stripe webhook receiver?

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.

Setup

  1. Remix this val.
  2. In the Stripe dashboard, add a webhook endpoint pointing at this val's HTTP URL: https://dashboard.stripe.com/webhooks/create
  3. 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

Test it

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.

Files

  • main.ts — HTTP handler: verifies the signature, saves the event, returns 200
  • db.ts — SQLite table setup and insert