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

Rails无法跳转至Stripe结账页面,页面无限加载,疑似跨域问题?

Rails无法跳转至Stripe结账页面,页面无限加载,疑似跨域问题?

兄弟,我太懂你这种明明代码逻辑没问题却卡在加载上的烦躁了!你遇到的这个Rails跳转Stripe结账页面无限加载的问题,其实是因为Stripe的会话验证机制和Rails重定向的特性冲突了,咱们一步步来捋清楚:

问题还原

你尝试集成Stripe API时,遇到了这么个诡异情况:

  • 用Rails的redirect_to跳转到生成的结账URL时,页面无限加载
  • 但把终端里生成的结账链接复制到新浏览器窗口打开,却完全正常
  • 你试过用form_tag手动构建表单,但一开始也没解决问题

你最初的控制器代码是这样的:

# /app/controllers/checkout_controller.rb
class CheckoutController < ApplicationController
  def new
    @stripe_checkout_session = Stripe::Checkout::Session.create(
      payment_method_types: ['card'],
      line_items: [{
        price: 'price_1MZuauECi1aTPXPYEtmpRxAI',
        quantity: 1
      }],
      mode: 'payment',
      success_url: checkout_success_url,
      cancel_url: checkout_cancel_url
    )
    redirect_to @stripe_checkout_session.url, method: :post, allow_other_host: true
  end
end

最初的视图代码:

# app/views/checkout/new.html.erb
<%= form_tag "#{Rails.configuration.stripe[:checkout_base]}/#{@stripe_checkout_session.id}", id: 'checkout-form', method: :post do %>
  <%= javascript_include_tag "https://js.stripe.com/v3", "data-stripe": Rails.configuration.stripe[:publishable_key] %>
  <%= hidden_field_tag :sessionId, @stripe_checkout_session.id %>
  <%= submit_tag "Proceed to Checkout" %>
<% end %>

问题根源

你踩了两个Stripe集成的常见坑:

  1. 错误使用redirect_to加POST方法:Rails的redirect_to本质是发起3xx重定向,浏览器会用GET请求去访问目标地址,强行指定method: :post会导致请求不符合Stripe的安全验证规则,再加上浏览器的跨域Cookie限制,就会出现无限加载。
  2. 手动拼接结账URL:你之前用checkout_base加会话ID拼接URL的方式,忽略了Stripe返回的会话URL里包含的临时验证参数和Cookie关联信息,直接拼接会让Stripe无法识别这是一个合法的会话请求,进而加载失败。

修复方案

修正后的控制器代码

去掉原本的redirect_to,只负责生成Stripe会话并传递给视图即可:

# /app/controllers/checkout_controller.rb
class CheckoutController < ApplicationController
  def new
    @stripe_checkout_session = Stripe::Checkout::Session.create(
      payment_method_types: ['card'],
      line_items: [{
        price: 'price_1MZuauECi1aTPXPYEtmpRxAI',
        quantity: 1
      }],
      mode: 'payment',
      success_url: checkout_success_url,
      cancel_url: checkout_cancel_url
    )
  end
end

修正后的视图代码

直接使用Stripe返回的完整@stripe_checkout_session.url作为表单提交地址,不要手动拼接:

# app/views/checkout/new.html.erb
<%= form_tag "#{@stripe_checkout_session.url}", id: 'checkout-form', method: :post do %>
  <%= javascript_include_tag "https://js.stripe.com/v3", "data-stripe": Rails.configuration.stripe[:publishable_key] %>
  <%= hidden_field_tag :sessionId, @stripe_checkout_session.id %>
  <%= submit_tag "Proceed to Checkout" %>
<% end %>

为什么这样能解决问题?

Stripe的结账会话URL包含了临时的安全验证参数和与当前请求关联的Cookie信息,手动拼接或者用GET重定向都会破坏这些信息的完整性。通过表单POST请求直接提交到Stripe返回的完整URL,能确保请求符合Stripe的安全验证要求,避免跨域和会话验证失败的问题,自然就不会出现无限加载了。

备注:内容来源于stack exchange,提问作者igorfz

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.04.23 13:57:38