在您的 React 应用中集成 Razorpay 支付网关

2025-05-27

在您的 React 应用中集成 Razorpay 支付网关

什么是 Razorpay?

Razorpay 是印度的一种支付解决方案,允许企业使用所有支付方式,包括信用卡、借记卡、网上银行、UPI 和其他流行的钱包。

Don't confuse India-only business with single currency payments.
Razorpay accepts payments in almost all currencies.
Enter fullscreen mode Exit fullscreen mode

在我们的应用程序中集成支付网关之前,让我们了解一下razorpay 的支付流程。

付款流程

替代文本

  1. 客户在您的网站或应用上下订单
  2. 您使用 Razorpay 实例从您的服务器创建订单。
  3. 然后,您将订单 ID 传递给结账处并收集付款详情。
  4. 然后,通过验证 Razorpay 返回的签名,在您的后端对付款进行身份验证。
  5. 捕获付款。

这是 Razorpay 支付流程的概览图。
您可以点击此处实时试用该支付流程


让我们将 Razorpay 集成到我们的应用中

创建 Razorpay 账户

前往Razorpay 控制面板并创建一个您自己的账户。无需激活,因为我们将立即开始操作Test mode

前往Settings选项卡,生成您的文件API keys并将其保存到某个地方。我们稍后会用到它。

创建我们的服务器

在您的电脑上创建一个文件夹并npm在该文件夹上进行初始化。

npm init
Enter fullscreen mode Exit fullscreen mode

我们需要为服务器安装一些依赖项。
安装这些依赖项。

  • 表达
  • razorpay
  • dotenv
  • 加密(用于最后一步验证签名)
  • mongoose(可选:如果您想将详细信息保存在数据库中)
npm i express razorpay dotenv crypto mongoose
Enter fullscreen mode Exit fullscreen mode

server.js现在在根目录中创建一个文件并初始化您的 express 服务器。

const express = require("express");

const app = express();
const port = process.env.PORT || 5000;

// middlewares
app.use(express.json({ extended: false }));

app.listen(port, () => console.log(`server started on port ${port}`));
Enter fullscreen mode Exit fullscreen mode

现在我们的服务器正在运行localhost:5000,我们需要在后端添加一些路线来处理支付步骤。

保存 API 密钥

我们将使用.env文件来保存密钥。.env在根目录中创建一个文件。在文件
中添加以下代码.env,并将值替换为您的密钥。

RAZORPAY_SECRET=<your razorpay secret>
RAZORPAY_KEY_ID=<your razorpay ket id>
Enter fullscreen mode Exit fullscreen mode

Don't add any quotes.

添加创建订单的路线

routes在根目录中创建一个名为的新文件夹,并在文件夹payment.js中添加一个新文件routes

  • 我们需要创建一条POST路线来创建订单。
  • 为此,我们必须创建 Razorpay 的一个实例。
  • 然后我们会打电话instance.orders.create()
require("dotenv").config();
const express = require("express");
const Razorpay = require("razorpay");

const router = express.Router();

router.post("/orders", async (req, res) => {
    try {
        const instance = new Razorpay({
            key_id: process.env.RAZORPAY_KEY_ID,
            key_secret: process.env.RAZORPAY_SECRET,
        });

        const options = {
            amount: 50000, // amount in smallest currency unit
            currency: "INR",
            receipt: "receipt_order_74394",
        };

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

        if (!order) return res.status(500).send("Some error occured");

        res.json(order);
    } catch (error) {
        res.status(500).send(error);
    }
});
Enter fullscreen mode Exit fullscreen mode

Note:金额需要采用最小货币单位,例如,对于 500 卢比,您必须在金额变量中指定 50000

现在将此payment.js路由文件导入到你的server.js文件中以启用路由。现在你的server.js文件将如下所示……

const express = require("express");

const app = express();
const port = process.env.PORT || 5000;

// middlewares
app.use(express.json({ extended: false }));

// route included
app.use("/payment", require("./routes/payment"));

app.listen(port, () => console.log(`server started on port ${port}`));
Enter fullscreen mode Exit fullscreen mode

现在我们需要一个前端表单,用于发出创建订单的请求。

创建 React 应用

我们将在根目录中创建 React 应用程序。

npx create-react-app client
Enter fullscreen mode Exit fullscreen mode

我已将应用命名为client。您可以随意命名。
完成这些之后,让我们回顾一下文件夹结构,以免您感到困惑。

替代文本

现在让我们清理所有 React 样板代码。
清理完成后,你的 React 应用文件夹应该如下所示。你可以从文件夹中删除所有无用的文件。

替代文本

还可以安装axios在您的 react app 文件夹中,以便向后端发出请求。

cd client
npm i axios
Enter fullscreen mode Exit fullscreen mode

添加按钮以启动付款流程

转到App.js文件并用以下内容替换所有代码。

import React from "react";
import logo from "./logo.svg";
import "./App.css";
import axios from "axios";

function App() {

    return (
        <div className="App">
            <header className="App-header">
                <img src={logo} className="App-logo" alt="logo" />
                <p>Buy React now!</p>
                <button className="App-link" onClick={displayRazorpay}>
                    Pay ₹500
                </button>
            </header>
        </div>
    );
}

export default App;
Enter fullscreen mode Exit fullscreen mode

可以看到,我只添加了一个按钮,并displayRazorpayonClick事件分配了一个函数。现在让我们创建这个函数。
点击按钮时,我们需要执行三件事。

  1. 加载Razorpay checkout script为我们在后台完成所有工作的。
  2. POST向我们的后端路由发出请求/payment/orders以创建一个新订单,该订单将返回订单的详细信息,包括idamount
  3. 然后使用它idamount最终显示 Razorpay 弹出窗口。

为了加载脚本,我添加了一个函数loadScript,该函数以script src字符串作为输入并返回Promise加载脚本的函数。

function loadScript(src) {
        return new Promise((resolve) => {
            const script = document.createElement("script");
            script.src = src;
            script.onload = () => {
                resolve(true);
            };
            script.onerror = () => {
                resolve(false);
            };
            document.body.appendChild(script);
        });
}
Enter fullscreen mode Exit fullscreen mode

然后我将添加displayRazorpay函数first load the scriptthen make a post request to our back-end routefinally show the popup

async function displayRazorpay() {
        const res = await loadScript(
            "https://checkout.razorpay.com/v1/checkout.js"
        );

        if (!res) {
            alert("Razorpay SDK failed to load. Are you online?");
            return;
        }

        // creating a new order
        const result = await axios.post("http://localhost:5000/payment/orders");

        if (!result) {
            alert("Server error. Are you online?");
            return;
        }

        // Getting the order details back
        const { amount, id: order_id, currency } = result.data;

        const options = {
            key: "rzp_test_r6FiJfddJh76SI", // Enter the Key ID generated from the Dashboard
            amount: amount.toString(),
            currency: currency,
            name: "Soumya Corp.",
            description: "Test Transaction",
            image: { logo },
            order_id: order_id,
            handler: async function (response) {
                const data = {
                    orderCreationId: order_id,
                    razorpayPaymentId: response.razorpay_payment_id,
                    razorpayOrderId: response.razorpay_order_id,
                    razorpaySignature: response.razorpay_signature,
                };

                const result = await axios.post("http://localhost:5000/payment/success", data);

                alert(result.data.msg);
            },
            prefill: {
                name: "Soumya Dey",
                email: "SoumyaDey@example.com",
                contact: "9999999999",
            },
            notes: {
                address: "Soumya Dey Corporate Office",
            },
            theme: {
                color: "#61dafb",
            },
        };

        const paymentObject = new window.Razorpay(options);
        paymentObject.open();
}
Enter fullscreen mode Exit fullscreen mode

对于每笔成功付款,结帐都会返回:

  • razorpay_payment_id
  • razorpay_order_id
  • razorpay_签名

我们可以在属性中访问这些值handler。正如您所见,我向新的后端路由发出了请求,并将order id之前创建订单时收到的详细信息发送到了 。这是为了验证付款是否合法。

Don't confuse the "razorpay_order_id" with the "order_id" we got
while creating a new order. These two are entirely different.
Enter fullscreen mode Exit fullscreen mode

现在您的App.js文件应该如下所示。

import React from "react";
import logo from "./logo.svg";
import "./App.css";
import axios from "axios";

function App() {
    function loadScript(src) {
        return new Promise((resolve) => {
            const script = document.createElement("script");
            script.src = src;
            script.onload = () => {
                resolve(true);
            };
            script.onerror = () => {
                resolve(false);
            };
            document.body.appendChild(script);
        });
    }

    async function displayRazorpay() {
        const res = await loadScript(
            "https://checkout.razorpay.com/v1/checkout.js"
        );

        if (!res) {
            alert("Razorpay SDK failed to load. Are you online?");
            return;
        }

        const result = await axios.post("http://localhost:5000/payment/orders");

        if (!result) {
            alert("Server error. Are you online?");
            return;
        }

        const { amount, id: order_id, currency } = result.data;

        const options = {
            key: "rzp_test_r6FiJfddJh76SI", // Enter the Key ID generated from the Dashboard
            amount: amount.toString(),
            currency: currency,
            name: "Soumya Corp.",
            description: "Test Transaction",
            image: { logo },
            order_id: order_id,
            handler: async function (response) {
                const data = {
                    orderCreationId: order_id,
                    razorpayPaymentId: response.razorpay_payment_id,
                    razorpayOrderId: response.razorpay_order_id,
                    razorpaySignature: response.razorpay_signature,
                };

                const result = await axios.post("http://localhost:5000/payment/success", data);

                alert(result.data.msg);
            },
            prefill: {
                name: "Soumya Dey",
                email: "SoumyaDey@example.com",
                contact: "9999999999",
            },
            notes: {
                address: "Soumya Dey Corporate Office",
            },
            theme: {
                color: "#61dafb",
            },
        };

        const paymentObject = new window.Razorpay(options);
        paymentObject.open();
    }

    return (
        <div className="App">
            <header className="App-header">
                <img src={logo} className="App-logo" alt="logo" />
                <p>Buy React now!</p>
                <button className="App-link" onClick={displayRazorpay}>
                    Pay ₹500
                </button>
            </header>
        </div>
    );
}

export default App;
Enter fullscreen mode Exit fullscreen mode

如果你启动 React 应用,该应用在浏览器中应该看起来像这样

替代文本

如果您单击该Pay ₹500按钮,就会出现一个弹出窗口。

替代文本

但不要立即付款。我们需要在后端添加另一条路由来验证付款。

验证付款

这一步我们只需要在后端自己创建一个签名,并检查我们的签名是否与razorpay发送的签名相同。
记住,付款成功后,我们的React应用会将四个值发送回后端路由/payment/success

  • orderCreationId(订单 ID,我们在创建订单时获取)
  • razorpay付款ID
  • razorpay订单号
  • razorpay签名

我们需要使用 SHA256 算法,使用razorpayPaymentIdorderCreationId构建 HMAC 十六进制摘要。然后将digest和进行比较razorpaySignature。如果两者相等,则我们的付款已验证。

创建验证路线

导航到文件夹payment.js内的文件routes并遵循以下POST路线。

router.post("/success", async (req, res) => {
    try {
        // getting the details back from our font-end
        const {
            orderCreationId,
            razorpayPaymentId,
            razorpayOrderId,
            razorpaySignature,
        } = req.body;

        // Creating our own digest
        // The format should be like this:
        // digest = hmac_sha256(orderCreationId + "|" + razorpayPaymentId, secret);
        const shasum = crypto.createHmac("sha256", "w2lBtgmeuDUfnJVp43UpcaiT");

        shasum.update(`${orderCreationId}|${razorpayPaymentId}`);

        const digest = shasum.digest("hex");

        // comaparing our digest with the actual signature
        if (digest !== razorpaySignature)
            return res.status(400).json({ msg: "Transaction not legit!" });

        // THE PAYMENT IS LEGIT & VERIFIED
        // YOU CAN SAVE THE DETAILS IN YOUR DATABASE IF YOU WANT

        res.json({
            msg: "success",
            orderId: razorpayOrderId,
            paymentId: razorpayPaymentId,
        });
    } catch (error) {
        res.status(500).send(error);
    }
});
Enter fullscreen mode Exit fullscreen mode

现在所有步骤都已完成。
您可以继续付款,如果付款成功,您可以在标签页中查看付款Razorpay DashboardTransactions以下
是一些演示卡的详细信息,您可以使用它们来测试付款流程Test mode

替代文本

使用未来任何有效的到期日期和任何随机 CVV 码即可成功付款。
准备就绪后,您可以在正式开始使用之前切换并激活您的账户。您将获得Live mode一套新的API keysLive mode

您可以在我的Github repo中找到所有源代码

当你在那里时,不要忘记在 Github 上关注我

非常感谢您的阅读。

我还会写一篇关于Stripe 与 React 集成的文章。敬请期待!


在网络上找到我🕸:

文章来源:https://dev.to/soumyadey/integrate-razorpay-in-your-react-app-2nib
PREV
一些鲜为人知但非常棒的 Web 开发在线工具
NEXT
Git-flow 相对于标准 git 命令的优势