plaid 2.0.0 → 2.1.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 CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA1:
3
- metadata.gz: a1d12271b5f68498843347df5493efca85a54331
4
- data.tar.gz: 77bd4a0ef5b50a6ac420a2067484a425d71b5f5b
3
+ metadata.gz: 275751fae8bd5e8b06ab3b12d577fb9287663fbd
4
+ data.tar.gz: 5b079f65196433ea7edfe0d27e5bcc917d4bc4f0
5
5
  SHA512:
6
- metadata.gz: 53b474fb7b12fbc2acb335aab4f072dd5d4ad96dcbc07b2a77fae42a73630b9ed7881336c7cab7e24a7b85543b666f07738eb8237df3eac8847a803244c71227
7
- data.tar.gz: d9935d472dd1cc6841a94acee6049c637777c5d9c19384b6c43443f867906ffa1631465a5707676628794c84189f4ab90df9adcb6364e208bf861601c711e033
6
+ metadata.gz: a2da99035165898c5634a704a12ee0a47f021df841e33a1172c7503b219a66451b60f6fb1bbf39f6c833ea450eeb00c13d0302dca56a8a3526b60a64126a6e6c
7
+ data.tar.gz: 53d4916be3b84f6833add1df715fad9de680391d13c4ff46969a1680d276507e46232a513f935d195a9e6515f2fa172a24e9b943c851846e02612caa7cb217ed
@@ -1,3 +1,13 @@
1
+ # 2.1.0. 19-Oct-2016
2
+
3
+ * Documentation fixes (@ishmael).
4
+ * Fix `Transaction#to_s` behavior (@michel-tricot).
5
+ * PATCH `/:product/step` flow.
6
+ * Use the same client in `User#upgrade` (@betesh).
7
+ * Webhook object (@zshannon).
8
+ * `processor_token` access in `User.exchange_token` (@gylaz).
9
+ * Raise `ServerError` in case server returned an empty response body.
10
+
1
11
  # 2.0.0. 24-May-2016
2
12
 
3
13
  * Use `~> 1.0` spec for multi_json dependency.
data/README.md CHANGED
@@ -34,7 +34,7 @@ Configure the gem with your client id, secret, and the environment you would lik
34
34
  Plaid.config do |p|
35
35
  p.client_id = '<<< Plaid provided client ID >>>'
36
36
  p.secret = '<<< Plaid provided secret key >>>'
37
- p.env = :tartan # or :api for production
37
+ p.env = :tartan # or :production
38
38
  end
39
39
  ```
40
40
 
@@ -86,7 +86,7 @@ user = Plaid::User.exchange_token('public_token') # bound to :connect product
86
86
  With more options:
87
87
 
88
88
  ```ruby
89
- user2 = Plaid::User.exchange_token('public_token', account_id: '...', product: :auth)
89
+ user2 = Plaid::User.exchange_token('public_token', 'account_id', product: :auth)
90
90
  ```
91
91
 
92
92
  If you want to [move money via Stripe's ACH
@@ -210,6 +210,55 @@ ltis = Plaid::LongTailInstitution.all(count: 20, offset: 20) # A page
210
210
  res = Plaid::LongTailInstitution.search(query: 'c') # Lookup by name
211
211
  ```
212
212
 
213
+ ### Webhooks
214
+
215
+ You can register to receive [Webhooks](https://plaid.com/docs/api/#webhook) from Plaid when your users have new events. If you do, you'll receive `POST` requests with JSON.
216
+
217
+ E.g. Initial Transaction Webhook:
218
+ ```json
219
+ {
220
+ "message": "Initial transaction pull finished",
221
+ "access_token": "xxxxx",
222
+ "total_transactions": 123,
223
+ "code": 0
224
+ }
225
+ ```
226
+
227
+ You should parse that JSON into a Ruby Hash with String keys (eg. `webhook_hash = JSON.parse(json_string)`). Then, you can convert that Hash into a Ruby object using `Plaid::Webhook`:
228
+
229
+ ```ruby
230
+ webhook = Plaid::Webhook.new(webhook_hash)
231
+
232
+ # Was that the Initial Transaction Webhook?
233
+ webhook.initial_transaction?
234
+ access_token = webhook.access_token
235
+ total_transactions = webhook.total_transactions
236
+
237
+ # Or did Historical Transactions become available?
238
+ webhook.historical_transaction?
239
+ access_token = webhook.access_token
240
+ total_transactions = webhook.total_transactions
241
+
242
+ # Or did Normal Transactions become available?
243
+ webhook.normal_transaction?
244
+ access_token = webhook.access_token
245
+ total_transactions = webhook.total_transactions
246
+
247
+ # Or maybe a transaction was removed?
248
+ webhook.removed_transaction?
249
+ access_token = webhook.access_token
250
+ removed_transactions_ids = webhook.removed_transactions_ids
251
+
252
+ # Or was the User's Webhook Updated?
253
+ webhook.user_webhook_updated?
254
+ access_token = webhook.access_token
255
+
256
+ # Otherwise, was it an error?
257
+ webhook.error_response?
258
+ # Which error?
259
+ error = webhook.error
260
+ ```
261
+
213
262
  ### Custom clients
214
263
 
215
264
  It's possible to use several Plaid environments and/or credentials in one app by
@@ -224,7 +273,7 @@ Plaid.config do |p|
224
273
  end
225
274
 
226
275
  # Creating a custom client
227
- api = Plaid::Client.new(client_id: 'client_id_2', 'secret_2', env: :api)
276
+ api = Plaid::Client.new(client_id: 'client_id_2', secret: 'secret_2', env: :production)
228
277
 
229
278
  # Tartan user (using default client)
230
279
  user1 = Plaid::User.create(:connect, 'wells', 'plaid_test', 'plaid_good')
@@ -8,6 +8,7 @@ require 'plaid/transaction'
8
8
  require 'plaid/info'
9
9
  require 'plaid/income'
10
10
  require 'plaid/client'
11
+ require 'plaid/webhook'
11
12
 
12
13
  require 'uri'
13
14
 
@@ -95,6 +95,10 @@ module Plaid
95
95
  @request = request
96
96
  @response = http.request(@request)
97
97
 
98
+ if @response.body.nil? || @response.body.empty?
99
+ raise Plaid::ServerError.new(0, 'Server error', 'Try to connect later')
100
+ end
101
+
98
102
  # All responses are expected to have a JSON body, so we always parse,
99
103
  # not looking at the status code.
100
104
  @body = MultiJson.load(@response.body)
@@ -110,7 +110,7 @@ module Plaid
110
110
  #
111
111
  # Returns a String.
112
112
  def inspect
113
- "#<Plaid::Transaction id=#{id.inspect}, account_id=#{id.inspect}, " \
113
+ "#<Plaid::Transaction id=#{id.inspect}, account_id=#{account_id.inspect}, " \
114
114
  "date=#{date}, amount=#{amount.inspect}, name=#{name.inspect}, " \
115
115
  "pending=#{pending.inspect}>"
116
116
  end
@@ -7,6 +7,9 @@ module Plaid
7
7
  # Public: The access token for authenticated user.
8
8
  attr_reader :access_token
9
9
 
10
+ # Public: The processor token for a given account and authenticated user.
11
+ attr_reader :processor_token
12
+
10
13
  # Public: The current product. Provides a context for #update and #delete
11
14
  # calls. See Plaid::PRODUCTS.
12
15
  attr_reader :product
@@ -146,7 +149,7 @@ module Plaid
146
149
  # access_token - The String access token obtained from Plaid.
147
150
  # response - The Hash response body to parse.
148
151
  # mfa - The Boolean flag indicating that response body
149
- # - contains an MFA response.
152
+ # contains an MFA response.
150
153
  # stripe_token - The String stripe bank account token.
151
154
  # client - The Plaid::Client instance used to connect to the API
152
155
  # (default is to use global Plaid client - Plaid.client).
@@ -207,7 +210,13 @@ module Plaid
207
210
  payload[:options] = MultiJson.dump(options)
208
211
  end
209
212
  conn = Connector.new(product, :step, auth: true)
210
- response = conn.post(payload)
213
+
214
+ # Use PATCH if we are in context of User#update.
215
+ response = if @mfa_patch
216
+ conn.patch(payload)
217
+ else
218
+ conn.post(payload)
219
+ end
211
220
 
212
221
  @mfa_required = conn.mfa?
213
222
  parse_response(response)
@@ -261,8 +270,17 @@ module Plaid
261
270
 
262
271
  payload[:pin] = pin if pin
263
272
 
264
- parse_response(Connector.new(product, auth: true, client: client)
265
- .patch(payload))
273
+ conn = Connector.new(product, auth: true, client: client)
274
+ resp = conn.patch(payload)
275
+
276
+ if conn.mfa?
277
+ @mfa_required = true
278
+ end
279
+
280
+ parse_response(resp)
281
+
282
+ # A note for User#mfa_step to send PATCH request too
283
+ @mfa_patch = true
266
284
 
267
285
  self
268
286
  end
@@ -321,7 +339,7 @@ module Plaid
321
339
  response = Connector.new(:upgrade, auth: true, client: client)
322
340
  .post(payload)
323
341
 
324
- User.new product, response: response
342
+ User.new product, response: response, client: client
325
343
  end
326
344
 
327
345
  # Public: Get the current user tied to another product.
@@ -443,6 +461,8 @@ module Plaid
443
461
  # Internal: Set up attributes from Add User response.
444
462
  def parse_response(response)
445
463
  @access_token = response['access_token']
464
+ @processor_token = response['processor_token']
465
+
446
466
  return parse_mfa_response(response) if mfa?
447
467
 
448
468
  @mfa_type = @mfa = nil
@@ -1,3 +1,3 @@
1
1
  module Plaid
2
- VERSION = '2.0.0'.freeze
2
+ VERSION = '2.1.0'.freeze
3
3
  end
@@ -0,0 +1,130 @@
1
+ module Plaid
2
+ # Public: Representation of a webhook.
3
+ class Webhook
4
+ # Public: The String human readable explanation of this webhook request.
5
+ # E.g. "Initial transaction pull finished".
6
+ attr_reader :message
7
+
8
+ # Public: The String access token for authenticated user.
9
+ attr_reader :access_token
10
+
11
+ # Public: The Integer number of transactions available in Plaid.
12
+ # E.g. 124
13
+ attr_reader :total_transactions
14
+
15
+ # Public: The Integer code denoting the type of webhook this is. E.g. 0
16
+ attr_reader :code
17
+
18
+ # Public: Initialize a Webhook instance.
19
+ #
20
+ # fields - The Hash with fields.
21
+ def initialize(fields)
22
+ @message = fields['message']
23
+ @access_token = fields['access_token']
24
+ @total_transactions = fields['total_transactions']
25
+ @code = fields['code']
26
+ # present only for Removed Transaction Webhook
27
+ @removed_transactions = fields['removed_transactions']
28
+ # present only for Error Response Webhook
29
+ @resolve = fields['resolve']
30
+ end
31
+
32
+ # Public: Share the type of Webhook this is from its code
33
+ #
34
+ # Returns String webhook type
35
+ def type
36
+ Webhook::CODEX[code] || 'ERROR_RESPONSE'
37
+ end
38
+
39
+ # Public: Detect if the webhook is Initial Transaction Webhook. Occurs
40
+ # once the initial transaction pull has finished.
41
+ #
42
+ # Returns true if it is.
43
+ def initial_transaction?
44
+ code == Webhook::INITIAL_TRANSACTION
45
+ end
46
+
47
+ # Public: Detect if the webhook is Historical Transaction Webhook. Occurs
48
+ # once the historical transaction pull has completed, shortly after the
49
+ # initial transaction pull.
50
+ #
51
+ # Returns true if it is.
52
+ def historical_transaction?
53
+ code == Webhook::HISTORICAL_TRANSACTION
54
+ end
55
+
56
+ # Public: Detect if the webhook is Normal Transaction Webhook. Occurs at
57
+ # set intervals throughout the day as data is updated from the financial
58
+ # institutions.
59
+ #
60
+ # Returns true if it is.
61
+ def normal_transaction?
62
+ code == Webhook::NORMAL_TRANSACTION
63
+ end
64
+
65
+ # Public: Detect if the webhook is Removed Transaction Webhook. Occurs when
66
+ # transactions have been removed from our system.
67
+ #
68
+ # Returns true if it is.
69
+ def removed_transaction?
70
+ code == Webhook::REMOVED_TRANSACTION
71
+ end
72
+
73
+ # Public: Detect if the webhook is User's Webhook Updated. Occurs when an
74
+ # user's webhook is updated via a PATCH request without credentials.
75
+ #
76
+ # Returns true if it is.
77
+ def user_webhook_updated?
78
+ code == Webhook::USER_WEBHOOK_UPDATED
79
+ end
80
+
81
+ # Public: Detect if the webhook is Error Response Webhook. Triggered when
82
+ # an error has occurred. Includes the relevant Plaid error code with
83
+ # details on both the error type and steps for error resolution.
84
+ #
85
+ # Returns true if it is.
86
+ def error_response?
87
+ Webhook::CODEX[code].nil?
88
+ end
89
+
90
+ # Public: Get transaction IDs that were removed.
91
+ #
92
+ # Returns Array[String] or nil
93
+ def removed_transactions_ids
94
+ @removed_transactions
95
+ end
96
+
97
+ # Public: Get a Plaid::Error instance if this is an Error Response Webhook
98
+ #
99
+ # Returns Plaid::Error or nil
100
+ def error
101
+ if error_response?
102
+ Plaid::PlaidError.new @code, @message, @resolve
103
+ end
104
+ end
105
+
106
+ # Public: Get a String representation of the transaction.
107
+ #
108
+ # Returns a String.
109
+ def inspect
110
+ "#<Plaid::Webhook type=#{type.inspect} code=#{code.inspect}, access_token=#{access_token.inspect}, " \
111
+ "total_transactions=#{total_transactions.inspect}, message=#{message.inspect}>"
112
+ end
113
+
114
+ # Public: Get a String representation of the transaction.
115
+ #
116
+ # Returns a String.
117
+ alias to_s inspect
118
+
119
+ private
120
+
121
+ Webhook::ERROR_RESPONSE = -1
122
+ codex = {}
123
+ ['initial transaction', 'historical transaction', 'normal transaction', 'removed transaction', 'user webhook updated'].each_with_index do |event, idx|
124
+ name = event.split.map(&:upcase).join('_')
125
+ codex[idx + 1] = name
126
+ const_set name, idx + 1
127
+ end
128
+ CODEX = codex.freeze
129
+ end
130
+ end
metadata CHANGED
@@ -1,14 +1,14 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: plaid
3
3
  version: !ruby/object:Gem::Version
4
- version: 2.0.0
4
+ version: 2.1.0
5
5
  platform: ruby
6
6
  authors:
7
7
  - Oleg Dashevskii
8
8
  autorequire:
9
9
  bindir: exe
10
10
  cert_chain: []
11
- date: 2016-05-24 00:00:00.000000000 Z
11
+ date: 2016-10-19 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: multi_json
@@ -138,6 +138,7 @@ files:
138
138
  - lib/plaid/transaction.rb
139
139
  - lib/plaid/user.rb
140
140
  - lib/plaid/version.rb
141
+ - lib/plaid/webhook.rb
141
142
  - plaid.gemspec
142
143
  homepage: https://github.com/plaid/plaid-ruby
143
144
  licenses:
@@ -159,7 +160,7 @@ required_rubygems_version: !ruby/object:Gem::Requirement
159
160
  version: '0'
160
161
  requirements: []
161
162
  rubyforge_project:
162
- rubygems_version: 2.5.1
163
+ rubygems_version: 2.4.5.1
163
164
  signing_key:
164
165
  specification_version: 4
165
166
  summary: Ruby bindings for Plaid