plaid 3.0.0 → 4.0.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- checksums.yaml +4 -4
- data/CONTRIBUTING.md +7 -1
- data/Gemfile +0 -1
- data/LICENSE.txt +21 -0
- data/README.md +233 -206
- data/Rakefile +1 -2
- data/bin/console +8 -7
- data/circle.yml +3 -0
- data/lib/plaid.rb +15 -60
- data/lib/plaid/client.rb +120 -52
- data/lib/plaid/connect.rb +75 -0
- data/lib/plaid/errors.rb +60 -24
- data/lib/plaid/products/accounts.rb +60 -0
- data/lib/plaid/products/auth.rb +29 -0
- data/lib/plaid/products/categories.rb +18 -0
- data/lib/plaid/products/credit_details.rb +21 -0
- data/lib/plaid/products/identity.rb +20 -0
- data/lib/plaid/products/income.rb +20 -0
- data/lib/plaid/products/institutions.rb +51 -0
- data/lib/plaid/products/item.rb +230 -0
- data/lib/plaid/products/processor.rb +48 -0
- data/lib/plaid/products/sandbox.rb +32 -0
- data/lib/plaid/products/transactions.rb +74 -0
- data/lib/plaid/version.rb +1 -1
- data/plaid.gemspec +13 -8
- metadata +21 -61
- data/CHANGELOG.md +0 -34
- data/LICENSE +0 -20
- data/UPGRADING.md +0 -60
- data/lib/plaid/account.rb +0 -144
- data/lib/plaid/category.rb +0 -62
- data/lib/plaid/connector.rb +0 -172
- data/lib/plaid/income.rb +0 -106
- data/lib/plaid/info.rb +0 -65
- data/lib/plaid/institution.rb +0 -253
- data/lib/plaid/risk.rb +0 -34
- data/lib/plaid/transaction.rb +0 -128
- data/lib/plaid/user.rb +0 -507
- data/lib/plaid/webhook.rb +0 -153
data/Rakefile
CHANGED
@@ -9,8 +9,7 @@ RDoc::Task.new do |rdoc|
|
|
9
9
|
rdoc.generator = 'sdoc'
|
10
10
|
rdoc.main = 'README.md'
|
11
11
|
|
12
|
-
rdoc.rdoc_files.include('README.md', 'LICENSE', 'UPGRADING.md',
|
13
|
-
'CONTRIBUTING.md', 'CHANGELOG.md', 'lib/**/*.rb')
|
12
|
+
rdoc.rdoc_files.include('README.md', 'LICENSE', 'UPGRADING.md', 'lib/**/*.rb')
|
14
13
|
rdoc.markup = 'tomdoc'
|
15
14
|
end
|
16
15
|
|
data/bin/console
CHANGED
@@ -2,12 +2,13 @@
|
|
2
2
|
|
3
3
|
require 'bundler/setup'
|
4
4
|
require 'plaid'
|
5
|
-
require 'pry'
|
6
5
|
|
7
|
-
|
8
|
-
|
9
|
-
p.client_id = ENV['PLAID_CLIENT_ID']
|
10
|
-
p.secret = ENV['PLAID_SECRET']
|
11
|
-
end
|
6
|
+
# You can add fixtures and/or initialization code here to make experimenting
|
7
|
+
# with your gem easier. You can also use a different console, if you like.
|
12
8
|
|
13
|
-
|
9
|
+
# (If you use this, don't forget to add pry to your Gemfile!)
|
10
|
+
# require "pry"
|
11
|
+
# Pry.start
|
12
|
+
|
13
|
+
require 'irb'
|
14
|
+
IRB.start(__FILE__)
|
data/circle.yml
ADDED
data/lib/plaid.rb
CHANGED
@@ -1,64 +1,19 @@
|
|
1
|
-
|
2
|
-
|
3
|
-
|
4
|
-
|
5
|
-
|
6
|
-
|
7
|
-
|
8
|
-
|
9
|
-
|
10
|
-
|
11
|
-
|
12
|
-
|
13
|
-
|
1
|
+
require_relative 'plaid/client'
|
2
|
+
require_relative 'plaid/connect'
|
3
|
+
require_relative 'plaid/errors'
|
4
|
+
require_relative 'plaid/version'
|
5
|
+
require_relative 'plaid/products/accounts'
|
6
|
+
require_relative 'plaid/products/auth'
|
7
|
+
require_relative 'plaid/products/categories'
|
8
|
+
require_relative 'plaid/products/credit_details'
|
9
|
+
require_relative 'plaid/products/identity'
|
10
|
+
require_relative 'plaid/products/income'
|
11
|
+
require_relative 'plaid/products/institutions'
|
12
|
+
require_relative 'plaid/products/item'
|
13
|
+
require_relative 'plaid/products/processor'
|
14
|
+
require_relative 'plaid/products/sandbox'
|
15
|
+
require_relative 'plaid/products/transactions'
|
14
16
|
|
15
17
|
# Public: The Plaid namespace.
|
16
18
|
module Plaid
|
17
|
-
# Public: Available Plaid products.
|
18
|
-
PRODUCTS = %i(connect auth info income risk).freeze
|
19
|
-
|
20
|
-
class <<self
|
21
|
-
# Public: The default Client.
|
22
|
-
attr_accessor :client
|
23
|
-
|
24
|
-
# Public: The Integer read timeout for requests to Plaid HTTP API.
|
25
|
-
# Should be specified in seconds. Default value is 120 (2 minutes).
|
26
|
-
attr_accessor :read_timeout
|
27
|
-
|
28
|
-
# Public: A helper function to ease configuration.
|
29
|
-
#
|
30
|
-
# Yields self.
|
31
|
-
#
|
32
|
-
# Examples
|
33
|
-
#
|
34
|
-
# Plaid.configure do |p|
|
35
|
-
# p.client_id = 'Plaid provided client ID here'
|
36
|
-
# p.secret = 'Plaid provided secret key here'
|
37
|
-
# p.env = :tartan
|
38
|
-
# p.read_timeout = 300 # it's 5 minutes, yay!
|
39
|
-
# end
|
40
|
-
#
|
41
|
-
# Returns nothing.
|
42
|
-
def config
|
43
|
-
client = Client.new
|
44
|
-
yield client
|
45
|
-
self.client = client
|
46
|
-
end
|
47
|
-
|
48
|
-
# Internal: Symbolize keys (and values) for a hash.
|
49
|
-
#
|
50
|
-
# hash - The Hash with string keys (or nil).
|
51
|
-
# values - The Boolean flag telling the function to symbolize values
|
52
|
-
# as well.
|
53
|
-
#
|
54
|
-
# Returns a Hash with keys.to_sym (or nil if hash is nil).
|
55
|
-
def symbolize_hash(hash, values: false)
|
56
|
-
return unless hash
|
57
|
-
return hash.map { |h| symbolize_hash(h) } if hash.is_a?(Array)
|
58
|
-
|
59
|
-
hash.each_with_object({}) do |(k, v), memo|
|
60
|
-
memo[k.to_sym] = values ? v.to_sym : v
|
61
|
-
end
|
62
|
-
end
|
63
|
-
end
|
64
19
|
end
|
data/lib/plaid/client.rb
CHANGED
@@ -1,69 +1,137 @@
|
|
1
|
+
# Public: The Plaid namespace.
|
1
2
|
module Plaid
|
2
|
-
#
|
3
|
+
# Internal: Map environment to Plaid environment URL
|
4
|
+
#
|
5
|
+
# env - The type of the environment in symbol form
|
6
|
+
#
|
7
|
+
# Returns a string representing an environment URL
|
8
|
+
def self.url_from_env(env)
|
9
|
+
case env
|
10
|
+
when :sandbox
|
11
|
+
'https://sandbox.plaid.com/'
|
12
|
+
when :development
|
13
|
+
'https://development.plaid.com/'
|
14
|
+
when :production
|
15
|
+
'https://production.plaid.com/'
|
16
|
+
end
|
17
|
+
end
|
18
|
+
|
19
|
+
# Public: A class encapsulating client_id, secret, public key, and Plaid environment.
|
3
20
|
class Client
|
4
|
-
#
|
5
|
-
|
21
|
+
# Internal: Set Plaid environment to use
|
22
|
+
#
|
23
|
+
# Handles converting an env symbol into an environment URL
|
24
|
+
#
|
25
|
+
# env - The Symbol (:sandbox, :development, :production)
|
26
|
+
#
|
27
|
+
# Returns a string representing the environment URL or raises an error
|
28
|
+
def env_map(env)
|
29
|
+
(@env = Plaid.url_from_env(env)) || raise(ArgumentError, 'Invalid value for ' \
|
30
|
+
'Plaid::Client.env ' \
|
31
|
+
"(#{env.inspect}): " \
|
32
|
+
'must be :sandbox, '\
|
33
|
+
':development, or :production ')
|
34
|
+
end
|
35
|
+
|
36
|
+
# Public: Memoized class instance to make requests from Plaid::Account
|
37
|
+
def accounts
|
38
|
+
@accounts ||= Plaid::Accounts.new(self)
|
39
|
+
end
|
40
|
+
|
41
|
+
# Public: Memoized class instance to make requests from Plaid::Auth
|
42
|
+
def auth
|
43
|
+
@auth ||= Plaid::Auth.new(self)
|
44
|
+
end
|
45
|
+
|
46
|
+
# Public: Memoized class instance to make requests from Plaid::Categories
|
47
|
+
def categories
|
48
|
+
@categories ||= Plaid::Categories.new(self)
|
49
|
+
end
|
50
|
+
|
51
|
+
# Public: Memoized class instance to make requests from Plaid::CreditDetails
|
52
|
+
def credit_details
|
53
|
+
@credit_details ||= Plaid::CreditDetails.new(self)
|
54
|
+
end
|
6
55
|
|
7
|
-
# Public:
|
8
|
-
|
56
|
+
# Public: Memoized class instance to make requests from Plaid::Identity
|
57
|
+
def identity
|
58
|
+
@identity ||= Plaid::Identity.new(self)
|
59
|
+
end
|
9
60
|
|
10
|
-
# Public:
|
61
|
+
# Public: Memoized class instance to make requests from Plaid::Income
|
62
|
+
def income
|
63
|
+
@income ||= Plaid::Income.new(self)
|
64
|
+
end
|
65
|
+
|
66
|
+
# Public: Memoized class instance to make requests from Plaid::Institutions
|
67
|
+
def institutions
|
68
|
+
@institutions ||= Plaid::Institutions.new(self)
|
69
|
+
end
|
70
|
+
|
71
|
+
# Public: Memoized class instance to make requests from Plaid::Item
|
72
|
+
def item
|
73
|
+
@item ||= Plaid::Item.new(self)
|
74
|
+
end
|
75
|
+
|
76
|
+
# Public: Memoized class instance to make requests from Plaid::Processor
|
77
|
+
def processor
|
78
|
+
@processor ||= Plaid::Processor.new(self)
|
79
|
+
end
|
80
|
+
|
81
|
+
# Public: Memoized class instance to make requests from Plaid::Sandbox
|
82
|
+
def sandbox
|
83
|
+
@sandbox ||= Plaid::Sandbox.new(self)
|
84
|
+
end
|
85
|
+
|
86
|
+
# Public: Memoized class instance to make requests from Plaid::Transactions
|
87
|
+
def transactions
|
88
|
+
@transactions ||= Plaid::Transactions.new(self)
|
89
|
+
end
|
90
|
+
|
91
|
+
# Public: Construct a Client instance
|
11
92
|
#
|
12
|
-
#
|
13
|
-
|
93
|
+
# env - The Symbol (:sandbox, :development, :production)
|
94
|
+
# client_id - The String Plaid account client ID to authenticate requests
|
95
|
+
# secret - The String Plaid account secret to authenticate requests
|
96
|
+
# public_key - The String Plaid account public key to authenticate requests
|
97
|
+
def initialize(env:, client_id:, secret:, public_key:)
|
98
|
+
@env = env_map(env)
|
99
|
+
@client_id = client_id
|
100
|
+
@secret = secret
|
101
|
+
@public_key = public_key
|
102
|
+
end
|
14
103
|
|
15
|
-
# Public:
|
104
|
+
# Public: Make a post request
|
16
105
|
#
|
17
|
-
#
|
18
|
-
#
|
19
|
-
def env=(env)
|
20
|
-
case env
|
21
|
-
when :tartan
|
22
|
-
@env = 'https://tartan.plaid.com/'
|
23
|
-
when :production
|
24
|
-
@env = 'https://api.plaid.com/'
|
25
|
-
when String
|
26
|
-
begin
|
27
|
-
URI.parse(env)
|
28
|
-
@env = env
|
29
|
-
rescue
|
30
|
-
raise ArgumentError, 'Invalid URL in Plaid::Client.env' \
|
31
|
-
" (#{env.inspect}). " \
|
32
|
-
'Specify either Symbol (:tartan, :production),' \
|
33
|
-
" or a full URL, like 'https://tartan.plaid.com'"
|
34
|
-
end
|
35
|
-
else
|
36
|
-
raise ArgumentError, 'Invalid value for Plaid::Client.env' \
|
37
|
-
" (#{env.inspect}): " \
|
38
|
-
'must be :tartan, :production, or a full URL, ' \
|
39
|
-
"e.g. 'https://tartan.plaid.com'"
|
40
|
-
end
|
41
|
-
end
|
42
|
-
|
43
|
-
# Public: Construct a Client instance.
|
106
|
+
# path - Path or URL to make the request to
|
107
|
+
# payload - The payload or data to post
|
44
108
|
#
|
45
|
-
#
|
46
|
-
|
47
|
-
|
48
|
-
# secret - The String Plaid account secret to authenticate requests.
|
49
|
-
def initialize(env: nil, client_id: nil, secret: nil)
|
50
|
-
env && self.env = env
|
51
|
-
self.client_id = client_id
|
52
|
-
self.secret = secret
|
109
|
+
# Returns the resulting parsed JSON of the request
|
110
|
+
def post(path, payload)
|
111
|
+
Plaid::Connect.post(File.join(@env, path), payload)
|
53
112
|
end
|
54
113
|
|
55
|
-
# Public:
|
114
|
+
# Public: Make a post request with appended authentication fields
|
115
|
+
#
|
116
|
+
# path - Path or URL to make the request to
|
117
|
+
# payload - The payload or data to post
|
56
118
|
#
|
57
|
-
# Returns
|
58
|
-
def
|
59
|
-
|
119
|
+
# Returns the resulting parsed JSON of the request
|
120
|
+
def post_with_auth(path, payload)
|
121
|
+
auth = { client_id: @client_id,
|
122
|
+
secret: @secret }
|
123
|
+
Plaid::Connect.post(File.join(@env, path), payload.merge(auth))
|
60
124
|
end
|
61
125
|
|
62
|
-
# Public:
|
126
|
+
# Public: Make a post request with appended public key field.
|
127
|
+
#
|
128
|
+
# path - Path or URL to make the request to.
|
129
|
+
# payload - The payload or data to post.
|
63
130
|
#
|
64
|
-
# Returns
|
65
|
-
def
|
66
|
-
@
|
131
|
+
# Returns the resulting parsed JSON of the request.
|
132
|
+
def post_with_public_key(path, payload)
|
133
|
+
public_key = { public_key: @public_key }
|
134
|
+
Plaid::Connect.post(File.join(@env, path), payload.merge(public_key))
|
67
135
|
end
|
68
136
|
end
|
69
137
|
end
|
@@ -0,0 +1,75 @@
|
|
1
|
+
require 'json'
|
2
|
+
require 'net/http'
|
3
|
+
require 'uri'
|
4
|
+
|
5
|
+
require_relative 'version'
|
6
|
+
|
7
|
+
module Plaid
|
8
|
+
# Internal: A module encapsulating HTTP post requests
|
9
|
+
module Connect
|
10
|
+
# Internal: Headers used for correct request and SDK tracking.
|
11
|
+
NETWORK_HEADERS = { 'User-Agent' => "Plaid Ruby v#{Plaid::VERSION}",
|
12
|
+
'Content-Type' => 'application/json' }.freeze
|
13
|
+
|
14
|
+
# Internal: Default read timeout for HTTP calls in seconds.
|
15
|
+
NETWORK_TIMEOUT = 600
|
16
|
+
|
17
|
+
# Internal: Run POST request on path with payload.
|
18
|
+
#
|
19
|
+
# path - The path to send the request to.
|
20
|
+
# payload - The hash with data.
|
21
|
+
#
|
22
|
+
# Returns the parsed JSON response body.
|
23
|
+
def self.post(path, payload)
|
24
|
+
uri = URI.parse(path)
|
25
|
+
|
26
|
+
http = Net::HTTP.new(uri.host, uri.port)
|
27
|
+
http.use_ssl = true
|
28
|
+
|
29
|
+
http.read_timeout = Plaid::Connect::NETWORK_TIMEOUT
|
30
|
+
|
31
|
+
request = Net::HTTP::Post.new(uri.path, Plaid::Connect::NETWORK_HEADERS)
|
32
|
+
request.body = JSON.generate(payload)
|
33
|
+
|
34
|
+
Plaid::Connect.run http, request
|
35
|
+
end
|
36
|
+
|
37
|
+
# Internal: Run the request and process the response.
|
38
|
+
#
|
39
|
+
# http - Object created by Net::HTTP.new
|
40
|
+
# request - Object created by Net::HTTP::Post.new (for POST)
|
41
|
+
#
|
42
|
+
# Returns the parsed JSON body or raises an appropriate PlaidError
|
43
|
+
def self.run(http, request)
|
44
|
+
response = http.request(request)
|
45
|
+
|
46
|
+
if response.body.nil? || response.body.empty?
|
47
|
+
raise Plaid::PlaidError.new(0, 'Server error', 'Try to connect later')
|
48
|
+
end
|
49
|
+
|
50
|
+
# All responses are expected to have a JSON body, so we always parse,
|
51
|
+
# not looking at the status code.
|
52
|
+
body = JSON.parse(response.body)
|
53
|
+
|
54
|
+
case response
|
55
|
+
when Net::HTTPSuccess
|
56
|
+
body
|
57
|
+
else
|
58
|
+
raise_error(body)
|
59
|
+
end
|
60
|
+
end
|
61
|
+
|
62
|
+
# Internal: Raise an error with the class depending on reponse body.
|
63
|
+
#
|
64
|
+
# body - A parsed response body with error.
|
65
|
+
#
|
66
|
+
# Raises a PlaidError
|
67
|
+
def self.raise_error(body)
|
68
|
+
raise Plaid::Error.error_from_type(body['error_type']).new(body['error_type'],
|
69
|
+
body['error_code'],
|
70
|
+
body['error_message'],
|
71
|
+
body['display_message'],
|
72
|
+
body['request_id'])
|
73
|
+
end
|
74
|
+
end
|
75
|
+
end
|
data/lib/plaid/errors.rb
CHANGED
@@ -1,37 +1,73 @@
|
|
1
1
|
module Plaid
|
2
|
-
# Public: Exception to throw when there are configuration problems
|
3
|
-
class NotConfiguredError < StandardError; end
|
4
|
-
|
5
2
|
# Internal: Base class for Plaid errors
|
6
3
|
class PlaidError < StandardError
|
7
|
-
attr_reader :
|
4
|
+
attr_reader :error_type, :error_code, :error_message, :display_message, :request_id
|
8
5
|
|
9
|
-
# Internal: Initialize
|
6
|
+
# Internal: Initialize an error with proper attributes
|
10
7
|
#
|
11
|
-
#
|
12
|
-
#
|
13
|
-
#
|
14
|
-
|
15
|
-
|
16
|
-
|
17
|
-
|
18
|
-
|
8
|
+
# error_type - A broad categorization of the error
|
9
|
+
# error_code - The particular error code
|
10
|
+
# error_message - A developer-friendly representation of the error message
|
11
|
+
# display_message - A user-friendly representation of the error message
|
12
|
+
# request_id - The ID of the request you made, can be used to escalate problems
|
13
|
+
def initialize(error_type, error_code, error_message, display_message, request_id)
|
14
|
+
@error_type = error_type
|
15
|
+
@error_code = error_code
|
16
|
+
@error_message = error_message
|
17
|
+
@display_message = display_message
|
18
|
+
@request_id = request_id
|
19
|
+
|
20
|
+
super "\n"\
|
21
|
+
"Error Type : #{@error_type}\n"\
|
22
|
+
"Error Code : #{@error_code}\n"\
|
23
|
+
"Error Message : #{@error_message}\n"\
|
24
|
+
"Display Message : #{@display_message}\n"\
|
25
|
+
"Request ID : #{@request_id}\n"
|
19
26
|
end
|
20
27
|
end
|
21
28
|
|
22
|
-
# Public:
|
23
|
-
class
|
29
|
+
# Public: returned when the request is malformed and cannot be processed.
|
30
|
+
class InvalidRequestError < PlaidError; end
|
24
31
|
|
25
|
-
# Public:
|
26
|
-
|
32
|
+
# Public: returned when all fields are provided and are in the correct format,
|
33
|
+
# but the values provided are incorrect in some way.
|
34
|
+
class InvalidInputError < PlaidError; end
|
27
35
|
|
28
|
-
# Public:
|
29
|
-
class
|
36
|
+
# Public: returned when the request is valid but has exceeded established rate limits.
|
37
|
+
class RateLimitExceededError < PlaidError; end
|
30
38
|
|
31
|
-
# Public:
|
32
|
-
|
39
|
+
# Public: returned during planned maintenance windows and
|
40
|
+
# in response to API internal server errors.
|
41
|
+
class APIError < PlaidError; end
|
33
42
|
|
34
|
-
# Public:
|
35
|
-
# is
|
36
|
-
class
|
43
|
+
# Public: indicates that information provided for the item (such as credentials or MFA)
|
44
|
+
# may be invalid or that the item is not supported on Plaid's platform.
|
45
|
+
class ItemError < PlaidError; end
|
46
|
+
|
47
|
+
# Internal: A module that provides utilities for errors.
|
48
|
+
module Error
|
49
|
+
# Internal: Map error_type to PlaidError
|
50
|
+
#
|
51
|
+
# Maps an error_type from an error HTTP response to an actual PlaidError class instance
|
52
|
+
#
|
53
|
+
# error_type - The type of the error as indicated by the error response body
|
54
|
+
#
|
55
|
+
# Returns an error class mapped from error_type
|
56
|
+
def self.error_from_type(error_type)
|
57
|
+
case error_type
|
58
|
+
when 'INVALID_REQUEST'
|
59
|
+
Plaid::InvalidRequestError
|
60
|
+
when 'INVALID_INPUT'
|
61
|
+
Plaid::InvalidInputError
|
62
|
+
when 'RATE_LIMIT_EXCEEDED_ERROR'
|
63
|
+
Plaid::RateLimitExceededError
|
64
|
+
when 'API_ERROR'
|
65
|
+
Plaid::APIError
|
66
|
+
when 'ITEM_ERROR'
|
67
|
+
Plaid::ItemError
|
68
|
+
else
|
69
|
+
Plaid::PlaidError
|
70
|
+
end
|
71
|
+
end
|
72
|
+
end
|
37
73
|
end
|