如何在charge.succeeded Webhook中获取Stripe的ClientReferenceId
核心原因
ClientReferenceId 是 Stripe Checkout Session 专属的自定义属性,不会自动同步到 Charge 对象中,你在 charge.succeeded 事件的负载里找不到这个字段属于正常逻辑。
方案1:改用 checkout.session.completed 事件处理
优先选择监听 checkout.session.completed 事件,该事件的负载根对象就是 Stripe.Checkout.Session 实例,你可以直接读取 ClientReferenceId 字段拿到存储的客户ID,同时事件负载也会关联返回对应的 Charge ID、付款状态等核心支付信息,足以覆盖绝大多数支付成功后的业务处理场景。
参考代码示例:
// 解析Webhook事件 var stripeEvent = EventUtility.ConstructEvent(json, signatureHeader, webhookSecret); if (stripeEvent.Type == Events.CheckoutSessionCompleted) { var session = stripeEvent.Data.Object as Session; var clientReferenceId = session.ClientReferenceId; // 直接读取你存入的客户ID var chargeId = session.PaymentIntent?.Charges?.Data?.FirstOrDefault()?.Id; // 也可获取关联的Charge ID }
方案2:从 charge.succeeded 事件反向查询关联Session
如果你必须在 charge.succeeded 事件中处理业务,可以通过 Charge 对象关联的 PaymentIntent ID 反向查询对应的Checkout Session:
- 从
charge.succeeded事件的Charge对象中读取PaymentIntentId字段 - 调用
SessionService的ListAsync方法,传入过滤参数PaymentIntent = [获取到的PaymentIntentId],即可查询到关联的Checkout Session实例,进而读取ClientReferenceId
参考代码示例:
if (stripeEvent.Type == Events.ChargeSucceeded) { var charge = stripeEvent.Data.Object as Charge; var paymentIntentId = charge.PaymentIntentId; var sessionService = new SessionService(); var sessionListOptions = new SessionListOptions { PaymentIntent = paymentIntentId, Limit = 1 }; var sessions = await sessionService.ListAsync(sessionListOptions); var targetSession = sessions.FirstOrDefault(); var clientReferenceId = targetSession?.ClientReferenceId; }
补充优化方案
如果你希望自定义参数直接同步到Charge对象,也可以在创建Checkout Session时,通过 PaymentIntentData 的 Metadata 字段存储客户ID,该字段会自动同步到关联的PaymentIntent和Charge对象的Metadata中,你可以直接在 charge.succeeded 事件的 Charge.Metadata 里读取对应值。
内容的提问来源于stack exchange,提问作者Eugene
相关产品推荐
相关产品推荐

