Payments in Rails with Stripe

Share this article


Handling payments in the past has been a complete pain. Just looking at PayPal’s API introduction makes me want to scream. Redirects, logins, checkouts; I just want process a payment!

Stripe is a much needed breath of fresh air into this chaos, and it’s no short of awesome. The API is easy to use, well documented, and the pricing is clear-cut. The admin interface is pretty informative and useful, too.

So, let’s get Stripe integrated into your Rails app.


First of all, you need to get a Stripe account and a copy of the API. Start by signing up. You don’t even have to provide credit card details; you’ll be put into a “developer mode”, so that none of the test payments we’ll be doing will mean anything.

Then, install the Stripe gem:

gem install stripe


The frontend code is what we will cover first; it’s an area where a few mistakes can cost you a lot (e.g. free accounts due to not checking errors).

There’s some stuff you need to get from the user:

  • Credit card number
  • Credit card VC (security code)
  • Credit card month and year

And, you might want to get an email address too.

Don’t create a model for this.

User credit card data should never hit your database — Stripe will be much more secure.

So, here’s the markup for a simple form that would work (should go in a view):

<div class=".payment-errors"></div>
<form action="REPLACE WITH AN ACTUAL URL HELPER" method="post" id="stripe-form">
    <div class="formset">
        <label>Card Number</label>
        <input type="text" size="20" autocomplete="off" class="credit-number" />
    <div class="formset">
        <label>Security Code/CVC</label>
        <input type="text" size="4" autocomplete="off" class="credit-scurity" />
    <div class="formset">
        <label>Expiration (MM/YYYY)</label>
        <input type="text" size="2" class="card-expiry-month"/>
        <span> / </span>
        <input type="text" size="4" class="card-expiry-year"/>
    <button type="submit" class="submit">Submit Payment</button>

Make sure you replace the action with a route that makes sense for your application.

Notice a couple of things. First, the autocomplete is turned off for the credit card number and security code input fields; some of your users might be using public computers. Second, a lot of the div’s that are in there are just for styling; they don’t really matter much.

Next, we’ll need Stripe’s Javascript API:

<script type="text/javascript" src=""></script>

That should probably go in your layout, so that it’s not tacked onto the body tag and it will be available throughout all the actions for a particular controller.

Next up, you’ll need your publishable key. Now, before we go on, it’s good to have an extremely general overview of public key cryptography so that you’re not just blindly pasting code.

Understanding how something works on the inside makes it easier to fix problems when they arise.

Side Track – Cryptography

Public key cryptography works by having two keys (keys are usually alphanumeric strings)- one that’s public (used for encryption), and one that’s private (used for decryption).

So, if I wanted to send you a message, I would first go and find out your public key (since its public) and then use that key to encrypt my message. When you receive the message you would decrypt using your private key.

What does that do? Well, if my message gets intercepted by ninjas along they way, they won’t be able to understand it. They don’t have the private key!

That’s especially important on the internet, because basically all packets can be intercepted, which means that if they contain important information, they’d better be encrypted!

Notice that I haven’t actually mentioned how someone uses an alphanumeric string (i.e. the key) to encrypt or decrypt a message; there’s different algorithms for that, if you’re interested, look into RSA (some math involved).

That’s grossly simplified, but, that’s the general idea, and that’s what Stripe (and a ton of other services) use.


To get your public key, login, then click “Your account”, then “Account Settings” and finally the “API Keys” tab

So, now, you need a bit of Javascript to tell Stripe about your key:

Stripe.setPublishableKey('PUBLISHABLE KEY');

That, of course, should go along with your Javascript files.

Then, we need a bit of Javascript to get a payment token from Stripe:

function stripeResponseHandler(status, response) {
    if (response.error) {
    else {
        var form$ = $("#stripe-form");
        var token = response['id'];
        form$.append("<input type='hidden' name='stripeToken' value='" + token + "'/>");
$(document).ready(function() {
  $("#stripe-form").submit(function(event) {
    $('.submit').attr("disabled", "disabled");
        number: $('.credit-number').val(),
        cvc: $('.credit-security').val(),
        exp_month: $('.card-expiry-month').val(),
        exp_year: $('.card-expiry-year').val()
    }, stripeResponseHandler);
    // prevent the form from submitting with the default action
    return false;

I’m using jQuery, but, if you don’t want to (for some odd reason), you can replace the jQuery specific code quite easily (it’s mostly just document.getElementById).

That’s a little complicated (especially if you’re not very familiar with Javascript), but, taken in pieces, its quite understandable. Basically, we are attaching an event to the Stripe form, so that an anonymous function (i.e. a function without a name given to it) gets fired when the user hits the “submit” button. Then, we disable the submit button, so that multiple clicks don’t result in multiple requests to the server (i.e. charging the user twice).

Using the Stripe API, we create a token. This is the (slightly) tricky part. Stripe doesn’t just return the token; we give a function called stripeResponseHandler to call once its got the response.

Side track – Response handlers

If you’re not a Javascript developer, you might not be too familiar with response handlers.

Basically, instead of making your code wait for Stripe to communicate with its servers and return a token, your code can just move on, and when Stripe is ready, a function is called.

So, now, look at stripeResponseHandler. That function is very simple — if there’s errors, report them (by adding them a div with the class of payment-errors, which we defined in our form markup), or, fire off a request to the server, with the stripe token as a hidden input.

Server side

Alright! So, now, we’re ready to make the move to the server, where this token will be used to actually charge the user.

Now, notice a couple of things. Firstly, we still haven’t charged the user a single penny – we’ve only got the token. Secondly, the credit card information never even touches the server, let alone the database. It’s taken to Stripe, which then gives you a token, which you can charge. Awesome, right?

This time around, you’ll need your private key, which is available from the same place you got your public key (Account Settings -> API Keys tab).

Stripe.api_key = "YOUR_API_KEY"
token = params[:stripeToken]
charge = Stripe::Charge.create(
  :amount => 1000, # amount in cents, again
  :currency => "usd",
  :card => token,
  :description => "something about your customer"

That should go in one of your controller classes, within an action method.

The code is extremely clean and easy to understand; we’re setting the key (which should be kept private and safe!), getting the token (which we inserted as a hidden input in the Javascript) and then creating a charge.

Your API key (maybe if you’re processing payments in multiple actions) can also go in an initializer file.

Monthly charges

Now, how about subscriptions? Repeating payments are incredibly common and many services make them unnecessarily difficult.

First of all, in order to get a subscription working, you have a setup a plan. This can be done in two ways, the easier of which is just using the dashboard and the other is with a bit of code.

To create a new plan, go into the dashboard, then, into plans, and, from there, there’s a nice little “wizard” that’ll walk you through the process.

In fact, you can even specify a trial period for your users, so, if you want them to have 15 days free, you just have to set it up on the dashboard – no code needed!

So, maybe you called the plan “medium” (remember the name, its actually important).

Now, we can use the Stripe customer abstraction:

Thanks for reading, and, may your app bring success to you and happiness to us all.

Dhaivat PandyaDhaivat Pandya
View Author

I'm a developer, math enthusiast and student.

Share this article
Read Next
Get the freshest news and resources for developers, designers and digital creators in your inbox each week
Loading form