redirect_to external Stripe checkout URL not working in Rails 7

Viewed 425

For Stripe's new checkout, it's required to redirect to an external URL after creating a session.

def create_checkout_session
    Stripe.api_key = "sk_test_"

session = Stripe::Checkout::Session.create({
  line_items: [{
    price_data: {
      currency: 'usd',
      product_data: {
        name: 'KYC services',
      },
      unit_amount: 1000,
    },
    quantity: 1,
  }],
  mode: 'payment',
  # These placeholder URLs will be replaced in a following step.
  success_url: 'https://example.com/success',
  cancel_url: 'https://example.com/cancel'
})


redirect_to session.url, status: 303, allow_other_host: true

My redirect_to does not take me anywhere, and there is no error in the terminal. If I don't include the allow_other_host: true I get an error saying Unsafe redirect to "https://checkout.stripe.com.

How do I enforce a redirect_to to an external URL in Rails 7? For the sake of this demo app, I don't mind vulnerabilities.

2 Answers

I'm getting this error as well. The Strip Checkout redirect was working well with Rails 6, but when I updated to Rails 7 the redirect is getting blocked. Here is the error I'm seeing in the console:

new:1 Access to fetch at '<VALID & FUNCTIONING STRIPE URL HERE>' (redirected from 'http://localhost:3000/sessions/1/charges') from origin 'http://localhost:3000' has been blocked by CORS policy: Response to preflight request doesn't pass access control check: No 'Access-Control-Allow-Origin' header is present on the requested resource. If an opaque response serves your needs, set the request's mode to 'no-cors' to fetch the resource with CORS disabled.

Here's the controller code:

  def create
@charge = Charge.new(charge_params)
@charge.seller = @session.user
@charge.purchaser = current_user if current_user
@charge.session = @session

if @charge.save
  the_root_url = URI.join(root_url).to_s.chomp('/')
  success_url = the_root_url + session_charge_success_path(@session, @charge)
  cancel_url = the_root_url + session_path(@session)

  @charge.update "success_url": success_url
  @charge.update "cancel_url": cancel_url
  stripe_session = Stripe::Checkout::Session.create({
    line_items: [{
       price_data: {
         currency: 'usd',
         product_data: {
           name: "Download the high resolution photo",
         },
         unit_amount: @session.default_price_cents,
       },
       quantity: 1,
    }],
    mode: 'payment',
    success_url: @charge.success_url,
    cancel_url: @charge.cancel_url,
  })
  redirect_to stripe_session.url, status: 303, allow_other_host: true
else
  redirect_to @session, notice: "Sorry, something went wrong."
end

end

This happens locally the same as it happens in production.

SOLUTION! (it was described above, but I missed it for a while)

I changed this:

<%= form.submit "Buy", class: "btn btn-primary btn-block col-12 my-1" %>

to this:

<%= form.submit "Buy", data: { turbo: false }, class: "btn btn-primary btn-block col-12 my-1" %>

I experienced the same issue in Rails 7 + Stripe Checkout, and I believe Turbolinks is intercepting and causing the redirect to blow up somewhere.

I found a workaround for now — adding data: { turbo: false } to the corresponding view's link or button helper fixed it for me.

Related