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

如何在单次结账中处理多订阅及Stripe Webhook事件?

解决Stripe单次结账多订阅场景下的Webhook处理问题

在单次结账包含多个订阅的场景中,Stripe的checkout.session.completed事件对象不会仅返回单个subscription字段,而是会返回subscriptions数组(包含所有生成的订阅记录)。你的代码目前直接使用checkout_session.subscription只能获取到其中一个订阅,这是核心问题。

修改后的代码实现

以下是调整后的Ruby代码,能够正确遍历所有订阅并创建对应的数据库记录:

def handle_checkout_session_completed(event)
  puts "checkout.session.completed\n"
  return unless User.exists?(event.data.object.client_reference_id)

  checkout_session = event.data.object
  puts "checkout_session: #{checkout_session}\n"

  # 同时扩展line_items和subscriptions字段,获取完整数据
  session = Stripe::Checkout::Session.retrieve({
    id: checkout_session['id'],
    expand: ['line_items', 'subscriptions']
  })

  line_items = session.line_items.data
  # 将订阅数组转为ID为key的哈希,方便快速查找
  subscriptions_hash = session.subscriptions.to_h { |sub| [sub.id, sub] }

  if checkout_session.payment_status == 'paid'
    fulfill_order(checkout_session, line_items, subscriptions_hash)
  end
end

def fulfill_order(checkout_session, line_items, subscriptions_hash)
  user = User.find(checkout_session.client_reference_id)
  user.update(stripe_id: checkout_session.customer)

  line_items.each do |line_item|
    # 从哈希中获取当前line_item对应的订阅
    subscription = subscriptions_hash[line_item.subscription]
    next unless subscription # 跳过非订阅类型的line item(如果有的话)

    product_id = line_item.price.product
    tool_id = determine_tool_id(product_id)

    Subscription.create(
      user: user,
      subscription_id: subscription.id,
      plan_id: tool_id,
      interval: line_item.price.recurring.interval,
      status: subscription.status,
      current_period_start: Time.at(subscription.current_period_start).to_datetime,
      current_period_end: Time.at(subscription.current_period_end).to_datetime
    )
  end
end

关键调整点

  • 扩展订阅数据:在获取Checkout Session时,同时扩展subscriptions字段,确保拿到所有生成的订阅对象。
  • 订阅哈希映射:将订阅数组转换为以ID为键的哈希,避免重复遍历查找,提升处理效率。
  • 关联Line Item与订阅:每个Line Item的subscription属性对应其所属的订阅ID,通过哈希快速匹配到对应的订阅对象,使用该订阅的真实状态、周期时间等数据创建记录。
  • 状态同步:直接使用Stripe订阅对象的status字段,而非硬编码为active,确保数据库记录与Stripe端状态一致。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.15 03:23:30