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

Stripe Basil API:如何将PaymentIntent与发票关联?

Stripe Basil API:Invoice与PaymentIntent/Charge的关联问题

我正在使用最新版Stripe Basil API,发现Invoice对象的payment_intent字段已被移除。此前可直接将PaymentIntent与发票关联,但现在无法建立该连接,尤其是在Webhook中——paymentIntent.created事件未提供任何关联信息(无invoice_id等),Charges的情况也类似。

我的使用场景是扩展订阅功能并在系统中记录交易,此前代码可正常运行:

case "invoice.payment_succeeded":
  const invoicePaymentSucceeded = event.data.object;

  const subscriptionId = invoicePaymentSucceeded.subscription;
  const paymentIntentId = invoicePaymentSucceeded.payment_intent;
  const chargeId = invoicePaymentSucceeded.charge;

  if (!subscriptionId || typeof subscriptionId !== "string") {
    console.error("Missing subscription ID:", invoicePaymentSucceeded);
    return res.status(400).json({ error: "Invalid subscription ID" });
  }

  if (!paymentIntentId || typeof paymentIntentId !== "string") {
    console.error("Missing payment intent ID:", invoicePaymentSucceeded);
    return res.status(400).json({ error: "Invalid payment intent ID" });
  }

  if (!chargeId || typeof chargeId !== "string") {
    console.error("Missing charge ID:", invoicePaymentSucceeded);
    // Optional: no early return here, just log to show it's unexpectedly null
  }

我需要获取payment intent ID以及charge以获取Stripe手续费和应用手续费,目前无法理清关联逻辑。请问如何通过Basil API将PaymentIntent与对应发票关联?


解决方案

1. 从invoice.payment_succeeded事件中获取PaymentIntent

Basil API将原Invoice对象的单个payment_intent字段替换为payment_intents数组,存储所有与该发票关联的PaymentIntent记录。对于成功支付的发票,可从数组中筛选出状态为succeeded的PaymentIntent:

case "invoice.payment_succeeded":
  const invoicePaymentSucceeded = event.data.object;

  const subscriptionId = invoicePaymentSucceeded.subscription;
  // 筛选成功的PaymentIntent
  const succeededPaymentIntent = invoicePaymentSucceeded.payment_intents.find(
    pi => pi.status === "succeeded"
  );
  const paymentIntentId = succeededPaymentIntent?.id;

  if (!subscriptionId || typeof subscriptionId !== "string") {
    console.error("Missing subscription ID:", invoicePaymentSucceeded);
    return res.status(400).json({ error: "Invalid subscription ID" });
  }

  if (!paymentIntentId || typeof paymentIntentId !== "string") {
    console.error("Missing payment intent ID:", invoicePaymentSucceeded);
    return res.status(400).json({ error: "Invalid payment intent ID" });
  }

2. 获取关联的Charge并提取手续费

Charge不再直接挂在Invoice对象上,需通过PaymentIntent关联:

  • 调用Stripe API获取PaymentIntent详情,从charges.data数组中取出对应Charge记录
  • Charge对象的application_fee_amount和fee_details字段包含手续费信息

修改后的代码片段:

// 接上面的代码,获取PaymentIntent后
let chargeId;
let stripeFee = 0;
let applicationFee = 0;

if (paymentIntentId) {
  // 调用Stripe API获取PaymentIntent详情
  const paymentIntent = await stripe.paymentIntents.retrieve(paymentIntentId);
  const charge = paymentIntent.charges.data[0];
  
  if (charge) {
    chargeId = charge.id;
    // 提取Stripe手续费和应用手续费
    stripeFee = charge.fee_details?.reduce((total, fee) => {
      return fee.type === "stripe_fee" ? total + fee.amount : total;
    }, 0);
    applicationFee = charge.application_fee_amount || 0;
  }
}

if (!chargeId || typeof chargeId !== "string") {
  console.error("Missing charge ID:", invoicePaymentSucceeded);
}

3. 从PaymentIntent事件反向关联发票

在payment_intent.succeeded或payment_intent.created事件中,PaymentIntent对象的invoice字段会直接指向关联的发票ID,可用于双向关联:

case "payment_intent.succeeded":
  const paymentIntent = event.data.object;
  const invoiceId = paymentIntent.invoice;
  
  if (invoiceId) {
    // 根据invoiceId查询对应的发票或订阅信息
    const invoice = await stripe.invoices.retrieve(invoiceId);
    const subscriptionId = invoice.subscription;
  }

4. 注意事项

  • 确保Stripe客户端初始化时指定Basil对应的API版本(如2024-06-20)
  • 若Webhook事件返回字段不全,可通过expand参数在API调用中扩展关联对象(如stripe.invoices.retrieve(invoiceId, { expand: ['payment_intents'] }))

内容的提问来源于stack exchange,提问作者user9247

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.06.13 07:42:17