On this article I’ll undergo a Subscription Integration in a Rails API, utilizing the Stripe API it.

For this utility, I’ll think about you have already got a Consumer’s mannequin in your utility. In case you don’t have it but, don’t fear! I already printed an article about that, you possibly can read it here.
Should you adopted the steps of my different article, to create your Consumer
mannequin, or just cloned it from GitHub, you will want to vary the Ruby model on the Gemfile. For this text, I shall be utilizing Ruby 3.0.0, so your Gemfile should seem like that:
supply 'https://rubygems.org'
git_source(:github) reporuby '3.0.0'...
Additionally, add the Stripe Gem to your Gemfile.
gem 'stripe'
Don’t overlook to run
bundle set up
in your terminal after that.
Now you will want to create a stripe initializer file in your utility. For that, run the command under in your terminal:
contact config/initializers/stripe.rb
Then, open the stripe.rb
file and write the content material under:
Stripe.api_key = Rails.utility.credentials.stripe_secret_key
We didn’t add that Stripe’s secret key in our credential file, so let’s do that.
To open your credential file, run in your terminal:
EDITOR=nano rails credentials:edit
Get your Stripe Secret Key here.
Your credential file should seem like this:
# aws:
# access_key_id: 123
# secret_access_key: 345
# Used as the bottom secret for all MessageVerifiers in Rails, together with the one defending cookies.secret_key_base: [YOUR SECRET KEY BASE]
stripe_secret_key: [YOUR SECRET KEY HERE]
Notice that the
secret_key_base
is autogenerated, you don’t have to edit.
To begin with, we’d like our customers to have a Stripe Buyer ID. We have to retailer that ID in our database, so run the command under to create a migration:
rails g migration AddStripeIdToUsers stripe_id
rails db:create db:migrate
We may also add a brand new validation to our Consumer, to verify the Stripe ID shall be all the time current. Add to your Consumer mannequin:
validates :stripe_id, presence: true, uniqueness: true
To create a reference of our Consumer on Stripe API, let’s add a callback to Consumer
mannequin.
Add the code under to the Consumer mannequin.
... before_validation :create_stripe_reference, on: :create def create_stripe_reference
response = Stripe::Buyer.create(e mail: e mail)
self.stripe_id = response.id
finish
finish
Could be fairly fascinating to have a way to retrieve the stripe details about the client if we’d like it. Luckily, Stripe SDK supplies this methodology, which we are going to add to our Consumer mannequin too.
... def retrieve_stripe_reference
Stripe::Buyer.retrieve(stripe_id)
finish
finish
Lastly, your Consumer
mannequin ought to seem like this:
class Consumer < ApplicationRecord
has_secure_password validates :e mail, uniqueness: case_sensitive: false
validates :stripe_id, presence: true, uniqueness: true before_validation :create_stripe_reference, on: :create def create_stripe_reference
response = Stripe::Buyer.create(e mail: e mail)
self.stripe_id = response.id
finish def retrieve_stripe_reference
Stripe::Buyer.retrieve(stripe_id)
finish
finish
Superior!! Let’s attempt our code on the console, run in your terminal:
rails c
Now you can create a Consumer
, and the code will routinely contact Stripe API and create the reference.
Consumer.create(e mail: "person@check.com", password: "123456")
You’ll be able to take a look at the Stripe ID of this person with the instructions under.
person = Consumer.first
person.stripe_id
And to retrieve all of the Stripe data for this person, run:
person.retrieve_stripe_reference
That appears incredible.
The Plan mannequin shall be answerable for representing and dealing with enterprise guidelines for the subscription choices we are going to provide.
Run-on your terminal:
rails g mannequin Plan title description interval:integer price_cents:integer stripe_price_id
rails db:migrate
Take a more in-depth take a look at the Plan
attributes:
Title
shall be a string and represents the title of the plan;Description
shall be a string and represents brief textual content, describing what the plan gives;Interval
shall be an integer and represents the interval of charging the subscriber;price_cents
shall be an integer and represents the worth for the subscription, it must be cents as a result of Stripe works with cents values and it’s simpler to deal with the worth this manner.stripe_price_id
shall be a string and represents a reference to our Plan within the Stripe API.
That’s how the Plan
mannequin will seem like:
class Plan < ApplicationRecord
validates :title,
:stripe_price_id,
:price_cents, presence: true
validates :title,
:stripe_price_id, uniqueness: true enum interval: %i[month year] before_validation :create_stripe_reference, on: :create def create_stripe_reference
response = Stripe::Worth.create(
unit_amount: price_cents,
foreign money: 'usd',
recurring: interval: interval ,
product_data: title: title
) self.stripe_price_id = response.id
finish def retrieve_stripe_reference
Stripe::Worth.retrieve(stripe_price_id)
finish
finish
Take a more in-depth take a look at the Plan
mannequin:
- First, we outlined some validations, to verify
title
,stripe_price_id
andprice_cents
shall be all the time current. We additionally outlined a validation to verify thetitle
and thestripe_price_id
shall be distinctive. - After that, we outlined our interval enum, rails will deal with these choices, so once we go the worth “month” for the interval, the framework will retailer 0 within the database and once we go the worth “12 months” it should retailer 1.
- Then we outlined a callback to create a reference to our
Plan
on Stripe API. - The
create_stripe_reference
methodology shall be answerable for the all of the logic triggered on the callback. - The
retrieve_stripe_reference
will mainly return the Stripe reference of ourPlan
.
Let’s attempt our new mannequin on the console. Run in your terminal:
rails c
Now you can create a Plan
, and the code will routinely contact Stripe API and create the reference:
# Month Subscription
Plan.create(
title: 'Month Subscription',
description: 'This subscription shall be charged each month',
interval: 'month',
price_cents: 500
)# Yr Subscription
Plan.create(
title: 'Yr Subscription',
description: 'This subscription shall be charged yearly. Save $10 with this subscription.',
interval: '12 months',
price_cents: 5000
)
To retrieve all of the Stripe data for some plans, run:
# The 1 represents the ID of the file.
Plan.discover(1).retrieve_stripe_reference
The Subscription mannequin shall be answerable for representing and dealing with enterprise guidelines for a person’s subscription.
Run the next command in your terminal:
rails g mannequin Subscription plan:references person:references lively:boolean stripe_id
rails db:migrate
Taking a more in-depth look to the Subscription attributes:
plan
shall be a reference to the plan that’s being bought;person
shall be a reference to the person that’s buying a plan;lively
shall be a boolean that represents if a subscription continues to be legitimate.stripe_id
shall be a string and represents a reference to the Subscription within the Stripe API.
Open the migration create_subscriptions and ensure to outline the default worth of the lively attribute:
...
t.boolean :lively, default: true
...
After that, let’s code the Subscription
mannequin. That’s the way it ought to seem like:
class Subscription < ApplicationRecord
attr_accessor :card_number, :exp_month, :exp_year, :cvc belongs_to :plan
belongs_to :person validates :stripe_id, presence: true, uniqueness: true before_validation :create_stripe_reference, on: :create def create_stripe_reference
Stripe::Buyer.create_source(
person.stripe_id,
supply: generate_card_token
) response = Stripe::Subscription.create(
buyer: person.stripe_id,
objects: [
price: plan.stripe_price_id
]
) self.stripe_id = response.id
finish def generate_card_token
Stripe::Token.create(
card:
quantity: card_number,
exp_month: exp_month,
exp_year: exp_year,
cvc: cvc
).id
finish
finish
Take a more in-depth take a look at the Subscription
mannequin:
- To begin with, we outlined some digital attributes. We is not going to retailer that knowledge, as a result of it’s delicate. So Stripe will deal with it for us.
- After that, we outlined the relations of the mannequin, a belongs to Plan and Consumer.
- The one attribute we are going to validate is
stripe_id
, it have to be current and be distinctive. - We even have a callback, that shall be triggered earlier than the validation of the file creation.
- The
create_stripe_reference
shall be answerable for creating the reference of our subscription on the Stripe API. Notice that earlier than creating the subscription on Stripe API, we create a supply for the client, that would be the cost methodology. - The
generate_card_token
shall be answerable for passing the cardboard knowledge to Stripe API and return a token. Passing a token is safer than passing the cardboard knowledge, that’s why Stripe handles the cost supply this manner.
Let’s attempt our new mannequin on the console. Run in your terminal:
rails c
Now you can create a Subscription
, and the code will routinely contact Stripe API and create the reference.
Subscription.create(
card_number: '5555555555554444',
exp_month: 06,
exp_year: 2029,
cvc: '123',
user_id: Consumer.first.id,
plan_id: Plan.first.id,
lively: true
)
Notice that Stripe has pre-defined allowed check card numbers. You’ll be able to test it out right here: Stripe Test Cards.
That’s superior!! Our Subscription is already working and you’ll see it on the Stripe Dashboard.

Typically we have to get monetary savings and a few subscriptions have to be canceled, let’s program the appliance to permit cancelations.
What we are going to do is mainly replace the file and the reference on Stripe API when lively is fake. Let’s code it.
Add a callback to cancel the subscription on Stripe API, with activeness conditional.
...before_update :cancel_stripe_subscription, if: :subscription_inactive?...
We additionally want so as to add the tactic that the callback name and the tactic that outline the situation.
... def cancel_stripe_subscription
Stripe::Subscription.delete(stripe_id)
finish def subscription_inactive?
!lively
finish
finish
To check if it really works, go to your rails console and run the instructions under:
Subscription.first.replace(lively: false)
Now the subscription is canceled, and you’ll verify it in your Stripe Dashboard.

For this submit, we could have controllers solely to indicate, create and replace subscriptions. As soon as the Plans CRUD is extra an administrative factor, I cannot create a controller for it now.
The Subscriptions Controller
To create the subscriptions controller, run the command under in your terminal:
rails g controller subscriptions present create replace
The command above will add some routes to our routes file, however we have to change it, as soon as we would like the routes contained in the namespace api/v1
.
So your routes could seem like this:
Rails.utility.routes.draw do
namespace :api do
namespace :v1 do
submit '/signup', to: 'customers#signup'
submit '/signin', to: 'customers#signin'
get '/signedin', to: 'customers#signedin' sources :subscriptions, solely: %i[show create update]
finish
finish
finish
After producing the controller, let’s write it. Since that’s a really generic rails controller, I cannot clarify the code of it on this article.
Your controller ought to seem like this:
module Api
module V1
class SubscriptionsController < ApplicationController
before_action :set_subscription, besides: %i[create] def present
render json: @subscription
finish def create
@subscription = Subscription.new(subscription_params) if @subscription.save
render json: @subscription, standing: :created
else
render json: @subscription.errors, standing: :unprocessable_entity
finish
finish def replace
if @subscription.replace(subscription_params)
render json: @subscription
else
render json: @subscription.errors, standing: :unprocessable_entity
finish
finish personal def set_subscription
@subscription = Subscription.discover(params[:id])
finish def subscription_params
params.require(:knowledge).allow(:card_number, :exp_month, :exp_year, :cvc, :user_id, :plan_id, :lively)
finish
finish
finish
finish
I’ll use Paw to run the requests and check the controller, however you’ll obtain the identical outcomes with any HTTP Consumer, like Postman or Insomnia.
Up your native server with the command under:
rails s
The Create Request
This request will set off a subscription creation.
Motion: POST
Endpoint:
http://localhost:3000/api/v1/subscriptions
Headers:
Content material-Sort: utility/json
Physique:
"knowledge":
"card_number": "5555555555554444",
"exp_month": "09",
"exp_year": "2029",
"cvc": "123",
"user_id": "1",
"plan_id": "1"
The response to this request ought to match the format under:

The Replace Request
This request will cancel a subscription.
Motion: PUT
or PATCH
Endpoint:
http://localhost:3000/api/v1/subscriptions/3
The quantity 3 on the endpoint above, represents the ID of the file we need to replace, it’s possible you’ll change it associated to the ID of your subscription.
Headers:
Content material-Sort: utility/json
Physique:
"knowledge":
"lively": false
The response of this request ought to match the format under:

The Present Request
This request will retrieve a subscription.
Motion: GET
Endpoint:
http://localhost:3000/api/v1/subscriptions/3
The quantity 3 on the endpoint above, represents the ID of the file we need to replace, it’s possible you’ll change it associated to the ID of your subscription.
The response of this request ought to match the format under:

Stripe make the cost system integration be fairly easy and simple.
There are loads of sources on Stripe API that weren’t explored throughout this text. I imply to publish one other one sooner or later, associated to cost intent and webhooks for receiving the intent to replace the standing of a subscription.
You’ll be able to check the complete Stripe Docs here.
Need to Join?Connect on Twitter.