zen-plaid 0.0.2
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 +7 -0
- data/.gitignore +22 -0
- data/.rspec +1 -0
- data/.travis.yml +7 -0
- data/Gemfile +2 -0
- data/LICENSE +20 -0
- data/README.md +7 -0
- data/Rakefile +6 -0
- data/lib/zen-plaid/auth.rb +7 -0
- data/lib/zen-plaid/balance.rb +7 -0
- data/lib/zen-plaid/category.rb +11 -0
- data/lib/zen-plaid/configuration.rb +23 -0
- data/lib/zen-plaid/connect.rb +15 -0
- data/lib/zen-plaid/entity.rb +7 -0
- data/lib/zen-plaid/institution.rb +11 -0
- data/lib/zen-plaid/util.rb +67 -0
- data/lib/zen-plaid/version.rb +3 -0
- data/lib/zen-plaid.rb +79 -0
- data/spec/auth_spec.rb +170 -0
- data/spec/balance_spec.rb +17 -0
- data/spec/category_spec.rb +15 -0
- data/spec/connect_spec.rb +251 -0
- data/spec/entity_spec.rb +9 -0
- data/spec/institution_spec.rb +15 -0
- data/spec/spec_helper.rb +4 -0
- data/zen-plaid.gemspec +19 -0
- metadata +125 -0
checksums.yaml
ADDED
@@ -0,0 +1,7 @@
|
|
1
|
+
---
|
2
|
+
SHA1:
|
3
|
+
metadata.gz: a6b519922fa379a6daeb4daab3532af7ce63fa46
|
4
|
+
data.tar.gz: cf7ee2f343ab48afc87a17ce65b5edca75333e40
|
5
|
+
SHA512:
|
6
|
+
metadata.gz: 00ad929ef2b22e9c452b44d53c125b3921dc321332e376adcef981c3d517c72a27c626c43cd34756b6321eb85b7ba3e1ca76ce7f398d671cbfac0d1a9bb333ca
|
7
|
+
data.tar.gz: 05df053ed9761ecf194dd22c25a2a0cc6b1df1253b449540c3e8d8568359aaf11fbb5c82c6554803d961d3e4029ac88d86c841c41e16e4a7bcc055b569639800
|
data/.gitignore
ADDED
@@ -0,0 +1,22 @@
|
|
1
|
+
*.gem
|
2
|
+
*.rbc
|
3
|
+
.bundle
|
4
|
+
.config
|
5
|
+
.yardoc
|
6
|
+
Gemfile.lock
|
7
|
+
InstalledFiles
|
8
|
+
_yardoc
|
9
|
+
coverage
|
10
|
+
doc/
|
11
|
+
lib/bundler/man
|
12
|
+
pkg
|
13
|
+
rdoc
|
14
|
+
spec/reports
|
15
|
+
test/tmp
|
16
|
+
test/version_tmp
|
17
|
+
tmp
|
18
|
+
*.bundle
|
19
|
+
*.so
|
20
|
+
*.o
|
21
|
+
*.a
|
22
|
+
mkmf.log
|
data/.rspec
ADDED
@@ -0,0 +1 @@
|
|
1
|
+
--color
|
data/.travis.yml
ADDED
data/Gemfile
ADDED
data/LICENSE
ADDED
@@ -0,0 +1,20 @@
|
|
1
|
+
The MIT License (MIT)
|
2
|
+
|
3
|
+
Copyright (c) 2014 Sean McCann
|
4
|
+
|
5
|
+
Permission is hereby granted, free of charge, to any person obtaining a copy of
|
6
|
+
this software and associated documentation files (the "Software"), to deal in
|
7
|
+
the Software without restriction, including without limitation the rights to
|
8
|
+
use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of
|
9
|
+
the Software, and to permit persons to whom the Software is furnished to do so,
|
10
|
+
subject to the following conditions:
|
11
|
+
|
12
|
+
The above copyright notice and this permission notice shall be included in all
|
13
|
+
copies or substantial portions of the Software.
|
14
|
+
|
15
|
+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
16
|
+
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS
|
17
|
+
FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR
|
18
|
+
COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER
|
19
|
+
IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
|
20
|
+
CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
data/README.md
ADDED
@@ -0,0 +1,7 @@
|
|
1
|
+
[](https://travis-ci.org/seanmccann/zen-plaid)
|
2
|
+
|
3
|
+
# zen-plaid
|
4
|
+
|
5
|
+
A zen Ruby gem wrapper for the Plaid API. For more details, please see the [full API documentation](https://plaid.com/docs).
|
6
|
+
|
7
|
+
The original gem sucked and this one rocks. Thanks to Stripe for borrowing some RestClient wrapper code and ideas.
|
data/Rakefile
ADDED
@@ -0,0 +1,23 @@
|
|
1
|
+
module Plaid
|
2
|
+
class << self
|
3
|
+
attr_accessor :configuration
|
4
|
+
end
|
5
|
+
|
6
|
+
def self.configuration
|
7
|
+
@configuration ||= Configuration.new
|
8
|
+
end
|
9
|
+
|
10
|
+
def self.configure
|
11
|
+
yield(configuration)
|
12
|
+
end
|
13
|
+
|
14
|
+
class Configuration
|
15
|
+
attr_accessor :environment, :client_id, :secret
|
16
|
+
|
17
|
+
def initialize
|
18
|
+
@environment ||= 'development'
|
19
|
+
@client_id ||= 'test_id'
|
20
|
+
@secret ||= 'test_secret'
|
21
|
+
end
|
22
|
+
end
|
23
|
+
end
|
@@ -0,0 +1,15 @@
|
|
1
|
+
module Plaid
|
2
|
+
class Connect
|
3
|
+
def self.get(params)
|
4
|
+
Plaid.request(:post, '/connect/get', params)
|
5
|
+
end
|
6
|
+
|
7
|
+
def self.add(params)
|
8
|
+
Plaid.request(:post, '/connect', params)
|
9
|
+
end
|
10
|
+
|
11
|
+
def self.mfa_step(params)
|
12
|
+
Plaid.request(:post, '/connect/step', params)
|
13
|
+
end
|
14
|
+
end
|
15
|
+
end
|
@@ -0,0 +1,67 @@
|
|
1
|
+
module Plaid
|
2
|
+
module Util
|
3
|
+
def self.objects_to_ids(h)
|
4
|
+
case h
|
5
|
+
when APIResource
|
6
|
+
h.id
|
7
|
+
when Hash
|
8
|
+
res = {}
|
9
|
+
h.each { |k, v| res[k] = objects_to_ids(v) unless v.nil? }
|
10
|
+
res
|
11
|
+
when Array
|
12
|
+
h.map { |v| objects_to_ids(v) }
|
13
|
+
else
|
14
|
+
h
|
15
|
+
end
|
16
|
+
end
|
17
|
+
|
18
|
+
def self.symbolize_names(object)
|
19
|
+
case object
|
20
|
+
when Hash
|
21
|
+
new = {}
|
22
|
+
object.each do |key, value|
|
23
|
+
key = (key.to_sym rescue key) || key
|
24
|
+
new[key] = symbolize_names(value)
|
25
|
+
end
|
26
|
+
new
|
27
|
+
when Array
|
28
|
+
object.map { |value| symbolize_names(value) }
|
29
|
+
else
|
30
|
+
object
|
31
|
+
end
|
32
|
+
end
|
33
|
+
|
34
|
+
def self.url_encode(key)
|
35
|
+
URI.escape(key.to_s, Regexp.new("[^#{URI::PATTERN::UNRESERVED}]"))
|
36
|
+
end
|
37
|
+
|
38
|
+
def self.flatten_params(params, parent_key=nil)
|
39
|
+
result = []
|
40
|
+
params.each do |key, value|
|
41
|
+
calculated_key = parent_key ? "#{parent_key}[#{url_encode(key)}]" : url_encode(key)
|
42
|
+
if value.is_a?(Hash)
|
43
|
+
result += flatten_params(value, calculated_key)
|
44
|
+
elsif value.is_a?(Array)
|
45
|
+
result += flatten_params_array(value, calculated_key)
|
46
|
+
else
|
47
|
+
result << [calculated_key, value]
|
48
|
+
end
|
49
|
+
end
|
50
|
+
result
|
51
|
+
end
|
52
|
+
|
53
|
+
def self.flatten_params_array(value, calculated_key)
|
54
|
+
result = []
|
55
|
+
value.each do |elem|
|
56
|
+
if elem.is_a?(Hash)
|
57
|
+
result += flatten_params(elem, calculated_key)
|
58
|
+
elsif elem.is_a?(Array)
|
59
|
+
result += flatten_params_array(elem, calculated_key)
|
60
|
+
else
|
61
|
+
result << ["#{calculated_key}[]", elem]
|
62
|
+
end
|
63
|
+
end
|
64
|
+
result
|
65
|
+
end
|
66
|
+
end
|
67
|
+
end
|
data/lib/zen-plaid.rb
ADDED
@@ -0,0 +1,79 @@
|
|
1
|
+
require 'rest_client'
|
2
|
+
require 'oj'
|
3
|
+
|
4
|
+
require 'zen-plaid/version'
|
5
|
+
require 'zen-plaid/configuration'
|
6
|
+
require 'zen-plaid/util'
|
7
|
+
|
8
|
+
require 'zen-plaid/auth'
|
9
|
+
require 'zen-plaid/connect'
|
10
|
+
require 'zen-plaid/institution'
|
11
|
+
require 'zen-plaid/category'
|
12
|
+
require 'zen-plaid/entity'
|
13
|
+
require 'zen-plaid/balance'
|
14
|
+
|
15
|
+
module Plaid
|
16
|
+
def self.uri_encode(params)
|
17
|
+
Util.flatten_params(params).
|
18
|
+
map { |k,v| "#{k}=#{Util.url_encode(v)}" }.join('&')
|
19
|
+
end
|
20
|
+
|
21
|
+
def self.handle_api_error(rcode, rbody)
|
22
|
+
error_obj = Util.symbolize_names(Oj.load(rbody))
|
23
|
+
|
24
|
+
{code: rcode, error: error_obj}
|
25
|
+
end
|
26
|
+
|
27
|
+
def self.parse(response)
|
28
|
+
begin
|
29
|
+
response = Util.symbolize_names(Oj.load(response.body))
|
30
|
+
rescue Oj::ParseError
|
31
|
+
raise general_api_error(response.code, response.body)
|
32
|
+
end
|
33
|
+
end
|
34
|
+
|
35
|
+
def self.api_url(url='')
|
36
|
+
api_base + url
|
37
|
+
end
|
38
|
+
|
39
|
+
def self.api_base
|
40
|
+
if Plaid.configuration.environment == 'production'
|
41
|
+
'https://api.plaid.com/'
|
42
|
+
else
|
43
|
+
'https://tartan.plaid.com/'
|
44
|
+
end
|
45
|
+
end
|
46
|
+
|
47
|
+
def self.request(method, url, params={}, headers={})
|
48
|
+
request_opts = { verify_ssl: false }
|
49
|
+
url = api_url(url)
|
50
|
+
params = params.merge!(auth)
|
51
|
+
|
52
|
+
case method.to_s.downcase.to_sym
|
53
|
+
when :get, :head, :delete
|
54
|
+
# Make params into GET parameters
|
55
|
+
url += "#{URI.parse(url).query ? '&' : '?'}#{uri_encode(params)}" if params && params.any?
|
56
|
+
payload = nil
|
57
|
+
else
|
58
|
+
payload = uri_encode(params)
|
59
|
+
end
|
60
|
+
|
61
|
+
request_opts.update(headers: headers,
|
62
|
+
method: method,
|
63
|
+
open_timeout: 30,
|
64
|
+
payload: payload,
|
65
|
+
url: url,
|
66
|
+
timeout: 80)
|
67
|
+
|
68
|
+
begin
|
69
|
+
response = RestClient::Request.execute(request_opts)
|
70
|
+
return {code: response.code, message: parse(response)}
|
71
|
+
rescue RestClient::ExceptionWithResponse => e
|
72
|
+
return handle_api_error(e.http_code, e.http_body)
|
73
|
+
end
|
74
|
+
end
|
75
|
+
|
76
|
+
def self.auth
|
77
|
+
{client_id: Plaid.configuration.client_id, secret: Plaid.configuration.secret}
|
78
|
+
end
|
79
|
+
end
|
data/spec/auth_spec.rb
ADDED
@@ -0,0 +1,170 @@
|
|
1
|
+
require 'spec_helper.rb'
|
2
|
+
|
3
|
+
describe Plaid::Auth do
|
4
|
+
context 'unsupported institution' do
|
5
|
+
it "returns 404 http code" do
|
6
|
+
connection = Plaid::Auth.add({type: 'amex', username: 'plaid_test', password: 'plaid_good'})
|
7
|
+
expect(connection[:code]).to eq(404)
|
8
|
+
end
|
9
|
+
end
|
10
|
+
|
11
|
+
context 'missing password' do
|
12
|
+
it "returns 400 http code" do
|
13
|
+
connection = Plaid::Auth.add({type: 'bofa', username: 'plaid_test'})
|
14
|
+
expect(connection[:code]).to eq(400)
|
15
|
+
end
|
16
|
+
end
|
17
|
+
|
18
|
+
context 'pin when its not needed' do
|
19
|
+
it "returns 200 http code" do
|
20
|
+
connection = Plaid::Auth.add({type: 'schwab', username: 'plaid_test', password: 'plaid_good', pin: 1234})
|
21
|
+
expect(connection[:code]).to eq(200)
|
22
|
+
end
|
23
|
+
end
|
24
|
+
|
25
|
+
context 'forget pin when its needed' do
|
26
|
+
it "returns 402 http code" do
|
27
|
+
connection = Plaid::Auth.add({type: 'usaa', username: 'plaid_test', password: 'plaid_good'})
|
28
|
+
expect(connection[:code]).to eq(402)
|
29
|
+
end
|
30
|
+
end
|
31
|
+
|
32
|
+
context 'wrong credentials with no mfa' do
|
33
|
+
it "returns 402 http code" do
|
34
|
+
connection = Plaid::Auth.add({type: 'schwab', username: 'plaid_test', password: 'plaid_bad'})
|
35
|
+
expect(connection[:code]).to eq(402)
|
36
|
+
end
|
37
|
+
|
38
|
+
it "returns error message" do
|
39
|
+
connection = Plaid::Auth.add({type: 'schwab', username: 'plaid_test', password: 'plaid_bad'})
|
40
|
+
expect(connection[:error][:message]).to eq('invalid credentials')
|
41
|
+
end
|
42
|
+
|
43
|
+
it "returns error resolution" do
|
44
|
+
connection = Plaid::Auth.add({type: 'schwab', username: 'plaid_test', password: 'plaid_bad'})
|
45
|
+
expect(connection[:error][:resolve]).to eq('The username or password provided were not correct.')
|
46
|
+
end
|
47
|
+
end
|
48
|
+
|
49
|
+
context 'wrong credentials with mfa' do
|
50
|
+
it "returns 402 http code" do
|
51
|
+
connection = Plaid::Auth.add({type: 'chase', username: 'plaid_test', password: 'plaid_bad'})
|
52
|
+
expect(connection[:code]).to eq(402)
|
53
|
+
end
|
54
|
+
|
55
|
+
it "returns error message" do
|
56
|
+
connection = Plaid::Auth.add({type: 'chase', username: 'plaid_test', password: 'plaid_bad'})
|
57
|
+
expect(connection[:error][:message]).to eq('invalid credentials')
|
58
|
+
end
|
59
|
+
|
60
|
+
it "returns error resolution" do
|
61
|
+
connection = Plaid::Auth.add({type: 'chase', username: 'plaid_test', password: 'plaid_bad'})
|
62
|
+
expect(connection[:error][:resolve]).to eq('The username or password provided were not correct.')
|
63
|
+
end
|
64
|
+
end
|
65
|
+
|
66
|
+
context 'correct credentials with no mfa' do
|
67
|
+
it "returns 200 http code" do
|
68
|
+
connection = Plaid::Auth.add({type: 'schwab', username: 'plaid_test', password: 'plaid_good'})
|
69
|
+
expect(connection[:code]).to eq(200)
|
70
|
+
end
|
71
|
+
|
72
|
+
it "returns accounts" do
|
73
|
+
connection = Plaid::Auth.add({type: 'schwab', username: 'plaid_test', password: 'plaid_good'})
|
74
|
+
expect(connection[:message]).to have_key(:accounts)
|
75
|
+
end
|
76
|
+
end
|
77
|
+
|
78
|
+
# context 'correct credentials with pin' do
|
79
|
+
# it "returns 200 http code" do
|
80
|
+
# connection = Plaid::Auth.add({type: 'usaa', username: 'plaid_test', password: 'plaid_good', pin: 1234})
|
81
|
+
# expect(connection[:code]).to eq(200)
|
82
|
+
# end
|
83
|
+
|
84
|
+
# it "returns accounts" do
|
85
|
+
# connection = Plaid::Auth.add({type: 'usaa', username: 'plaid_test', password: 'plaid_good', pin: 1234})
|
86
|
+
# expect(connection[:message]).to have_key(:accounts)
|
87
|
+
# end
|
88
|
+
|
89
|
+
# it "returns transactions" do
|
90
|
+
# connection = Plaid::Auth.add({type: 'usaa', username: 'plaid_test', password: 'plaid_good', pin: 1234})
|
91
|
+
# expect(connection[:message]).to have_key(:transactions)
|
92
|
+
# end
|
93
|
+
# end
|
94
|
+
|
95
|
+
context 'correct credentials with default chase mfa' do
|
96
|
+
it "returns 201 http code" do
|
97
|
+
connection = Plaid::Auth.add({type: 'chase', username: 'plaid_test', password: 'plaid_good'})
|
98
|
+
expect(connection[:code]).to eq(201)
|
99
|
+
end
|
100
|
+
|
101
|
+
it "returns access_token" do
|
102
|
+
connection = Plaid::Auth.add({type: 'chase', username: 'plaid_selections', password: 'plaid_good'})
|
103
|
+
expect(connection[:message]).to have_key(:access_token)
|
104
|
+
end
|
105
|
+
|
106
|
+
it "returns mfa type" do
|
107
|
+
connection = Plaid::Auth.add({type: 'chase', username: 'plaid_selections', password: 'plaid_good'})
|
108
|
+
expect(connection[:message][:type]).to eq("device")
|
109
|
+
end
|
110
|
+
|
111
|
+
it "returns mfa message" do
|
112
|
+
connection = Plaid::Auth.add({type: 'chase', username: 'plaid_selections', password: 'plaid_good'})
|
113
|
+
expect(connection[:message][:mfa][:message]).to eq("Code sent to t..t@plaid.com")
|
114
|
+
end
|
115
|
+
end
|
116
|
+
|
117
|
+
context 'correct credentials with chase mfa choice' do
|
118
|
+
it "returns 201 http code" do
|
119
|
+
connection = Plaid::Auth.add({type: 'chase', username: 'plaid_selections', password: 'plaid_good', options: {list: true}})
|
120
|
+
expect(connection[:code]).to eq(201)
|
121
|
+
end
|
122
|
+
|
123
|
+
it "returns access_token" do
|
124
|
+
connection = Plaid::Auth.add({type: 'chase', username: 'plaid_selections', password: 'plaid_good', options: {list: true}})
|
125
|
+
expect(connection[:message]).to have_key(:access_token)
|
126
|
+
end
|
127
|
+
|
128
|
+
it "returns mfa type as list" do
|
129
|
+
connection = Plaid::Auth.add({type: 'chase', username: 'plaid_selections', password: 'plaid_good', options: {list: true}})
|
130
|
+
expect(connection[:message][:type]).to eq("list")
|
131
|
+
end
|
132
|
+
|
133
|
+
it "returns mfa list array" do
|
134
|
+
connection = Plaid::Auth.add({type: 'chase', username: 'plaid_selections', password: 'plaid_good', options: {list: true}})
|
135
|
+
expect(connection[:message][:mfa]).to be_an(Array)
|
136
|
+
end
|
137
|
+
end
|
138
|
+
|
139
|
+
context 'correct credentials with citi bank' do
|
140
|
+
it "returns 201 http code" do
|
141
|
+
connection = Plaid::Auth.add({type: 'citi', username: 'plaid_selections', password: 'plaid_good'})
|
142
|
+
expect(connection[:code]).to eq(201)
|
143
|
+
end
|
144
|
+
|
145
|
+
it "returns access_token" do
|
146
|
+
connection = Plaid::Auth.add({type: 'citi', username: 'plaid_selections', password: 'plaid_good'})
|
147
|
+
expect(connection[:message]).to have_key(:access_token)
|
148
|
+
end
|
149
|
+
|
150
|
+
it "returns mfa type" do
|
151
|
+
connection = Plaid::Auth.add({type: 'citi', username: 'plaid_selections', password: 'plaid_good'})
|
152
|
+
expect(connection[:message][:type]).to eq("selections")
|
153
|
+
end
|
154
|
+
|
155
|
+
it "returns mfa list array" do
|
156
|
+
connection = Plaid::Auth.add({type: 'citi', username: 'plaid_selections', password: 'plaid_good'})
|
157
|
+
expect(connection[:message][:mfa]).to be_an(Array)
|
158
|
+
end
|
159
|
+
|
160
|
+
it "returns mfa questions" do
|
161
|
+
connection = Plaid::Auth.add({type: 'citi', username: 'plaid_selections', password: 'plaid_good'})
|
162
|
+
expect(connection[:message][:mfa][0]).to have_key(:question)
|
163
|
+
end
|
164
|
+
|
165
|
+
it "returns mfa question selections" do
|
166
|
+
connection = Plaid::Auth.add({type: 'citi', username: 'plaid_selections', password: 'plaid_good'})
|
167
|
+
expect(connection[:message][:mfa][0]).to have_key(:answers)
|
168
|
+
end
|
169
|
+
end
|
170
|
+
end
|
@@ -0,0 +1,17 @@
|
|
1
|
+
require 'spec_helper.rb'
|
2
|
+
|
3
|
+
describe Plaid::Balance do
|
4
|
+
describe "#get" do
|
5
|
+
it "returns 200 http code" do
|
6
|
+
expect(Plaid::Balance.get('test')[:code]).to eq(200)
|
7
|
+
end
|
8
|
+
|
9
|
+
it "returns accounts" do
|
10
|
+
expect(Plaid::Balance.get('test')[:message][:accounts]).to be_an(Array)
|
11
|
+
end
|
12
|
+
|
13
|
+
it "returns accounts with balances" do
|
14
|
+
expect(Plaid::Balance.get('test')[:message][:accounts][0]).to have_key(:balance)
|
15
|
+
end
|
16
|
+
end
|
17
|
+
end
|
@@ -0,0 +1,15 @@
|
|
1
|
+
require 'spec_helper.rb'
|
2
|
+
|
3
|
+
describe Plaid::Category do
|
4
|
+
describe "#all" do
|
5
|
+
it "returns categories" do
|
6
|
+
expect(Plaid::Category.all).to be_an(Array)
|
7
|
+
end
|
8
|
+
end
|
9
|
+
|
10
|
+
describe "#find" do
|
11
|
+
it "finds American Express" do
|
12
|
+
expect(Plaid::Category.find('52544965f71e87d007000049')[:hierarchy].first).to eq('Food and Drink')
|
13
|
+
end
|
14
|
+
end
|
15
|
+
end
|
@@ -0,0 +1,251 @@
|
|
1
|
+
require 'spec_helper.rb'
|
2
|
+
|
3
|
+
describe Plaid::Connect do
|
4
|
+
describe "#get" do
|
5
|
+
it "returns 200 http code" do
|
6
|
+
connection = Plaid::Connect.get({access_token: 'test', type: 'chase'})
|
7
|
+
expect(connection[:code]).to eq(200)
|
8
|
+
end
|
9
|
+
|
10
|
+
it "returns transactions" do
|
11
|
+
connection = Plaid::Connect.get({access_token: 'test', type: 'chase'})
|
12
|
+
expect(connection[:message]).to have_key(:transactions)
|
13
|
+
end
|
14
|
+
|
15
|
+
it "returns accounts" do
|
16
|
+
connection = Plaid::Connect.get({access_token: 'test', type: 'chase'})
|
17
|
+
expect(connection[:message]).to have_key(:accounts)
|
18
|
+
end
|
19
|
+
end
|
20
|
+
|
21
|
+
describe "#mfa_step" do
|
22
|
+
context 'correct mfa reply code' do
|
23
|
+
it "returns 200 http code" do
|
24
|
+
connection = Plaid::Connect.mfa_step({access_token: 'test', type: 'chase', mfa: '1234'})
|
25
|
+
expect(connection[:code]).to eq(200)
|
26
|
+
end
|
27
|
+
end
|
28
|
+
|
29
|
+
context 'wrong mfa reply code' do
|
30
|
+
it "returns 402 http code" do
|
31
|
+
connection = Plaid::Connect.mfa_step({access_token: 'test', type: 'chase', mfa: '666'})
|
32
|
+
expect(connection[:code]).to eq(402)
|
33
|
+
end
|
34
|
+
|
35
|
+
it "returns error message" do
|
36
|
+
connection = Plaid::Connect.mfa_step({access_token: 'test', type: 'chase', mfa: '666'})
|
37
|
+
expect(connection[:error][:message]).to eq("invalid mfa")
|
38
|
+
end
|
39
|
+
end
|
40
|
+
|
41
|
+
context 'correct mfa reply answer' do
|
42
|
+
it "returns 200 http code" do
|
43
|
+
connection = Plaid::Connect.mfa_step({access_token: 'test', type: 'us', mfa: 'tomato'})
|
44
|
+
expect(connection[:code]).to eq(200)
|
45
|
+
end
|
46
|
+
end
|
47
|
+
|
48
|
+
context 'wrong mfa reply answer' do
|
49
|
+
it "returns 402 http code" do
|
50
|
+
connection = Plaid::Connect.mfa_step({access_token: 'test', type: 'us', mfa: 'wrong'})
|
51
|
+
expect(connection[:code]).to eq(402)
|
52
|
+
end
|
53
|
+
|
54
|
+
it "returns error message" do
|
55
|
+
connection = Plaid::Connect.mfa_step({access_token: 'test', type: 'us', mfa: 'wrong'})
|
56
|
+
expect(connection[:error][:message]).to eq("invalid mfa")
|
57
|
+
end
|
58
|
+
end
|
59
|
+
|
60
|
+
context 'correct mfa reply selections' do
|
61
|
+
it "returns 200 http code" do
|
62
|
+
connection = Plaid::Connect.mfa_step({access_token: 'test', type: 'citi', credentials: {pin: 1234}})
|
63
|
+
expect(connection[:code]).to eq(200)
|
64
|
+
end
|
65
|
+
end
|
66
|
+
end
|
67
|
+
|
68
|
+
describe "#add" do
|
69
|
+
context 'missing password' do
|
70
|
+
it "returns 400 http code" do
|
71
|
+
connection = Plaid::Connect.add({type: 'amex', username: 'plaid_test'})
|
72
|
+
expect(connection[:code]).to eq(400)
|
73
|
+
end
|
74
|
+
end
|
75
|
+
|
76
|
+
context 'pin when its not needed' do
|
77
|
+
it "returns 200 http code" do
|
78
|
+
connection = Plaid::Connect.add({type: 'amex', username: 'plaid_test', password: 'plaid_good', pin: 1234})
|
79
|
+
expect(connection[:code]).to eq(200)
|
80
|
+
end
|
81
|
+
end
|
82
|
+
|
83
|
+
context 'forget pin when its needed' do
|
84
|
+
it "returns 402 http code" do
|
85
|
+
connection = Plaid::Connect.add({type: 'usaa', username: 'plaid_test', password: 'plaid_good'})
|
86
|
+
expect(connection[:code]).to eq(402)
|
87
|
+
end
|
88
|
+
end
|
89
|
+
|
90
|
+
context 'locked credentials with no mfa' do
|
91
|
+
it "returns 402 http code" do
|
92
|
+
connection = Plaid::Connect.add({type: 'amex', username: 'plaid_test', password: 'plaid_locked'})
|
93
|
+
expect(connection[:code]).to eq(402)
|
94
|
+
end
|
95
|
+
|
96
|
+
it "returns error message" do
|
97
|
+
connection = Plaid::Connect.add({type: 'amex', username: 'plaid_test', password: 'plaid_locked'})
|
98
|
+
expect(connection[:error][:message]).to eq('account locked')
|
99
|
+
end
|
100
|
+
|
101
|
+
it "returns error resolution" do
|
102
|
+
connection = Plaid::Connect.add({type: 'amex', username: 'plaid_test', password: 'plaid_locked'})
|
103
|
+
expect(connection[:error][:resolve]).to include('The account is locked.')
|
104
|
+
end
|
105
|
+
end
|
106
|
+
|
107
|
+
context 'wrong credentials with no mfa' do
|
108
|
+
it "returns 402 http code" do
|
109
|
+
connection = Plaid::Connect.add({type: 'amex', username: 'plaid_test', password: 'plaid_bad'})
|
110
|
+
expect(connection[:code]).to eq(402)
|
111
|
+
end
|
112
|
+
|
113
|
+
it "returns error message" do
|
114
|
+
connection = Plaid::Connect.add({type: 'amex', username: 'plaid_test', password: 'plaid_bad'})
|
115
|
+
expect(connection[:error][:message]).to eq('invalid credentials')
|
116
|
+
end
|
117
|
+
|
118
|
+
it "returns error resolution" do
|
119
|
+
connection = Plaid::Connect.add({type: 'amex', username: 'plaid_test', password: 'plaid_bad'})
|
120
|
+
expect(connection[:error][:resolve]).to eq('The username or password provided were not correct.')
|
121
|
+
end
|
122
|
+
end
|
123
|
+
|
124
|
+
context 'wrong credentials with mfa' do
|
125
|
+
it "returns 402 http code" do
|
126
|
+
connection = Plaid::Connect.add({type: 'chase', username: 'plaid_test', password: 'plaid_bad'})
|
127
|
+
expect(connection[:code]).to eq(402)
|
128
|
+
end
|
129
|
+
|
130
|
+
it "returns error message" do
|
131
|
+
connection = Plaid::Connect.add({type: 'chase', username: 'plaid_test', password: 'plaid_bad'})
|
132
|
+
expect(connection[:error][:message]).to eq('invalid credentials')
|
133
|
+
end
|
134
|
+
|
135
|
+
it "returns error resolution" do
|
136
|
+
connection = Plaid::Connect.add({type: 'chase', username: 'plaid_test', password: 'plaid_bad'})
|
137
|
+
expect(connection[:error][:resolve]).to eq('The username or password provided were not correct.')
|
138
|
+
end
|
139
|
+
end
|
140
|
+
|
141
|
+
context 'correct credentials with no mfa' do
|
142
|
+
it "returns 200 http code" do
|
143
|
+
connection = Plaid::Connect.add({type: 'amex', username: 'plaid_test', password: 'plaid_good'})
|
144
|
+
expect(connection[:code]).to eq(200)
|
145
|
+
end
|
146
|
+
|
147
|
+
it "returns accounts" do
|
148
|
+
connection = Plaid::Connect.add({type: 'amex', username: 'plaid_test', password: 'plaid_good'})
|
149
|
+
expect(connection[:message]).to have_key(:accounts)
|
150
|
+
end
|
151
|
+
|
152
|
+
it "returns transactions" do
|
153
|
+
connection = Plaid::Connect.add({type: 'amex', username: 'plaid_test', password: 'plaid_good'})
|
154
|
+
expect(connection[:message]).to have_key(:transactions)
|
155
|
+
end
|
156
|
+
end
|
157
|
+
|
158
|
+
context 'correct credentials with pin' do
|
159
|
+
it "returns 200 http code" do
|
160
|
+
connection = Plaid::Connect.add({type: 'amex', username: 'plaid_test', password: 'plaid_good', pin: 1234})
|
161
|
+
expect(connection[:code]).to eq(200)
|
162
|
+
end
|
163
|
+
|
164
|
+
it "returns accounts" do
|
165
|
+
connection = Plaid::Connect.add({type: 'amex', username: 'plaid_test', password: 'plaid_good', pin: 1234})
|
166
|
+
expect(connection[:message]).to have_key(:accounts)
|
167
|
+
end
|
168
|
+
|
169
|
+
it "returns transactions" do
|
170
|
+
connection = Plaid::Connect.add({type: 'amex', username: 'plaid_test', password: 'plaid_good', pin: 1234})
|
171
|
+
expect(connection[:message]).to have_key(:transactions)
|
172
|
+
end
|
173
|
+
end
|
174
|
+
|
175
|
+
context 'correct credentials with default chase mfa' do
|
176
|
+
it "returns 201 http code" do
|
177
|
+
connection = Plaid::Connect.add({type: 'chase', username: 'plaid_test', password: 'plaid_good'})
|
178
|
+
expect(connection[:code]).to eq(201)
|
179
|
+
end
|
180
|
+
|
181
|
+
it "returns access_token" do
|
182
|
+
connection = Plaid::Connect.add({type: 'chase', username: 'plaid_selections', password: 'plaid_good'})
|
183
|
+
expect(connection[:message]).to have_key(:access_token)
|
184
|
+
end
|
185
|
+
|
186
|
+
it "returns mfa type" do
|
187
|
+
connection = Plaid::Connect.add({type: 'chase', username: 'plaid_selections', password: 'plaid_good'})
|
188
|
+
expect(connection[:message][:type]).to eq("device")
|
189
|
+
end
|
190
|
+
|
191
|
+
it "returns mfa message" do
|
192
|
+
connection = Plaid::Connect.add({type: 'chase', username: 'plaid_selections', password: 'plaid_good'})
|
193
|
+
expect(connection[:message][:mfa][:message]).to eq("Code sent to t..t@plaid.com")
|
194
|
+
end
|
195
|
+
end
|
196
|
+
|
197
|
+
context 'correct credentials with chase mfa choice' do
|
198
|
+
it "returns 201 http code" do
|
199
|
+
connection = Plaid::Connect.add({type: 'chase', username: 'plaid_selections', password: 'plaid_good', options: {list: true}})
|
200
|
+
expect(connection[:code]).to eq(201)
|
201
|
+
end
|
202
|
+
|
203
|
+
it "returns access_token" do
|
204
|
+
connection = Plaid::Connect.add({type: 'chase', username: 'plaid_selections', password: 'plaid_good', options: {list: true}})
|
205
|
+
expect(connection[:message]).to have_key(:access_token)
|
206
|
+
end
|
207
|
+
|
208
|
+
it "returns mfa type as list" do
|
209
|
+
connection = Plaid::Connect.add({type: 'chase', username: 'plaid_selections', password: 'plaid_good', options: {list: true}})
|
210
|
+
expect(connection[:message][:type]).to eq("list")
|
211
|
+
end
|
212
|
+
|
213
|
+
it "returns mfa list array" do
|
214
|
+
connection = Plaid::Connect.add({type: 'chase', username: 'plaid_selections', password: 'plaid_good', options: {list: true}})
|
215
|
+
expect(connection[:message][:mfa]).to be_an(Array)
|
216
|
+
end
|
217
|
+
end
|
218
|
+
|
219
|
+
context 'correct credentials with citi bank' do
|
220
|
+
it "returns 201 http code" do
|
221
|
+
connection = Plaid::Connect.add({type: 'citi', username: 'plaid_selections', password: 'plaid_good'})
|
222
|
+
expect(connection[:code]).to eq(201)
|
223
|
+
end
|
224
|
+
|
225
|
+
it "returns access_token" do
|
226
|
+
connection = Plaid::Connect.add({type: 'citi', username: 'plaid_selections', password: 'plaid_good'})
|
227
|
+
expect(connection[:message]).to have_key(:access_token)
|
228
|
+
end
|
229
|
+
|
230
|
+
it "returns mfa type" do
|
231
|
+
connection = Plaid::Connect.add({type: 'citi', username: 'plaid_selections', password: 'plaid_good'})
|
232
|
+
expect(connection[:message][:type]).to eq("selections")
|
233
|
+
end
|
234
|
+
|
235
|
+
it "returns mfa list array" do
|
236
|
+
connection = Plaid::Connect.add({type: 'citi', username: 'plaid_selections', password: 'plaid_good'})
|
237
|
+
expect(connection[:message][:mfa]).to be_an(Array)
|
238
|
+
end
|
239
|
+
|
240
|
+
it "returns mfa questions" do
|
241
|
+
connection = Plaid::Connect.add({type: 'citi', username: 'plaid_selections', password: 'plaid_good'})
|
242
|
+
expect(connection[:message][:mfa][0]).to have_key(:question)
|
243
|
+
end
|
244
|
+
|
245
|
+
it "returns mfa question selections" do
|
246
|
+
connection = Plaid::Connect.add({type: 'citi', username: 'plaid_selections', password: 'plaid_good'})
|
247
|
+
expect(connection[:message][:mfa][0]).to have_key(:answers)
|
248
|
+
end
|
249
|
+
end
|
250
|
+
end
|
251
|
+
end
|
data/spec/entity_spec.rb
ADDED
@@ -0,0 +1,15 @@
|
|
1
|
+
require 'spec_helper.rb'
|
2
|
+
|
3
|
+
describe Plaid::Institution do
|
4
|
+
describe "#all" do
|
5
|
+
it "returns institutions" do
|
6
|
+
expect(Plaid::Institution.all).to be_an(Array)
|
7
|
+
end
|
8
|
+
end
|
9
|
+
|
10
|
+
describe "#find" do
|
11
|
+
it "finds American Express" do
|
12
|
+
expect(Plaid::Institution.find('5301a9d704977c52b60000db')[:name]).to eq('American Express')
|
13
|
+
end
|
14
|
+
end
|
15
|
+
end
|
data/spec/spec_helper.rb
ADDED
data/zen-plaid.gemspec
ADDED
@@ -0,0 +1,19 @@
|
|
1
|
+
$:.unshift(File.join(File.dirname(__FILE__), 'lib'))
|
2
|
+
require 'zen-plaid/version'
|
3
|
+
|
4
|
+
Gem::Specification.new do |s|
|
5
|
+
s.name = 'zen-plaid'
|
6
|
+
s.version = Plaid::VERSION
|
7
|
+
s.date = '2014-10-22'
|
8
|
+
s.summary = 'Plaid Ruby Gem'
|
9
|
+
s.description = 'Ruby Gem wrapper for Plaid API.'
|
10
|
+
s.authors = ['Sean McCann']
|
11
|
+
s.email = 'sean@smccann.com'
|
12
|
+
s.files = `git ls-files`.split("\n")
|
13
|
+
s.homepage = 'https://github.com/seanmccann/zen-plaid'
|
14
|
+
s.license = 'MIT'
|
15
|
+
s.add_runtime_dependency 'rest-client'
|
16
|
+
s.add_runtime_dependency 'oj'
|
17
|
+
s.add_development_dependency 'rake'
|
18
|
+
s.add_development_dependency 'rspec'
|
19
|
+
end
|
metadata
ADDED
@@ -0,0 +1,125 @@
|
|
1
|
+
--- !ruby/object:Gem::Specification
|
2
|
+
name: zen-plaid
|
3
|
+
version: !ruby/object:Gem::Version
|
4
|
+
version: 0.0.2
|
5
|
+
platform: ruby
|
6
|
+
authors:
|
7
|
+
- Sean McCann
|
8
|
+
autorequire:
|
9
|
+
bindir: bin
|
10
|
+
cert_chain: []
|
11
|
+
date: 2014-10-22 00:00:00.000000000 Z
|
12
|
+
dependencies:
|
13
|
+
- !ruby/object:Gem::Dependency
|
14
|
+
name: rest-client
|
15
|
+
requirement: !ruby/object:Gem::Requirement
|
16
|
+
requirements:
|
17
|
+
- - '>='
|
18
|
+
- !ruby/object:Gem::Version
|
19
|
+
version: '0'
|
20
|
+
type: :runtime
|
21
|
+
prerelease: false
|
22
|
+
version_requirements: !ruby/object:Gem::Requirement
|
23
|
+
requirements:
|
24
|
+
- - '>='
|
25
|
+
- !ruby/object:Gem::Version
|
26
|
+
version: '0'
|
27
|
+
- !ruby/object:Gem::Dependency
|
28
|
+
name: oj
|
29
|
+
requirement: !ruby/object:Gem::Requirement
|
30
|
+
requirements:
|
31
|
+
- - '>='
|
32
|
+
- !ruby/object:Gem::Version
|
33
|
+
version: '0'
|
34
|
+
type: :runtime
|
35
|
+
prerelease: false
|
36
|
+
version_requirements: !ruby/object:Gem::Requirement
|
37
|
+
requirements:
|
38
|
+
- - '>='
|
39
|
+
- !ruby/object:Gem::Version
|
40
|
+
version: '0'
|
41
|
+
- !ruby/object:Gem::Dependency
|
42
|
+
name: rake
|
43
|
+
requirement: !ruby/object:Gem::Requirement
|
44
|
+
requirements:
|
45
|
+
- - '>='
|
46
|
+
- !ruby/object:Gem::Version
|
47
|
+
version: '0'
|
48
|
+
type: :development
|
49
|
+
prerelease: false
|
50
|
+
version_requirements: !ruby/object:Gem::Requirement
|
51
|
+
requirements:
|
52
|
+
- - '>='
|
53
|
+
- !ruby/object:Gem::Version
|
54
|
+
version: '0'
|
55
|
+
- !ruby/object:Gem::Dependency
|
56
|
+
name: rspec
|
57
|
+
requirement: !ruby/object:Gem::Requirement
|
58
|
+
requirements:
|
59
|
+
- - '>='
|
60
|
+
- !ruby/object:Gem::Version
|
61
|
+
version: '0'
|
62
|
+
type: :development
|
63
|
+
prerelease: false
|
64
|
+
version_requirements: !ruby/object:Gem::Requirement
|
65
|
+
requirements:
|
66
|
+
- - '>='
|
67
|
+
- !ruby/object:Gem::Version
|
68
|
+
version: '0'
|
69
|
+
description: Ruby Gem wrapper for Plaid API.
|
70
|
+
email: sean@smccann.com
|
71
|
+
executables: []
|
72
|
+
extensions: []
|
73
|
+
extra_rdoc_files: []
|
74
|
+
files:
|
75
|
+
- .gitignore
|
76
|
+
- .rspec
|
77
|
+
- .travis.yml
|
78
|
+
- Gemfile
|
79
|
+
- LICENSE
|
80
|
+
- README.md
|
81
|
+
- Rakefile
|
82
|
+
- lib/zen-plaid.rb
|
83
|
+
- lib/zen-plaid/auth.rb
|
84
|
+
- lib/zen-plaid/balance.rb
|
85
|
+
- lib/zen-plaid/category.rb
|
86
|
+
- lib/zen-plaid/configuration.rb
|
87
|
+
- lib/zen-plaid/connect.rb
|
88
|
+
- lib/zen-plaid/entity.rb
|
89
|
+
- lib/zen-plaid/institution.rb
|
90
|
+
- lib/zen-plaid/util.rb
|
91
|
+
- lib/zen-plaid/version.rb
|
92
|
+
- spec/auth_spec.rb
|
93
|
+
- spec/balance_spec.rb
|
94
|
+
- spec/category_spec.rb
|
95
|
+
- spec/connect_spec.rb
|
96
|
+
- spec/entity_spec.rb
|
97
|
+
- spec/institution_spec.rb
|
98
|
+
- spec/spec_helper.rb
|
99
|
+
- zen-plaid.gemspec
|
100
|
+
homepage: https://github.com/seanmccann/zen-plaid
|
101
|
+
licenses:
|
102
|
+
- MIT
|
103
|
+
metadata: {}
|
104
|
+
post_install_message:
|
105
|
+
rdoc_options: []
|
106
|
+
require_paths:
|
107
|
+
- lib
|
108
|
+
required_ruby_version: !ruby/object:Gem::Requirement
|
109
|
+
requirements:
|
110
|
+
- - '>='
|
111
|
+
- !ruby/object:Gem::Version
|
112
|
+
version: '0'
|
113
|
+
required_rubygems_version: !ruby/object:Gem::Requirement
|
114
|
+
requirements:
|
115
|
+
- - '>='
|
116
|
+
- !ruby/object:Gem::Version
|
117
|
+
version: '0'
|
118
|
+
requirements: []
|
119
|
+
rubyforge_project:
|
120
|
+
rubygems_version: 2.0.14
|
121
|
+
signing_key:
|
122
|
+
specification_version: 4
|
123
|
+
summary: Plaid Ruby Gem
|
124
|
+
test_files: []
|
125
|
+
has_rdoc:
|