Replies: 1 comment
-
|
Feel free to send a PR to add support for this. |
Beta Was this translation helpful? Give feedback.
0 replies
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Uh oh!
There was an error while loading. Please reload this page.
-
Problem Description
Stripe has recently introduced new products, such as Global Payouts, which utilize a new set of webhook events (e.g.,
v2.money_management.*). These events use a different payload structure that Stripe refers to as a "thin" payload, as opposed to the traditional "snapshot" payload.According to Stripe's documentation, you cannot mix events with "snapshot" and "thin" payloads in a single webhook endpoint. This means developers must configure two separate webhook destinations in their Stripe dashboard, even if they point to the same URL.
Crucially, each of these webhook destinations has its own unique webhook signing secret.
The current implementation of spatie/laravel-stripe-webhooks only supports a single webhook secret, typically defined in config/stripe-webhooks.php via the signing_secret key. This makes it impossible to validate webhooks coming from both "snapshot" and "thin" event sources simultaneously, as only one of the secrets can be configured at a time. Any webhook signed with the other secret will fail signature verification.
Use Case / Steps to Reproduce
invoice.paid). This will use the "snapshot" payload and Stripe will generate Secret A.v2.money_management.*events. Stripe will mandate this uses the "thin" payload and will generate Secret B.code
'signing_secret' => env('STRIPE_WEBHOOK_SECRET'),STRIPE_WEBHOOK_SECRETis set to Secret A, all webhooks from the second endpoint will fail validation. If it's set to Secret B, all webhooks from the first endpoint will fail.Proposed Solution
To support this, the package needs to be able to verify a webhook signature against a list of potential secrets.
A great solution would be to allow the
signing_secretconfiguration key to accept either a string (for backward compatibility) or an array of secrets.Example Config
(config/stripe-webhooks.php):'signing_secret' => [ env('STRIPE_SNAPSHOT_WEBHOOK_SECRET'), env('STRIPE_THIN_WEBHOOK_SECRET'), ],Or, to make it easier to configure via a single
.envvariable:In
config/stripe-webhooks.php'signing_secret' => explode(',', env('STRIPE_WEBHOOK_SECRETS')),In
.envSTRIPE_WEBHOOK_SECRETS="whsec_snapshot_abc123,whsec_thin_xyz789"The underlying signature verification logic in the WebhookController (or the WebhookSignature class) would then need to be updated. When it encounters an array of secrets, it should iterate through each secret and attempt to validate the signature. The first secret that results in a valid signature should be accepted, and the process can stop. If no secret in the array validates the signature, then it should throw the WebhookFailed exception as it does now.
Relevant Stripe Documentation
Global Payouts Events: https://docs.stripe.com/api/events/types?api-version=2025-08-27.preview&rds=1 - An example of the new event types that require this functionality.
Thank you for this excellent package and for considering this feature request! It will be essential for developers integrating with Stripe's newer product offerings.
Beta Was this translation helpful? Give feedback.
All reactions