The shared WebhookDispatcher in @emulators/core sends webhook deliveries with X-Hub-Signature-256 and X-GitHub-Event headers (GitHub's format). When the Stripe plugin dispatches checkout.session.completed webhooks, they arrive with these GitHub-style headers instead of Stripe's stripe-signature header.
This means stripe.webhooks.constructEvent(body, sig, secret) in the receiving app always fails because stripe-signature is never present. Apps that verify webhook signatures (which Stripe strongly recommends) can't use the emulator for end-to-end webhook testing without a workaround.
Expected: Stripe webhook deliveries should use the stripe-signature header with Stripe's t=<timestamp>,v1=<hmac> format so constructEvent works out of the box.
Workaround: Accept both stripe-signature (production) and X-Hub-Signature-256 (emulator) in the webhook handler, or skip verification for unsigned payloads in test environments.
Where the fix would go: The WebhookDispatcher.dispatch() in packages/@emulators/core/src/webhooks.ts is service-agnostic. Either make the signature format configurable per service, or have the Stripe plugin use a Stripe-specific dispatcher that produces the right header format.
The shared
WebhookDispatcherin@emulators/coresends webhook deliveries withX-Hub-Signature-256andX-GitHub-Eventheaders (GitHub's format). When the Stripe plugin dispatchescheckout.session.completedwebhooks, they arrive with these GitHub-style headers instead of Stripe'sstripe-signatureheader.This means
stripe.webhooks.constructEvent(body, sig, secret)in the receiving app always fails becausestripe-signatureis never present. Apps that verify webhook signatures (which Stripe strongly recommends) can't use the emulator for end-to-end webhook testing without a workaround.Expected: Stripe webhook deliveries should use the
stripe-signatureheader with Stripe'st=<timestamp>,v1=<hmac>format soconstructEventworks out of the box.Workaround: Accept both
stripe-signature(production) andX-Hub-Signature-256(emulator) in the webhook handler, or skip verification for unsigned payloads in test environments.Where the fix would go: The
WebhookDispatcher.dispatch()inpackages/@emulators/core/src/webhooks.tsis service-agnostic. Either make the signature format configurable per service, or have the Stripe plugin use a Stripe-specific dispatcher that produces the right header format.