DEV Community

Cover image for Razorpay + MERN
Madhuban Khatri
Madhuban Khatri

Posted on

Razorpay + MERN

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
Enter fullscreen mode Exit fullscreen mode

.env

PORT=5000
KEY_SECRET=razorpay_key_secret
KEY_ID=razorpay_key_id
Enter fullscreen mode Exit fullscreen mode

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);
 });
Enter fullscreen mode Exit fullscreen mode

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;
Enter fullscreen mode Exit fullscreen mode

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}
Enter fullscreen mode Exit fullscreen mode

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;
Enter fullscreen mode Exit fullscreen mode

Frontend Setup

index.html

<script src="https://checkout.razorpay.com/v1/checkout.js"></script>
Enter fullscreen mode Exit fullscreen mode

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);
    }
  }
Enter fullscreen mode Exit fullscreen mode

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
Enter fullscreen mode Exit fullscreen mode

Top comments (0)