Stripe API自定义结账功能报错:必须提供source或customer
解决Stripe Charge创建时的「Must provide source or customer」错误
嘿,我来帮你捋清楚这个问题——你遇到的错误本质是Stripe的Charge API没收到有效的支付来源(source)或者关联客户(customer)信息,哪怕你觉得已经传了参数,大概率是代码逻辑或者参数传递出了小问题。
可能的问题点&修复方案
1. 代码逻辑顺序或关联方式错了
从你给出的代码片段看,你分开调用了Stripe::Charge.create和Stripe::Customer.create,但这两个操作是独立的,得根据你的业务需求选对正确的关联方式:
- 如果是一次性支付:直接用前端传来的token创建Charge就行,但要确保token有效且正确传递。
- 如果是需要留存客户信息(比如后续订阅、重复扣款):得先把token关联到Customer上,再用Customer的ID创建Charge,因为Stripe的一次性token只能用一次。
给你两个正确的代码示例:
方案一:直接用一次性token创建Charge(适合单次支付)
begin charge = Stripe::Charge.create( amount: @amount, currency: 'usd', source: params[:stripeToken], # 这里必须是前端传来的有效一次性token description: "Charge for #{params[:stripeEmail]}" ) rescue Stripe::CardError => e # 处理卡片相关错误,比如资金不足、卡片过期 flash[:error] = e.message redirect_to your_checkout_path end
方案二:先创建Customer再关联Charge(推荐长期业务)
begin # 第一步:把token和用户邮箱绑定,创建Customer customer = Stripe::Customer.create( email: params[:stripeEmail], source: params[:stripeToken] # Stripe会自动把token转成可复用的支付方式存在Customer下 ) # 第二步:用Customer的ID创建Charge charge = Stripe::Charge.create( amount: @amount, currency: 'usd', customer: customer.id, # 这里用Customer ID替代source参数 description: "Charge for #{customer.email}" ) rescue Stripe::CardError => e flash[:error] = e.message redirect_to your_checkout_path rescue Stripe::InvalidRequestError => e # 处理参数错误,比如token无效、金额格式不对 flash[:error] = e.message redirect_to your_checkout_path end
2. 先确认params[:stripeToken]是否真的传过来了
你可以在控制器里加一行puts params[:stripeToken],运行后看终端输出——如果是空的,说明前端没把token正确传递到后端:
- 检查前端是否正确引入了Stripe的JS库(比如
https://js.stripe.com/v3/) - 确认Checkout按钮的事件处理逻辑,是否在生成token后正确把它放到表单里提交
3. 额外排查小细节
- 去Stripe控制台的日志页面(开发者工具→日志),找到对应的Charge请求,看请求参数里的
source或customer字段是不是为空,这能直接定位问题。 - 如果是测试环境,记得用Stripe提供的测试卡片(比如
4242 4242 4242 4242,有效期选未来任意月份,CVV随便填3位)生成测试token。 - 确保你的Stripe Ruby SDK是最新版,旧版本可能有参数兼容问题,运行
gem update stripe就能升级。
内容的提问来源于stack exchange,提问作者Jason Harder
相关产品推荐
相关产品推荐

