DEV Community

Cover image for Razorpay Webhooks in MERN Stack
Vijay Kumar
Vijay Kumar

Posted on

Razorpay Webhooks in MERN Stack

If you are building payment features with Razorpay in a MERN stack application, you will eventually face a problem that every freelancer encounters:

How do I reliably confirm a payment when the user closes the browser, refreshes the page, or the network fails?

This is where Razorpay Webhooks become essential.

In this guide, I’ll walk you through how webhooks work in Razorpay and how to implement them in a MERN stack (MongoDB, Express, React, Node.js) — in a way that is reliable, secure, and production-ready.


What is a Razorpay Webhook?

A webhook is an automated message sent from Razorpay to your server whenever a specific event occurs.

Instead of your server repeatedly asking Razorpay:

“Did the payment succeed yet?”

Razorpay sends your server a notification automatically.

Examples of webhook events include:

  • payment.captured
  • payment.failed
  • order.paid
  • refund.processed
  • subscription.charged

So whenever something happens, Razorpay pushes the event to your backend API.


Why Webhooks are Critical in MERN Applications

Many developers rely only on the frontend payment success callback.

That works during testing, but in production it causes problems like:

  • User closes the payment window
  • Internet disconnects
  • Frontend crashes
  • Payment succeeds but frontend never updates

With webhooks:

  • Payment confirmation happens server-to-server
  • It works even if the user leaves the page
  • Your database stays accurate

This is why serious payment systems always use webhooks.


MERN Stack Architecture with Razorpay Webhooks

The typical flow looks like this:

User -> React Frontend
       -> Node/Express Backend
           -> Razorpay Order Created

User completes payment

Razorpay -> Webhook -> Node Server

Node Server -> Verify Signature -> Update MongoDB
Enter fullscreen mode Exit fullscreen mode

So the webhook endpoint becomes the source of truth for payment success.


Step 1: Create a Webhook in Razorpay Dashboard

Go to:

Razorpay Dashboard → Settings → Webhooks

Add a new webhook:

URL: https://yourdomain.com/api/webhook/razorpay
Secret: your_webhook_secret
Enter fullscreen mode Exit fullscreen mode

Select events like:

  • payment.captured
  • payment.failed
  • order.paid

Save it.

Now Razorpay will send POST requests to your backend whenever these events occur.


Step 2: Create Webhook Endpoint in Express

In your Node.js backend, create a webhook route.

Example:

const express = require("express");
const crypto = require("crypto");

const router = express.Router();

router.post("/webhook/razorpay", express.raw({ type: "application/json" }), (req, res) => {

  const webhookSecret = process.env.RAZORPAY_WEBHOOK_SECRET;

  const signature = req.headers["x-razorpay-signature"];

  const generatedSignature = crypto
    .createHmac("sha256", webhookSecret)
    .update(req.body)
    .digest("hex");

  if (generatedSignature === signature) {
    const event = JSON.parse(req.body);

    console.log("Webhook verified:", event.event);

    // Handle events here
    if (event.event === "payment.captured") {
        const payment = event.payload.payment.entity;

        // Update MongoDB
        console.log("Payment Successful:", payment.id);
    }

    res.status(200).send("Webhook received");

  } else {
    res.status(400).send("Invalid signature");
  }
});

module.exports = router;
Enter fullscreen mode Exit fullscreen mode

Step 3: Update MongoDB Payment Status

When a webhook confirms the payment, update your database.

Example:

await Order.findOneAndUpdate(
  { razorpayOrderId: payment.order_id },
  {
    paymentStatus: "paid",
    razorpayPaymentId: payment.id
  }
);
Enter fullscreen mode Exit fullscreen mode

Now your system knows the real payment status.


Step 4: Connect This with Your React Frontend

Your frontend should not blindly trust the payment success response.

Instead:

  1. Payment happens
  2. Webhook confirms payment
  3. Backend updates MongoDB
  4. Frontend fetches updated order status

This ensures data consistency.


Step 5: Testing Razorpay Webhooks

Testing webhooks can be confusing at first.

Here are the easiest methods:

Option 1: Use ngrok

Expose your local server:

ngrok http 5000
Enter fullscreen mode Exit fullscreen mode

Use the generated URL as the webhook URL.

Example:

https://abcd1234.ngrok.io/api/webhook/razorpay
Enter fullscreen mode Exit fullscreen mode

Option 2: Razorpay Webhook Test Tool

Razorpay dashboard lets you send test webhook events.

Use this to simulate:

  • payment success
  • payment failure

Security Best Practices

Never skip these steps in production.

Always Verify Webhook Signature

Without verification, anyone could send fake payment events to your API.

Always check:

x-razorpay-signature
Enter fullscreen mode Exit fullscreen mode

Use Raw Body Parsing

Do NOT use normal express.json() for webhook routes.

Use:

express.raw()
Enter fullscreen mode Exit fullscreen mode

Otherwise the signature verification fails.


Store Webhook Logs

Save webhook responses for debugging.

Example Mongo schema:

WebhookLogs
- event
- payload
- receivedAt
Enter fullscreen mode Exit fullscreen mode

This helps track payment issues.


Common Mistakes Developers Make

Updating payment status from frontend

This leads to fake confirmations.

Always update from webhook events.


Ignoring retry events

If your server fails, Razorpay retries webhooks automatically.

Make your API idempotent.


Not handling failed payments

Track both:

  • payment.captured
  • payment.failed

Final Thoughts

If you are a freelancer building payment systems with Razorpay and MERN, webhooks are not optional — they are the backbone of reliable payment processing.

Once implemented correctly, webhooks allow you to:

  • confirm payments securely
  • automate order processing
  • prevent payment inconsistencies
  • build production-grade payment systems

And most importantly, they ensure your database always reflects the real payment status.


✅ If you're building Razorpay integrations with MERN, mastering webhooks is one of the most valuable backend skills you can have.


Open for freelance work fiverr

Top comments (0)