Building a E-commerce App with React and Stripe API

Building an E-commerce App with React and Stripe API

In this tutorial, we will learn how to build a fully functional E-commerce app using React and integrate it with the Stripe API for payment processing. We will start by setting up the development environment, then proceed to building the user interface, integrating the Stripe API, and finally managing orders and inventory. By the end of this tutorial, you will have a complete E-commerce app that is ready for testing and deployment.

building e commerce app react stripe api

Introduction

What is an E-commerce App?

An E-commerce app is a web application that allows users to browse, select, and purchase products online. It typically consists of product listings, a shopping cart, and a payment processing system. With the rise of online shopping, E-commerce apps have become an essential tool for businesses to reach a wider audience and increase sales.

Why use React for E-commerce?

React is a popular JavaScript library for building user interfaces. It provides a component-based architecture that allows developers to create reusable UI components, making it easier to build complex user interfaces. React's virtual DOM also improves performance by efficiently updating only the necessary parts of the UI.

For E-commerce apps, React's component-based architecture is particularly useful in creating reusable UI components such as product listings, shopping carts, and checkout forms. It also allows for easy integration with external APIs, such as the Stripe API for payment processing.

Overview of Stripe API

The Stripe API is a set of tools and services provided by Stripe, a popular payment processing platform. It allows developers to securely accept and process payments online. The Stripe API provides various features such as creating and managing customer accounts, processing payments, and handling refunds.

In this tutorial, we will focus on integrating the Stripe API to enable payment processing in our E-commerce app. We will create a Stripe account, configure the necessary API keys, and implement the payment processing logic.

Setting up the Development Environment

Installing React

To get started, we need to install React. Open your terminal and run the following command:

npx create-react-app ecommerce-app

This will create a new directory named ecommerce-app with a basic React project structure.

Installing and configuring Stripe API

Next, we need to install the stripe package, which provides a client library for interacting with the Stripe API. Run the following command in your terminal:

npm install stripe

Once the installation is complete, we need to configure the Stripe API keys. Go to the Stripe website and create a new account if you haven't already. Once logged in, navigate to the API keys section in the dashboard. You will find two sets of keys: the publishable key and the secret key.

Copy the publishable key and paste it into your React app, specifically in the file src/App.js. Replace the following line:

const stripe = require('stripe')('your_publishable_key');

with your actual publishable key:

const stripe = require('stripe')('pk_test_XXXXXXXXXXXXXXXXXXXXXXXX');

Make sure to keep your secret key confidential and never expose it on the client-side.

Building the User Interface

Creating the main layout

Now that our development environment is set up, let's start building the user interface for our E-commerce app. We will begin by creating the main layout of the app. Open the file src/App.js and replace the default content with the following code:

import React from 'react';

function App() {
  return (
    <div className="App">
      <header className="App-header">
        <h1>E-commerce App</h1>
      </header>
      <main>
        {/* Product listing */}
        {/* Shopping cart */}
      </main>
    </div>
  );
}

export default App;

In this code, we have a basic structure with a header and a main section. We will add the product listing and shopping cart components later.

Designing product listing page

Next, let's design the product listing page. Create a new file src/components/ProductList.js and add the following code:

import React from 'react';

function ProductList() {
  return (
    <div className="ProductList">
      {/* Product cards */}
    </div>
  );
}

export default ProductList;

This component will display a list of product cards. Each product card will contain information such as the product name, price, and an Add to Cart button.

To create the product cards, add the following code inside the ProductList component:

function ProductList() {
  const products = [
    { id: 1, name: 'Product 1', price: 10 },
    { id: 2, name: 'Product 2', price: 20 },
    { id: 3, name: 'Product 3', price: 30 },
  ];

  return (
    <div className="ProductList">
      {products.map((product) => (
        <div key={product.id} className="ProductCard">
          <h3>{product.name}</h3>
          <p>${product.price}</p>
          <button>Add to Cart</button>
        </div>
      ))}
    </div>
  );
}

In this code, we define an array of products and use the map function to render a product card component for each product. The key prop is set to the product's id to ensure efficient rendering.

Implementing shopping cart functionality

Now let's implement the shopping cart functionality. Create a new file src/components/ShoppingCart.js and add the following code:

import React from 'react';

function ShoppingCart() {
  return (
    <div className="ShoppingCart">
      {/* Cart items */}
      {/* Checkout button */}
    </div>
  );
}

export default ShoppingCart;

This component will display the items in the shopping cart and a checkout button.

To display the cart items, add the following code inside the ShoppingCart component:

function ShoppingCart() {
  const cartItems = [];

  return (
    <div className="ShoppingCart">
      {cartItems.length === 0 ? (
        <p>Your cart is empty</p>
      ) : (
        <ul>
          {cartItems.map((item) => (
            <li key={item.id}>
              {item.name} - ${item.price}
            </li>
          ))}
        </ul>
      )}
      <button>Checkout</button>
    </div>
  );
}

In this code, we define an empty array cartItems to store the items added to the cart. We then conditionally render either a message stating that the cart is empty or a list of cart items.

Integrating Stripe API

Creating a Stripe account

Before we can integrate the Stripe API, we need to create a Stripe account. Go to the Stripe website and sign up for an account if you haven't already. Once logged in, navigate to the API keys section in the dashboard. You will find two sets of keys: the publishable key and the secret key.

Configuring Stripe API keys

To configure the Stripe API keys in our React app, open the file src/App.js and replace the following line:

const stripe = require('stripe')('your_publishable_key');

with your actual publishable key:

const stripe = require('stripe')('pk_test_XXXXXXXXXXXXXXXXXXXXXXXX');

Make sure to keep your secret key confidential and never expose it on the client-side.

Implementing payment processing

Now let's implement the payment processing logic using the Stripe API. Open the file src/components/ShoppingCart.js and add the following code inside the ShoppingCart component:

import { loadStripe } from '@stripe/stripe-js';

function ShoppingCart() {
  const stripePromise = loadStripe('pk_test_XXXXXXXXXXXXXXXXXXXXXXXX');

  const handleCheckout = async () => {
    const stripe = await stripePromise;
    const response = await fetch('/api/checkout', {
      method: 'POST',
      headers: {
        'Content-Type': 'application/json',
      },
      body: JSON.stringify(cartItems),
    });
    const session = await response.json();
    const result = await stripe.redirectToCheckout({
      sessionId: session.id,
    });
    if (result.error) {
      console.error(result.error.message);
    }
  };

  return (
    <div className="ShoppingCart">
      {/* Cart items */}
      {cartItems.length === 0 ? (
        <p>Your cart is empty</p>
      ) : (
        <ul>
          {cartItems.map((item) => (
            <li key={item.id}>
              {item.name} - ${item.price}
            </li>
          ))}
        </ul>
      )}
      <button onClick={handleCheckout}>Checkout</button>
    </div>
  );
}

In this code, we import the loadStripe function from the @stripe/stripe-js package to load the Stripe library. We then define a stripePromise variable that stores the promise returned by loadStripe, which will resolve to the Stripe object once it is loaded.

The handleCheckout function is triggered when the user clicks the checkout button. It sends a request to our server-side API endpoint /api/checkout, passing the cart items as the request payload. The server-side code will handle creating a new payment session with Stripe and return the session ID. We then use the redirectToCheckout method to redirect the user to the Stripe checkout page, passing the session ID as an argument.

Managing Orders and Inventory

Creating order management system

To manage orders and inventory, we need to create a server-side API endpoint that handles the order creation and updates the inventory. Create a new file server.js in the root directory of your project and add the following code:

const express = require('express');
const stripe = require('stripe')('sk_test_XXXXXXXXXXXXXXXXXXXXXXXX');
const app = express();

app.use(express.json());

app.post('/api/checkout', async (req, res) => {
  const session = await stripe.checkout.sessions.create({
    payment_method_types: ['card'],
    line_items: req.body.map((item) => ({
      price_data: {
        currency: 'usd',
        product_data: {
          name: item.name,
        },
        unit_amount: item.price * 100,
      },
      quantity: 1,
    })),
    mode: 'payment',
    success_url: 'http://localhost:3000/success',
    cancel_url: 'http://localhost:3000/cancel',
  });

  res.json({ id: session.id });
});

app.listen(5000, () => {
  console.log('Server started on port 5000');
});

In this code, we import the express framework and the stripe package. We create a new instance of the express app and configure it to parse JSON requests.

The /api/checkout endpoint handles the checkout process by creating a new payment session with Stripe. It expects an array of cart items in the request body and uses the stripe.checkout.sessions.create method to create a new session. We pass the cart items as line items, specifying the product name and price. We also provide the success and cancel URLs for the user to be redirected to after completing or canceling the payment.

Updating inventory

To update the inventory when an order is placed, we can implement a simple in-memory inventory management system. Create a new file src/utils/inventory.js and add the following code:

let inventory = [
  { id: 1, name: 'Product 1', price: 10, quantity: 10 },
  { id: 2, name: 'Product 2', price: 20, quantity: 10 },
  { id: 3, name: 'Product 3', price: 30, quantity: 10 },
];

const updateInventory = (cartItems) => {
  cartItems.forEach((cartItem) => {
    const inventoryItem = inventory.find((item) => item.id === cartItem.id);
    if (inventoryItem) {
      inventoryItem.quantity -= 1;
    }
  });
};

module.exports = { inventory, updateInventory };

In this code, we define an array inventory that represents the available products and their quantities. We also define an updateInventory function that takes an array of cart items as an argument. It iterates over each cart item and finds the corresponding inventory item, then decreases its quantity by 1.

In a real-world scenario, you would typically store the inventory in a database and update it accordingly. However, for the purpose of this tutorial, we'll keep it simple with an in-memory solution.

Handling order fulfillment

To handle order fulfillment, we need to update the /api/checkout endpoint to call the updateInventory function after creating the payment session. Modify the /api/checkout endpoint in server.js as follows:

const { inventory, updateInventory } = require('./src/utils/inventory');

app.post('/api/checkout', async (req, res) => {
  const session = await stripe.checkout.sessions.create({
    payment_method_types: ['card'],
    line_items: req.body.map((item) => ({
      price_data: {
        currency: 'usd',
        product_data: {
          name: item.name,
        },
        unit_amount: item.price * 100,
      },
      quantity: 1,
    })),
    mode: 'payment',
    success_url: 'http://localhost:3000/success',
    cancel_url: 'http://localhost:3000/cancel',
  });

  updateInventory(req.body);

  res.json({ id: session.id });
});

In this code, we import the inventory and updateInventory functions from src/utils/inventory. After creating the payment session, we call the updateInventory function, passing the cart items from the request body.

Testing and Deployment

Unit testing React components

To ensure the correctness of our React components, we can write unit tests using a testing framework such as Jest. Create a new file src/components/ProductList.test.js and add the following code:

import React from 'react';
import { render } from '@testing-library/react';
import ProductList from './ProductList';

test('renders product cards', () => {
  const { getByText } = render(<ProductList />);
  const product1 = getByText('Product 1');
  const product2 = getByText('Product 2');
  const product3 = getByText('Product 3');
  expect(product1).toBeInTheDocument();
  expect(product2).toBeInTheDocument();
  expect(product3).toBeInTheDocument();
});

This test verifies that the product cards are rendered correctly by checking if the product names are present in the rendered output.

Testing Stripe API integration

To test the integration with the Stripe API, we can use the Stripe CLI to create a webhook endpoint that listens for events from Stripe. Install the Stripe CLI by following the instructions on the Stripe website. Once installed, open your terminal and run the following command:

stripe listen --forward-to http://localhost:5000/api/webhook

This command starts the Stripe CLI in listen mode and forwards events to the specified endpoint.

In your server-side code, add the following endpoint to handle webhook events in server.js:

app.post('/api/webhook', async (req, res) => {
  const event = req.body;
  // Handle event
  res.sendStatus(200);
});

You can then handle the specific events you are interested in, such as order fulfillment or updating the inventory.

Deploying the E-commerce app

To deploy the E-commerce app, you can use a hosting service such as Vercel, Netlify, or AWS Amplify. These services provide an easy way to deploy and host React applications.

Create an account on your chosen hosting service, connect your project repository, and follow the instructions to deploy your app. Make sure to configure any necessary environment variables, such as the Stripe API keys, in your hosting service's dashboard.

Conclusion

In this tutorial, we covered the process of building an E-commerce app with React and integrating it with the Stripe API for payment processing. We started by setting up the development environment, including installing React and configuring the Stripe API keys. We then built the user interface by creating the main layout, designing the product listing page, and implementing the shopping cart functionality. Next, we integrated the Stripe API by creating a Stripe account, configuring the API keys, and implementing the payment processing logic. Finally, we discussed managing orders and inventory, testing the app, and deploying it to a hosting service.

By following this tutorial, you should now have a solid understanding of how to build an E-commerce app using React and integrate it with the Stripe API. You can further enhance the app by adding features such as user authentication, order history, and more. Happy coding!