Skip to content

WebNinjaDeveloper.com

Programming Tutorials




Menu
  • Home
  • Youtube Channel
  • Official Blog
  • Nearby Places Finder
  • Direction Route Finder
  • Distance & Time Calculator
Menu

Build a React.js Ecommerce Shopping Cart Using Stripe in Node.js & Express Using Javascript Full Project For Beginners

Posted on October 22, 2022

 

 

Welcome folks today in this blog post we will be building a ecommerce shopping cart using stripe payment gateway in node.js and express using javascript. All the full source code of the application is shown below.

 

 

Get Started

 

 

In order to get started you need to initialize a new react.js project by typing the below command

 

 

npx create-react-app shoppingcart

 

 

cd shoppingcart

 

 

npm i bootstrap

 

 

npm i react-router-dom

 

 

Directory structure of App

 

 

 

 

As you know see we are installing the bootstrap library and also we are installing the react-router-dom library. After that we will be copy paste the below code in App.js as shown below

 

 

App.js

 

 

JavaScript
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
import './App.css';
import 'bootstrap/dist/css/bootstrap.min.css';
import NavbarComponent from './components/Navbar';
import { Container } from 'react-bootstrap';
import { BrowserRouter, Routes, Route} from "react-router-dom";
import Cancel from './pages/Cancel';
import Store from './pages/Store';
import Success from './pages/Success';
import CartProvider from './CartContext';
// localhost:3000 -> Home
// localhost:3000/success -> Success
 
function App() {
  return (
    <CartProvider>
      <Container>
        <NavbarComponent></NavbarComponent>
        <BrowserRouter>
          <Routes>
            <Route index element={<Store />} />
            <Route path="success" element={<Success />} />
            <Route path="cancel" element={<Cancel />} />
          </Routes>
        </BrowserRouter>
      </Container>
    </CartProvider>
  );
}
 
export default App;

 

 

As you can see in the above code we have the react router in which we are adding all the routes to different pages. As we are adding the success and error routes. So when we go to success page then success component will be loaded some goes for error page also. And also we are wrapping all the routes using BrowserRouter. And at the top we are importing the bootstrap cdn and also react-bootstrap package as well. And also we are wrapping all the jsx using the CartProvider context. We are importing the context at the very top.

 

 

Creating the Context and Storing Data

 

 

Now we will be creating context or storing all the data which will be used inside this ecommerce shopping cart application. First of all in the root directory we will be making the CartContext.js file as shown below

 

Creating the Products inside Stripe

 

Now first of all go to your stripe account dashboard you need to create the products that you want to sell. Just give the name of the product and give the pricing to the product. And after creating the product we will get the price Id.

 

 

 

 

 

And after that as you can see we will get the price_id of the particular product. And you will similarly created unlimited products that you want to create and you will copy paste the price_id. And after that inside the root directory we need to make a file called Productsstore.js file and copy paste the below code

 

 

ProductsStore.js

 

 

TypeScript
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
// Coffee: price_1LnUTFDM1jwCEz8OGoOSXiSM
// Sunglasses: price_1LnUTxDM1jwCEz8OAqHYTwKQ
// Camera: price_1LnUUoDM1jwCEz8OvxIcJ7to
 
const productsArray = [
    {
        id: "price_1LvS2aSCXzUC9mHj6ZcjnqZQ",
        title: "Coffee",
        price: 15.00
    },
    {
        id: "price_1LvS3ISCXzUC9mHjhEBjuwLz",
        title: "Sunglasses",
        price: 50.00
    },
    {
        id: "price_1LvS3fSCXzUC9mHjyb5xVbKF",
        title: "Camera",
        price: 50.00
    }
];
 
function getProductData(id) {
    let productData = productsArray.find(product => product.id === id);
 
    if (productData == undefined) {
        console.log("Product data does not exist for ID: " + id);
        return undefined;
    }
 
    return productData;
}
 
export { productsArray, getProductData };

 

 

As you can see we are declaring three products that we will be selling inside this shopping cart. We have the array of objects which contain three properties which will be id,title and price of the particular product. And then we will have the method which is called getProductData() and we will be passing the id to this method. And lastly we are exporting these two things.

 

 

Now we will be making the CartContext.js file as shown below

 

 

CartContext.js

 

 

TypeScript
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
import { createContext, useState } from "react";
import { productsArray, getProductData } from "./productsStore";
 
 
export const CartContext = createContext({
    items: [],
    getProductQuantity: () => {},
    addOneToCart: () => {},
    removeOneFromCart: () => {},
    deleteFromCart: () => {},
    getTotalCost: () => {}
});
 
export function CartProvider({children}) {
    const [cartProducts, setCartProducts] = useState([]);
    
    // [ { id: 1 , quantity: 3 }, { id: 2, quantity: 1 } ]
 
    function getProductQuantity(id) {
        const quantity = cartProducts.find(product => product.id === id)?.quantity;
        
        if (quantity === undefined) {
            return 0;
        }
 
        return quantity;
    }
 
    function addOneToCart(id) {
        const quantity = getProductQuantity(id);
 
        if (quantity === 0) { // product is not in cart
            setCartProducts(
                [
                    ...cartProducts,
                    {
                        id: id,
                        quantity: 1
                    }
                ]
            )
        } else { // product is in cart
            // [ { id: 1 , quantity: 3 }, { id: 2, quantity: 1 } ]    add to product id of 2
            setCartProducts(
                cartProducts.map(
                    product =>
                    product.id === id                                // if condition
                    ? { ...product, quantity: product.quantity + 1 } // if statement is true
                    : product                                        // if statement is false
                )
            )
        }
    }
 
    function removeOneFromCart(id) {
        const quantity = getProductQuantity(id);
 
        if(quantity == 1) {
            deleteFromCart(id);
        } else {
            setCartProducts(
                cartProducts.map(
                    product =>
                    product.id === id                                // if condition
                    ? { ...product, quantity: product.quantity - 1 } // if statement is true
                    : product                                        // if statement is false
                )
            )
        }
    }
 
    function deleteFromCart(id) {
        // [] if an object meets a condition, add the object to array
        // [product1, product2, product3]
        // [product1, product3]
        setCartProducts(
            cartProducts =>
            cartProducts.filter(currentProduct => {
                return currentProduct.id != id;
            })  
        )
    }
 
    function getTotalCost() {
        let totalCost = 0;
        cartProducts.map((cartItem) => {
            const productData = getProductData(cartItem.id);
            totalCost += (productData.price * cartItem.quantity);
        });
        return totalCost;
    }
 
    const contextValue = {
        items: cartProducts,
        getProductQuantity,
        addOneToCart,
        removeOneFromCart,
        deleteFromCart,
        getTotalCost
    }
 
    return (
        <CartContext.Provider value={contextValue}>
            {children}
        </CartContext.Provider>
    )
}
 
export default CartProvider;

 

 

As you can see we are importing the productsStore file at the very top. From that file we are importing the getProductData method and also we are importing the list of products which will be sold inside this app

 

 

Creating the Pages for this Shopping Cart

 

 

Now we will be creating the pages for this react.js App. For this you need to make the pages directory and inside that we will be making the success.js as shown below

 

 

pages/Success.js

 

 

JavaScript
1
2
3
4
5
6
7
function Success() {
    return (
        <h1>Thank you for your purchase!</h1>
    )
}
 
export default Success;

 

 

And similarly we will making the error page template as shown below in the pages directory

 

 

pages/Cancel.js

 

 

JavaScript
1
2
3
4
5
6
7
function Cancel() {
    return (
        <h1>Sorry to see you cancelled your Stripe payment!</h1>
    )
}
 
export default Cancel;

 

 

As you can we have a simple error message in this component saying sorry to see you cancelled your stripe payment to the user.

 

 

Rendering All the Products on the Screen

 

 

Now just make the store.js file in the pages directory and copy paste the below codoe

 

 

pages/store.js

 

 

JavaScript
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
import {Row, Col} from 'react-bootstrap';
import { productsArray } from '../productsStore';
import ProductCard from '../components/ProductCard';
 
function Store() {
 
    return (
        <>
            <h1 align="center" className="p-3">Welcome to the store!</h1>
            <Row xs={1} md={3} className="g-4">
                {productsArray.map((product, idx) => (
                    <Col align="center" key={idx}>
                        <ProductCard product={product}/>
                    </Col>
                ))}
            </Row>
        </>
    )
}
 
export default Store;

 

 

As you can see we are importing the productsArray from the store file which we have created. And in jsx we are using the loop to render all the products. For rendering the product we are making a special component called ProductCard.js inside the components folder.

 

Now we need to make the components folder and inside it we will be making the ProductCard.js file and copy paste the below code

 

 

components/ProductCard.js

 

 

TypeScript
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
import { Card, Button, Form, Row, Col } from 'react-bootstrap';
import { CartContext } from '../CartContext';
import { useContext } from 'react';
 
function ProductCard(props) { // props.product is the product we are selling
    const product = props.product;
    const cart = useContext(CartContext);
    const productQuantity = cart.getProductQuantity(product.id);
    console.log(cart.items);
    return (
        <Card>
            <Card.Body>
                <Card.Title>{product.title}</Card.Title>
                <Card.Text>${product.price}</Card.Text>
                { productQuantity > 0 ?
                    <>
                        <Form as={Row}>
                            <Form.Label column="true" sm="6">In Cart: {productQuantity}</Form.Label>
                            <Col sm="6">
                                <Button sm="6" onClick={() => cart.addOneToCart(product.id)} className="mx-2">+</Button>
                                <Button sm="6" onClick={() => cart.removeOneFromCart(product.id)} className="mx-2">-</Button>
                            </Col>
                        </Form>
                        <Button variant="danger" onClick={() => cart.deleteFromCart(product.id)} className="my-2">Remove from cart</Button>
                    </>
                    :
                    <Button variant="primary" onClick={() => cart.addOneToCart(product.id)}>Add To Cart</Button>
                }
            </Card.Body>
        </Card>
    )
}
 
export default ProductCard;

 

 

As you can see inside this component we are rendering all the information about a particular product which is the name of the product, the price of the product and also some buttons available to increase or decrease the number of products to the cart as shown below

 

 

 

Adding the Navigation Bar Component

 

 

Now we will be adding the navigation bar component inside the components folder. First of all we will be making the Navbar.js file inside the folder as shown below

 

 

components/Navbar.js

 

 

TypeScript
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
import {Button, Container, Navbar, Modal} from 'react-bootstrap';
import { useState, useContext } from 'react';
import { CartContext } from "../CartContext";
import CartProduct from './CartProduct';
 
function NavbarComponent() {
    const cart = useContext(CartContext);
 
    const [show, setShow] = useState(false);
    const handleClose = () => setShow(false);
    const handleShow = () => setShow(true);
 
    const checkout = async () => {
        await fetch('http://localhost:4000/checkout', {
            method: "POST",
            headers: {
                'Content-Type': 'application/json'
            },
            body: JSON.stringify({items: cart.items})
        }).then((response) => {
            return response.json();
        }).then((response) => {
            if(response.url) {
                window.location.assign(response.url); // Forwarding user to Stripe
            }
        });
    }
 
    const productsCount = cart.items.reduce((sum, product) => sum + product.quantity, 0);
 
    return (
        <>
            <Navbar expand="sm">
                <Navbar.Brand href="/">Ecommerce Store</Navbar.Brand>
                <Navbar.Toggle />
                <Navbar.Collapse className="justify-content-end">
                    <Button onClick={handleShow}>Cart ({productsCount} Items)</Button>
                </Navbar.Collapse>
            </Navbar>
            <Modal show={show} onHide={handleClose}>
                <Modal.Header closeButton>
                    <Modal.Title>Shopping Cart</Modal.Title>
                </Modal.Header>
                <Modal.Body>
                    {productsCount > 0 ?
                        <>
                            <p>Items in your cart:</p>
                            {cart.items.map( (currentProduct, idx) => (
                                <CartProduct key={idx} id={currentProduct.id} quantity={currentProduct.quantity}></CartProduct>
                            ))}
 
                            <h1>Total: {cart.getTotalCost().toFixed(2)}</h1>
 
                            <Button variant="success" onClick={checkout}>
                                Purchase items!
                            </Button>
                        </>
                    :
                        <h1>There are no items in your cart!</h1>
                    }
                </Modal.Body>
            </Modal>
        </>
    )
}
 
export default NavbarComponent;

 

 

As you can see first of all we have the header component in which we are displaying the logo and title of the application and then we have the simple cart button where we hit the button to see the products in the cart. This cart will automatically get updated when we add products or remove products. And this is a toggle navigation bootstrap component. And this is completely responsive. When we view on mobile devices it will be taking the shape of a hamburger menu icon.

 

At the top we are declaring some state variables which is useful in showing and hide the cart button in small devices. And also showing the modal window of cart. All the cart products will be shown in the modal window and sum of the total products will be shown at the bottom as shown below. And also when we click the checkout button we are calling the backend api and making a simple POST request passing the list of items to be purchased.

 

 

 

 

As you can see above as we select products to buy the shopping cart will get updated to show the number of products present. And inside the modal window we are looping through all the products to show information. For showing the information we are again another component called CartProduct passing some props in the form of id,key and price as well to that component. Now build CartProduct.js file inside the components folder as shown below

 

 

components/CartProduct.js

 

 

TypeScript
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
import Button from 'react-bootstrap/Button';
import { CartContext } from "../CartContext";
import { useContext } from "react";
import { getProductData } from "../productsStore";
 
function CartProduct(props) {
    const cart = useContext(CartContext);
    const id = props.id;
    const quantity = props.quantity;
    const productData = getProductData(id);
 
    return (
        <>
            <h3>{productData.title}</h3>
            <p>{quantity} total</p>
            <p>${ (quantity * productData.price).toFixed(2) }</p>
            <Button size="sm" onClick={() => cart.deleteFromCart(id)}>Remove</Button>
            <hr></hr>
        </>
    )
}
 
export default CartProduct;

 

 

As you can see we are rendering all the information about the product such as the name and the price and also we have the remove button to remove the product from the cart as shown below

 

 

 

 

 

As you can see the frontend of the application is complete now we need to write the backend code in node.js and express to actually carry out the checkout process to actually make the payment.

 

 

Making the Backend

 

 

Now first of all we need to initialize the package.json file using the below command

 

 

npm init -y

 

 

npm i express

 

 

npm i stripe

 

 

npm i cors

 

 

As you can see we are installing cors so that we can make our backend api accessible in all origins. Now you need to make the index.js file inside the root of the project

 

 

index.js

 

 

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
const express = require('express');
var cors = require('cors');
const stripe = require('stripe')('##yourstripesecretkey##');
 
const app = express();
app.use(cors());
app.use(express.static("public"));
app.use(express.json());
 
app.post("/checkout", async (req, res) => {
    console.log(req.body);
    const items = req.body.items;
    let lineItems = [];
    items.forEach((item)=> {
        lineItems.push(
            {
                price: item.id,
                quantity: item.quantity
            }
        )
    });
 
    const session = await stripe.checkout.sessions.create({
        line_items: lineItems,
        mode: 'payment',
        success_url: "http://localhost:3000/success",
        cancel_url: "http://localhost:3000/cancel"
    });
 
    res.send(JSON.stringify({
        url: session.url
    }));
});
 
app.listen(4000, () => console.log("Listening on port 4000!"));

 

 

As you can see we are including all the packages at the very top of the file. For this you will need the stripe secret key from your dashboard as shown below

 

 

 

 

And after it we are making a new POST Request to the route /checkout and inside that we are inserting the price and the quantity. And lastly we are creating a checkout session to purchase these products. So from where the user will be redirected to the stripe payment page where there is no restriction that we built. Now if you run the node.js app by the below command

 

 

nodemon index.js

 

 

The app will listen port:4000. After you click the checkout button it will redirect the user to the homepage.

 

 

 

 

As you can see we have the stripe payment page where all the product will be shown that you are purchasing and then in the test mode you can write the test credit card details to test the app.

 

 

 

 

As you can see after successful payment we are redirecting the user back to the success page.

 

 

Recent Posts

  • Android Java Project to Capture Image From Camera & Save it in SharedPreferences & Display it in Grid Gallery
  • Android Java Project to Store,Read & Delete Data Using SharedPreferences Example
  • Android Java Project to Download Multiple Images From URL With Progressbar & Save it inside Gallery
  • Android Java Project to Capture Image From Camera & Save it inside Gallery
  • Android Java Project to Crop,Scale & Rotate Images Selected From Gallery and Save it inside SD Card
  • Angular
  • Bunjs
  • C#
  • Deno
  • django
  • Electronjs
  • java
  • javascript
  • Koajs
  • kotlin
  • Laravel
  • meteorjs
  • Nestjs
  • Nextjs
  • Nodejs
  • PHP
  • Python
  • React
  • ReactNative
  • Svelte
  • Tutorials
  • Vuejs




©2023 WebNinjaDeveloper.com | Design: Newspaperly WordPress Theme