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 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
@@ -0,0 +1,7 @@
1
+ language: ruby
2
+ rvm:
3
+ - 1.9.2
4
+ - 1.9.3
5
+ - 2.0.0
6
+ - 2.1.1
7
+ - 2.1.2
data/Gemfile ADDED
@@ -0,0 +1,2 @@
1
+ source 'https://rubygems.org'
2
+ gemspec
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
+ [![Build Status](https://travis-ci.org/seanmccann/zen-plaid.svg)](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,6 @@
1
+ require 'rake'
2
+ require 'rspec/core/rake_task'
3
+
4
+ RSpec::Core::RakeTask.new(:spec)
5
+
6
+ task default: :spec
@@ -0,0 +1,7 @@
1
+ module Plaid
2
+ class Auth
3
+ def self.add(params)
4
+ Plaid.request(:post, '/auth', params)
5
+ end
6
+ end
7
+ end
@@ -0,0 +1,7 @@
1
+ module Plaid
2
+ class Balance
3
+ def self.get(access_token)
4
+ Plaid.request(:post, '/balance/', {access_token: access_token} )
5
+ end
6
+ end
7
+ end
@@ -0,0 +1,11 @@
1
+ module Plaid
2
+ class Category
3
+ def self.all
4
+ Plaid.request(:get, '/categories')[:message]
5
+ end
6
+
7
+ def self.find(id)
8
+ Plaid.request(:get, '/categories/' + id )[:message]
9
+ end
10
+ end
11
+ end
@@ -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,7 @@
1
+ module Plaid
2
+ class Entity
3
+ def self.find(id)
4
+ Plaid.request(:get, '/entities/' + id )[:message]
5
+ end
6
+ end
7
+ end
@@ -0,0 +1,11 @@
1
+ module Plaid
2
+ class Institution
3
+ def self.all
4
+ Plaid.request(:get, '/institutions')[:message]
5
+ end
6
+
7
+ def self.find(id)
8
+ Plaid.request(:get, '/institutions/' + id )[:message]
9
+ end
10
+ end
11
+ 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
@@ -0,0 +1,3 @@
1
+ module Plaid
2
+ VERSION = '0.0.2'
3
+ 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
@@ -0,0 +1,9 @@
1
+ require 'spec_helper.rb'
2
+
3
+ describe Plaid::Entity do
4
+ describe "#find" do
5
+ it "finds " do
6
+ expect(Plaid::Entity.find('526842af335228673f0000b7')[:name]).to eq('Starbucks')
7
+ end
8
+ end
9
+ end
@@ -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
@@ -0,0 +1,4 @@
1
+ require 'bundler/setup'
2
+ Bundler.setup
3
+
4
+ require 'zen-plaid'
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: