Using the new Stripe Checkout in Gatsby + AWS Amplify: Redirect to checkout (client-side)
Tags: gatsby, stripe, awsamplify, serverless
Published: 2020-06-19 17:21:02

In the first part of this series of posts you created a Lambda function, using AWS Amplify, to create a Stripe Checkout session. In this post, you'll redirect your customer to the Stripe Checkout page using the checkout session Id.

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

## Step 1. Install Stripe.js
Stripe Checkout relies on Stripe's javascript library, Stripe.js. At the root of your Gatsby project, within terminal, install Stripe.js:

```shell
npm install @stripe/stripe-js
```

### Stripe fraud detection

Stripe includes some advanced fraud functionality that helps detect suspicious behaviour as prospective customers browse your site. The Stripe.js module inserts a `<script>` tag that loads Stripe.js from `https://js.stripe.com` as a side effect when the module is imported. For optimal fraud detection, the Stripe.js script needs to be available on every page of your website. [The gatsby-browser.js API file](https://www.gatsbyjs.org/docs/api-files-gatsby-browser/) is the perfect place to import the Stripe.js module in order to meet this requirement. 

At the route of your project, create a `gatsby-browser.js` file:
```shell
touch gatsby-browser.js
```
At the top of the gatsby-browser.js file import the Stripe.js module:

```javascript
// gatsby-browser.js
import '@stripe/stripe-js'
```

## Step 2. Create a checkout button component

Create a `CheckoutButton.js` component within the `/src/components/` folder
```shell
touch src/components/CheckoutButton.js
```
`Import React` and `export default` an empty `CheckoutButton` function:
```javascript
import React from "react"

const CheckoutButton = () => {}

export default CheckoutButton
```
Return a `<button>Continue to payment</button>` from the `CheckoutButton` function:
```javascript
import React from "react"

const CheckoutButton = () => {
  return <button>Continue to payment</button>
}

export default CheckoutButton
```
Add an empty async `redirectToCheckout` function to the `CheckoutButton` component function:
```javascript
import React from "react"

const CheckoutButton = () => {
  const redirectToCheckout = async () => {}

  return <button>Continue to payment</button>
}

export default CheckoutButton
```
You want this function to be called when the customer clicks the `Continue to payment` button. Use an `onClick` event handler to call the `redirectToCheckout` function when the button is clicked.
```javascript
import React from "react"

const CheckoutButton = () => {
  const redirectToCheckout = async () => {}

  return <button onClick={redirectToCheckout}>Continue to payment</button>
}

export default CheckoutButton
```
## Step 3. Fetch the Stripe Checkout session
The `redirectToCheckout` function needs to call the Lambda function you created in part 1 to retrieve the Stripe Checkout session. To interact with the Lambda you need to import `API` from `aws-amplify`. To add Amplify to your app, in terminal run:
```bash
npm install aws-amplify
```
Import and configure Amplify within `gatsby-browser.js`:
```javascript
import Amplify from "aws-amplify"
import awsconfig from "./src/aws-exports"
Amplify.configure(awsconfig)
```
Import `API` from `aws-amplify` at the top of your `CheckoutButton.js` component file:
```javascript
import { API } from 'aws-amplify'
```
Add an empty async `fetchSession` function to your `redirectToCheckout` function
```javascript
const redirectToCheckout = async () => {
      const fetchSession = async () => {}
  }
```
Within this function send a `POST` request to the `stripeAPI`, `/checkout` endpoint that AWS Amplify created for you using AWS API Gateway in part 1. The Lambda function you wrote in part 1 is expecting 3 body params in this request – `priceId`, `quantity` and `client_reference_id`. Modify your `fetchSession` function to call the API endpoint to return the session Id:
```javascript
const redirectToCheckout = async () => {
      const fetchSession = async () => {
        const apiName = 'stripeAPI'
        const apiEndpoint = '/checkout'
        const body = {
            quantity: 1,
            client_reference_id: 'UniqueString',
            priceId: ''
        }
        const session = await API.post(apiName, apiEndpoint, { body })
        return session
      }
  }
```
As mentioned in part 1, the `client_reference_id` is a unique reference you can send to Stripe that will help you identify this purchase for the payment confirmation webhook later. The `priceId` is the priceId of the product you setup on Stripe in part 1. 

To fetch the `priceId` of the product you created from the Stripe dashboard: 

1. Log into your Stripe dashboard
2. Navigate to `Products`
3. Select the product `Pro Plan` you created earlier
4. Within the `Pricing` section, look for the `API ID`. It will look something like `price_1GuxxSBwl4TwghDgsuUB0RGd`. *If the Id you've copied begins with `prod_` this is not the right Id.*

Add the `priceId` to the body object within the `fetchSession` function:
```javascript
const body = {
        quantity: 1,
        client_reference_id: "UniqueString",
        priceId: "price_1GuxxSBwl4TwghDgsuUB0RGd",
      }
```
## Step 4. Redirect to the Stripe Checkout using the session Id
Fetch your Stripe publishable API key from [Stripe Dashboard > Developers > API Keys](https://dashboard.stripe.com/account/apikeys). It will look something like `pk_test_KT4KxozC6O8d3krb3FEjbBp00eruf93Bh`.

At the top of the `CheckoutButton.js` file, Import `loadStripe` from `@stripe/stripe-js`
```javascript
import { loadStripe } from '@stripe/stripe-js';
```
In order to setup the stripePromise you need to call the `loadStripe` function using your publishable key:
```javascript
const stripePromise = loadStripe('pk_test_KT4KxozC6O8d3krb3FEjbBp00eruf93Bh');
```
Within the main body of the `redirectToCheckout` function, await the `stripePromise`, fetch the `sessionId` and call Stripe's `redirectToCheckout` function using the sessionId:
```javascript
const session = await fetchSession()
const sessionId = session.id
const stripe = await stripePromise
stripe.redirectToCheckout({ sessionId })
```
Your `CheckoutButton.js` component should now look like:
```javascript
import React from "react"
import { API } from "aws-amplify"
import { loadStripe } from "@stripe/stripe-js"

const stripePromise = loadStripe("pk_test_KT4KxozC6O8d3krb3FEjbBp00eruf93Bh")

const CheckoutButton = () => {
  const redirectToCheckout = async () => {
    const fetchSession = async () => {
      const apiName = "stripeAPI"
      const apiEndpoint = "/checkout"
      const body = {
        quantity: 1,
        client_reference_id: "UniqueString",
        priceId: "price_1GuxxSBwl4TwghDgsuUB0RGd",
      }
      const session = await API.post(apiName, apiEndpoint, { body })
      return session
    }

    const session = await fetchSession()
    const sessionId = session.id
    const stripe = await stripePromise
    stripe.redirectToCheckout({ sessionId })
  }

  return <button onClick={redirectToCheckout}>Continue to payment</button>
}

export default CheckoutButton
```
Now import the `CheckoutButton` into a page within your site. When your customer clicks `Continue to payment` they will be taken to the Stripe Checkout page:
![Stripe Checkout page](https://dev-to-uploads.s3.amazonaws.com/i/qd5iwtdxooqtrs1vl7c5.png)
In the next post, you'll implement the Stripe webhook to receive confirmation when the payment has been completed.