Adding Plaid to your Rails App

Duarte M
4 min readMay 19, 2024

--

This is a repost of the orignal article at: https://popadex.com/2024/05/19/adding-plaid-to-rails-app

Integrating Plaid into your Rails application allows you to link bank accounts and retrieve financial data, providing a seamless way to access and manage financial information. This guide will walk you through the process of adding Plaid to your Rails app, assuming you have TailwindCSS already set up for styling. We will cover the necessary steps to configure the backend, set up routes, and create views for linking bank accounts and displaying account details.

Step 1: Add the Plaid Gem

Gemfile:

gem ‘plaid’

Then, run:

bundle install

Step 2: Set Up Plaid Configuration

Next, you need to initialize Plaid in your application. Add the following code to your initializers:

config/initializers/plaid.rb:


# Initialize Plaid configuration
plaid_config = Plaid::Configuration.new
plaid_config.server_index = Plaid::Configuration::Environment[“sandbox”] # or another environment as needed
plaid_config.api_key[“PLAID-CLIENT-ID”] = Rails.application.credentials.dig(:development, :plaid, :client_id)
plaid_config.api_key[“PLAID-SECRET”] = Rails.application.credentials.dig(:development, :plaid, :secret)
# Create an API client instance
api_client = Plaid::ApiClient.new(plaid_config)
# Create a Plaid API instance to use across the application
PlaidClient = Plaid::PlaidApi.new(api_client)
api_client.create_connection do |builder|
builder.use Faraday::Response::Logger
end

Step 3: Set Up Routes

Add the necessary routes to your `config/routes.rb` file:

Rails.application.routes.draw do
root ‘plaid#index’
post ‘plaid/create_link_token’, to: ‘plaid#create_link_token’
post ‘plaid/exchange_public_token’, to: ‘plaid#exchange_public_token’
get ‘plaid/accounts’, to: ‘plaid#accounts’
end

Step 4: Create the Plaid Controller

Create a controller to handle Plaid operations:

**app/controllers/plaid_controller.rb:**

ruby
class PlaidController < ApplicationController
before_action :authenticate_user!
protect_from_forgery with: :null_session # to handle CSRF protection for API requests
def index
end

def create_link_token
user = current_user
link_token_create_request = Plaid::LinkTokenCreateRequest.new({
user: { client_user_id: user.id.to_s },
client_name: ‘Your App Name’,
products: %w[auth transactions],
country_codes: [‘US’],
language: ‘en’
})
begin
link_token_response = PlaidClient.link_token_create(link_token_create_request)
render json: { link_token: link_token_response.link_token }
rescue Plaid::ApiError => e
Rails.logger.error(“Plaid API error: #{e.response_body}”)
render json: { error: e.response_body }, status: :internal_server_error
end
end
def exchange_public_token
Rails.logger.debug(“Received public_token: #{params[:public_token]}”)
if params[:public_token].blank?
Rails.logger.error(‘No public_token received’)
return render json: { error: ‘No public_token received’ }, status: :bad_request
end
begin
exchange_token(params[:public_token])
render json: { message: ‘Bank account linked successfully.’ }, status: :ok
rescue Plaid::ApiError => e
Rails.logger.error(“Plaid API error: #{e.response_body}”)
render json: { error: e.response_body }, status: :internal_server_error
end
end
def exchange_token(public_token)
request = Plaid::ItemPublicTokenExchangeRequest.new({ public_token: public_token })
response = PlaidClient.item_public_token_exchange(request)
access_token = response.access_token
item_id = response.item_id
Rails.logger.debug(“Access token: #{access_token}”)
Rails.logger.debug(“Item ID: #{item_id}”)
if current_user.update(plaid_access_token: access_token, plaid_item_id: item_id)
Rails.logger.debug(‘Access token and item ID saved successfully.’)
Rails.logger.debug(“Current user after save: #{current_user.inspect}”)
else
Rails.logger.error(“Failed to save access token and item ID. Errors: #{current_user.errors.full_messages.join(‘, ‘)}”)
end
end
def accounts
access_token = current_user.plaid_access_token

if access_token.blank?
flash[:error] = ‘Access token is missing. Please link your account again.’
return redirect_to root_path
end

begin
accounts_request = Plaid::AccountsGetRequest.new({ access_token: access_token })
accounts_response = PlaidClient.accounts_get(accounts_request)
@accounts = accounts_response.accounts
rescue Plaid::ApiError => e
Rails.logger.error(“Plaid API error: #{e.response_body}”)
flash[:error] = “Plaid API error: #{e.response_body}”
return redirect_to root_path
rescue StandardError => e
Rails.logger.error(“Internal server error: #{e.message}”)
flash[:error] = ‘Internal server error’
return redirect_to root_path
end
end
end

Step 5: Create the View

Create a view to display the link button and account details.

app/views/plaid/index.html.erb:


<!DOCTYPE html>
<html class=”dark”>
<head>
<title>Account Details</title>
</head>
<body class=”bg-white dark:bg-gray-900 text-black dark:text-white”>
<div class=”container mx-auto p-4">
<h1 class=”text-3xl font-bold mb-4">Link Your Bank Account</h1>
<button id=”link-button” class=”bg-blue-500 hover:bg-blue-700 text-white font-bold py-2 px-4 rounded dark:bg-gray-900 dark:hover:bg-gray-700 dark:text-white”>Link Account</button>
<script src=”https://cdn.plaid.com/link/v2/stable/link-initialize.js"></script>
<script>
document.getElementById(‘link-button’).onclick = function() {
var csrfToken = document.querySelector(‘meta[name=”csrf-token”]’).getAttribute(‘content’);fetch(‘/plaid/create_link_token’, {
method: ‘POST’,
headers: {
‘Content-Type’: ‘application/json’,
‘X-CSRF-Token’: csrfToken
},
body: JSON.stringify({})
})
.then(response => response.json())
.then(data => {
if (data.error) {
console.error(‘Error:’, data.error);
return;
}var linkHandler = Plaid.create({
token: data.link_token,
onSuccess: function(public_token, metadata) {
fetch(‘/plaid/exchange_public_token’, {
method: ‘POST’,
headers: {
‘Content-Type’: ‘application/json’,
‘X-CSRF-Token’: csrfToken
},
body: JSON.stringify({ public_token: public_token })
})
.then(response => response.json())
.then(data => {
if (data.error) {
console.error(‘Error:’, data.error);
return;
}
window.location.href = ‘/plaid/accounts’;
});
},
onExit: function(err, metadata) {
console.log(‘Plaid link exit’, err, metadata);
}
});linkHandler.open();
})
.catch(error => {
console.error(‘Fetch error:’, error);
});
};
</script>
</div>
</body>
</html>

app/views/plaid/accounts.html.erb:


<!DOCTYPE html>
<html class=”dark”>
<head>
<title>Account Details</title>
</head>
<body class=”bg-white dark:bg-gray-900 text-black dark:text-white”>

<div class=”container mx-auto p-4">
<h1 class=”text-3xl font-bold mb-4">Account Details</h1>
<% if @error %>
<div class=”bg-red-500 text-white p-2 rounded mb-4">
Error: <%= @error %>
</div>
<% else %>
<div class=”overflow-x-auto”>
<table class=”min-w-full bg-white dark:bg-gray-800 border border-gray-300 dark:border-gray-700">
<thead>
<tr class=”bg-gray-200 dark:bg-gray-700">
<th class=”py-2 px-4 border-b border-gray-300 dark:border-gray-600">Name</th>
<th class=”py-2 px-4 border-b border-gray-300 dark:border-gray-600">Type</th>
<th class=”py-2 px-4 border-b border-gray-300 dark:border-gray-600">Subtype</th>
<th class=”py-2 px-4 border-b border-gray-300 dark:border-gray-600">Mask</th>
<th class=”py-2 px-4 border-b border-gray-300 dark:border-gray-600">Balance</th>
</tr>
</thead>
<tbody>
<% @accounts.each do |account| %>
<tr class=”border-b border-gray-300 dark:border-gray-700">
<td class=”py-2 px-4"><%= account.name %></td>
<td class=”py-2 px-4"><%= account.type %></td>
<td class=”py-2 px-4"><%= account.subtype %></td>
<td class=”py-2 px-4"><%= account.mask %></td>
<td class=”py-2 px-4"><%= number_to_currency(account.balances.available) %></td>
</tr>
<% end %>
</tbody>
</table>
</div>
<% end %>
</div>
</body>
</html>

Conclusion

By following these steps, you can integrate Plaid into your Rails application to link bank accounts and display account details. This guide covers the necessary configuration, routes, controller actions, and views to set up Plaid. Make sure to handle API keys securely and configure the environment properly for production.

--

--