plaid 1.7.1 → 2.0.0.alpha
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/CHANGELOG.md +3 -0
- data/CONTRIBUTING.md +15 -0
- data/LICENSE +20 -0
- data/README.md +215 -63
- data/Rakefile +50 -4
- data/UPGRADING.md +45 -0
- data/bin/console +13 -0
- data/bin/setup +8 -0
- data/lib/plaid.rb +51 -88
- data/lib/plaid/account.rb +144 -0
- data/lib/plaid/category.rb +62 -0
- data/lib/plaid/client.rb +67 -0
- data/lib/plaid/connector.rb +168 -0
- data/lib/plaid/errors.rb +24 -14
- data/lib/plaid/income.rb +106 -0
- data/lib/plaid/info.rb +65 -0
- data/lib/plaid/institution.rb +240 -0
- data/lib/plaid/risk.rb +34 -0
- data/lib/plaid/transaction.rb +123 -0
- data/lib/plaid/user.rb +430 -0
- data/lib/plaid/version.rb +1 -1
- data/plaid.gemspec +20 -12
- metadata +58 -62
- data/.gitignore +0 -15
- data/.rspec +0 -2
- data/.travis.yml +0 -5
- data/LICENSE.txt +0 -22
- data/PUBLISHING.md +0 -21
- data/lib/plaid/config.rb +0 -19
- data/lib/plaid/connection.rb +0 -109
- data/lib/plaid/models/account.rb +0 -24
- data/lib/plaid/models/category.rb +0 -17
- data/lib/plaid/models/exchange_token_response.rb +0 -11
- data/lib/plaid/models/info.rb +0 -12
- data/lib/plaid/models/institution.rb +0 -22
- data/lib/plaid/models/transaction.rb +0 -24
- data/lib/plaid/models/user.rb +0 -189
- data/spec/plaid/config_spec.rb +0 -67
- data/spec/plaid/connection_spec.rb +0 -191
- data/spec/plaid/error_spec.rb +0 -10
- data/spec/plaid/models/account_spec.rb +0 -37
- data/spec/plaid/models/category_spec.rb +0 -16
- data/spec/plaid/models/institution_spec.rb +0 -19
- data/spec/plaid/models/transaction_spec.rb +0 -28
- data/spec/plaid/models/user_spec.rb +0 -172
- data/spec/plaid_spec.rb +0 -263
- data/spec/spec_helper.rb +0 -14
data/lib/plaid/risk.rb
ADDED
@@ -0,0 +1,34 @@
|
|
1
|
+
module Plaid
|
2
|
+
# Public: Representation of risk data (per account).
|
3
|
+
class Risk
|
4
|
+
# Public: The Float comprehensive risk score associated with the account,
|
5
|
+
# where 0 is the lowest risk and 1 is the highest. E.g. 0.5.
|
6
|
+
attr_reader :score
|
7
|
+
|
8
|
+
# Public: The Hash with Symbol reasons and associated Float subscores
|
9
|
+
# contributing to the overall risk score.
|
10
|
+
#
|
11
|
+
# E.g. { transaction_amounts: 0.78, foreign_fees: 0.96, ... }.
|
12
|
+
attr_reader :reason
|
13
|
+
|
14
|
+
# Internal: Construct a Risk object.
|
15
|
+
#
|
16
|
+
# fields - The Hash with fields.
|
17
|
+
def initialize(fields)
|
18
|
+
@score = fields['score']
|
19
|
+
@reason = Plaid.symbolize_hash(fields['reason'])
|
20
|
+
end
|
21
|
+
|
22
|
+
# Public: Get a String representation of Risk.
|
23
|
+
#
|
24
|
+
# Returns a String.
|
25
|
+
def inspect
|
26
|
+
"#<Plaid::Risk score=#{score.inspect}, ..."
|
27
|
+
end
|
28
|
+
|
29
|
+
# Public: Get a String representation of Risk.
|
30
|
+
#
|
31
|
+
# Returns a String.
|
32
|
+
alias to_s inspect
|
33
|
+
end
|
34
|
+
end
|
@@ -0,0 +1,123 @@
|
|
1
|
+
# coding: utf-8
|
2
|
+
require 'date'
|
3
|
+
|
4
|
+
module Plaid
|
5
|
+
# Public: Representation of a transaction.
|
6
|
+
class Transaction
|
7
|
+
# Public: The String unique ID of the transaction. E.g.
|
8
|
+
# "0AZ0De04KqsreDgVwM1RSRYjyd8yXxSDQ8Zxn".
|
9
|
+
attr_reader :id
|
10
|
+
|
11
|
+
# Public: The String ID of the account in which this transaction occurred.
|
12
|
+
# E.g. "XARE85EJqKsjxLp6XR8ocg8VakrkXpTXmRdOo".
|
13
|
+
attr_reader :account_id
|
14
|
+
|
15
|
+
# Public: The Date that the transaction took place.
|
16
|
+
# E.g. #<Date: 2016-04-28 ...>
|
17
|
+
attr_reader :date
|
18
|
+
|
19
|
+
# Public: The settled dollar value as Float. Positive values when
|
20
|
+
# money moves out of the account; negative values when money moves
|
21
|
+
# in. E.g. 0.10 (10 cents).
|
22
|
+
attr_reader :amount
|
23
|
+
|
24
|
+
# Public: The String descriptive name of the transaction. E.g.
|
25
|
+
# "Golden Crepes".
|
26
|
+
attr_reader :name
|
27
|
+
|
28
|
+
# Public: The Hash with additional information regarding the
|
29
|
+
# transaction. The keys are Symbols. E.g.
|
30
|
+
# { location: { "city": "San Francisco", "state": "CA" } }
|
31
|
+
attr_reader :meta
|
32
|
+
|
33
|
+
# Public: The Hash with location information obtained from the
|
34
|
+
# meta field. The keys are Strings.
|
35
|
+
#
|
36
|
+
# E.g. {"address" => "262 W 15th St",
|
37
|
+
# "city" => "New York",
|
38
|
+
# "state" => "NY",
|
39
|
+
# "zip" => "10011",
|
40
|
+
# "coordinates" => {
|
41
|
+
# "lat" => 40.740352,
|
42
|
+
# "lon" => -74.001761
|
43
|
+
# }}
|
44
|
+
attr_reader :location
|
45
|
+
|
46
|
+
# Public: The Boolean flag which identifies the transaction as
|
47
|
+
# pending or unsettled.
|
48
|
+
attr_reader :pending
|
49
|
+
|
50
|
+
# Public: The Hash with numeric representation of Plaid confidence
|
51
|
+
# in the meta data attached to the transaction. In the case of a
|
52
|
+
# score <.9 Plaid will default to guaranteed and known
|
53
|
+
# information. E.g.
|
54
|
+
#
|
55
|
+
# {location: {
|
56
|
+
# "address" => 1,
|
57
|
+
# "city" => 1,
|
58
|
+
# "state" => 1
|
59
|
+
# }, name: 0.9}.
|
60
|
+
attr_reader :score
|
61
|
+
|
62
|
+
# Public: The Hash transaction type.
|
63
|
+
#
|
64
|
+
# E.g. {:primary => :place}.
|
65
|
+
attr_reader :type
|
66
|
+
|
67
|
+
# Public: The Array of String category hierarchy.
|
68
|
+
#
|
69
|
+
# E.g. ["Food and Drink", "Restaurants"].
|
70
|
+
attr_reader :category_hierarchy
|
71
|
+
|
72
|
+
# Public: The String Category ID.
|
73
|
+
#
|
74
|
+
# E.g. "13005000".
|
75
|
+
attr_reader :category_id
|
76
|
+
|
77
|
+
# Public: The String ID of a posted transaction's associated
|
78
|
+
# pending transaction - where applicable.
|
79
|
+
attr_reader :pending_transaction_id
|
80
|
+
|
81
|
+
# Public: Initialize a Transaction instance.
|
82
|
+
#
|
83
|
+
# fields - The Hash with fields.
|
84
|
+
def initialize(fields)
|
85
|
+
@id = fields['_id']
|
86
|
+
@account_id = fields['_account']
|
87
|
+
|
88
|
+
@date = fields['date'] && Date.parse(fields['date'])
|
89
|
+
@amount = fields['amount']
|
90
|
+
@name = fields['name']
|
91
|
+
@meta = Plaid.symbolize_hash(fields['meta'])
|
92
|
+
@location = (@meta && @meta[:location]) || {}
|
93
|
+
@pending = fields['pending']
|
94
|
+
@pending_transaction_id = fields['_pendingTransaction']
|
95
|
+
@score = Plaid.symbolize_hash(fields['score'])
|
96
|
+
|
97
|
+
@type = Plaid.symbolize_hash(fields['type'], values: true)
|
98
|
+
@category_hierarchy = fields['category']
|
99
|
+
@category_id = fields['category_id']
|
100
|
+
end
|
101
|
+
|
102
|
+
# Public: Detect if the transaction is pending or unsettled.
|
103
|
+
#
|
104
|
+
# Returns true if it is.
|
105
|
+
def pending?
|
106
|
+
pending
|
107
|
+
end
|
108
|
+
|
109
|
+
# Public: Get a String representation of the transaction.
|
110
|
+
#
|
111
|
+
# Returns a String.
|
112
|
+
def inspect
|
113
|
+
"#<Plaid::Transaction id=#{id.inspect}, account_id=#{id.inspect}, " \
|
114
|
+
"date=#{date}, amount=#{amount.inspect}, name=#{name.inspect}, " \
|
115
|
+
"pending=#{pending.inspect}>"
|
116
|
+
end
|
117
|
+
|
118
|
+
# Public: Get a String representation of the transaction.
|
119
|
+
#
|
120
|
+
# Returns a String.
|
121
|
+
alias to_s inspect
|
122
|
+
end
|
123
|
+
end
|
data/lib/plaid/user.rb
ADDED
@@ -0,0 +1,430 @@
|
|
1
|
+
require_relative 'account'
|
2
|
+
|
3
|
+
module Plaid
|
4
|
+
# Public: A class which encapsulates the authenticated user for all Plaid
|
5
|
+
# products.
|
6
|
+
class User
|
7
|
+
# Public: The access token for authenticated user.
|
8
|
+
attr_reader :access_token
|
9
|
+
|
10
|
+
# Public: The current product. Provides a context for #update and #delete
|
11
|
+
# calls. See Plaid::PRODUCTS.
|
12
|
+
attr_reader :product
|
13
|
+
|
14
|
+
# Public: The Array of Account instances providing accounts information
|
15
|
+
# for the user.
|
16
|
+
attr_reader :accounts
|
17
|
+
|
18
|
+
# Public: The Array of Transactions provided by initial call to User.create.
|
19
|
+
#
|
20
|
+
# If the :login_only option of User.create is set to false, the initial
|
21
|
+
# 30-day transactional data are returned during the API call. This attribute
|
22
|
+
# contains them.
|
23
|
+
attr_reader :initial_transactions
|
24
|
+
|
25
|
+
# Public: The Symbol MFA type to be used (or nil, if no MFA required).
|
26
|
+
#
|
27
|
+
# E.g. :questions, :list, or :device.
|
28
|
+
attr_reader :mfa_type
|
29
|
+
|
30
|
+
# Public: The MFA data (Hash or Array of Hash) or nil, if no MFA required.
|
31
|
+
#
|
32
|
+
# E.g. [{ question: "What was the name of your first pet?" }]
|
33
|
+
# or
|
34
|
+
# [{ mask: 't..t@plaid.com', type: 'email' },
|
35
|
+
# { mask: 'xxx-xxx-5309', type: 'phone' }]
|
36
|
+
# or
|
37
|
+
# { message: 'Code sent to xxx-xxx-5309' }
|
38
|
+
attr_reader :mfa
|
39
|
+
|
40
|
+
# Internal: The Plaid::Client instance used to make queries.
|
41
|
+
attr_reader :client
|
42
|
+
|
43
|
+
# Public: Create (add) a user.
|
44
|
+
#
|
45
|
+
# product - The Symbol product name you are adding the user to, one of
|
46
|
+
# Plaid::PRODUCTS (e.g. :info, :connect, etc.).
|
47
|
+
# institution - The String/Symbol financial institution type that you
|
48
|
+
# want to access (e.g. :wells).
|
49
|
+
# username - The String username associated with the financial
|
50
|
+
# institution.
|
51
|
+
# password - The String password associated with the financial
|
52
|
+
# institution.
|
53
|
+
# pin - The String PIN number associated with the financial
|
54
|
+
# institution (default: nil).
|
55
|
+
# options - the Hash options (default: {}):
|
56
|
+
# :list - The Boolean flag which would request the
|
57
|
+
# available send methods if the institution
|
58
|
+
# requires code-based MFA credential (default:
|
59
|
+
# false).
|
60
|
+
# :webhook - The String webhook URL. Used with :connect,
|
61
|
+
# :income, and :risk products (default: nil).
|
62
|
+
# :pending - The Boolean flag requesting to return
|
63
|
+
# pending transactions. Used with :connect
|
64
|
+
# product (default: false).
|
65
|
+
# :login_only - The Boolean option valid for initial
|
66
|
+
# authentication only. If set to false, the
|
67
|
+
# initial request will return transaction data
|
68
|
+
# based on the start_date and end_date.
|
69
|
+
# :start_date - The start Date from which to return
|
70
|
+
# transactions (default: 30 days ago).
|
71
|
+
# :end_date - The end Date to which transactions
|
72
|
+
# will be collected (default: today).
|
73
|
+
# client - The Plaid::Client instance used to connect to the API
|
74
|
+
# (default is to use global Plaid client - Plaid.client).
|
75
|
+
#
|
76
|
+
# Returns a Plaid::User instance.
|
77
|
+
def self.create(product, institution, username, password,
|
78
|
+
pin: nil, options: nil, client: nil)
|
79
|
+
check_product product
|
80
|
+
|
81
|
+
payload = { username: username, password: password,
|
82
|
+
type: institution.to_s }
|
83
|
+
payload[:pin] = pin if pin
|
84
|
+
payload[:options] = MultiJson.dump(options) if options
|
85
|
+
|
86
|
+
conn = Connector.new(product, auth: true, client: client)
|
87
|
+
resp = conn.post(payload)
|
88
|
+
|
89
|
+
new product, response: resp, mfa: conn.mfa?, client: client
|
90
|
+
end
|
91
|
+
|
92
|
+
# Public: Get User instance in case user access token is known.
|
93
|
+
#
|
94
|
+
# No requests are made, but the returned User instance is ready to be
|
95
|
+
# used.
|
96
|
+
#
|
97
|
+
# product - The Symbol product name you want to use, one of
|
98
|
+
# Plaid::PRODUCTS (e.g. :info, :connect, etc.).
|
99
|
+
# token - The String access token for the user.
|
100
|
+
# client - The Plaid::Client instance used to connect to the API
|
101
|
+
# (default is to use global Plaid client - Plaid.client).
|
102
|
+
#
|
103
|
+
# Returns a Plaid::User instance.
|
104
|
+
def self.load(product, token, client: nil)
|
105
|
+
new check_product(product), access_token: token, client: client
|
106
|
+
end
|
107
|
+
|
108
|
+
# Public: Exchange a Link public_token for an API access_token.
|
109
|
+
#
|
110
|
+
# public_token - The String Link public_token.
|
111
|
+
# account_id - The String account ID.
|
112
|
+
# product - The Symbol product name (default: :connect).
|
113
|
+
# client - The Plaid::Client instance used to connect to the API
|
114
|
+
# (default is to use global Plaid client - Plaid.client).
|
115
|
+
#
|
116
|
+
# Returns a new User with access token obtained from Plaid and default
|
117
|
+
# product set to product.
|
118
|
+
def self.exchange_token(public_token, account_id = nil,
|
119
|
+
product: :connect, client: nil)
|
120
|
+
check_product product
|
121
|
+
|
122
|
+
payload = { public_token: public_token }
|
123
|
+
payload[:account_id] = account_id if account_id
|
124
|
+
|
125
|
+
response = Connector.new(:exchange_token, auth: true, client: client)
|
126
|
+
.post(payload)
|
127
|
+
new product, response: response, client: client
|
128
|
+
end
|
129
|
+
|
130
|
+
# Internal: Initialize a User instance.
|
131
|
+
#
|
132
|
+
# product - The Symbol product name.
|
133
|
+
# access_token - The String access token obtained from Plaid.
|
134
|
+
# response - The Hash response body to parse.
|
135
|
+
# mfa - The Boolean flag indicating that response body
|
136
|
+
# - contains an MFA response.
|
137
|
+
# client - The Plaid::Client instance used to connect to the API
|
138
|
+
# (default is to use global Plaid client - Plaid.client).
|
139
|
+
def initialize(product, access_token: nil, response: nil, mfa: nil,
|
140
|
+
client: nil)
|
141
|
+
@product = product
|
142
|
+
@client = client
|
143
|
+
@access_token = access_token if access_token
|
144
|
+
@mfa_required = mfa
|
145
|
+
@accounts = @initial_transactions = @info = @risk = @income = nil
|
146
|
+
|
147
|
+
parse_response(response) if response
|
148
|
+
end
|
149
|
+
|
150
|
+
# Public: Find out if MFA is required based on last request.
|
151
|
+
#
|
152
|
+
# After calling e.g. User.create you might need to make an additional
|
153
|
+
# authorization step if MFA is required by the financial institution.
|
154
|
+
#
|
155
|
+
# Returns true if this step is needed, a falsey value otherwise.
|
156
|
+
def mfa?
|
157
|
+
@mfa_required
|
158
|
+
end
|
159
|
+
|
160
|
+
# Public: Submit MFA information.
|
161
|
+
#
|
162
|
+
# info - The String with MFA information (default: nil).
|
163
|
+
# send_method - The Hash with code send method information.
|
164
|
+
# E.g. { type: 'phone' } or { mask: '123-...-4321' }.
|
165
|
+
# Default is first available email.
|
166
|
+
#
|
167
|
+
# Returns true if whole MFA process is completed, false otherwise.
|
168
|
+
def mfa_step(info = nil, send_method: nil)
|
169
|
+
payload = { access_token: access_token }
|
170
|
+
payload[:mfa] = info if info
|
171
|
+
payload[:send_method] = MultiJson.dump(send_method) if send_method
|
172
|
+
|
173
|
+
conn = Connector.new(product, :step, auth: true)
|
174
|
+
response = conn.post(payload)
|
175
|
+
|
176
|
+
@mfa_required = conn.mfa?
|
177
|
+
parse_response(response)
|
178
|
+
end
|
179
|
+
|
180
|
+
# Public: Get transactions.
|
181
|
+
#
|
182
|
+
# Does a /connect/get call. Updates self.accounts with latest information.
|
183
|
+
#
|
184
|
+
# pending - the Boolean flag requesting to return pending transactions.
|
185
|
+
# account_id - the String Account ID (default: nil). If this argument is
|
186
|
+
# present, only transactions for given account will be
|
187
|
+
# requested.
|
188
|
+
# start_date - The start Date (inclusive).
|
189
|
+
# end_date - The end Date (inclusive).
|
190
|
+
#
|
191
|
+
# Returns an Array of Transaction records.
|
192
|
+
def transactions(pending: false, account_id: nil,
|
193
|
+
start_date: nil, end_date: nil)
|
194
|
+
options = { pending: pending }
|
195
|
+
options[:account] = account_id if account_id
|
196
|
+
options[:gte] = start_date.to_s if start_date
|
197
|
+
options[:lte] = end_date.to_s if end_date
|
198
|
+
|
199
|
+
response = Connector.new(:connect, :get, auth: true, client: client)
|
200
|
+
.post(access_token: access_token,
|
201
|
+
options: MultiJson.dump(options))
|
202
|
+
update_accounts(response)
|
203
|
+
build_objects(response['transactions'], Transaction)
|
204
|
+
end
|
205
|
+
|
206
|
+
# Public: Update user credentials.
|
207
|
+
#
|
208
|
+
# Updates the user credentials for the current product. See
|
209
|
+
# User#for_product.
|
210
|
+
#
|
211
|
+
# username - The String username associated with the financial
|
212
|
+
# institution.
|
213
|
+
# password - The String password associated with the financial
|
214
|
+
# institution.
|
215
|
+
# pin - The String PIN number associated with the financial
|
216
|
+
# institution (default: nil).
|
217
|
+
#
|
218
|
+
# Returns self.
|
219
|
+
def update(username, password, pin = nil)
|
220
|
+
payload = {
|
221
|
+
access_token: access_token,
|
222
|
+
username: username,
|
223
|
+
password: password
|
224
|
+
}
|
225
|
+
|
226
|
+
payload[:pin] = pin if pin
|
227
|
+
|
228
|
+
parse_response(Connector.new(product, auth: true, client: client)
|
229
|
+
.patch(payload))
|
230
|
+
|
231
|
+
self
|
232
|
+
end
|
233
|
+
|
234
|
+
# Public: Delete the user.
|
235
|
+
#
|
236
|
+
# Makes a delete request and freezes self to prevent further modifications
|
237
|
+
# to the object.
|
238
|
+
#
|
239
|
+
# Returns self.
|
240
|
+
def delete
|
241
|
+
Connector.new(product, auth: true, client: client)
|
242
|
+
.delete(access_token: access_token)
|
243
|
+
|
244
|
+
freeze
|
245
|
+
end
|
246
|
+
|
247
|
+
# Public: Upgrade the user.
|
248
|
+
#
|
249
|
+
# For an existing user that has been added via any of products (:connect,
|
250
|
+
# :auth, :income, :info, or :risk), you can upgrade that user to have
|
251
|
+
# functionality with other products.
|
252
|
+
#
|
253
|
+
# Does a POST /upgrade request.
|
254
|
+
#
|
255
|
+
# See also User#for_product.
|
256
|
+
#
|
257
|
+
# product - The Symbol product name you are upgrading the user to, one of
|
258
|
+
# Plaid::PRODUCTS.
|
259
|
+
#
|
260
|
+
# Returns another User record with the same access token, but tied to the
|
261
|
+
# new product.
|
262
|
+
def upgrade(product)
|
263
|
+
payload = { access_token: access_token, upgrade_to: product.to_s }
|
264
|
+
response = Connector.new(:upgrade, auth: true, client: client)
|
265
|
+
.post(payload)
|
266
|
+
|
267
|
+
User.new product, response: response
|
268
|
+
end
|
269
|
+
|
270
|
+
# Public: Get the current user tied to another product.
|
271
|
+
#
|
272
|
+
# No API request is made, just the current product is changed.
|
273
|
+
#
|
274
|
+
# product - The Symbol product you are selecting, one of Plaid::PRODUCTS.
|
275
|
+
#
|
276
|
+
# See also User#upgrade.
|
277
|
+
#
|
278
|
+
# Returns a new User instance.
|
279
|
+
def for_product(product)
|
280
|
+
User.load product, access_token, client: client
|
281
|
+
end
|
282
|
+
|
283
|
+
# Public: Get auth information for the user (routing numbers for accounts).
|
284
|
+
#
|
285
|
+
# Not only this method returns the new data, but it updates self.accounts as
|
286
|
+
# well.
|
287
|
+
#
|
288
|
+
# The method does a POST /auth/get request.
|
289
|
+
#
|
290
|
+
# sync - The Boolean flag which, if true, causes auth information to be
|
291
|
+
# rerequested from the server. Otherwise cached version is returned,
|
292
|
+
# if it exists.
|
293
|
+
#
|
294
|
+
# Returns an Array of Account with numbers baked in.
|
295
|
+
def auth(sync: false)
|
296
|
+
if sync || !@accounts || !@accounts[0] || !@accounts[0].numbers
|
297
|
+
response = Connector.new(:auth, :get, auth: true, client: client)
|
298
|
+
.post(access_token: access_token)
|
299
|
+
|
300
|
+
update_accounts(response)
|
301
|
+
end
|
302
|
+
|
303
|
+
accounts
|
304
|
+
end
|
305
|
+
|
306
|
+
# Public: Get info for the user.
|
307
|
+
#
|
308
|
+
# Does a POST /info/get request.
|
309
|
+
#
|
310
|
+
# sync - The Boolean flag which, if true, causes information to be
|
311
|
+
# rerequested from the server. Otherwise cached version is returned,
|
312
|
+
# if it exists.
|
313
|
+
#
|
314
|
+
# Returns a Plaid::Info instance.
|
315
|
+
def info(sync: false)
|
316
|
+
if sync || !@info
|
317
|
+
parse_response(Connector.new(:info, :get, auth: true, client: client)
|
318
|
+
.post(access_token: access_token))
|
319
|
+
end
|
320
|
+
|
321
|
+
@info
|
322
|
+
end
|
323
|
+
|
324
|
+
# Public: Get income information for the user.
|
325
|
+
#
|
326
|
+
# Does a POST /income/get request.
|
327
|
+
#
|
328
|
+
# sync - The Boolean flag which, if true, causes income information to be
|
329
|
+
# rerequested from the server. Otherwise cached version is returned,
|
330
|
+
# if it exists.
|
331
|
+
#
|
332
|
+
# Returns a Plaid::Income instance.
|
333
|
+
def income(sync: false)
|
334
|
+
if sync || !@income
|
335
|
+
parse_response(Connector.new(:income, :get, auth: true, client: client)
|
336
|
+
.post(access_token: access_token))
|
337
|
+
end
|
338
|
+
|
339
|
+
@income
|
340
|
+
end
|
341
|
+
|
342
|
+
# Public: Get risk data for the user's accounts.
|
343
|
+
#
|
344
|
+
# Does a POST /risk/get request.
|
345
|
+
#
|
346
|
+
# sync - The Boolean flag which, if true, causes risk information to be
|
347
|
+
# rerequested from the server. Otherwise cached version is returned,
|
348
|
+
# if it exists.
|
349
|
+
#
|
350
|
+
# Returns an Array of accounts with risk attribute set.
|
351
|
+
def risk(sync: false)
|
352
|
+
if sync || !@accounts || !@accounts[0] || !@accounts[0].risk
|
353
|
+
parse_response(Connector.new(:risk, :get, auth: true, client: client)
|
354
|
+
.post(access_token: access_token))
|
355
|
+
end
|
356
|
+
|
357
|
+
@accounts
|
358
|
+
end
|
359
|
+
|
360
|
+
# Public: Get current account balance.
|
361
|
+
#
|
362
|
+
# Does a POST /balance request.
|
363
|
+
#
|
364
|
+
# Returns an Array of Plaid::Account.
|
365
|
+
def balance
|
366
|
+
response = Connector.new(:balance, auth: true, client: client)
|
367
|
+
.post(access_token: access_token)
|
368
|
+
|
369
|
+
update_accounts(response)
|
370
|
+
end
|
371
|
+
|
372
|
+
private
|
373
|
+
|
374
|
+
# Internal: Validate the product name.
|
375
|
+
def self.check_product(product)
|
376
|
+
if Plaid::PRODUCTS.include?(product)
|
377
|
+
product
|
378
|
+
else
|
379
|
+
raise ArgumentError, "product (#{product.inspect}) must be one of " \
|
380
|
+
"Plaid products (#{Plaid::PRODUCTS.inspect})"
|
381
|
+
end
|
382
|
+
end
|
383
|
+
|
384
|
+
private_class_method :check_product
|
385
|
+
|
386
|
+
# Internal: Set up attributes from Add User response.
|
387
|
+
def parse_response(response)
|
388
|
+
@access_token = response['access_token']
|
389
|
+
return parse_mfa_response(response) if mfa?
|
390
|
+
|
391
|
+
@mfa_type = @mfa = nil
|
392
|
+
|
393
|
+
update_accounts(response) if response['accounts']
|
394
|
+
|
395
|
+
if (trans = response['transactions'])
|
396
|
+
@initial_transactions = build_objects(trans, Transaction)
|
397
|
+
end
|
398
|
+
|
399
|
+
if (income = response['income'])
|
400
|
+
@income = Plaid::Income.new(income)
|
401
|
+
end
|
402
|
+
|
403
|
+
return unless (i = response['info'])
|
404
|
+
@info = Plaid::Info.new(i)
|
405
|
+
end
|
406
|
+
|
407
|
+
# Internal: Parse an MFA response
|
408
|
+
def parse_mfa_response(response)
|
409
|
+
@mfa_type = response['type'].to_sym
|
410
|
+
@mfa = Plaid.symbolize_hash(response['mfa'])
|
411
|
+
end
|
412
|
+
|
413
|
+
# Internal: Convert an array of data into an array of objects, encapsulating
|
414
|
+
# that data.
|
415
|
+
def build_objects(data, klass)
|
416
|
+
data ? data.map { |element| klass.new(element) } : []
|
417
|
+
end
|
418
|
+
|
419
|
+
# Internal: Update account data from the response.
|
420
|
+
def update_accounts(response)
|
421
|
+
new_accounts = build_objects(response['accounts'], Account)
|
422
|
+
|
423
|
+
if @accounts
|
424
|
+
Account.merge @accounts, new_accounts
|
425
|
+
else
|
426
|
+
@accounts = new_accounts
|
427
|
+
end
|
428
|
+
end
|
429
|
+
end
|
430
|
+
end
|