Stripe integration with Rails and the Pay gem for Subscription Billing.
Stripe Checkout Stripe Checkout is a checkout flow where Stripe hosts the payments page that collects the credit card details.
- A checkout session is created.
- The user is redirected to Stripe's payment page.
- The user completed a payment on Stripe's page.
- The user is redirected back to the app.
- The app receives a "payment success" webhook from Stripe.
Products and prices are used for subscription billing in lieu of plans. In this app, each "plan" is its own product, and each product has a single price.
To complete the integration
- Set up your payment processor credentials and initializers.
- Add the
pay_customer
the User Model. - Request a Checkout URL and Redirect the User
- Handle Stripe Events
Follow Pay's configuration instructions to set up your Stripe credentials.
-
Generate the Pay Models:
- Pay is already installed. For a fresh app, run
bin/rails pay:install:migrations
to create the necessary Pay models.
- Pay is already installed. For a fresh app, run
-
Update the User Model:
- Add
pay_customer
to the User model:class User < ApplicationRecord pay_customer end
- Add
Including pay_customer
in the User model establishes an internal association between the User and the Pay::Customer
model. This association uses the owner_type
and owner_id
fields.
payment_processor
is the entry point to Pay's functionality. By including pay_customer in the User model, the payment_processor method becomes available on all User instances, providing access to customer, subscription, and charge models.
Using Pay, request a checkout URL from Stripe and then redirect the user to that URL. Once the transaction is complete, Stripe will return the user to the URL defined by success_URL
, along with a session_id
.
def checkout
user.payment_processor.checkout(
mode: "subscription",
line_items: stripe_price_id,
success_url: success_url,
billing_address_collection: "auto",
allow_promotion_codes: false,
)
end
The Pay Gem requires Stripe Webhooks to function properly. When building the Pay integration locally, you'll need to set up the Stripe CLI and have it running to forward the events to your app.
$ stripe listen --forward-to localhost:3000/pay/webhooks/stripe
Update your stripe credentials to include the webhook signing secreted generated by the CLI.
When Stripe processes a payment successfully, it triggers the invoice.payment_succeeded [event] (https://github.com/pay-rails/pay/tree/main/test/pay/stripe/webhooks). Use this event to initiate other workflows in Rails. For instance, access a paid feature or a custom receipt.
class PaymentSucceededHandler
def call(event)
pay_charge = Pay::Stripe::Charge.sync(
event.data.object.charge,
stripe_account: event.try(:account)
)
return if pay_charge.nil?
adjust_user(pay_charge)
end
def adjust_user(pay_charge)
user = pay_charge.customer.owner
user.update!(updated_at: Time.zone.now)
end
end