How to Integrate Stripe Payment Gateway in Node JS

Hey everyone! Are you ready to supercharge your Node.js application with the power of online payments? Well, you're in luck! In this guide, I'm going to walk you through the process of integrating the Stripe payment gateway into your Node.js application, all while using React for a sleek and user-friendly front end.

In this guide, we'll integrate the stripe payment gateway in node.js with react.js.

So, let's see how to integrate stripe payment gateway in node js, node.js stripe payment gateway integration, stripe integration with node.js, and stripe payment gateway integration in node js with react js.

Step 1: Sign Up for a Stripe Account

First things, you need to sign up for a Stripe account if you haven't already. Head over to the Stripe website and create an account.


Step 2: Obtain API Keys

To integrate Stripe into your PHP application, you'll need to obtain your API keys. In your Stripe dashboard, navigate to the Developers section and click on API keys.

Here, you'll find your publishable key and secret key. Keep these keys secure, as they will be used to authenticate your requests to the Stripe API.


Step 3: Set Up Your Node.js Environment

Before diving into the integration process, ensure that you have Node.js installed on your development machine. You can download and install Node.js from the official website or use a package manager like npm or yarn.

Once Node.js is set up, create a new directory for your project and initialize a new Node.js application using the following commands:

mkdir stripe-payment-gateway-integration-node-js
cd stripe-payment-gateway-integration-node-js
npm init -y

Here is the directory structure.

- stripe-payment-gateway-integration-node-js
|- public
 |- index.html
|- src
 |- App.css
 |- App.jsx
 |- CheckoutForm.jsx
 |- index.js
|- package.json
|- server.js


Step 4: Install Dependencies

Now, let's install the necessary dependencies for our Node.js application. We'll need the stripe package to interact with the Stripe API and express to set up our server.

npm install --save stripe express react react-dom
	"dependencies": {
		"@stripe/react-stripe-js": "^1.0.0",
		"@stripe/stripe-js": "^1.0.0",
		"express": "^4.17.1",
		"react": "^16.9.0",
		"react-dom": "^16.9.0",
		"react-scripts": "^3.4.0",
		"stripe": "^8.202.0"


Step 5: Set Up Your Server

Create a new file named server.js in your project directory and set up a basic Express server.

This server will handle incoming requests from your front end and interact with the Stripe API. Here's a simple example of how your server.js file might look:

const express = require("express");
const app = express();
const stripe = require("stripe")('sk_test_xxxxxxxxxxxxxxxxxxxxx');

app.use(express.json());"/create-payment-intent", async (req, res) => {
	const { items } = req.body;

	// Create a PaymentIntent with the order amount and currency
	const paymentIntent = await stripe.paymentIntents.create({
		amount: 20*100,
		currency: "usd",
		// In the latest version of the API, specifying the `automatic_payment_methods` parameter is optional because Stripe enables its functionality by default.
		automatic_payment_methods: {
			enabled: true,

		clientSecret: paymentIntent.client_secret,

app.listen(4242, () => console.log("Node server listening on port 4242!"));

Replace 'your_secret_api_key' with your actual Stripe secret API key obtained from the Stripe dashboard.

In this we create creates a PaymentIntent. A PaymentIntent tracks the customer’s payment lifecycle, keeping track of any failed payment attempts and ensuring the customer is only charged once. Also, Configure payment methods.


Step 6: Build a checkout page on the client

Now, add Stripe to your React app using the following command.

npm install --save @stripe/react-stripe-js @stripe/stripe-js


import React, { useState, useEffect } from "react";
import { loadStripe } from "@stripe/stripe-js";
import { Elements } from "@stripe/react-stripe-js";

import CheckoutForm from "./CheckoutForm";
import "./App.css";

// This is a public API key.
const stripePromise = loadStripe("pk_test_xxxxxxxxxxxxxxxxxx");

export default function App() {
	const [clientSecret, setClientSecret] = useState("");

	useEffect(() => {
		// Create PaymentIntent as soon as the page loads
		fetch("/create-payment-intent", {
			method: "POST",
			headers: { "Content-Type": "application/json" },
			body: JSON.stringify({ items: [{ id: "xl-tshirt" }] }),
			.then((res) => res.json())
			.then((data) => setClientSecret(data.clientSecret));
	}, []);

	const appearance = {
		theme: 'night',
	const options = {

	return (
		<div className="App">
			{clientSecret && (
				<Elements options={options} stripe={stripePromise}>
					<CheckoutForm />

In this file, Fetch a PaymentIntent, Initialize Stripe Elements, Set up the state and Add PaymentElement to the payment form.


Step 7: Create a Payment Form

In your React application, create a payment form component where users can enter their payment details.


import React, { useEffect, useState } from "react";
import {
} from "@stripe/react-stripe-js";

export default function CheckoutForm() {
	const stripe = useStripe();
	const elements = useElements();

	const [message, setMessage] = useState(null);
	const [isLoading, setIsLoading] = useState(false);

	useEffect(() => {
		if (!stripe) {

		const clientSecret = new URLSearchParams(

		if (!clientSecret) {

		stripe.retrievePaymentIntent(clientSecret).then(({ paymentIntent }) => {
			switch (paymentIntent.status) {
				case "succeeded":
					setMessage("Payment succeeded!");
				case "processing":
					setMessage("Your payment is processing.");
				case "requires_payment_method":
					setMessage("Your payment was not successful, please try again.");
					setMessage("Something went wrong.");
	}, [stripe]);

	const handleSubmit = async (e) => {

		if (!stripe || !elements) {
			// Stripe.js hasn't yet loaded.
			// Make sure to disable form submission until Stripe.js has loaded.


		const { error } = await stripe.confirmPayment({
			confirmParams: {
				// Make sure to change this to your payment completion page
				return_url: "http://localhost:3000",

		// This point will only be reached if there is an immediate error when
		// confirming the payment. Otherwise, your customer will be redirected to
		// your `return_url`. For some payment methods like IDEAL, your customer will
		// be redirected to an intermediate site first to authorize the payment, then
		// redirected to the `return_url`.
		if (error.type === "card_error" || error.type === "validation_error") {
		} else {
			setMessage("An unexpected error occurred.");


	const paymentElementOptions = {
		layout: "tabs"

	return (
		<form id="payment-form" onSubmit={handleSubmit}>

			<PaymentElement id="payment-element" options={paymentElementOptions} />
			<button disabled={isLoading || !stripe || !elements} id="submit">
				<span id="button-text">
					{isLoading ? <div className="spinner" id="spinner"></div> : "Pay now"}
			{/* Show any error or success messages */}
			{message && <div id="payment-message">{message}</div>}

Complete the payment: In this, When your customer clicks the pay button, call confirmPayment() with the PaymentElement and pass a return_url to indicate where Stripe should redirect the user after they complete the payment.

Handle errors: If there are any immediate errors (for example, your customer’s card is declined), Stripe.js returns an error. Show that error message to your customer so they can try again.

Show a payment status message: When Stripe redirects the customer to the return_url, the payment_intent_client_secret query parameter is appended by Stripe.js.


Step 8: Style the Payment Element

Customize the Payment Element UI by creating an appearance object and initializing Elements with it. Use your company’s color scheme and font to make it match with the rest of your checkout page.


#root {
	display: flex;
	align-items: center;

body {
	font-family: -apple-system, BlinkMacSystemFont, sans-serif;
	font-size: 16px;
	-webkit-font-smoothing: antialiased;
	display: flex;
	justify-content: center;
	align-content: center;
	height: 100vh;
	width: 100vw;

form {
	width: 30vw;
	min-width: 500px;
	align-self: center;
	box-shadow: 0px 0px 0px 0.5px rgba(50, 50, 93, 0.1),
		0px 2px 5px 0px rgba(50, 50, 93, 0.1), 0px 1px 1.5px 0px rgba(0, 0, 0, 0.07);
	border-radius: 7px;
	padding: 40px;

#payment-message {
	color: rgb(105, 115, 134);
	font-size: 16px;
	line-height: 20px;
	padding-top: 12px;
	text-align: center;

#payment-element {
	margin-bottom: 24px;

/* Buttons and links */
button {
	background: #5469d4;
	font-family: Arial, sans-serif;
	color: #ffffff;
	border-radius: 4px;
	border: 0;
	padding: 12px 16px;
	font-size: 16px;
	font-weight: 600;
	cursor: pointer;
	display: block;
	transition: all 0.2s ease;
	box-shadow: 0px 4px 5.5px 0px rgba(0, 0, 0, 0.07);
	width: 100%;

button:hover {
	filter: contrast(115%);

button:disabled {
	opacity: 0.5;
	cursor: default;

/* spinner/processing state, errors */
.spinner:after {
	border-radius: 50%;

.spinner {
	color: #ffffff;
	font-size: 22px;
	text-indent: -99999px;
	margin: 0px auto;
	position: relative;
	width: 20px;
	height: 20px;
	box-shadow: inset 0 0 0 2px;
	-webkit-transform: translateZ(0);
	-ms-transform: translateZ(0);
	transform: translateZ(0);

.spinner:after {
	position: absolute;
	content: '';

.spinner:before {
	width: 10.4px;
	height: 20.4px;
	background: #5469d4;
	border-radius: 20.4px 0 0 20.4px;
	top: -0.2px;
	left: -0.2px;
	-webkit-transform-origin: 10.4px 10.2px;
	transform-origin: 10.4px 10.2px;
	-webkit-animation: loading 2s infinite ease 1.5s;
	animation: loading 2s infinite ease 1.5s;

.spinner:after {
	width: 10.4px;
	height: 10.2px;
	background: #5469d4;
	border-radius: 0 10.2px 10.2px 0;
	top: -0.1px;
	left: 10.2px;
	-webkit-transform-origin: 0px 10.2px;
	transform-origin: 0px 10.2px;
	-webkit-animation: loading 2s infinite ease;
	animation: loading 2s infinite ease;

@keyframes loading {
	0% {
		-webkit-transform: rotate(0deg);
		transform: rotate(0deg);

	100% {
		-webkit-transform: rotate(360deg);
		transform: rotate(360deg);

@media only screen and (max-width: 600px) {
	form {
		width: 80vw;
		min-width: initial;


Step 9: Create an Index.js file

Now, we'll create an index.js file and add react app.

import React from "react";
import ReactDOM from "react-dom";
import App from "./App";

ReactDOM.render(<App />, document.getElementById("root"));


Step 10: Test Your Integration

Finally, test your Stripe integration thoroughly to ensure that payments are processed correctly.

Use test card numbers provided by Stripe to simulate different scenarios (e.g., successful payments, and declined payments) and verify that your application handles them appropriately.

Before you run the application

Add proxy to your package.json file during local development.

"homepage": "http://localhost:3000/checkout",
"proxy": "http://localhost:4242",

Run the application

Run the React app and the server. Go to localhost:3000/checkout to see your checkout page.

npm start


You might also like:


Techsolutionstuff | The Complete Guide

I'm a software engineer and the founder of Hailing from India, I craft articles, tutorials, tricks, and tips to aid developers. Explore Laravel, PHP, MySQL, jQuery, Bootstrap, Node.js, Vue.js, and AngularJS in our tech stack.