Rails7中Stripe Webhook服务调用无法识别Booking类问题
问题解决思路与方案
核心问题分析
错误NoMethodError (undefined method 'update' for nil:NilClass)的本质是:Webhook触发时,根据Stripe返回的Checkout Session ID,找不到对应的Booking记录,导致booking变量为nil,调用update方法报错。
分步解决方案
1. 验证Checkout Session与Booking的关联是否正确
先确认创建Stripe Checkout Session的代码,是否在成功生成Session后,将session.id正确保存到了Booking的checkout_session_id字段中:
# 示例:创建Checkout Session并关联Booking的代码 session = Stripe::Checkout::Session.create( payment_method_types: ['card'], line_items: [...], mode: 'payment', success_url: '...', cancel_url: '...' ) # 关键:必须把Stripe返回的session.id保存到对应的Booking记录里 booking.update(checkout_session_id: session.id)
同时直接查看数据库中的bookings表,核对错误日志里的Session ID(cs_test_a1bcREeeCzBEtGQJPUyr5YqCiPtVJYXBItvHEeayYgKP2Rtr1qOih3SJRI)是否存在于checkout_session_id字段中,排查是否存在保存失败、值不匹配的情况。
2. 修复服务类的nil安全与非法方法调用
服务类中存在两个问题:
- 未处理
booking为nil的情况 - 错误使用了控制器专属的
render方法(服务类不属于控制器上下文,无法调用)
修改后的服务类代码:
class StripeCheckoutSessionService def call(event) booking = Booking.find_by(checkout_session_id: event.data.object.id) if booking.present? booking.update(payment_status: 1) { state: "processed", status: :ok } else # 记录日志方便后续排查 Rails.logger.warn "未找到对应Booking记录,Stripe Session ID: #{event.data.object.id}" { state: "not_found", status: :not_found } end end end
3. 修正Webhook控制器的调用逻辑
在处理Webhook的控制器中,接收服务类的返回值并完成响应:
class StripeWebhookController < ApplicationController skip_before_action :verify_authenticity_token def handle_event service = StripeCheckoutSessionService.new result = service.call(event) render json: { state: result[:state] }, status: result[:status] end private def event @event ||= Stripe::Webhook.construct_event( request.body.read, request.headers['Stripe-Signature'], Rails.application.credentials.stripe[:webhook_secret] ) end end
4. 关于模型引入的说明
Rails默认会自动加载app/models目录下的模型,app/services中的服务类无需手动require_relative引入,这个问题无需额外处理。
内容的提问来源于stack exchange,提问作者Lisbeth Purrucker
相关产品推荐
相关产品推荐

