Be part of JetBrains PHPverse 2026 on June 9 – a free online event bringing PHP devs worldwide together.

valentinmorice's avatar

Stripe webhook validation with multiple secrets

I'm working on an application that has multiple stripe webhook routes, and consequently multiple webhook secrets. In the Stripe documentation, they have the following snippet to verify the authenticity of the POST request:

$endpoint_secret = 'whsec_...';

$payload = @file_get_contents('php://input');
$sig_header = $_SERVER['HTTP_STRIPE_SIGNATURE'];
$event = null;

try {
    $event = \Stripe\Webhook::constructEvent(
        $payload, $sig_header, $endpoint_secret
    );
} catch(\UnexpectedValueException $e) {
    // Invalid payload
  http_response_code(400);
  echo json_encode(['Error parsing payload: ' => $e->getMessage()]);
  exit();
} catch(\Stripe\Exception\SignatureVerificationException $e) {
    // Invalid signature
    http_response_code(400);
    echo json_encode(['Error verifying webhook signature: ' => $e->getMessage()]);
    exit();
}

The problem is that the constructEvent function assumes there's only one webhook secret to try, and then throws an exception. Is there any way I could loop through my webhook secrets until the correct value is found, and throw the Exception only if none are matching? I'd like to keep the validation in a single middleware.

0 likes
5 replies
Snapey's avatar

Or have a webhook endpoint per secret?

valentinmorice's avatar

@martinbean I've got one form on the front-end that lets users decide to which entity they wish to donate money. Because each of those entities are legally distinct, they have a separate Stripe account.

On top of that, there's an admin panel form which allows for creating webhook routes that are saved in the DB, so I'd like to iterate through all of those in one place.

martinbean's avatar

@valentinmorice It sounds like you should be using Stripe Connect instead, if you want multiple vendors to be able to connect their own Stripe accounts, and receive donations.

Parminder1494's avatar

@valentinmorice You can introduce dynamic segments within your route. These dynamic segments enable you to filter out which endpoint_secret you wish to utilize based on the provided dynamic segments.

Please or to participate in this conversation.