Using the new Stripe Checkout in Gatsby + AWS Amplify: Return a session (server-side)
Tags: gatsby, awsamplify, stripe, serverless
Published: 2020-06-19 17:20:42

The new [Stripe Checkout](https://stripe.com/docs/payments/checkout) introduces a beautiful UI. When combined with AWS Amplify, you can use it to add payments and subscriptions to your Gatsby site. Over the next three posts I will walk through how to integrate Stripe Checkout within a Gatsby project using AWS Amplify.

Take a look at the code from this blog post on [Github](https://github.com/beezeebly/gatsby-stripe-checkout-amplify-example).

![The new Stripe Checkout](https://dev-to-uploads.s3.amazonaws.com/i/qqpzhdvn8hfa3g6uadcu.gif)

There are three parts to integrating Stripe Checkout with Gatsby:

### Part 1. Return a session (*server side*)
In order for a customer to be able to pay for a product or subscription using Stripe Checkout a checkout session, that represents the customer's order, needs to be created. You'll use an AWS Lambda function, created via AWS Amplify, to interact with the Stripe API and create/return the Stripe Checkout session.

### Part 2. Redirect to checkout (*client side*)
Your customers will select a product to purchase on your Gatsby website. Your site will call the Lambda function you created in part 1 to retrieve your Stripe Checkout session. You'll need the session Id to redirect your customer to the Stripe hosted checkout.

### Part 3. Payment confirmation (*webhook*)
Finally, you'll add a webhook within the Stripe Dashboard that will send confirmation to your app when the Stripe payment has been completed. You'll use another AWS Lambda function here, created via AWS Amplify, to listen out for when Stripe calls the webhook.

## Part 1. Return a session

*These instructions assume you have a [Gatsby project](https://www.gatsbyjs.org/docs/quick-start/), that you have [installed and configured the AWS Amplify CLI](https://docs.amplify.aws/cli/start/install#option-2-follow-the-instructions) and that you have signed up for [Stripe](https://stripe.com).*

### Step 1. Add a product to the Stripe dashboard
To use Stripe Checkout you first need a product to sell. For the purposes of this tutorial, you are going to sell a subscription `Pro Plan` priced at `$12/month` for your service.

1. Sign into [Stripe](https://stripe.com).
2. From the [Dashboard](https://dashboard.stripe.com) navigate to the [Products](https://dashboard.stripe.com/test/products) page.
3. Click `+ Add product`.
4. Enter a product `name` i.e. Pro Plan.
5. Enter a `price` i.e. $12.
6. Ensure that `recurring` is selected.
7. Select a billing period of `monthly`.
8. Click `Save product`

### Step 2. Initiate Amplify for your Gatsby project

Use the Amplify CLI to initiate your Amplify project by running the following command within your terminal at the root of your Gatsby project:

```shell
amplify init
```
Amplify will run through the following series of configuration questions:

```shell
Enter a name for the project
```
Enter `gatsbyStripeCheckout`.
```shell
Enter a name for the environment
```
Press Enter to select the default environment of `dev`.
```shell
Choose your default editor:
```
Select your default code editor i.e. `Visual Studio Code`.
```shell
Choose the type of app that you're building
```
Select `javascript`.
```shell
What javascript framework are you using
```
Select `react`.
```shell
Source Directory Path:
```
Press Enter to select the default path of `src`.
```shell
Distribution Directory Path:
```
Press Enter to select the default path of `build`.
```shell
Build Command:
```
Press Enter to select the default command of `npm run-script build`.
```shell
Start Command:
```
Press Enter to select the default command of `npm run-script start`.
```shell
Do you want to use an AWS profile?
```
Enter `Y`.
```shell
Please choose the profile you want to use
```
Select the profile you'd like to use i.e. `default`.
### Step 3. Create a Lambda function
Now you've configured Amplify for your project, use the Amplify CLI to setup a boilerplate AWS Lambda function that is accessible via AWS API Gateway. You'll modify this function later to call the Stripe API and retrieve the checkout session.

To setup the Lambda function and API Gateway, within terminal, at the root of your project, run:

```shell
amplify add api
```
Amplify will walk through the following configuration question:
```shell
Please select from one of the below mentioned services:
GraphQL
❯ REST
```
Choose `REST`.
```shell
Provide a friendly name for your resource to be used as a label for this category in the project:
```
Enter `stripeAPI` or a name of your choosing.
```shell
Provide a path (e.g., /book/{isbn}):
```
Enter `/checkout`
```shell
Choose a Lambda source (Use arrow keys)
❯ Create a new Lambda function
```
Choose `Create a new Lambda function`
```shell
Provide a friendly name for your resource to be used as a label for this category in the project:
```
Enter `stripeCheckout`
```shell
Provide the AWS Lambda function name:
```
Press Enter to select the default name of `stripeCheckout`
```shell
Choose the function runtime that you want to use:
```
Select `NodeJS`
```shell
Choose the function template that you want to use: 
  Hello World 
  CRUD function for DynamoDB (Integration with API Gateway) 
❯ Serverless ExpressJS function (Integration with API Gateway) 
  Lambda trigger 
```
Select `Serverless ExpressJS function (Integration with API Gateway)`
```shell
Do you want to access other resources created in this project from your Lambda function? (Y/n)
```
Enter `n`.
```shell
Do you want to invoke this function on a recurring schedule? (y/N)
```
Enter `n`.
```shell
Do you want to edit the local lambda function now? (Y/n)
```
Enter `n`.
```shell
Restrict API access (Y/n)
```
Enter `n`.
```shell
Do you want to add another path? (y/N)
```
Enter `n`.

Within your Gatsby project, Amplify has created a directory `/amplify`. This contains a `/backend` folder within which sits the boilerplate `/api` and `/function` code.

![Gatsby Amplify folder directories](https://dev-to-uploads.s3.amazonaws.com/i/ku4x7f6n12bibx5ru95g.png)

### Step 4. Write the Stripe checkout function
Now the Amplify configuration has been completed, in your terminal navigate to the `amplify/backend/function/stripeCheckout/src` folder within your Gatsby project:

```shell
cd /<GATSBY_ROOT_PATH>/amplify/backend/function/stripeCheckout/src
```
Install Stripe:
```shell
npm install stripe
```
Now, in your code editor, open the `app.js` folder within the `/amplify/backend/functions/stripeCheckout/src/` directory.

To the top of the file add:

```javascript
const stripe = require('stripe')(process.env.STRIPE_SECRET_KEY);
```

`process.env.STRIPE_SECRET_KEY` refers to an environment variable the Lambda will have access to that you will add manually using the AWS console later on. *It is best not to hardcode the Stripe secret key here as it would be saved to your git repo.* 

Delete the example `get`, `post`, `put` and `delete` code and replace it with the following async `post` function:

```javascript
app.post('/checkout', async function(req, res) {
  try {
    const session = await stripe.checkout.sessions.create({
      payment_method_types: ['card'],
      line_items: [
        {
          price: req.body.priceId, // The priceId of the product being purchased, retrievable from the Stripe dashboard
          quantity: req.body.quantity,
        },
      ],
      mode: 'subscription',
      client_reference_id: req.body.client_reference_id,
      success_url:
        'https://example.com/success?session_id={CHECKOUT_SESSION_ID}', // The URL the customer will be directed to after the payment or subscription creation is successful.
      cancel_url: 'https://example.com/cancel', // The URL the customer will be directed to if they decide to cancel payment and return to your website.
    })
    res.json(session)
  } catch (err) {
    res.json(err)
  }
})
```

This function returns the response of the `stripe.checkout.sessions.create` call. The object passed to this function includes:
```javascript
  line_items: [
        {
          price: req.body.priceId,
          quantity: req.body.quantity,
        },
      ]
```
#### Stripe attributes
The price is the `priceId` of the product your customer is purchasing, as created within the Stripe dashboard in step 1. You will pass the `priceId` and `quantity` from the checkout page that you will create in the next post in this series.

The `client_reference_id` is a reference that will be available to the webhook you will create in the final post of this series. It is useful for matching up a payment to a customer or purchase.

Visit the [Stripe checkout session API docs](https://stripe.com/docs/api/checkout/sessions/object) to see all the attributes you can pass to the session object.

### Step 5. Publish your updates to your AWS account

From the terminal, run:

```shell
amplify push
```
It will show you the following table:
![Amplify push table](https://dev-to-uploads.s3.amazonaws.com/i/ytstrr01i62cdd8vt3ia.png)
and it will ask:
```shell
Are you sure you want to continue? (Y/n)
```
Enter `y`.

The `amplify push` command takes a few minutes to complete.


### Step 6. Add your Stripe secret key as an environment variable to your Lambda

1. Log in to your Stripe account and click on the `Developers` link and [navigate to your API keys](https://dashboard.stripe.com/account/apikeys). Reveal and copy the secret key token, it will look something like `sk_test_LE4KxozC6O8d3krb3FEjbBp00erufO2Bm`.

2. Log in to your AWS console and navigate to your Lambda page.

3. Find your `stripeCheckout-dev` function on the Lambda > Functions list (If you can't find it, check you are in the correct region within the AWS console)

4. On the stripeCheckout function page within the AWS console, scroll down to the Environment Variables area and click `Edit`.

5. Add a new variable called `STRIPE_SECRET_KEY` with the value of the Stripe secret key you downloaded earlier and click `Save`.

![AWS Lambda environment variables](https://dev-to-uploads.s3.amazonaws.com/i/2dk1a0ion4m0eyb3m30k.png)

You have setup AWS API Gateway and an AWS Lambda function to handle retrieving and returning a Stripe Checkout function. In the next post, you'll write a `checkoutButton` component that will redirect your customer to the Stripe Checkout.