They are helpful and powerful, but can be tricky to set up. So when would Stripe webhooks be used? One major use-case is to add transparency to your payments (See Fig. 1.). This is not only beneficial for users but for administrators since it reduces support requests.
At Faros we’ve recently rewritten our payments architecture to utilize Stripe webhooks. The only major pain point we found in this process was that the documentation was a little lacking. This is unlike most of Stripe’s documentation, which is amongst the best we’ve encountered. So we figured we’d write about our findings, with a step-by-step guide, in case it can help you.
Note: These steps include code for a Node Express app. Check out the official Node.js library for the Stripe API.
Step one is to correctly parse the body to verify the signature (explained in the next step) and read the data. This requires some extra work because the body needs to be parsed to raw binary while the rest of our API is parsed to JSON. Basically this means we need to handle the webhook route before the other routes are parsed with bodyParser.
A very important step is to make sure you’re using Stripe webhooks securely. How can you do this? One important thing you can do is to verify that all webhooks are coming from Stripe. This requires verifying the stripe-signature in the header of the request. If you’re correctly parsing the body then this step should be smooth sailing. The API provides a method to verify the signature and construct the event (stripe.webhooks.constructEvent).
3. Events / Webhook types
Next you’ll need to set up your webhooks in your Stripe account. One major difficulty you’ll run into is testing these webhooks locally. For development we use ngrok to tunnel our localhost to a url so Stripe events can hit our local development environment. Once the Stripe webhook is created a secret will be generated that you can input into step two where it says env.endpointSecret.
At Faros we use Stripe Connect to send student payments to landlords. We need two types of webhooks for this; Account and Connect Apps (see Fig. 2). As the names imply, Account webhooks are used for all events that occur on your Stripe account, while Connect Apps webhooks are used for all events that occur on your connected accounts.
4. Other things to remember
Event Idempotency: Be sure not to process the same event twice. To do this, store previously processed events in a table (since every Stripe event has an associated ID) and cross-reference that table for every received event.
Limit events: Filter the specific events sent (see Fig. 3), so as not to overwhelm your API with unneeded requests. Basically make sure you only send events that you actually want to process on your API.
Metadata: Add metadata objects in Stripe to use in the webhooks. For instance, on a charge creation we add our internal payment id to cross-reference when the webhook for that payment is sent. Note: Metadata is associated with the events on your account so they aren’t forwarded to the connected account.
Cheatsheet: Here is an event cheatsheet to help you out a little.
We hope this helps and feedback is welcome!