Stripe?
Let’s check Stripe’s About page:
Stripe is a technology company that builds economic infrastructure for the internet. Businesses of every size—from new startups to public companies—use our software to accept payments and manage their businesses online.
Documentation
Main website:
API:
Demo:
Stripe Ruby
https://github.com/stripe/stripe-ruby
The Stripe Ruby library provides convenient access to the Stripe API from applications written in the Ruby language. It includes a pre-defined set of classes for API resources that initialize themselves dynamically from API responses which makes it compatible with a wide range of versions of the Stripe API.
The library also provides other features. For example:
-
Easy configuration path for fast setup and use.
-
Helpers for pagination.
-
Built-in mechanisms for the serialization of parameters according to the expectations of Stripe’s API.
Installation
Let’s start from Gemfile:
gem 'stripe'
Configuration
development.rb / production.rb
config.stripe.secret_key = Rails.application.credentials.stripe[:development][:secret_key]
config.stripe.publishable_key = Rails.application.credentials.stripe[:development][:publishable_key]
Implementation
Let’s modify our routes.rb file first:
get '/card/new' => 'charges#new', as: :add_payment
And add some logic to the StripeChargesService class:
class StripeChargesService
DEFAULT_CURRENCY = 'usd'.freeze
def initialize(params, user, order_id, plan_id)
@stripe_email = params[:stripeEmail]
@stripe_token = params[:stripeToken]
@order = order_id
@plan_id = plan_id
@user = user
end
def call
create_charge(find_customer)
end
private
attr_accessor :user, :stripe_email, :stripe_token, :order
def find_customer
if user.stripe_token
retrieve_customer(user.stripe_token)
else
create_customer
end
end
def retrieve_customer(stripe_token)
Stripe::Customer.retrieve(stripe_token)
end
def create_customer
customer = Stripe::Customer.create(
email: stripe_email,
source: stripe_token
)
# set stripe token
user.update(stripe_token: customer.id)
customer
end
def create_charge(customer)
Stripe::Charge.create(
customer: customer.id,
amount: order_amount,
description: @order,
currency: DEFAULT_CURRENCY
)
# update user's subscription
user.update(subscription_plan_end_date: Time.zone.now + SubscriptionPlan::LENGTH.days, subscription_plan_id: @plan_id)
end
def order_amount
# order amount in cents
Order.find_by(id: order).amount * 100
end
end
Charges controller implementation:
class ChargesController < ApplicationController
before_action :authenticate_user!
rescue_from Stripe::CardError, with: :catch_exception
before_action :set_subscription_plan
def new
@order = Order.create(user_id: current_user.id, price: @plan&.price, amount: @plan&.price)
session[:order] = @order.to_param
end
def create
result = ::StripeChargesService.new(charges_params, current_user, session[:order], @plan&.id).call
redirect_to cabinet_path, flash: { success: "Thanks for your order" }
end
private
def set_subscription_plan
@plan = SubscriptionPlan.default
end
def charges_params
params.permit(:stripeEmail, :stripeToken, :order_id)
end
def catch_exception(exception)
flash[:error] = exception.message
end
end
View for our route: charges/new.html.erb:
<section class="section section--hero contact" id="contact">
<h1 class='text-center'>Plan purchase page</h1>
<div class="container center">
<%= form_tag charges_path do %>
<article>
<% if flash[:error].present? %>
<div id="error_explanation">
<p><%= flash[:error] %></p>
</div>
<% end %>
<label class="amount">
<span>Amount: $<%= @order.price %></span>
</label>
</article>
<script src="https://checkout.stripe.com/checkout.js" class="stripe-button"
data-key="<%= Rails.configuration.stripe[:publishable_key] %>"
data-description="A month's subscription"
data-amount="<%= @order.price * 100 %>"
data-locale="auto"></script>
<% end %>
</div>
</section>
Testing
Navigate to the /card/new page in your app:
Make payment with test card:
Conclusion
That’s it - super simple, just a few files, configuration changes and your payments are ready to go!