Integrating Stripe into your Ruby on Rails Application

Integrating Stripe into your Ruby on Rails Application

Integrating Stripe into your Ruby on Rails Application

Stripe is a very popular payment solution that integrates really well into a Rails application. There are probably many ways to get up and running, including sophisticated gems such as Payola. Here you’ll find a step-by-step tutorial to get you started collecting payments that worked for us.

Setup

Integrating Stripe to your Rails project is really simple and follows the usual practices:

  • Adding the Stripe gem to your Gemfile.
  • Running bundle install
  • Generating a controller for charge requests
  • Configuring your Stripe keys

Adding the Stripe Gem

The Stripe ruby gem page in GitHub advises to make sure you use the https RubyGems source in your Gemfile (which is the default when you create a new Rails app):

source 'https://rubygems.org'

And including the gem as follows:

gem 'stripe'

But then, the Ruby on Rails integration tutorial suggests it should look like this:

gem 'stripe', git: 'https://github.com/stripe/stripe-ruby'

So let’s go with the latter, and let’s run bundler:

bundle install

It’s a good idea to commit the changes at this point.

Charges Controller

We’ll need a controller (and the proper routes) to handle two tasks:

  • Show the credit card form (new action).
  • Create the actual charge (create action).

Let’s generate the controller first:

bundle exec rails g controller charges

Once the file exists, you need to add the two methods:

class ChargesController < ApplicationController
  def new
    # this will remain empty unless you need to set some instance variables to pass on
  end

  def create
    # your charge code will live here
  end
end

And now you want to add the routes for your controller:

resources :charges

Configuring Your Stripe Keys

Stripe provides a set of two keys: ‘Publishable key’ and ‘Secret key’ and they strongly advise to keep them out of source control (at least the ones for production). At Still River Software we use a YML file to read Settings from, and the Stripe sections look like this:

general: &general
  stripe:
    secret_key: your_test_secret_key
    publishable_key: your_test_publishable_key

development: &development
  <<: *general

test: &test
  <<: *general

production: &production
  <<: *general

And for the production keys, we need to create an initializer as follows:

Rails.configuration.stripe = {
  :publishable_key => ENV['PUBLISHABLE_KEY'],
  :secret_key      => ENV['SECRET_KEY']
}

The relevant step here is to setup your Stripe class object with the secret key:

Stripe.api_key = Rails.env.production? ?
                 Rails.configuration.stripe[:secret_key] :
                 Settings[Rails.env]['stripe']['secret_key']

Your initializer file should be called stripe.rb and has to be located under config/initializers.

And we’re good to start working on the user interface…

Implementing the Interface

(Optional) Adding a new layout

If you want to implement your payment page with a minimal user interface, or just want to make it look different to the user, then you can add a layout, and following Rails conventions, you should name it charges.html.erb and place it under app/views/layouts:

<!DOCTYPE html>
<html>
    <head>
    </head>
    <body>
        <%= yield %>
    </body>
</html>

Showing the Payment Form

This is where the new action comes in; you need to create new.html.erb within you app/views/charges folder. Now, the best payment flow Stripe has for you is Checkout (there are other paths, such as Stripe.js); using this library (checkout.js) you have two options:

  • Simple
  • Custom

Simple Payment Form

This implementation displays a credit card overlay with all the functionality you need, including validation and error handling. All you have to do is to create a form and include a script tag to enable the functionality from Stripe:

<%= form_tag charges_path do -%>
 <article>
     <%= label_tag 'amount', 'To Pay', class: 'amount' %>
     <%= label_tag 'amount', "$#{@amount}.00", class: 'amount-figure' %>
 </article>

 <script src="https://checkout.stripe.com/checkout.js" class="stripe-button"
    data-key="<%= Settings[Rails.env]['stripe']['publishable_key'] %>"
    data-description="Your payment description"
    data-amount="<%= @amount * 100 %>">
  </script>
<% end %>

The previous code submits the form with a stripeToken along with any other input tags within the form. This will not create any charges, but a token instead. The tokens will be used in your create action to create the actual charge server-side. Other use cases include saving the card for later charges or signing up the user for subscription recurring charges.

(Note that in this example we’re using  development/test publishable key.)

Custom Payment Form

With this implementation you can use your own styled button or enable any element in your DOM or JavaScript event to trigger a Checkout payment. The key here is to create a handler object (StripeCheckout.configure()) for you to call it later with the open() function in response to any event, and, if you need to abort the Checkout process, then you can call close() on the the handler.

Keep in mind that the publishable key and the token parameters must be specified in the configure() function. You can pass any other parameters to either configure() or open().

Using jQuery makes it easier to implement, but not required, here’s the way to do it with selectors:

 <%= form_tag charges_path, id: 'stripeForm' do -%>
   <script src="https://checkout.stripe.com/checkout.js"></script>
   <article>
     <%= label_tag 'amount', 'To Pay', class: 'amount' %>
     <%= label_tag 'amount', "$#{@amount}.00", class: "amount-figure" %>
   </article> <br>
   <button id="stripe-button">&nbsp;</button>
   <%= hidden_field_tag 'stripeToken' %>
   <%= hidden_field_tag 'stripeEmail' %>
   <%= hidden_field_tag 'stripeAmount' %>

   <script>
     var handler = StripeCheckout.configure({
       key: "<%= Settings[Rails.env]['stripe']['publishable_key'] %>",
       token: function (token, args) {
         $("#stripeToken").value = token.id;
         $("#stripeEmail").value = token.email;
         $("#stripeAmount").value = <%= @amount %>;
         $("#stripeForm").submit();
       }
     });

     $('#stripe-button').on('click', function (e) {
       // Open Checkout with further options
       handler.open({
         name: 'Your customer name',
         description: 'Your description goes here',
         amount: <%= @amount * 100 %>
       });
     e.preventDefault();
     });

     $(window).on('popstate', function() {
       handler.close();
     });
   </script>
 <% end %>

Stripe publishes a full set of configuration options that you can use.

Back to the Controller

Once the customer has interacted with the Stripe payment form, a POST request will be sent to your charges_controller so this is the time  to go through the code to handle the request:

class ChargesController < ApplicationController
  def new
    # this will remain empty unless you need to set some instance variables to pass on
  end

  def create
    # Amount in cents
    amount = params[:stripeAmount].to_i * 100

    # Create the customer in Stripe
    customer = Stripe::Customer.create(
      email: params[:stripeEmail],
      card: params[:stripeToken]
    )

    # Create the charge using the customer data returned by Stripe API
    charge = Stripe::Charge.create(
      customer: customer.id,
      amount: amount,
      description: 'Rails Stripe customer',
      currency: 'usd'
    )

    # place more code upon successfully creating the charge
  rescue Stripe::CardError => e
    flash[:error] = e.message
    redirect_to charges_path
    flash[:notice] = "Please try again"
  end
end

You can either create a view to show your users a success message or just redirect with a flash message.

And that’s it! Now you’re set with all you need to start collecting payments and explore the docs to extend the functionality in your app to take full advantage of Stripe.

Enjoy.

Tags: , ,

4 Comments

leave a comment

Your email address will not be published.

This site uses Akismet to reduce spam. Learn how your comment data is processed.

This content shows up if there are no widgets defined in the backend.