Serverless ecommerce with AWS Lambda

UX image

In this post, we build a serverless e-commerce app using AWS Lambda, Stripe and React ensuring your website is ready for large traffic spikes.

Architecture

The bullet-proof, low-cost solution is based on a serverless architecture. Serverless is a hot topic today. There are basically two types of definitions:

First it can be used to describe applications that significantly or fully depend on 3rd party services in the cloud. These types of services can be described as “Backend as a Service” (BaaS). We can use Stripe as a BaaS provider for both inventory & order management and payments.

Second, it can also contain some amount of server-side logic but unlike traditional architectures the code is run as plain functions in “stateless compute containers that are event-triggered”. We can use AWS Lambda as a ‘’Functions as a Service” (FaaS) provider to communicate securely with Stripe servers and provide a basic Shop API for a web-based Shop Frontend.

The proposed architecture consists of four components.

  1. Inventory & Order Management: Stripe allows to add and receive product and inventory data (product information, sizes, colors, etc.) right from its dashboard or Products API. https://stripe.com/docs/api#products
  2. Shop API: To communicate with the Stripe API a secure server environment is still needed. Therefore we use AWS Lambda to execute server functions in the cloud and expose a public Shop API for products and inventory data. AWS Lambda is extremely cheap and we pay only for the time our code runs, and not for hours we rented servers for.
  3. Payments: Processing credit cards manually is difficult and dangerous. We use Stripe Checkout as an embeddable payment plugin. Customers can pay instantly, without exposing sensible credit card information to our code. https://stripe.com/checkout
  4. Shop Frontend: Instead of building the site on-demand on the server, we entirely host our shop as a static site on a content delivery network (CDN). CDNs offer improved scalability and fast load times by distributing assets globally. The current proof-of-concept site is built with Facebook’s React library.

Stripe's Relay allows retailers to sell goods directly in social networking and content apps. In addition, the architecture could leverage Relay’s built-in distribution capabilities and effortlessly add additional customer touch points such as social, voice or messenger bots. For more information take a look at the Stripe Relay documentation.

Implementation

First, we setup the product inventory. Second, we build a Shop API to make our product inventory publicly available. Third, we build the Shop Frontend to showcase our product inventory. Fourth, we include a payment method. Lastly, we send an order from our site to Stripe.

Setup the product inventory & order management

  1. Signup for a Stripe account on https://stripe.com
  2. Click on “Create your first product” in the dashboard’s products section and fill in some product details (ID, Name, Description, Images)
  3. Add SKUs (Stock Keeping Units) to the created product. Each product can be linked to one or many variants taking into account any combination of attributes (such as color, sizes) and cost. Note: A customer buys a variant of a product (e.g. specific color and size combination), not the product.

After this setup, Stripe exposes those products / variants via its Products API .

Build the Shop Frontend

We use Facebook’s Create React app template to setup an initial site with no build configuration.

yarn install -g create-react-appcreate-react-app serverless-shopcd serverless-shopyarn start

Build the Shop API

To communicate with the Stripe API a secure server environment is still needed. The secret key can be found in the API section of the Stripe dashboard. We use AWS Lambda to execute server functions in the cloud and expose a public Shop API for products and inventory data.

To simplify the FaaS setup we use the Serverless framework.

1. Setup the serverless environment

Install serverless globally$ npm install serverless -g

Create a separate folder for your serverless code$ mkdir serverless && cd serverless

Create a serverless function for fetching the products$ serverless create --template fetch-products

2. Respond with the fetched products from Stripe.

const stripe = require('stripe')(process.env.STRIPE_SECRET_KEY); module.exports.handler = (event, context, callback) => {    return stripe.products.list({limit: 10})    .then((products) => {          const response = {              statusCode: 200,              headers: {                  'Access-Control-Allow-Origin': '*',              },              body: JSON.stringify({                  data: products.data              }),          };          callback(null, response);  });

3. Deploy to AWS

# Deploy to cloud provider$ serverless deploy# Function deployed! Trigger with live urlhttp://xyz.amazonaws.com/fetch-products

The Shop Frontend should fetch the products from this endpoint.

4. Insert the displayed endpoint URL as productsUrl in config.json file

# Go to frontend folder$ cd src# Copy config.json.example$ cp config.json.example config.json# insert http://xyz.amazonaws.com/fetch-products as productsUrl into # config.json

Setup the Payment methods

Finally we use Stripe Checkout as an embeddable payment plugin.

1. Insert the Stripe Checkout Javascript library

$ cd public# Insert <script src=”https://checkout.stripe.com/checkout.js"></script> into the index.html file

2. Initialize Stripe Checkout in the componentDidMount() method in the PayButton component.

componentDidMount() {   this.handler = window.StripeCheckout.configure({     key: config.stripe.apiKey,     token: function (token) { self.onToken(token); }   }); }

3. Insert the Stripe API’s publishable key as apiKey in config.json.

After filling out the payment form, Stripe checks the credit card information and returns a token on success. We use the token to create and pay a order for a selected product variant.

Extend the Shop API with an order endpoint.

1. Create a serverless checkout function

   $ serverless create — template create-charge

2. Create an order and pay for it with the received payment token

const stripe = require('stripe')(process.env.STRIPE_SECRET_KEY);module.exports.handler = (event, context, callback) => {    const requestBody = JSON.parse(event.body);     // Payment information (from Stripe Checkout)    const token = requestBody.token.id;    const email = requestBody.token.email;     // Order information    const currency = requestBody.order.currency;    const items = requestBody.order.items;    const shipping = requestBody.order.shipping;  // Create order    return stripe.orders.create({        currency: currency,        items: items,        shipping: shipping,        email: email    }).then((order) => {    // Pay order with received token (from Stripe Checkout)       return stripe.orders.pay(order.id, {           source: token // obtained with Stripe.js        });       // Return success info to client (see full code on github)});

3. Deploy to AWS

# Deploy to cloud provider$ serverless deploy# Function deployed! Trigger with live urlhttp://xyz.amazonaws.com/create-charge

The Shop Frontend should post the order to this endpoint.

4. Insert endpoint URL as checkoutUrl in config.json file

# Go to frontend folder$ cd src# insert http://xyz.amazonaws.com/create-charge as checkoutUrl into # config.json

Run the app & make a test order

Finally, the whole site should be working. You can either run the app locally or in production.

# Run the app locall$ yarn start# Deploy the app e.g. via Firebase$ npm install -g firebase-tools$ firebase login$ firebase init# You will need to agree with database.rules.json being created, choose build as the public directory, and also agree to Configure as a single-page app by replying with y.# Create a production build$ yarn run build# Deploy the app$ firebase deploy

Visit the running site. Choose a size, fill in the delivery form, insert a test credit card and click on the pay button.

After that you should get a success notification and the recent order should be displayed in the products -> orders section of the Stripe dashboard.

Congratulations, you have finished all required steps to build a serverless e-commerce app!