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
相关产品推荐
相关产品推荐

