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

React集成Stripe时Webhook返回空Metadata问题求助

解决Stripe Webhook中Metadata为空的问题

要让Webhook的payment_intent.succeeded事件中包含自定义Metadata,不能在前端的confirmPayment方法中添加Metadata——因为前端属于公开环境,Metadata的设置必须在后端创建Payment Intent时完成,这是Stripe的安全设计要求。

核心解决方案步骤

  1. 后端创建Payment Intent时添加Metadata
    所有需要传递的产品、用户等信息,必须在后端调用Stripe SDK创建Payment Intent时,通过metadata字段传入。这是唯一能让Metadata出现在Webhook事件中的方式。

  2. 前端从后端获取Client Secret
    前端不再直接生成Payment Intent,而是调用后端接口获取client_secret,再传入stripe.confirmPayment中完成支付流程。


具体代码示例

1. 后端代码(以Node.js为例)

const stripe = require('stripe')('你的Stripe私密密钥');

// 后端接口:创建Payment Intent并返回client_secret
app.post('/create-payment-intent', async (req, res) => {
  // 从前端请求中获取需要存入Metadata的信息
  const { productId, productName, userId } = req.body;

  const paymentIntent = await stripe.paymentIntents.create({
    amount: 1500, // 支付金额(单位:分,示例为15日元)
    currency: 'jpy',
    // 在这里设置需要传递的Metadata
    metadata: {
      product_id: productId,
      product_name: productName,
      user_id: userId,
      order_note: '用户定制备注' // 其他自定义信息
    },
    automatic_payment_methods: {
      enabled: true,
    },
  });

  res.json({ clientSecret: paymentIntent.client_secret });
});

2. 前端代码修改

更新handleSubmit逻辑,先调用后端接口获取client_secret,再执行支付确认:

const handleSubmit = async (e) => {
  e.preventDefault();
  setIsLoading(true);

  try {
    // 第一步:调用后端接口获取client_secret,传递产品信息
    const response = await fetch('/create-payment-intent', {
      method: 'POST',
      headers: { 'Content-Type': 'application/json' },
      body: JSON.stringify({
        productId: 'prod_XXXXXX',
        productName: '日式咖啡套装',
        userId: 'user_123456'
      }),
    });
    const { clientSecret } = await response.json();

    // 第二步:执行支付确认
    const result = await stripe.confirmPayment({
      elements,
      clientSecret, // 传入从后端获取的client_secret
      confirmParams: {
        return_url: `${your url}/thanks`,
      },
    });

    // 支付结果处理
    if (result.error) {
      setFinishedPayment(false);
      setMessage(result.error.message || '支付失败,请重试');
    } else {
      console.log('支付成功,跳转至感谢页');
    }
  } catch (err) {
    setMessage('网络错误,请稍后再试');
  }
  setIsLoading(false);
};

关键说明

  • Metadata的键值对均为字符串类型,若需传递数字/布尔值,需先转为字符串。
  • 后端的Stripe私密密钥绝对不能暴露在前端代码中,必须保存在服务器环境变量里。
  • 设置完成后,当payment_intent.succeeded事件触发时,Webhook返回的事件对象中data.object.metadata会包含你设置的所有信息,直接读取并存入数据库即可。

内容的提问来源于stack exchange,提问作者ほせまさ

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.01 08:31:18