VOOZH about

URL: https://dev.to/madhubankhatri/razorpay-mern-3gge

⇱ Integrate Razorpay payment gateway in MERN project - DEV Community


Hello guys,
I am MADHUBAN KHATRI. I make blogs on Django and MERN stack . Today we will learn how to integrate Razorpay payment gateway in a MERN project.
Before starting, I want that check the blog of Razorpay integration with Django Project:
Razorpay Integration in Django Project

Backend Setup

Install packages

npm install express razorpay cors dotenv crypto

.env

PORT=5000
KEY_SECRET=razorpay_key_secret
KEY_ID=razorpay_key_id

server.js

require("dotenv").config();
const express = require("express");
const connectDb = require("./utils/db");
const paymentRouters = require("./routers/paymentRoute");
const cors = require("cors");

const app = express();

const corsOptions = {
 origin: 'http://localhost:5173',
 methods: 'GET,HEAD,PUT,PATCH,POST,DELETE',
 credentials: true,
}



app.use(cors(corsOptions));
app.use(express.json());
app.use(express.urlencoded({extended: true}));

app.use("/api/v1", paymentRouters);

const PORT = process.env.PORT || 5000;

connectDb()
 .then(() => {
 app.listen(PORT, () => {
 console.log(`server is listening on ${PORT}`);
 });
 })
 .catch((err) => {
 console.error("Database connection error:");
 console.error(err);
 });

utils/razorpay.js

import Razorpay from "razorpay";
const instance = new Razorpay({
 key_id: process.env.KEY_ID,
 key_secret: process.env.KEY_SECRET
});
export default instance;

controllers/paymentController.js

import instance from "../utils/razorpayIntegration.js"
import crypto from "crypto";

const paymentHandller = async (req, res)=>{
 const {amount} = req.body;
 const options = {
 amount: amount * 100,
 currency: "INR"
 }

 const order = await instance.orders.create(options);

 res.status(200).json({
 status: true,
 order
 })
}

const getRazorpayKey = async (req, res)=>{
 res.status(200).json({
 key: process.env.RAZORPAY_API_KEY
 })

}

const paymentVerification = async (req, res)=>{
 const {razorpay_payment_id, razorpay_order_id, razorpay_signature} = req.body;
// Note : If the positions of order id and payment id will be changed then the expectedSign will create different from original razorpay signature.
 const body = razorpay_order_id + "|" + razorpay_payment_id;

 const expectedSign = crypto.createHmac("sha256", process.env.RAZORPAY_KEY_SECRET)
 .update(body.toString()).digest("hex")

 const isAuthentic = razorpay_signature === expectedSign;
 if(isAuthentic){
 res.status(200).json({
 status: true,
 payment_id: razorpay_payment_id
 })
 }else{
 res.success(404).json({
 success: false,
 message: "Payment failed"
 })

 }
 res.status(200).json({
 success: true
 })
}

module.exports = {paymentHandller, getRazorpayKey, paymentVerification}

routers/paymentRouter.js

const express = require('express');
const router = express.Router();
const paymentControllers = require("../controllers/paymentController");

router.post('/payment-handller', paymentControllers.paymentHandller);
router.get('/get-key', paymentControllers.getRazorpayKey);
router.post('/paymentVerification', paymentControllers.paymentVerification)

module.exports = router;

Frontend Setup

index.html

<script src="https://checkout.razorpay.com/v1/checkout.js"></script>

checkout.jsx

const checkout = async (amount)=>{
 try {
 const response1 = await api.get("/api/v1/get-key");
 const key = await response1.data.key;


 const response2 = await api.post("/api/v1/payment-handller", {
 amount: amount
 })
 const order = await response2.data.order
 const options = {
 key: key, 
 amount: amount, 
 currency: 'INR',
 name: 'Test name',
 description: 'Test Transaction',
 order_id: order.id, 
 handler: async function (response) {
 const res = await api.post("/api/v1/paymentVerification",
 response
 );
 if(res.data.status){
 navigate(`/paymentSuccess?reference=${res.data.payment_id}`);
 }else{
 console.log("Payment Failed.")
 }
 }, 
 prefill: {
 name: 'test Kumar',
 email: 'test.kumar@example.com',
 contact: '9999999999'
 },
 theme: {
 color: '#F37254'
 },
 };
 const rzp = new Razorpay(options);
 rzp.open();
 return order; 
 } catch (error) {
 console.log(error);
 }
 }

paymentSuccess.jsx

import { useSearchParams} from 'react-router-dom'

function PaymentSuccess() {
 const [searchParams] = useSearchParams();
 const paymentId = searchParams.get("reference");

 return (
 <div>
 <h1>Payment Id: {paymentId }</h1>
 </div>
 )
}

export default PaymentSuccess