Setting up Stripe Connect w/ Rails

Credit: Pexels

I have recently come across a project that required me to set up some form of payment gateway so that users of my site can effectuate transactions amongst each other, while I get a percentage out of each (think Uber, Lyft or Shopify). Stripe came up as the most effective way to go about this, with their convenient Connect feature. But there surprisingly is almost zero documentation out there on how to integrate Stripe Connect into a Rails app (oddly enough). Nevertheless, I’ve been able to build my own implementation, and I figured it fitting to share my process. I’m going to skip ahead of the basics (creating a stripe account and having a rails environment set up).

The basic flow of Connect is as follows: An authenticated user on your app will click on a link (ie. “Create my stripe account to accept payments”) that will redirect them to Stripe. Then Stripe will have them either create a new account or log into an existing account. Then they will be prompted to “connect” their stripe account, which will redirect them back to your site, where they will now be ready to accept payments from other users. While this seems simple enough, a couple important things are being done under the hood. We need to retrieve one important piece of info, the user’s stripe_uid, or account number. Here’s how I did it:

Step 1 — Install the Stripe and OAuth gems and run bundler

gem 'stripe'
gem install oauth2

We’re using OAuth2 for the omniauth authentication and to make calls to Stripe’s API.

Step 2 — Go to /config/initializers and create a stripe.rb file

//fill it with the following
Rails.configuration.stripe = {
:stripe_publishable_key => ENV['STRIPE_PUBLISHABLE_KEY'],
:secret_key => ENV['STRIPE_SECRET_KEY']
}
Stripe.api_key = Rails.configuration.stripe[:secret_key]

Stripe provides 3 key “keys” (see what I did there?). The two keys above will be held in your environment configuration. If you are using Heroku, you can either set these keys from the command line, or from your Heroku dashboard. For Heroku, type the following in your command line:

heroku config set STRIPE_PUBLISHABLE_KEY:yourstripepublishablekey
heroku config set STRIPE_SECRET_KEY:yourstripesecretkey

As you may already know, Stripe provides both test and live keys. Make sure you are using the appropriate ones in the appropriate settings.

Step 3 — Now for the controllers (we’ll fill them out later)

//from the command line
rails g controller Event stripe_callback payment_profile
//in the controller
Class EventController < ApplicationController

//this action gets called after a user creates their Stripe acct
   def stripe_callback
   end

//this is where a user will be able to see their balance info
   def payment_profile
   end
end

Step 4 — In your payment_profile view

<% if @user.stripe_uid.present? %>
//show something
<% else %>
<a href="https://connect.stripe.com/oauth/authorize? response_type=code&client_id=<%= ENV['STRIPE_CONNECT_CLIENT_ID'] %>&scope=read_write">set up my free stripe account</a>
<% end %>
//this is the link that a user will click on to create their stripe account

When a user goes to this page, if they’ve already created a Stripe account and linked it to your site, then you’ll display information like their stripe balance or something. Otherwise, you’ll provide this Stripe-provided link to get them started. The url takes in your client_id (can be found in your Connect settings on your Stripe dashboard) and passes it as a paramater, calling Stripe’s API with a read and write scope, and expecting a code as a response.

Step 5 — Add new attributes to the User model (or w/e model the user is)

//from the command line
rails g migration add_stripe_attributes_to_users stripe_uid:string

The stripe_uid attribute will be the user’s identification number (stripe account number). There are few other attributes (such as provider info, access token, etc) that can be added, but this should do at the most basic level.

Step 6 — Fill out your controller

Class UsersController < ApplicationController

//this action gets called after a user creates their Stripe acct
   def stripe_callback
            options = {
site: 'https://connect.stripe.com',
authorize_url: '/oauth/authorize',
token_url: '/oauth/token'
}
code = params[:code]
client = OAuth2::Client.new(ENV['STRIPE_CONNECT_CLIENT_ID'], ENV['STRIPE_SECRET_KEY'], options)
@resp = client.auth_code.get_token(code, :params => {:scope => 'read_write'})
@access_token = @resp.token
@user.update!(uid: @resp.params["stripe_user_id"]) if @resp
flash[:notice] = "Your account has been successfully created and is ready to process payments!"
end

//this is where a user will be able to see their balance info
   def payment_profile
      @account = Stripe::Account.retrieve("#{@user.uid.to_s}") if @user.uid.present?
@balance = Stripe::Balance.retrieve() if @user.uid.present?
end
end

What’s happening here?

Well let’s start with our stripe_callback action. After a user has been prompted to connect their stripe account, they will be redirected by stripe to your site with some important info. This action will be called when this happens, and we have to retrieve the information from the url, in order to make some calls to Stripe’s API to collect the information that the user has just created, and store it in our own database.

The code parameter is what gets sent by Stripe everytime a user has created an account with them. We retrieve it, then create a new client on their behalf using OAuth and passing in our keys. Then we retrive that client’s information from Stripe and store it in an instance variable @resp. From there you can get as much information as you want about the user. In our example, we need their uid:

@resp.params["stripe_user_id"]
//other info include access token
@resp.params["token"]
//provider
@resp.params["provider"]

Finally, we update the user’s information in our own database:

User.find(@user.id).update!(uid: @resp.params["stripe_user_id"]) if @resp

We now have the user’s account number stored in our database. This lets us pull important data such as the user’s balance, transactions, charges, etc. Which we take care of in the payment_profile action.

Step 7 — Routing

We need to make it so that the redirect_uri (you can set that up from the Connect settings on your stripe dashboard) calls the appropriate actions from our controller. Set your Stripe redirect_uri to the following:

Development

localhost/settings/payment-info/users/auth/stripe_connect/callback

Production

www.yourwebsite.com/settings/payment-info/users/auth/stripe_connect/callback

Then add the following to your routes:

get "settings/payment-info/users/auth/stripe_connect/callback", to:"users#stripe_callback"

Now when the user gets redirected to your site after creating their Stripe account, the stripe_callback action will be called. And our code will handle the rest. Then in your stripe_callback view, you can add a link to send the user back to their payment info:

<%= link_to "Return to payment settings", payment_profile_path %>

And in your payment profile view:

<h1>$<%= @balance.pending.first["amount"].to_f/100 %></h1>
//displays the user's current balance

The next steps after this will be to actually try creating some test charges between two users in development. There are a couple of excellent tutorials on this portion of the problem:

DevCamp

LaunchSchool

You will need to also add the following to your project:

//let's say your users are selling tickets between each other, you'll add this to your Ticket model
Class Ticket < ActiveRecord::Base
belongs_to :user **or seller**
belongs_to :buyer
   def process_payment
amount = ticket.price * 100 **the amount must be in cents
percentage = ((amount * 20)/100) **this is your cut**
customer = Stripe::Customer.create email: email,
card: card_token

Stripe::Charge.create(
{
:amount => ticket.price * 100,
:description => ticket.description,
:currency => 'usd',
:source => "tok_visa",
:application_fee => percentage,
},
:stripe_account => ticket.user.stripe_uid
)
end
end

In this method, we’re creating a new customer thru Stripe when someone puts their card information to purchase a ticket, and we then create a charge to their card, passing in the price (amount), a description, the currency, the source, an application fee (the percentage you collect from every purchase), and the account to which the money (minus the application fee) will go to (the ticket seller).

Then in your Ticket Controller:

def create
@ticket = @ticket.new(ticket_params.merge(email: stripe_params["stripeEmail"], card_token: stripe_params["stripeToken"]))
@ticket.process_payment
if @ticket.save
flash[:notice] = "Thank you for purchasing this ticket!"
redirect_to ticket_path(@ticket)
else
render :new
end
end

The awesome thing about using Stripe for checkout processes is that your users’ card info are secured, as they never touch your database. Everything is handled directly through stripe.

These are pretty much the basic steps you need to get the ball rolling. More complex apps will require more complex implementations, but the above steps should be more than enough to get even a marketplace app in going in production.

Some helpful links:

Instacart’s implementation

Stripe Connect implementation using the omniauth-stripe-connect gem

Stripe Connect documentation

Stripe Connect oauth reference

I, by any means, do not consider this to be the best solution. Feedback is very much welcomed and appreciated.