You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

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

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.08.07 04:02:56