Rails:如何为Stripe Checkout的button_to添加用户输入的数量参数
解决Stripe Checkout按钮添加数量参数的问题
问题原因
你的number_field和button_to不在同一个表单中,提交按钮时无法带上数量参数。button_to会自动生成独立表单,单独的输入框不在这个表单内,导致参数无法传递。
方法一:将数量输入框嵌入button_to表单
利用button_to的块语法,把数量输入框和按钮放在同一个表单里,提交时自动带上参数:
<%= button_to checkout_create_path, remote: true do %> <%# 隐藏字段传递article_id %> <%= hidden_field_tag :article_id, @article.id %> <%# 数量输入框,设置默认值1、最小值1 %> <%= number_field_tag :quantity, 1, class: "form-control", min: 1 %> <span>Pay Now</span> <% end %>
也可以直接把article_id拼接到路径中:
<%= button_to checkout_create_path(article_id: @article.id), remote: true do %> <%= number_field_tag :quantity, 1, class: "form-control", min: 1 %> <span>Pay Now</span> <% end %>
方法二:用JavaScript修改AJAX请求参数
如果不想改动按钮结构,可通过监听Rails UJS的AJAX事件,在请求发送前加入数量参数:
- 给输入框和按钮添加ID:
<%= number_field_tag :quantity, 1, class: "form-control", min: 1, id: "quantity-input" %> <%= button_to "Pay Now", checkout_create_path(params: { article_id: @article.id }), remote: true, id: "pay-button" %>
- 添加JavaScript代码(基于jQuery,Rails默认集成):
$(document).on('ajax:beforeSend', '#pay-button form', function(event, xhr, settings) { const quantity = $('#quantity-input').val(); if (quantity) { // 根据请求类型添加参数 const param = `quantity=${encodeURIComponent(quantity)}`; if (settings.type === 'GET') { settings.url += (settings.url.includes('?') ? '&' : '?') + param; } else { settings.data += (settings.data ? '&' : '') + param; } } });
控制器处理参数
在checkout#create动作中获取并使用数量参数:
def create @article = Article.find(params[:article_id]) quantity = params[:quantity].to_i.clamp(1, 100) # 限制数量范围,避免非法值 # 创建Stripe Checkout会话 session = Stripe::Checkout::Session.create({ payment_method_types: ['card'], line_items: [{ price: @article.stripe_price_id, # 替换为你的商品价格ID quantity: quantity }], mode: 'payment', success_url: checkout_success_url, cancel_url: checkout_cancel_url }) render json: { id: session.id } end
注意事项
- 使用
number_field_tag而非number_field:后者需要绑定ActiveRecord模型,这里是独立输入框,用tag更合适。 - 限制数量范围:通过
min属性和控制器的clamp方法避免用户输入非法值。 - 前端跳转Stripe:如果用
remote: true,需要在AJAX成功回调中调用Stripe.redirectToCheckout({ sessionId: response.id })完成跳转。
内容的提问来源于stack exchange,提问作者Tikroz
相关产品推荐
相关产品推荐

