Stripe's popularity is due largely to its developer-friendliness. Stripe removes much of the messiness from the payment integration process. It verifies credit card information for you, shielding you from the actual data so that your users are secure. It charges the cards for you, and routes the money wherever you want (with some restrictions). But payment gateways are complicated by nature, and even with Stripe, stringing together a payment system for your app can be difficult to conceptualize.
So let's take a look at a basic Stripe integration. There are countless ways to integrate Stripe into your app; we'll cover a simpler method here.
As with many Rails common problems, gems are a great place to start. The Stripe Gem greatly simplifies working with the Stripe API. Add the gem to your Gemfile:
Gemfile
gem 'stripe'And don't forget to:
Terminal
bundle installOnce you've installed Stripe, head on over to the site to register for an account. Once signed in, you'll have access to an account dashboard with information like your balance, purchase history, customers, and more.
Most importantly for right now, this new account gives you access to personalized API keys, accessible through the account drop-down in the upper right.
The toggle in the upper left of your account page allows you to switch between "Live" and "Test" views. This will prove very useful throughout the development process.
Armed with API keys, we're ready to head back to the app. At a high level, here's the thinking:
-
First things first, we need to hook our app up to our Stripe account.
-
Once we've made it through configuration, we move onto the actual charging. We want to treat charges like any old resource, so we should create a ChargesController that that can initialize new Charge objects, and then "create" charges (sending them to Stripe through its API).
-
When Stripe receives the Charge information from your app, with your API keys, it verifies the card and, if all looks good, runs the charge.
-
If something goes wrong (bad card information, or luck), the API will return an error message, and, just as with an error in a name field, the user can be redirected to try again.
-
Once the charge has passed through, you can see it on your account page.
The first step in this process is configuration. The cleanest way to do this is in a separate initialization file. Let's call it config/initializers/stripe.rb:
config/initializers/stripe.rb
# Store the environment variables on the Rails.configuration object
Rails.configuration.stripe = {
publishable_key: ENV['STRIPE_PUBLISHABLE_KEY'],
secret_key: ENV['STRIPE_SECRET_KEY']
}
# Set our app-stored secret key with Stripe
Stripe.api_key = Rails.configuration.stripe[:secret_key]Nice and easy, right? Don't forget that you have to add these environment variables, locally and on production, before you use them.
Congrats! Once you've set your env variables, you're all done with configuration.
Onward to step two - the creation of the ChargesController, where charges will be initialized and created.
Let's start with creation. The create action of the controller will receive params and turn them into a charge object to send to Stripe. In this example, we won't actually be storing this charge object in our database, because Stripe takes care of the bookkeeping for us.
The params are:
-
stripeToken- A token, unique to the charge, that contains the encrypted credit card information to be sent to Stripe. -
amount- The payment amount in pennies. (Pennies are less of a pain to deal with than fractional money amounts. Trust us. And Stripe.)
So, that action could look something like this:
app/controllers/charges_controller.rb
def create
# Creates a Stripe Customer object, for associating
# with the charge
customer = Stripe::Customer.create(
email: current_user.email,
card: params[:stripeToken]
)
# Where the real magic happens
charge = Stripe::Charge.create(
customer: customer.id, # Note -- this is NOT the user_id in your app
amount: Amount.default,
description: "BigMoney Membership - #{current_user.email}",
currency: 'usd'
)
flash[:notice] = "Thanks for all the money, #{current_user.email}! Feel free to pay me again."
redirect_to user_path(current_user) # or wherever
# Stripe will send back CardErrors, with friendly messages
# when something goes wrong.
# This `rescue block` catches and displays those errors.
rescue Stripe::CardError => e
flash[:alert] = e.message
redirect_to new_charge_path
endWe'll leave it to you to create a
Amountclass and itsdefaultclass method, which should return the number you wish to charge, in pennies. One such value might be10_00, for ten dollars.
Before we get to the new action, one quick detour into views. Here's a basic charges/new.html.erb:
charges/new.html.erb
<%= form_tag charges_path do %>
<h4>Click the button!</h4>
<script class='stripe-button' src="https://checkout.stripe.com/checkout.js" data-key="<%= @stripe_btn_data[:key] %>" data-amount="<%= @stripe_btn_data[:amount] %>" data-description="<%= @stripe_btn_data[:description] %>" ></script>
<% end %>Confused by that variable? We're declaring it in the controller, just to clean up the view:
app/controllers/charges_controller.rb
def new
@stripe_btn_data = {
key: "#{ Rails.configuration.stripe[:publishable_key] }",
description: "BigMoney Membership - #{current_user.name}",
amount: Amount.default
}
endTo get this all to work, add a new resources route to point to the ChargesController actions:
config/routes.rb
resources :charges, only: [:new, :create]OK. So it all works, maybe. But how do you test this all out? Stripe provides several test card numbers, everyone's favorite of which is 4242 4242 4242 4242. So to test out charging, navigate to the charges/new page on local, click the button, fill in that card number and a fake CVC and (future) expiration date, and submit the charge.
It should show up shortly on your Stripe dashboard, in the Test tab.