You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

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),不能直接传金额数值,这是核心问题。另外你还犯了两个小错误:

  1. 用number_to_currency把金额转成了带货币符号的字符串(比如$99.99),即使Stripe支持传金额,这种格式也会报错
  2. 直接把总价作为单个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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.01 08:56:09