You need to enable JavaScript to run this app. Rails项目调用Stripe::Customer时报customer.sources未定义NoMethodError
优惠活动
大模型
产品
解决方案
定价
更多

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.10.27 09:36:01