Rails项目调用Stripe::Customer时报customer.sources未定义NoMethodError
Rails对接Stripe触发
sources未定义方法的报错排查 问题场景
在Rails项目中对接Stripe服务,执行用户绑定支付方式更新、获取客户关联支付数据的逻辑时,抛出NoMethodError: 'sources' for #<Stripe::Customer>报错。开发已提前验证Stripe接口返回的customer变量非空,排除空对象触发方法不存在的可能性。
触发报错的原有实现代码
def update_payment if !current_user.stripe_id customer = Stripe::Customer.create( email: current_user.email, source: params[:stripeToken] ) else customer = Stripe::Customer.update( current_user.stripe_id, source: params[:stripeToken] ) end if current_user.update(stripe_id: customer.id, stripe_last_4: customer.sources.data.first["last4"]) flash[:notice] = "New card is saved" else flash[:alert] = "Invalid card" end redirect_to request.referrer rescue Stripe::CardError => e flash[:alert] = e.message redirect_to request.referrer end
报错根本原因
Stripe从7.0.0版本开始正式移除了Stripe::Customer对象上挂载的sources属性,该关联字段属于早已废弃的老版支付方式API设计。
新版本Stripe服务将客户关联的支付方式统一收敛到payment_methods关联体系下,通过Customer接口默认返回的对象结构中,已经不存在sources属性。这也和开发已经验证customer变量非空的排查结果匹配:报错不是来自空对象,而是来自有效Customer实例本身的结构变更,因此访问customer.sources时必然触发未定义方法的报错。
修复实现方案
- 不再使用已废弃的
sources字段获取银行卡信息。针对当前需要提取绑定银行卡尾号(stripe_last_4)的业务场景,不需要穿透sources数组取第一个元素,可以直接从Customer对象挂载的默认支付渠道关联中读取信息。 - 若确实需要拉取客户全量关联的支付卡列表,需要调用
PaymentMethod.list接口,传入customer标识与type: 'card'参数查询,不能依赖Customer对象上挂载的旧版sources属性。 - 适配高版本Stripe的字段迁移逻辑:如果使用的Stripe gem版本在10.x以上,Customer对象的
default_source返回值会逐步迁移到invoice_settings.default_payment_method关联下,这种场景下需要通过支付方式详情接口读取对应卡片的尾号字段。
修复后的代码示例
def update_payment if !current_user.stripe_id customer = Stripe::Customer.create( email: current_user.email, source: params[:stripeToken] ) else customer = Stripe::Customer.update( current_user.stripe_id, source: params[:stripeToken] ) end # 修复:移除废弃的customer.sources调用,从默认支付渠道读取卡片尾号 card_last4 = customer.default_source.try(:last4) if current_user.update(stripe_id: customer.id, stripe_last_4: card_last4) flash[:notice] = "New card is saved" else flash[:alert] = "Invalid card" end redirect_to request.referrer rescue Stripe::CardError => e flash[:alert] = e.message redirect_to request.referrer end
内容的提问来源于stack exchange,提问作者meinert
相关产品推荐
相关产品推荐

