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

Rails 7集成Stripe:如何在Webhook控制器获取Payment Intent元数据

问题解决:从Stripe Webhook获取Metadata并创建Payment记录

核心问题分析

你当前监听的payment_intent.succeeded事件对应的是PaymentIntent对象,但你在Checkout Session中设置的metadata不会自动同步到PaymentIntent里。另外,Payment.create里的email: "${session.email}"是错误的字符串写法,无法正确获取邮箱值。


方案一:改用checkout.session.completed事件(推荐)

这个事件返回的对象就是你创建的Checkout Session,直接包含你设置的metadata和用户邮箱信息,代码调整如下:

# webhooks_controller.rb
when 'checkout.session.completed'
  checkout_session = event.data.object
  # 从Checkout Session中获取metadata
  post_id = checkout_session.metadata['post_id']
  user_id = checkout_session.metadata['user_id']
  # 获取用户邮箱(Stripe会自动返回结账时填写的邮箱)
  customer_email = checkout_session.customer_email

  # 创建Payment记录
  Payment.create(
    post_id: post_id,
    user_id: user_id, # 可选,如需关联用户可保留
    time_stamp: Time.now.to_datetime.utc,
    email: customer_email
  )
  render json: { message: 'success' }
end

方案二:继续使用payment_intent.succeeded事件

如果一定要监听这个事件,需要在创建Checkout Session时,通过payment_intent_data把metadata同步到PaymentIntent中:

第一步:修改checkouts_controller的创建逻辑

# checkouts_controller.rb
def create
  session = Stripe::Checkout::Session.create({
    payment_method_types: ['card'],
    line_items: [
      { # 补全line_items数组元素的外层花括号,修复语法错误
        price_data: {
          product: 'prod_Miva1sJtJ29QeC',
          unit_amount: 500,
          currency: 'usd',
        },
        quantity: 1,
      }
    ],
    metadata: {user_id: current_user.id, post_id: params[:post_id]},
    # 添加此行,将metadata同步到PaymentIntent
    payment_intent_data: {
      metadata: {user_id: current_user.id, post_id: params[:post_id]}
    },
    mode: 'payment',
    success_url: root_url(success: true),
    cancel_url: root_url,
  })
end

第二步:修改webhooks_controller的逻辑

# webhooks_controller.rb
when 'payment_intent.succeeded'
  payment_intent = event.data.object
  post_id = payment_intent.metadata['post_id']
  # 通过PaymentIntent关联的Checkout Session获取邮箱
  checkout_session = Stripe::Checkout::Session.retrieve(payment_intent.checkout_session)
  customer_email = checkout_session.customer_email

  Payment.create(
    post_id: post_id,
    time_stamp: Time.now.to_datetime.utc,
    email: customer_email
  )
  render json: { message: 'success' }
end

额外注意点

  • Ruby的字符串插值语法是"#{variable}",但此处直接调用对象属性即可,无需插值写法。
  • 原checkouts_controller中line_items数组的元素缺少外层花括号,属于语法错误,已在方案二中补全。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.18 12:30:13