DEV Community

Cover image for Embedded Stripe Checkout
Yaroslav Shmarov
Yaroslav Shmarov

Posted on • Originally published at blog.corsego.com on

Embedded Stripe Checkout

😖 I really dislike Stripe Elements: you have to build and style the checkout form yourself.

stripe-checkout-elements.png

🤩 Instead, stripe-hosted full screen checkout is a much better approach where you outsource all the payment logic to Stripe. It looks great:

stripe-checkout-hosted.gif

Heres a Github Repo where I have it implemented.

Stripe Hosted Checkout on SupeRails:

stripe-checkout-hosted-superails.gif

🥰🥰 But now you can use Embedded Stripe Checkout inside your app and keep your branding!

stripe-checkout-embedded-superails.gif

Here’s how you can implement Embedded Stripe Checkout:

Create a pricing page that redirects to the checkout page

# config/routes.rb get "pricing", to: "stripe/checkout#pricing" get "checkout/new", to: "stripe/checkout#checkout", as: "new_checkout" 
Enter fullscreen mode Exit fullscreen mode

Stripe Embedded Checkout API has ui_mode: :embedded and return_url params that you should set:

# app/controllers/stripe/checkout_controller.rb # GET def pricing lookup_key = %w[month year lifetime] @prices = Stripe::Price.list(lookup_keys: lookup_key, active: true, expand: ['data.product']).data.sort_by(&:unit_amount) end # GET def checkout price = Stripe::Price.retrieve(params[:price_id]) @session = Stripe::Checkout::Session.create({ customer: current_user.stripe_customer_id, # allow_promotion_codes: true, # automatic_tax: {enabled: @plan.taxed?}, # consent_collection: {terms_of_service: :required}, # customer_update: {address: :auto}, # payment_method_collection: :if_required, line_items: [{ price:, quantity: 1 }], mode: mode(price), return_url: user_url(current_user), ui_mode: :embedded }) end private MODES = { 'recurring' => 'subscription', 'one_time' => 'payment', 'setup' => 'setup' }.freeze def mode(price) MODES[price.type] end 
Enter fullscreen mode Exit fullscreen mode

Display links to checkout for each different price:

# app/views/stripe/checkout/pricing.html.erb <% @prices.each do |price| %> <%= link_to "Checkout" new_checkout_path(price_id: price.id) %> <% end %> 
Enter fullscreen mode Exit fullscreen mode

This will redirect to the checkout page. You will need some JS to embed the Stripe Checkout.

# app/views/stripe/checkout/checkout.html.erb <%= javascript_include_tag "https://js.stripe.com/v3/" %> <%= tag.div data: { controller: "stripe--embedded-checkout", stripe__embedded_checkout_public_key_value: Rails.application.credentials.dig(Rails.env, :stripe, :public), stripe__embedded_checkout_client_secret_value: @session.client_secret } %> rails g stimulus stripe/embedded_checkout // app/javascript/controllers/stripe/embedded_checkout_controller.js import { Controller } from "@hotwired/stimulus" export default class extends Controller { static values = { publicKey: String, clientSecret: String, } async connect() { this.stripe = Stripe(this.publicKeyValue) this.checkout = await this.stripe.initEmbeddedCheckout({clientSecret: this.clientSecretValue}) this.checkout.mount(this.element) } disconnect() { this.checkout.destroy() } } 
Enter fullscreen mode Exit fullscreen mode

That’s it! Now you have the latest, coolest Stripe Checkout!

Don’t forget to also add:

  • Webhooks to create customers, handle successful and failed payments, subscription state changes
  • Billing portal for user to manage plan, change payment methods, see invoice history

See examples here: github.com/corsego/rails-7-stripe-subscriptions

Top comments (0)