Stripe Checkout allows you to simply redirect to Stripe for handling payments. The main benefit is that it's super fast to setup payments in your application, they're SCA compatible, and they will get improved automatically by Stripe.
📝 Warning: You need to configure webhooks before using Stripe Checkout otherwise your application won't be updated with the correct data.
Choose the checkout button mode you need and pass any required arguments. Read the Stripe Checkout Session API docs to see what options are available. For instance:
class SubscriptionsController < ApplicationController
def checkout
# Make sure the user's payment processor is Stripe
current_user.set_payment_processor :stripe
# One-time payments (https://stripe.com/docs/payments/accept-a-payment)
@checkout_session = current_user.payment_processor.checkout(mode: "payment", line_items: "price_1ILVZaKXBGcbgpbZQ26kgXWG")
# Or Subscriptions (https://stripe.com/docs/billing/subscriptions/build-subscription)
@checkout_session = current_user.payment_processor.checkout(
mode: 'subscription',
locale: I18n.locale,
line_items: [{
price: 'price_1ILVZaKXBGcbgpbZQ26kgXWG',
quantity: 4
}],
subscription_data: {
trial_period_days: 15,
metadata: {
pay_name: "base" # Optional. Overrides the Pay::Subscription name attribute
},
},
success_url: root_url,
cancel_url: root_url
)
# Or Setup a new card for future use (https://stripe.com/docs/payments/save-and-reuse)
@checkout_session = current_user.payment_processor.checkout(mode: "setup")
# If you want to redirect directly to checkout
redirect_to @checkout_session.url, allow_other_host: true, status: :see_other
end
end
Then link to it in your view:
<%= link_to "Checkout", checkout_path, data: { turbo: false } %>
NOTE: Due to a bug in the browser's fetch
implementation, you will need to disable Turbo if redirecting to Stripe checkout server-side.
The session_id
param will be included on success and cancel URLs automatically. This allows you to lookup the checkout session on your success page and confirm the payment was successful before fulfilling the customer's purchase.
https://stripe.com/docs/payments/checkout/custom-success-page
Customers will want to update their payment method, subscription, etc. This can be done with the Customer Billing Portal. It works the same as the other Stripe Checkout pages.
First, create a session in your controller:
class SubscriptionsController < ApplicationController
def index
@portal_session = current_user.payment_processor.billing_portal
end
end
Then link to it in your view:
<%= link_to "Billing Portal", @portal_session.url %>
Or redirect to it in your controller:
redirect_to @portal_session.url, allow_other_host: true, status: :see_other
For one-time payments, you'll need to add a webhook listener for the Checkout stripe.checkout.session.completed
and stripe.checkout.session.async_payment_succeeded
events. Some payment methods are delayed so you need to verify the payment_status == "paid"
. The async payment succeeded event fires when delayed payments are complete.
For subscriptions, Pay will automatically create the Pay::Subscription
record for you.
To create custom webhook listeners for specific events, you can create your custom webhook listener classes under a folder like app/webhooks
, like this:
# app/webhooks/fulfill_checkout.rb
class FulfillCheckout
def call(event)
object = event.data.object
return if object.payment_status != "paid"
# Handle fulfillment
end
end
And then subscribe your custom webhook listener class to specific Stripe events on config/initializers/pay.rb
:
ActiveSupport.on_load(:pay) do
Pay::Webhooks.delegator.subscribe "stripe.checkout.session.completed", FulfillCheckout.new
Pay::Webhooks.delegator.subscribe "stripe.checkout.session.async_payment_succeeded", FulfillCheckout.new
end
That's it!