An easy way to integrate PhonePe payment gateway into the Node.js backend and React-front-end respectively to allow secure UPI-based transactions in your web application.
Key Points
- As of 2024, 50+ Crore Registered Users on PhonePe across India.
- With over 48% Market Share in UPI transactions, it remains the most used UPI platform in India.
- More than 7.5 Billion Transactions are processed every month through PhonePe in the early months of 2024.
Co-Founder
Harsh Abrol
3 min read
With Over 14 years of Experience in the IT Field, Helping Companies Optimise there Products for more Conversions

Introduction
PhonePe is one of the primary digital payment platforms in India, which is widely used for making seamless transactions on eCommerce platforms, mobile application development, and web project development. When integrated into a Node.js and React-based application, PhonePe ensures secure and efficient payment options for the users.
This guide illustrates step-by-step approaches to integrate PhonePe into your application built on Node.js and React.js. This integration shall assist you in fast-tracking the transaction process whether you are working on eCommerce, a service-based platform, or a mobile application development project.
Why Integrate PhonePe in Your Application?
-
Secure Transactions: PhonePe uses encryption levels and security standards such as those adopted by the industry.
-
Fast Processing: The processing of transactions takes place in real-time with very little delay.
-
Wide Acceptance: PhonePe is used to pay by more than 400 million users across India.
-
Multi-Platform: The PhonePe integration works perfectly on web and mobile applications.
-
Seamless User Experience: Less friction at the checkout improves conversions.
Prerequisites
Before integrating PhonePe, ensure you have:
-
A PhonePe Business account.
-
Access to the PhonePe Developer Portal.
-
A merchant ID and salt key (provided by PhonePe).
-
A Node.js environment (Node.js v14+ recommended).
-
A React.js application for frontend integration.
-
Basic knowledge of REST APIs and Express.js for backend setup
Setting Up Your Node.js Backend for PhonePe Integration
Step 1: Initialize a Node.js Project
Run the following commands in your terminal to create a new project:
mkdir phonepe-integration && cd phonepe-integration
npm init -y
Step 2: Install Required Dependencies
npm init -y
npm install express axios crypto dotenv uuid
Step 3: Create Environment Variables
Create a .env file to store sensitive data.
- Redirect the user to the redirectUrl to complete payment.
Verify Payment Status
Endpoint: POST /verify-status?transactionId=YOUR_TRANSACTION_ID
Description: Verifies the transaction status and redirects accordingly.
transactionId - Unique identifier for the transaction
If success, redirects to: http://localhost:5173/success
If failed, redirects to: http://localhost:5173/failed
Code Implementation
Create server.js and add the following code:
import express from "express";
import dotenv from "dotenv";
import crypto from "crypto";
import { v4 as uuidv4 } from "uuid";
import axios from "axios";
import cors from "cors";
dotenv.config();
const app = express();
const port = process.env.PORT || 8080;
// Load environment variables
const {
PHONEPE_MERCHANT_ID,
PHONEPE_SALT_KEY,
PHONEPE_SALT_INDEX,
REDIRECT_URL,
FRONTEND_SUCCESS_URL,
FRONTEND_FAILURE_URL,
PHONEPE_BASE_URL,
PHONEPE_STATUS_URL,
} = process.env;
app.use(cors());
app.use(express.json());
app.use(express.urlencoded({ extended: true }));
// Root Route
app.get("/", (req, res) => {
res.send("PhonePe Payment Gateway API is running.");
});
/**
* Function to generate a checksum (SHA256 hash)
*/
const generateChecksum = (payload, endpoint) => {
const stringToHash = payload + endpoint + PHONEPE_SALT_KEY;
const sha256 = crypto.createHash("sha256").update(stringToHash).digest("hex");
return `${sha256}###${PHONEPE_SALT_INDEX}`;
};
/**
* Initialize Payment API
* Endpoint: POST /initialize-payment
*/
app.post("/initialize-payment", async (req, res) => {
try {
const { phone, amount } = req.body;
if (!phone || !amount) {
return res
.status(400)
.json({ success: false, message: "Invalid request parameters" });
}
const transactionId = uuidv4();
const paymentPayload = {
merchantId: PHONEPE_MERCHANT_ID,
merchantUserId: "1",
mobileNumber: phone,
amount: Number(amount) * 100, // Convert to paisa
merchantTransactionId: transactionId,
redirectUrl: `${REDIRECT_URL}?transactionId=${transactionId}`,
redirectMode: "POST",
paymentInstrument: { type: "PAY_PAGE" },
};
const payload = Buffer.from(JSON.stringify(paymentPayload)).toString(
"base64"
);
const checksum = generateChecksum(payload, "/pg/v1/pay");
const response = await axios.post(
PHONEPE_BASE_URL,
{ request: payload },
{
headers: {
"Content-Type": "application/json",
"X-VERIFY": checksum,
"X-MERCHANT-ID": PHONEPE_MERCHANT_ID,
},
}
);
return res.status(200).json({
success: true,
message: "Payment initiated",
redirectUrl: response.data.data.instrumentResponse.redirectInfo.url,
});
} catch (error) {
console.error("Payment Initialization Error:", error);
return res.status(500).json({
success: false,
message: "Payment initialization failed",
error: error.message,
});
}
});
/**
* Verify Payment Status API
* Endpoint: POST /verify-status
*/
app.post("/verify-status", async (req, res) => {
try {
const { transactionId } = req.query;
if (!transactionId) {
return res
.status(400)
.json({ success: false, message: "Transaction ID is required" });
}
const statusUrl = `${PHONEPE_STATUS_URL}/${PHONEPE_MERCHANT_ID}/${transactionId}`;
const checksum = generateChecksum(
"",
`/pg/v1/status/${PHONEPE_MERCHANT_ID}/${transactionId}`
);
const response = await axios.get(statusUrl, {
headers: {
"Content-Type": "application/json",
"X-VERIFY": checksum,
},
});
const paymentStatus = response.data.success
? FRONTEND_SUCCESS_URL
: FRONTEND_FAILURE_URL;
return res.redirect(paymentStatus);
} catch (error) {
console.error("Payment Status Verification Error:", error);
return res.redirect(FRONTEND_FAILURE_URL);
}
});
// Start the server
app.listen(port, () => {
console.log(`Server running on port ${port}`);
});
Deployment Considerations
- Use HTTPS – Secure communication for payment processing
- Store API keys securely – Use .env
- Change Urls– Change sandbox phonepe url and frontend url with live url
- Ensure that it's Mobile & Web Compatible- Tested across multiple devices and browsers.
Final Words
Integrating PhonePe into your Node.js and React.js application guarantees a secure, seamless, and user-friendly payment experience. This integration shall benefit developers involved in mobile app development, web development, and payment app development, enabling them to manage transactions efficiently through PhonePe.