Use Stripe Webhook to implement your business logic in an Amplify project (serverless with AWS Lambda)

Yann Dnz
Yann Dnz
Nov 27, 2019 · 6 min read

On my last tutorial, I showed you how to implement a pay button in your React/Amplify website so you can start receiving payments. That’s good, but in the vast majority of use cases this will not be enough. You also want to update your own backend (here it will be DynamoDB) with the payment information, for instance to unlock the service your visitor just purchased. So if you’re ready, let’s see what you’ll need!

Prerequisites

  • You already have a React project setup with Amplify initialized with a graphQL api
  • You already have a Stripe account
  • You can proceed to a payment (the method here show a way but it doesn’t really matter if you used another method)

GraphQL setup

For this tutorial purpose, we will assume that the business logic you want to implement is simply to add an entry in your DB when you receive a payment.

Of course, you don’t want users to be able to write directly in it but you want them to be able to read this table. So you can add something like that in your schema.graphql:

The mutation: null insure that only our backend will be able to update this table so we can trust data we get from there.

Now push this table:

Create the endpoint

On the previous tutorial, we already added an API named stripeapi with a checkout endpoint. So we will add another endpoint in the same API, but it is exactly the same process if you are creating one from scratch:

and answer as bellow:

The new lambda function should now be accessible on you amplify backend project.

Update permissions

The first thing we need to do, is allowing this lambda to access/update DynamoDB. We can do that by updating the cloudformation template in the function folder: stripeWebhook-cloudformation-template.json

Open this json and find lambdaexecutionpolicy. Under this key, you will find Properties/PolicyDocument/Statement. The Statement array is the one listing your permission, thus it is the one you want to update. Add two entry in this array as followed (bold):

Import dependencies

Add the following in app.js.

You’ll also need to install uuid and stripe inside the function folder:

Toogle variables based on current environment

I didn’t talk about it before but I am using two environment in this project, one dev and one prod. I am not going to explain in detail how it works as there are plenty of tutorials out there that do it pretty well. If you only use one environment, then you can only add the set of variable you are using. For two environment, this is how you can do:

You test and live Stripe secrete keys and can be found in your Stripe account. For the endpointSecret, you will obtain it later when you create the Stripe webhook, leave it empty for now. For the payment table, it would be very nice if the name could be injected directly by Amplify as environment variable, let me know in the comments if you have a cleaner way to do it.

Important: Get the raw body

This is the part I spent the most time to have my code working. The issue is that lambda automatically Stringify the body which doesn’t create any issue most of the time. However, to prevent fraud, we will check that Stripe is sending us the request and not someone else. To do so, we will use stripe.webhooks.constructEvent(body, signature, endpointSecret). This function will fail if the body have been even slightly modified (which is exactly what we are expecting from it!).

To prevent that we need to access the rawBody. Add this code before your post function:

Add your code

Now we are all set, we can start implementing the business logic!

We are going to implement the post request. Inside the app.post(‘/webhook’, function (request, response) add the following lines:

This ask Stripe to authenticate the request and create an event object we can easily manipulate.

Then we can execute different code, based on the event we received. Here we are interested in the checkout.session.completed, when we receive it we add an entry to our db:

We are done here! Your function can handle a Stripe webhook event! Push it:

Create the webhook on Stripe

Now that your backend is ready, you need to ask Stripe to send an event when a checkout session is complete (or any other event you like).

First you’ll need to find the complete address of the lambda you just created. To do so, connect to your aws console and go to apiGateway select stripeapi (if you gave the same name as me), Stages, dev (or the name of your environment). You should see the Invoke URL in blue on the top of the screen. Add the name of your endpoint to this url, for me /webhook. Your url should looks like that:

https://******.execute-api.eu-central-1.amazonaws.com/dev/webhook

Now that you know the url to hit, go on your Stripe dashboard. Click Developers, Webhooks and Add endpoint. Add your url and choose the checkout.session.completed event. Validate.

Now you can obtain your endpoint secret, go back on your lambda function (app.js) and update it. Push the change with amplify push.

Congrats!

That’s done now! When someone pays on your website through a checkout session, your lambda will be triggered and a new entry will be added on your DynamoDB. You can get this information as usual with graphQl and update your frontend accordingly!

Thanks for reading, you can find a the source code of the app.js in my Github.

Serveless with React and AWS Amplify

Tutorials and discussions to implement fast and innovative solutions using React and AWS Amplify

Yann Dnz

Written by

Yann Dnz

Aeronautical and Software engineer, worked in R&D for drone development. Passionate by high technology, I also develop custom cloud based solutions for company.

Serveless with React and AWS Amplify

Tutorials and discussions to implement fast and innovative solutions using React and AWS Amplify

Welcome to a place where words matter. On Medium, smart voices and original ideas take center stage - with no ads in sight. Watch
Follow all the topics you care about, and we’ll deliver the best stories for you to your homepage and inbox. Explore
Get unlimited access to the best stories on Medium — and support writers while you’re at it. Just $5/month. Upgrade