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集成的常见坑:
- 错误使用
redirect_to加POST方法:Rails的redirect_to本质是发起3xx重定向,浏览器会用GET请求去访问目标地址,强行指定method: :post会导致请求不符合Stripe的安全验证规则,再加上浏览器的跨域Cookie限制,就会出现无限加载。 - 手动拼接结账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
相关产品推荐
相关产品推荐

