Nadiya
Nadiya

Reputation: 402

handling stripe webhook in multiple stripe account laravel

I've multiple stripe account on my site, and each stripe account is associated with a webhook.
My webhook is returning 403 Error "No signatures found matching the expected signature for payload"

i've checked the Cashier middleware and its getting the webhook secret key from the env file.
Since this project attached to multiple stripe account, we can't store the webhook secret in env file. so, we're placing the webhook secret key of each stripe account in a table.

cashier webhook signature middleware

I would like to get the secret key from database instead of this config file.

Is it possible to listen to multiple stripe account's webhook?

Any help will be appreciated.

Upvotes: 0

Views: 776

Answers (1)

Norbert Norbertson
Norbert Norbertson

Reputation: 2230

I am not sure if this is a good approach but you can:

  1. Send meta data in the checkout which gets posted to the web hook
  2. Get the raw json posted by the web hook before you use the web hook key to validate that the post was from Stripe. Stripe.Net contains a parse method and a construct method. Parse does not require the key. Construct uses the key to validate the post was from Stripe.

So with Stripe.net:

string endpointSecret;

// get the json posted
var json = await new 
StreamReader(HttpContext.Request.Body).ReadToEndAsync();

// convert the json into a stripe event object
var objStripeEvent = EventUtility.ParseEvent(json);
if (objStripeEvent.Type == Events.CheckoutSessionCompleted)
{
   // get the session object and see if it contains the Meta data we passed 
   // in at checkout
   var session = objStripeEvent.Data.Object as Session;
   var met = session.Metadata;
   if (met.ContainsKey("FranchiseGuid"))
   {
       // if the meta data contains the franchise guid get the correct
       // wh secret from the DB
       var FranchiseGuid= new Guid(met["FranchiseGuid"]);
       endpointSecret = _repo.GetWebHookSecret(FranchiseGuid);

    }
 }

// Then you can go on to use the Construct method to validate the post with the correct key for the Stripe account where the web hook is based.

try
{
  // check if was from Stripe
  var stripeEvent = EventUtility.ConstructEvent(
  json,
  Request.Headers["Stripe-Signature"],
  endpointSecret);

  ---- etc

I've requested help on this from Stripe support but they have promised to get back to me. I'll test out the above to see if it works. I don't think it's ideal though because if a hacker were able to get a valid franchise guid they could possibly fake posts and spam the endpoint. It would not be easy to guess a guid and these id's are not available in any way publicly. Plus https is used. But it still makes me nervous because the franchise guid would be one of a dozen or more. Not like a booking guid which is generated and sent once for the booking that is marked as paid. The franchise guid would be sent every time a payment was made for that franchise.

I think what I may do is use the booking guid since this is randomly generated for every booking. I can join to the franchise table from the booking and get the web hook secret.

We'll see if Stripe come back with something useful.

Upvotes: 0

Related Questions