plaid_rails 0.10.0 → 0.11.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- checksums.yaml +4 -4
- data/README.md +8 -0
- data/app/assets/javascripts/plaid_rails/link.js +22 -12
- data/app/controllers/plaid_rails/accounts_controller.rb +9 -5
- data/app/controllers/plaid_rails/link_controller.rb +24 -19
- data/app/controllers/plaid_rails/webhooks_controller.rb +4 -3
- data/app/models/plaid_rails/account.rb +6 -4
- data/app/models/plaid_rails/webhook.rb +7 -3
- data/app/services/plaid_rails/create_account_service.rb +17 -12
- data/app/views/plaid_rails/accounts/new.html.erb +2 -2
- data/app/views/plaid_rails/link/_auth.html.erb +1 -1
- data/config/routes.rb +1 -1
- data/db/migrate/20180617232228_api_update.rb +12 -0
- data/lib/generators/plaid_rails/templates/initializer.rb +4 -6
- data/lib/plaid_rails.rb +1 -1
- data/lib/plaid_rails/event.rb +6 -6
- data/lib/plaid_rails/version.rb +1 -1
- data/spec/controllers/plaid_rails/accounts_controller_spec.rb +12 -14
- data/spec/controllers/plaid_rails/link_controller_spec.rb +18 -11
- data/spec/controllers/plaid_rails/webhooks_controller_spec.rb +79 -5
- data/spec/dummy/db/schema.rb +9 -3
- data/spec/dummy/db/test.sqlite3 +0 -0
- data/spec/dummy/log/test.log +10529 -0
- data/spec/models/plaid_rails/account_spec.rb +28 -10
- data/spec/models/plaid_rails/webhook_spec.rb +3 -3
- data/spec/services/plaid_rails/create_account_service_spec.rb +7 -3
- data/spec/spec_helper.rb +31 -4
- data/spec/support/token_helper.rb +25 -0
- metadata +54 -37
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA1:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 1be2e2ff076fc81d6744b9b9ad21713f25ee03f6
|
4
|
+
data.tar.gz: 1f97d8a175a1de3e132de0ef53483d439cd2b347
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 3606d4d8a413950fd005a3eb334e89649ac85ace2f686caf59d05bd9faf30e9ca6ad1e785a4b45a96492cb47dc89fd2acfb864b9b5d7170c9e49c1c238196c8a
|
7
|
+
data.tar.gz: bbbfa8aaa1ec946e9f8cab2acd7fd3c3aaad7656fa340f3fdc45c357a6b1b4366ac45f4587e11c64fe4ef077dc7667e493f61a3e19eb2777dba9c4da59951ee2
|
data/README.md
CHANGED
@@ -73,3 +73,11 @@ The plaid webhooks runs subscribers for to process transactions and report error
|
|
73
73
|
|
74
74
|
Update the PlaidRails.configuration.webhook with the address of the webhook url. The route is `plaid/webhook`
|
75
75
|
i.e. http(s)://my.app.com/plaid/webhooks
|
76
|
+
|
77
|
+
### Testing
|
78
|
+
To run the tests you need to set the PLAID credentials in environment variables.
|
79
|
+
```bash
|
80
|
+
export PLAID_CLIENT_ID='your client_id'
|
81
|
+
export PLAID_SECRET='your secret'
|
82
|
+
export PLAID_PUBLIC_KEY='your public_key'
|
83
|
+
```
|
@@ -1,24 +1,33 @@
|
|
1
|
+
function getPublicToken(access_token) {
|
2
|
+
$.post('/plaid/create_token',
|
3
|
+
{access_token: access_token},
|
4
|
+
function (data, status, xhr) {
|
5
|
+
return data.public_token;
|
6
|
+
},
|
7
|
+
'json'
|
8
|
+
);
|
9
|
+
}
|
1
10
|
function getPlaid(plaidData) {
|
2
11
|
var url = null;
|
3
|
-
var
|
12
|
+
var access_token = plaidData.data('access-token');
|
4
13
|
var env = plaidData.data('env');
|
5
|
-
|
14
|
+
var token;
|
15
|
+
if (typeof access_token === 'undefined') {
|
6
16
|
url = '/plaid/authenticate';
|
7
17
|
token = null;
|
8
18
|
} else {
|
9
19
|
url = '/plaid/update';
|
10
|
-
|
11
|
-
// set token for test environment
|
12
|
-
if (env === 'tartan' && typeof plaidData.data('type') !== 'undefined') {
|
13
|
-
token = 'test,' + plaidData.data('type') + ',connected'
|
20
|
+
token = getPublicToken(access_token);
|
14
21
|
}
|
15
22
|
|
16
23
|
var linkHandler = Plaid.create({
|
17
24
|
env: env,
|
25
|
+
apiVersion: 'v2',
|
18
26
|
clientName: plaidData.data('client-name'),
|
19
27
|
key: plaidData.data('key'),
|
20
|
-
product: '
|
28
|
+
product: 'transactions',
|
21
29
|
webhook: plaidData.data('webhook'),
|
30
|
+
token: token,
|
22
31
|
onLoad: function () {
|
23
32
|
// The Link module finished loading.
|
24
33
|
},
|
@@ -32,11 +41,12 @@ function getPlaid(plaidData) {
|
|
32
41
|
url: url,
|
33
42
|
data: {
|
34
43
|
public_token: public_token,
|
35
|
-
|
36
|
-
|
44
|
+
access_token: plaidData.data('access-token'),
|
45
|
+
name: metadata.account.name,
|
46
|
+
type: metadata.account.type,
|
37
47
|
owner_type: plaidData.data('owner-type'),
|
38
48
|
owner_id: plaidData.data('owner-id'),
|
39
|
-
number:
|
49
|
+
number: metadata.account.mask
|
40
50
|
}
|
41
51
|
});
|
42
52
|
},
|
@@ -50,10 +60,10 @@ function getPlaid(plaidData) {
|
|
50
60
|
$(document).on("click", '#plaidLinkButton', function () {
|
51
61
|
var plaidData = $(this);
|
52
62
|
linkHandler = getPlaid(plaidData);
|
53
|
-
var plaidType = plaidData.data('type')
|
63
|
+
var plaidType = plaidData.data('type');
|
54
64
|
//open handler for the institution
|
55
65
|
if (typeof plaidType === 'undefined') {
|
56
|
-
|
66
|
+
linkHandler.open();
|
57
67
|
} else {
|
58
68
|
linkHandler.open(plaidType);
|
59
69
|
}
|
@@ -9,10 +9,14 @@ module PlaidRails
|
|
9
9
|
|
10
10
|
# display list of accounts for authenticated user
|
11
11
|
def new
|
12
|
-
|
13
|
-
|
14
|
-
|
15
|
-
|
12
|
+
client = Plaid::Client.new(env: PlaidRails.env,
|
13
|
+
client_id: PlaidRails.client_id,
|
14
|
+
secret: PlaidRails.secret,
|
15
|
+
public_key: PlaidRails.public_key)
|
16
|
+
|
17
|
+
response = client.accounts.get(account_params["access_token"])
|
18
|
+
@plaid_accounts = response.accounts
|
19
|
+
|
16
20
|
end
|
17
21
|
|
18
22
|
#create new bank account and return all the accounts for the owner
|
@@ -33,7 +37,7 @@ module PlaidRails
|
|
33
37
|
|
34
38
|
# Never trust parameters from the scary internet, only allow the white list through.
|
35
39
|
def account_params
|
36
|
-
params.require(:account).permit(:
|
40
|
+
params.require(:account).permit(:access_token, :type,:name,
|
37
41
|
:owner_id,:owner_type, :transactions_start_date, account_ids:[])
|
38
42
|
end
|
39
43
|
end
|
@@ -3,44 +3,49 @@ require_dependency "plaid_rails/application_controller"
|
|
3
3
|
module PlaidRails
|
4
4
|
class LinkController < ApplicationController
|
5
5
|
|
6
|
+
# /plaid/authenticate
|
6
7
|
def authenticate
|
7
8
|
begin
|
8
|
-
|
9
|
-
|
9
|
+
client = Plaid::Client.new(env: PlaidRails.env,
|
10
|
+
client_id: PlaidRails.client_id,
|
11
|
+
secret: PlaidRails.secret,
|
12
|
+
public_key: PlaidRails.public_key)
|
13
|
+
@exchange_token = client.item.public_token.exchange(link_params[:public_token])
|
10
14
|
@params = link_params.merge!(token: link_params[:public_token])
|
11
15
|
|
12
16
|
rescue => e
|
13
17
|
Rails.logger.error "Error: #{e}"
|
14
|
-
Rails.logger.error e.backtrace.join("\n")
|
15
18
|
render text: e.message, status: 500
|
16
19
|
end
|
17
20
|
end
|
18
21
|
|
19
22
|
# updates the access token after changing password with institution
|
23
|
+
# /plaid/update
|
20
24
|
def update
|
21
25
|
begin
|
22
|
-
exchange_token = Plaid::User.exchange_token(link_params[:public_token])
|
23
|
-
|
24
|
-
# find old access_token
|
25
|
-
old_access_token = PlaidRails::Account.find_by(owner_type: link_params[:owner_type],
|
26
|
-
owner_id: link_params[:owner_id],number: link_params[:number]).access_token
|
27
|
-
|
28
|
-
# find all plaid_accounts with old access_token
|
29
|
-
accounts = PlaidRails::Account.where(owner_type: link_params[:owner_type],
|
30
|
-
owner_id: link_params[:owner_id], access_token: old_access_token)
|
31
|
-
|
32
|
-
# update found accounts with new token.
|
33
|
-
accounts.update_all(access_token: exchange_token.access_token,
|
34
|
-
transactions_start_date: Date.today)
|
35
|
-
|
36
26
|
# get all accounts to display back to user.
|
37
27
|
@plaid_accounts = PlaidRails::Account.where(owner_type: link_params[:owner_type],
|
38
|
-
|
28
|
+
owner_id: link_params[:owner_id])
|
39
29
|
|
40
30
|
flash[:success]="You have successfully updated your account(s)"
|
41
31
|
rescue => e
|
42
32
|
Rails.logger.error "Error: #{e}"
|
43
|
-
render
|
33
|
+
render json: e.message, status: 500
|
34
|
+
end
|
35
|
+
end
|
36
|
+
|
37
|
+
# creates a new public token
|
38
|
+
# /plaid/create_token
|
39
|
+
def create_token
|
40
|
+
client = Plaid::Client.new(env: PlaidRails.env,
|
41
|
+
client_id: PlaidRails.client_id,
|
42
|
+
secret: PlaidRails.secret,
|
43
|
+
public_key: PlaidRails.public_key)
|
44
|
+
if link_params['access_token']
|
45
|
+
response = client.item.public_token.create(link_params['access_token'])
|
46
|
+
render json: {public_token: response['public_token']}.to_json
|
47
|
+
else
|
48
|
+
render json: {error: 'missing access_token'}.to_json, status: 500
|
44
49
|
end
|
45
50
|
end
|
46
51
|
|
@@ -3,13 +3,14 @@ module PlaidRails
|
|
3
3
|
skip_before_filter :verify_authenticity_token
|
4
4
|
|
5
5
|
def create
|
6
|
-
|
7
|
-
render json:
|
6
|
+
webhook = PlaidRails::Webhook.create!(webhook_params)
|
7
|
+
render json: webhook
|
8
8
|
end
|
9
9
|
|
10
10
|
private
|
11
11
|
def webhook_params
|
12
|
-
params.require(:webhook).permit(:
|
12
|
+
params.require(:webhook).permit(:webhook_type, :webhook_code,:error,
|
13
|
+
:item_id, :new_transactions, :removed_transactions, :code, :message,:access_token )
|
13
14
|
end
|
14
15
|
end
|
15
16
|
end
|
@@ -8,7 +8,6 @@ module PlaidRails
|
|
8
8
|
validates :plaid_id, presence: true
|
9
9
|
validates :name, presence: true
|
10
10
|
validates :access_token, presence: true
|
11
|
-
validates :plaid_type, presence: true
|
12
11
|
|
13
12
|
private
|
14
13
|
|
@@ -25,10 +24,13 @@ module PlaidRails
|
|
25
24
|
def delete_connect
|
26
25
|
begin
|
27
26
|
Rails.logger.info "Deleting Plaid User with token #{token_last_8}"
|
28
|
-
|
27
|
+
client = Plaid::Client.new(env: PlaidRails.env,
|
28
|
+
client_id: PlaidRails.client_id,
|
29
|
+
secret: PlaidRails.secret,
|
30
|
+
public_key: PlaidRails.public_key)
|
29
31
|
# skip delete if there are no transactions
|
30
|
-
if
|
31
|
-
|
32
|
+
if client.transactions.any?
|
33
|
+
client.item.remove(access_token)
|
32
34
|
Rails.logger.info "Deleted Plaid User with token #{token_last_8}"
|
33
35
|
end
|
34
36
|
rescue => e
|
@@ -1,9 +1,13 @@
|
|
1
1
|
module PlaidRails
|
2
2
|
class Webhook < ActiveRecord::Base
|
3
3
|
|
4
|
-
validates :code, presence: true
|
5
|
-
validates :message, presence: true
|
6
|
-
validates :access_token, presence: true
|
4
|
+
# validates :code, presence: true
|
5
|
+
# validates :message, presence: true
|
6
|
+
# validates :access_token, presence: true
|
7
|
+
# validates :webhook_type, presence: true
|
8
|
+
# validates :webhook_code, presence: true
|
9
|
+
# validates :item_id, presence: true
|
10
|
+
serialize :removed_transactons, Array
|
7
11
|
after_save :event
|
8
12
|
|
9
13
|
private
|
@@ -4,25 +4,30 @@ module PlaidRails
|
|
4
4
|
# creates a new plaid_rails_account for each account the user has selected
|
5
5
|
def self.call(account_params)
|
6
6
|
account_params["account_ids"].each do |id|
|
7
|
-
#
|
8
|
-
|
9
|
-
|
10
|
-
|
7
|
+
# Create the Plaid Client
|
8
|
+
client = Plaid::Client.new(env: PlaidRails.env,
|
9
|
+
client_id: PlaidRails.client_id,
|
10
|
+
secret: PlaidRails.secret,
|
11
|
+
public_key: PlaidRails.public_key)
|
11
12
|
#find the account by account_id
|
12
|
-
account =
|
13
|
+
account = client.accounts.get(account_params["access_token"]).accounts.find{|a| a.account_id==id}
|
14
|
+
response = client.item.get(account_params["access_token"])
|
15
|
+
item = response.item
|
16
|
+
response = client.institutions.get_by_id(item['institution_id'])
|
17
|
+
institution = response.institution
|
13
18
|
PlaidRails::Account.create!(
|
14
19
|
access_token: account_params["access_token"],
|
15
|
-
|
16
|
-
plaid_type: account_params["type"],
|
20
|
+
plaid_type: item.institution_id,
|
17
21
|
name: account.name,
|
18
|
-
bank_name:
|
19
|
-
number: account.
|
22
|
+
bank_name: institution.name,
|
23
|
+
number: account.mask,
|
20
24
|
owner_id: account_params["owner_id"],
|
21
25
|
owner_type: account_params["owner_type"],
|
22
|
-
available_balance: account.
|
23
|
-
current_balance: account.
|
26
|
+
available_balance: account.balances.available,
|
27
|
+
current_balance: account.balances.current,
|
24
28
|
transactions_start_date: account_params["transactions_start_date"],
|
25
|
-
plaid_id: id
|
29
|
+
plaid_id: id,
|
30
|
+
item_id: item.item_id
|
26
31
|
) unless PlaidRails::Account.exists?(plaid_id: id)
|
27
32
|
end
|
28
33
|
|
@@ -9,8 +9,8 @@
|
|
9
9
|
<%= hidden_field_tag "account[owner_type]", params["owner_type"] %>
|
10
10
|
<%= label_tag "start_date" %> <%= date_field_tag "account[transactions_start_date]" %>
|
11
11
|
<% @accounts.each_with_index do |account,index| %>
|
12
|
-
<%= check_box_tag "account[account_ids][]", account.
|
13
|
-
<label for="account_account_ids_<%=index%>"> <%= "#{account.
|
12
|
+
<%= check_box_tag "account[account_ids][]", account.account_idid,nil,{id: "account_account_ids_#{index}"}%>
|
13
|
+
<label for="account_account_ids_<%=index%>"> <%= "#{account.name} - #{account.mask}"%></label><br/>
|
14
14
|
<%end%>
|
15
15
|
|
16
16
|
<%= submit_tag "Save", :class=>"button small" %>
|
@@ -3,7 +3,7 @@
|
|
3
3
|
|
4
4
|
<div id="plaid-data"
|
5
5
|
data-client-name="<%= client_name %>"
|
6
|
-
data-env="<%= Rails.env.production? ? "production" : "
|
6
|
+
data-env="<%= Rails.env.production? ? "production" : "sandbox"%>"
|
7
7
|
data-key="<%= PlaidRails.public_key %>"
|
8
8
|
data-webhook="<%= PlaidRails.webhook %>"
|
9
9
|
data-owner-type="<%= owner.class.name %>"
|
data/config/routes.rb
CHANGED
@@ -0,0 +1,12 @@
|
|
1
|
+
class ApiUpdate < ActiveRecord::Migration
|
2
|
+
def change
|
3
|
+
add_column :plaid_rails_webhooks, :item_id, :string
|
4
|
+
add_column :plaid_rails_webhooks, :webhook_type, :string
|
5
|
+
add_column :plaid_rails_webhooks, :webhook_code, :string
|
6
|
+
add_column :plaid_rails_webhooks, :error, :string
|
7
|
+
add_column :plaid_rails_webhooks, :new_transactions, :integer
|
8
|
+
add_column :plaid_rails_webhooks, :removed_transactions, :text
|
9
|
+
add_column :plaid_rails_accounts, :item_id, :string
|
10
|
+
remove_column :plaid_rails_accounts, :token
|
11
|
+
end
|
12
|
+
end
|
@@ -1,12 +1,10 @@
|
|
1
|
-
|
2
|
-
p.customer_id = Rails.application.secrets[:plaid][:customer_id]
|
3
|
-
p.secret = Rails.application.secrets[:plaid][:secret]
|
4
|
-
p.environment_location = Rails.env.production? ? 'https://api.plaid.com/' : 'https://tartan.plaid.com/'
|
5
|
-
end
|
1
|
+
|
6
2
|
PlaidRails.configure do |config|
|
3
|
+
config.client_id = Rails.application.secrets[:plaid][:client_id]
|
4
|
+
config.secret = Rails.application.secrets[:plaid][:secret]
|
7
5
|
config.public_key = Rails.application.secrets[:plaid][:public_key]
|
8
6
|
config.longtail = true
|
9
|
-
config.env = Rails.env.production? ? "production" : "
|
7
|
+
config.env = Rails.env.production? ? "production" : "sandbox"
|
10
8
|
config.webhook = 'https://my.app.com/plaid/webhooks'
|
11
9
|
|
12
10
|
# https://plaid.com/docs/#webhook
|
data/lib/plaid_rails.rb
CHANGED
data/lib/plaid_rails/event.rb
CHANGED
@@ -12,16 +12,16 @@ module PlaidRails
|
|
12
12
|
alias :setup :configure
|
13
13
|
|
14
14
|
def instrument(event)
|
15
|
-
name = case event.
|
16
|
-
when
|
15
|
+
name = case event.webhook_code
|
16
|
+
when 'INITIAL_UPDATE'
|
17
17
|
"transactions.initial"
|
18
|
-
when
|
18
|
+
when 'HISTORICAL_UPDATE'
|
19
19
|
"transactions.new"
|
20
|
-
when
|
20
|
+
when 'DEFAULT_UPDATE'
|
21
21
|
"transactions.interval"
|
22
|
-
when
|
22
|
+
when 'TRANSACTIONS_REMOVED'
|
23
23
|
"transactions.removed"
|
24
|
-
when
|
24
|
+
when 'WEBHOOK_UPDATE_ACKNOWLEDGED'
|
25
25
|
"webhook.updated"
|
26
26
|
else
|
27
27
|
"plaid.error"
|
data/lib/plaid_rails/version.rb
CHANGED
@@ -4,8 +4,12 @@ module PlaidRails
|
|
4
4
|
describe AccountsController do
|
5
5
|
routes { PlaidRails::Engine.routes }
|
6
6
|
let(:account){create(:account)}
|
7
|
-
let(:public_token){
|
8
|
-
let(:
|
7
|
+
let(:public_token){create_public_token}
|
8
|
+
let(:client){Plaid::Client.new(env: PlaidRails.env,
|
9
|
+
client_id: PlaidRails.client_id,
|
10
|
+
secret: PlaidRails.secret,
|
11
|
+
public_key: PlaidRails.public_key)}
|
12
|
+
let(:access_token){create_access_token}
|
9
13
|
|
10
14
|
it "get index" do
|
11
15
|
get :index, account:{owner_id: 1}
|
@@ -15,20 +19,21 @@ module PlaidRails
|
|
15
19
|
end
|
16
20
|
|
17
21
|
it "get new" do
|
18
|
-
get :new, account:{access_token:
|
22
|
+
get :new, account:{access_token: access_token, name:'Wells Fargo', type: 'wells',
|
19
23
|
owner_id: "1", owner_type: "User"}
|
20
24
|
expect(response).to be_success
|
21
25
|
expect(assigns(:plaid_accounts)).to_not be_nil
|
26
|
+
expect(assigns(:plaid_accounts).first.name).to eq('Plaid Checking')
|
22
27
|
end
|
23
28
|
|
24
29
|
it "can create" do
|
25
|
-
accounts =
|
26
|
-
post :create, account: {access_token:
|
30
|
+
accounts = client.accounts.get(access_token).accounts.map{|a| a.account_id}
|
31
|
+
post :create, account: {access_token: access_token, account_ids: accounts,
|
27
32
|
name:'Wells Fargo', type: 'wells', owner_id: "1", owner_type: "User",
|
28
33
|
token: public_token}
|
29
34
|
expect(response).to be_success
|
30
35
|
expect(assigns(:plaid_accounts).size).to eq 4
|
31
|
-
expect(assigns(:plaid_accounts).first.
|
36
|
+
expect(assigns(:plaid_accounts).first.name).to eq('Plaid Checking')
|
32
37
|
end
|
33
38
|
|
34
39
|
it "can destroy" do
|
@@ -36,13 +41,6 @@ module PlaidRails
|
|
36
41
|
expect(response).to be_success
|
37
42
|
expect(assigns(:plaid_account)).to eq account
|
38
43
|
end
|
39
|
-
|
40
|
-
# it {
|
41
|
-
# should permit(:access_token, :type,:name,:owner_id,:owner_type,:account_id).
|
42
|
-
# for(:create, params: {access_token: 'test_wells', account_id: '1',
|
43
|
-
# name: 'name'})}
|
44
|
-
# it {
|
45
|
-
# should permit(:token, :type,:name,:owner_id,:owner_type).
|
46
|
-
# for(:new, verb: :get, params: {access_token: 'test_wells'})}
|
44
|
+
|
47
45
|
end
|
48
46
|
end
|