Rails集成Stripe支付时price参数传入错误问题求助
问题:Rails集成Stripe支付时传递价格参数出错
我用Rails搭建在线商店,已经集成了Stripe支付功能。现在我获取购物车商品总价,把它作为参数传给控制器:
<div class="keep-shopping pv1 mt4 has-text-right"> <%= link_to 'Keep Shopping', instruments_path, class: 'button is-warning' %> </div> <hr /> <section class="section"> <%= render(@cart.line_items) %> <div class="columns"> <div class="column"> <%= button_to 'Empty Cart', @cart, method: :delete, data: { confirm: "Are you sure? " }, class: "button is-danger" %> </div> <div class="column total has-text-right"> <h4 class="title is-4"> <span class="f5 has-text-grey">Total:</span> <%= number_to_currency(@cart.total_price) %> </h4> <%= link_to 'Buy', {controller:"checkouts", action:"show", my_param:number_to_currency(@cart.total_price) }%> </div> </div> </section>
控制器代码:
class CheckoutsController < ApplicationController before_action :authenticate_user! def show() amount = params[:my_param] current_user.set_payment_processor :stripe current_user.payment_processor.customer @checkout_session = Stripe::Checkout::Session.create({ line_items: [{ # Provide the exact Price ID (e.g. pr_1234) of the product you want to sell price: amount }], mode: 'payment', success_url:checkout_success_url }) end def success end end
点击购买按钮后出现错误:
The price parameter should be the ID of a price object, rather than the literal numerical price. Please see https://stripe.com/docs/billing/prices-guide#create-prices for more information about how to set up price objects.
我需要正确把价格传入line_items参数中。
解决方案
Stripe的Checkout Session要求line_items里的price必须是Stripe后台创建的价格对象ID(比如pr_xxxxxx),不能直接传金额数值,这是核心问题。另外你还犯了两个小错误:
- 用
number_to_currency把金额转成了带货币符号的字符串(比如$99.99),即使Stripe支持传金额,这种格式也会报错 - 直接把总价作为单个line item传递,忽略了购物车里的具体商品,不符合Stripe的使用规范
正确实现步骤:
1. 修正前端参数传递
不要传格式化后的总价,也无需在前端传价格参数(避免用户篡改),直接跳转即可:
<%= link_to 'Buy', {controller:"checkouts", action:"show"}, class: 'button is-primary' %>
2. 控制器里生成临时价格对象(适合自定义总价场景)
如果是购物车组合总价,可在控制器临时创建Stripe Price对象:
class CheckoutsController < ApplicationController before_action :authenticate_user! before_action :load_cart def show current_user.set_payment_processor :stripe current_user.payment_processor.customer # 把总价转成最小货币单位(比如美元:总价*100,人民币同理) total_amount = (@cart.total_price * 100).to_i # 临时创建Stripe Price对象 stripe_price = Stripe::Price.create({ currency: 'usd', # 根据业务修改货币类型 unit_amount: total_amount, product_data: { name: '购物车商品总价' } }) @checkout_session = Stripe::Checkout::Session.create({ line_items: [{ price: stripe_price.id, # 使用刚创建的Price ID quantity: 1 }], mode: 'payment', success_url: checkout_success_url, cancel_url: cart_path # 添加取消跳转地址,回到购物车 }) # 跳转到Stripe支付页面 redirect_to @checkout_session.url, allow_other_host: true end def success # 支付成功逻辑:清空购物车、生成订单等 @cart.destroy flash[:notice] = '支付成功!' end private def load_cart @cart = current_user.cart # 假设购物车与用户关联 end end
3. 规范做法(推荐,适用于商品已关联Stripe价格)
如果每个商品都在Stripe后台创建了对应的Product和Price,遍历购物车商品生成line items:
# 控制器show方法中替换line_items部分 line_items = @cart.line_items.map do |item| { price: item.product.stripe_price_id, # 假设商品模型存储了Stripe的Price ID quantity: item.quantity } end @checkout_session = Stripe::Checkout::Session.create({ line_items: line_items, mode: 'payment', success_url: checkout_success_url, cancel_url: cart_path })
关键注意点:
- Stripe金额必须用最小货币单位,比如10美元传1000(10100),人民币10元传1000(10100)
- 禁止直接传金额数值到
price字段,必须使用Stripe的Price对象ID - 生产环境不要在前端传递价格参数,防止用户篡改,应在控制器从数据库读取计算总价
内容的提问来源于stack exchange,提问作者first
相关产品推荐
相关产品推荐

