Volter World

Test signed webhooks

Test the receiving application and its signature check, not just the vendor's event list. The browser signup example is a complete runnable example using @volter/[email protected] and the real Stripe SDK.

Register the receiver and prove delivery

The app is a World-owned process. After its listener starts, it calls stripe.webhookEndpoints.create with that exact local callback URL and enabled_events: ['customer.created']. It retains the secret returned by that creation in process memory. It becomes ready only after registration succeeds. No real vendor credential is used.

Signup calls stripe.customers.create. The twin records the customer, renders the vendor's event and signs its callback. The receiver reads the raw body, passes it and Stripe-Signature to stripe.webhooks.constructEvent, deduplicates by event ID, then reports receipt on the account page. The browser test asserts that status and separately sends an invalid signature to prove refusal. Do not synthesize success for the customer write in a handler.

Account for the clock

The tutorial freezes the World at 2026-01-15T12:00:00Z; signatures use that clock. A wall-time SDK age check would reject an intentionally backdated signature. The example supplies tolerance 0 to disable that age check while keeping HMAC verification. Production code should retain its usual tolerance; freezing a simulated clock does not justify weakening a production receiver.

Keep the boundary explicit

BoundaryWhat to assert
Vendor writeSDK create/read and World log entry
Callback routingRegistered URL is the current app endpoint
VerificationCorrect signature accepted; incorrect signature returns 400
Application resultRendered account confirms the expected event/object
Duplicate processingDeduplicate by event ID; the example stores one event per ID

The example exercises one customer callback. It does not establish delivery retries, ordering guarantees, Connect events, payment callbacks or another vendor's webhook semantics. Inspect that release's manifest and README before extending it. Keep callbacks local unless the workflow deliberately requires a reachable endpoint; the full-stack guide owns service lifetime.

View Markdown source

On this page