Node.js集成PayPal:如何在支付触发请求中附带自定义数据
解决PayPal支付中客户端向Node.js服务端传递额外数据的问题
步骤1:客户端代码修改(传递额外数据)
在createOrder的fetch请求中,添加请求头和请求体,把需要传递的数据(比如product: "potato")发送给服务端:
paypal.Buttons({ createOrder: (data, actions) => { // 要传递的额外数据 const extraData = { product: "potato" }; return fetch("/api/orders", { method: "post", headers: { "Content-Type": "application/json" // 声明请求体为JSON格式 }, body: JSON.stringify(extraData) // 将数据转为JSON字符串发送 }) .then((response) => response.json()) .then((order) => order.id); }, onApprove: (data, actions) => { return fetch(`/api/orders/${data.orderID}/capture`, { method: "post", }) .then((response) => response.json()) .then((orderData) => { console.log('Capture result', orderData, JSON.stringify(orderData, null, 2)); const transaction = orderData.purchase_units[0].payments.captures[0]; alert(`Transaction ${transaction.status}: ${transaction.id}\n\nSee console for all available details`); }); } }).render('#paypal-button-container');
步骤2:服务端准备(确保解析JSON请求体)
在Express应用中添加解析JSON的中间件,否则服务端无法读取req.body的数据:
// 在app初始化后添加 app.use(express.json());
步骤3:服务端修改(接收数据并动态设置支付金额)
修改/api/orders路由,接收客户端传来的数据,根据数据匹配对应金额后,传递给createOrder函数:
// 示例:产品与金额的映射,可根据业务从数据库/配置文件读取 const productPriceMap = { "potato": "10.00", "tomato": "15.00", "default": "100.00" }; app.post("/api/orders", async (req, res) => { // 获取客户端传递的产品标识 const { product } = req.body; // 根据产品获取对应金额,无匹配则用默认值 const targetAmount = productPriceMap[product] || productPriceMap.default; const order = await createOrder(targetAmount); res.json(order); }); // 修改createOrder函数,接收动态金额参数 async function createOrder(amount) { const accessToken = await generateAccessToken(); const url = `${base}/v2/checkout/orders`; const response = await fetch(url, { method: "post", headers: { "Content-Type": "application/json", Authorization: `Bearer ${accessToken}`, }, body: JSON.stringify({ intent: "CAPTURE", purchase_units: [ { amount: { currency_code: "USD", value: amount, // 使用动态传入的金额 }, }, ], }), }); const data = await response.json(); return data; } // 其余代码保持不变 app.post("/api/orders/:orderID/capture", async (req, res) => { const { orderID } = req.params; const captureData = await capturePayment(orderID); // 可选:在这里也可使用req.body的数据,比如记录订单对应的产品信息 res.json(captureData); }); async function capturePayment(orderId) { const accessToken = await generateAccessToken(); const url = `${base}/v2/checkout/orders/${orderId}/capture`; const response = await fetch(url, { method: "post", headers: { "Content-Type": "application/json", Authorization: `Bearer ${accessToken}`, }, }); const data = await response.json(); return data; }
关键注意点
- 客户端必须设置
Content-Type: application/json请求头,否则服务端无法正确解析JSON格式的请求体。 - 服务端的
express.json()中间件是读取req.body的必要前提,不可遗漏。 - 产品金额映射可根据实际业务场景调整,比如从数据库查询真实定价。
内容的提问来源于stack exchange,提问作者HelloTher
相关产品推荐
相关产品推荐

