DEV Community

Cover image for 💳 Payment Integration with React and Node.js (Super Simple via Stripe with Dummy Data)
Ishwor karki
Ishwor karki

Posted on

💳 Payment Integration with React and Node.js (Super Simple via Stripe with Dummy Data)

If you're building a React project and want to add a payment feature, you're in the right place. In this post, I’ll show you the easiest way to integrate Stripe Checkout using:

  • React for the frontend
  • Node.js + Express for the backend
  • No database — just dummy data

Perfect for beginners who want to learn fast or create a tutorial or demo app!


🛠 What We’re Building

You’ll create:

  • A fake cart (no real database)
  • A “Pay Now” button
  • A Stripe payment flow
  • A simple success/failure result screen

🧰 Tech Stack

  • Frontend: React (using basic components)
  • Backend: Node.js with Express
  • Payment: Stripe (Checkout session)

📦 Backend Setup (Node.js + Express + Stripe)

Step 1: Create the backend project

mkdir backend
cd backend
npm init -y
npm install express stripe cors dotenv
Enter fullscreen mode Exit fullscreen mode

Step 2: Add your .env file

Create a .env file in the backend folder and add your Stripe secret key:

STRIPE_SECRET_KEY=sk_test_your_stripe_secret_key_here
Enter fullscreen mode Exit fullscreen mode

Step 3: Create index.js

import express from "express";
import dotenv from "dotenv";
import Stripe from "stripe";
import cors from "cors";

dotenv.config();
const app = express();
const stripe = new Stripe(process.env.STRIPE_SECRET_KEY);

app.use(cors());
app.use(express.json());

app.post("/api/checkout", async (req, res) => {
  try {
    const { items, email } = req.body;

    const line_items = items.map((item) => ({
      price_data: {
        currency: "aud",
        product_data: { name: item.name },
        unit_amount: item.price * 100,
      },
      quantity: item.quantity,
    }));

    const session = await stripe.checkout.sessions.create({
      payment_method_types: ["card"],
      line_items,
      customer_email: email,
      mode: "payment",
      success_url: "http://localhost:5173/payment-result?success=true&session_id={CHECKOUT_SESSION_ID}",
      cancel_url: "http://localhost:5173/payment-result?success=false&session_id={CHECKOUT_SESSION_ID}",
    });

    res.json({ url: session.url });
  } catch (error) {
    console.error(error);
    res.status(500).json({ error: "Checkout session failed" });
  }
});

app.listen(5000, () => console.log("Backend is running on port 5000"));
Enter fullscreen mode Exit fullscreen mode

💻 Frontend Setup (React)

You can use Vite or Create React App. Let’s say you're inside App.jsx.

Step 1: Dummy Cart UI

import React from "react";
import axios from "axios";

const dummyCart = [
  { name: "T-shirt", price: 30, quantity: 2 },
  { name: "Hat", price: 20, quantity: 1 },
];

const App = () => {
  const total = dummyCart.reduce((acc, item) => acc + item.price * item.quantity, 0);

  const handleCheckout = async () => {
    try {
      const res = await axios.post("http://localhost:5000/api/checkout", {
        items: dummyCart,
        email: "[email protected]", // Dummy email for now
      });

      window.location.href = res.data.url;
    } catch (err) {
      alert("Checkout failed");
      console.error(err);
    }
  };

  return (
    <div style={{ maxWidth: 400, margin: "40px auto", textAlign: "center" }}>
      <h2>🛒 Dummy Cart</h2>
      {dummyCart.map((item, index) => (
        <p key={index}>
          {item.name} x {item.quantity} = ${item.price * item.quantity}
        </p>
      ))}
      <h3>Total: ${total}</h3>
      <button onClick={handleCheckout} style={{ padding: "10px 20px" }}>
        Pay Now
      </button>
    </div>
  );
};

export default App;
Enter fullscreen mode Exit fullscreen mode

🚀 Run and Test

  1. Start the backend:
node index.js
Enter fullscreen mode Exit fullscreen mode
  1. Start the frontend (React app):
npm run dev
Enter fullscreen mode Exit fullscreen mode
  1. Go to your app and click the "Pay Now" button — you’ll be taken to Stripe’s secure checkout page! Here's what to expect:
  • ✅ Itemized summary of the products (name, price, quantity)
  • 💳 Input fields for card details (number, expiry, CVC)
  • 📧 Pre-filled customer email (if provided in session)
  • 🔒 Secure and PCI-compliant design

This is a hosted page by Stripe — meaning you don't need to worry about building the form or storing card info. It’s fast, secure, and mobile-friendly.


💳 Stripe Test Card Details for Development

Stripe provides a range of test card numbers that work in test mode and simulate different payment scenarios.


✅ Commonly Used Card

Purpose Card Number Expiry CVC Result
Success Payment 4242 4242 4242 4242 Any future date Any 3 digits ✅ Approved

❌ Other Test Cards

Scenario Card Number Result
Declined card 4000 0000 0000 0002 ❌ Declined
Insufficient funds 4000 0000 0000 9995 ❌ Declined
Card requires authentication 4000 0027 6000 3184 3D Secure required
Incorrect CVC 4000 0000 0000 0127 ❌ Declined

🧾 Usage Guide

  • Expiry Date: Use any future date like 12/34
  • CVC: Use any 3-digit number like 123
  • ZIP/Postal Code: You can enter any value, e.g., 12345

✅ What Happens After Payment?

Notice this part in our backend:

success_url: "http://localhost:5173/payment-result?success=true&session_id={CHECKOUT_SESSION_ID}",
cancel_url: "http://localhost:5173/payment-result?success=false&session_id={CHECKOUT_SESSION_ID}",
Enter fullscreen mode Exit fullscreen mode

Stripe will automatically replace {CHECKOUT_SESSION_ID} with the actual session ID. That means you can verify the payment on the next page using that session.


🧠 Challenge For You!

Here’s a fun task to practice what you’ve learned:

✅ Use the session_id in the URL to verify the payment on your /payment-result page.

Hint:

  • Use useSearchParams() in React to get the session ID.
  • Create a new backend route:
  stripe.checkout.sessions.retrieve(session_id)
Enter fullscreen mode Exit fullscreen mode
  • Check if session.payment_status === "paid"

You can then show either a "Payment Successful 🎉" or "Payment Failed ❌" message based on the result.


🎉 That’s It!

You now have a working Stripe Checkout integration using dummy data. Feel free to expand this into a real cart later. Let me know if you’d like help verifying the session or deploying it online!

Top comments (2)

Collapse
 
nevodavid profile image
Nevo David

Nice, love when stuff just works and you don’t gotta fight with docs for hours.

Collapse
 
dotallio profile image
Dotallio

Love how simple you made this! Any tips on turning the dummy cart into a real one with a database?