Razorpay Payment Integration (MERN STACK)

Backend

Packages:  Razorpay

Code:


const Razorpay = require('razorpay');
const dotenv = require("dotenv")
dotenv.config()
const razorpay = new Razorpay({
  key_id: process.env.RAZ_KEY_ID,
  key_secret: process.env.RAZ_KEY_SECRET,
});

exports.createOrder = async (req, res) => {
    try {
      const options = {
        amount: req.body.amount,
        currency: 'INR',
        receipt: 'receipt_' + Math.random().toString(36).substring(7),
        notes: req.body.notes
       
      };
      const order = await razorpay.orders.create(options);
      res.status(200).json(order);
    } catch (err) {
      res.status(500).json({ error: err.message });
    }
  }
  exports.verifyPayment = async (req, res) => {
    try {
      const { razorpay_order_id, razorpay_payment_id, razorpay_signature } = req.body;
      const sign = razorpay_order_id + '|' + razorpay_payment_id;
      const expectedSign = crypto.createHmac('sha256', process.env.RAZ_KEY_SECRET)
                              .update(sign.toString())
                              .digest('hex');
      if (razorpay_signature === expectedSign) {
        // Payment is verified
        res.status(200).json({ message: 'Payment verified successfully' });
      } else {
        res.status(400).json({ error: 'Invalid payment signature' });
      }
    } catch (err) {
      res.status(500).json({ error: err.message });
    }
  }

 

  exports.getOrderDetails = async(req, res, next)=>{
    try {
     
      razorpay.orders.fetch(req.body.orderId).then(order => {
        const notes = order; // Retrieve the product ID from the notes
        res.status(200).json(notes)
        // Proceed with the rest of the payment handling logic
      });      
    } catch (error) {
      next(error)
    }
  }


Frontend

packages: react-razorpay

Code:

import {useRazorpay} from "react-razorpay";

function PaymentButton() {
  const [buyNowBtnClicked, setBuyNowBtnClicked] = useState(false);
  const {Razorpay} = useRazorpay();
  const currentVariant = useSelector(
    (state) => state.activeProduct.currentVariant
  );
  const RAZORPAY_KEY_ID = import.meta.env.VITE_RAZ_ID;

  const handlePayment = async () => {
    try {
      const response = await fetch(import.meta.env.VITE_BACKEND_HOST+"/order/create", {
        method: "POST",
        headers: {
          "Content-Type": "application/json",
        },
        body: JSON.stringify({ amount: 5000 }),
      });

      const order = await response.json();
      console.log(order)
      const options = {
        key: RAZORPAY_KEY_ID,
        amount: order.amount,
        currency: order.currency,
        name: "NARA",
        description: "Payment for your order",
        order_id: order.id,
        handler: async (response) => {    
          try {
            console.log("OrderId Backend", order.id)
            console.log("OrderId RazorPay",response.razorpay_order_id)
            await fetch(import.meta.env.VITE_BACKEND_HOST+"/order/verify", {
              method: "POST",
              headers: {
                "Content-Type": "application/json",
              },

              body: JSON.stringify({
                razorpay_order_id: response.razorpay_order_id,
                razorpay_payment_id: response.razorpay_payment_id,
                razorpay_signature: response.razorpay_signature,
              }),
            });
            // You have to check if the response is ok or not
                before alerting the user that the payment was successful
            alert("Payment successful!");
          } catch (err) {
           
            alert("Payment failed: " + err.message);
          }
        },
        prefill: {
          name: "John Doe",
          email: "john@example.com",
          contact: "+918210853664",
       
        },
        theme: {
          color: "#080906",
        },
      };
      const rzpay = new Razorpay(options);
      rzpay.open(options);
    } catch (err) {
      alert("Error creating order: " + err.message);
    }
  };

  return <button
    disabled={!currentVariant}
    className="relative mr-2 disabled:text-gray-200 px-4 py-2 border-2 shadow-lg xl:!shadow-none"
    onClick={handlePayment}
  >
    {buyNowBtnClicked && (
      <div className="absolute flex items-center justify-center top-0 right-0 left-0 bottom-0">
        <Spinner />
      </div>
    )}

    <span className={buyNowBtnClicked && "opacity-0"}>Buy Now</span>
  </button>;
}

Comments

Popular posts from this blog

How to add reCAPTCHA validation to your MERN stack app

Google OAuth implementation in MERN stack