plaider 0.1.0

Sign up to get free protection for your applications and to get access to all the features.
@@ -0,0 +1,7 @@
1
+ ---
2
+ SHA1:
3
+ metadata.gz: 784fe8b77ed4336121bfe0ca3627f7f1f10a64ca
4
+ data.tar.gz: 1e0ed9af526c2ac579e5524cc50f1280d0e5b2c6
5
+ SHA512:
6
+ metadata.gz: e8bd65c4519c147fa830b6f2aaa20f55e698f50d0875ff299dadec7eee5d13c76124e4216b4163fbf26ddc3ab49ad748e6902678538c83f0338afdb04f9b62b9
7
+ data.tar.gz: b6253345ea5d2ec1b3604ed65bcc5a27d250d6749ce114735ee78c69671f7a9a58b763976586e0fda3f9c02f42e524e263f7633edcc8c40ba0724eec52f82e68
@@ -0,0 +1,9 @@
1
+ /.bundle
2
+ /log/*.log
3
+ /tmp
4
+ /.idea
5
+ public/assets
6
+ .DS_Store
7
+ */.DS_Store
8
+ /coverage
9
+ /pkg
@@ -0,0 +1 @@
1
+ plaid
@@ -0,0 +1 @@
1
+ ruby-2.1.2
@@ -0,0 +1,11 @@
1
+ language: ruby
2
+ bundler_args: "--without development"
3
+ before_install:
4
+ - gem install bundler
5
+ rvm:
6
+ - 1.9.3
7
+ - 2.0.0
8
+ - 2.1.2
9
+ script:
10
+ - gem build plaider.gemspec
11
+ - gem install plaider-*
data/Gemfile ADDED
@@ -0,0 +1,12 @@
1
+ source 'https://rubygems.org'
2
+
3
+ group :test do
4
+ gem 'rake'
5
+ gem 'minitest'
6
+ gem 'test-unit'
7
+ gem 'simplecov', require: false
8
+ gem 'coveralls', require: false
9
+ gem 'webmock'
10
+ end
11
+
12
+ gemspec
@@ -0,0 +1,57 @@
1
+ PATH
2
+ remote: .
3
+ specs:
4
+ plaider (0.1.0)
5
+
6
+ GEM
7
+ remote: https://rubygems.org/
8
+ specs:
9
+ addressable (2.3.6)
10
+ coveralls (0.7.1)
11
+ multi_json (~> 1.3)
12
+ rest-client
13
+ simplecov (>= 0.7)
14
+ term-ansicolor
15
+ thor
16
+ crack (0.4.2)
17
+ safe_yaml (~> 1.0.0)
18
+ docile (1.1.5)
19
+ json (1.8.1)
20
+ mime-types (2.4.3)
21
+ minitest (5.4.2)
22
+ multi_json (1.10.1)
23
+ netrc (0.8.0)
24
+ power_assert (0.1.4)
25
+ rake (10.3.2)
26
+ rest-client (1.7.2)
27
+ mime-types (>= 1.16, < 3.0)
28
+ netrc (~> 0.7)
29
+ safe_yaml (1.0.4)
30
+ simplecov (0.9.1)
31
+ docile (~> 1.1.0)
32
+ multi_json (~> 1.0)
33
+ simplecov-html (~> 0.8.0)
34
+ simplecov-html (0.8.0)
35
+ term-ansicolor (1.3.0)
36
+ tins (~> 1.0)
37
+ test-unit (3.0.3)
38
+ power_assert
39
+ thor (0.19.1)
40
+ tins (1.3.3)
41
+ webmock (1.20.0)
42
+ addressable (>= 2.3.6)
43
+ crack (>= 0.3.2)
44
+
45
+ PLATFORMS
46
+ ruby
47
+
48
+ DEPENDENCIES
49
+ bundler (~> 1.6)
50
+ coveralls
51
+ json (~> 1.8)
52
+ minitest
53
+ plaider!
54
+ rake
55
+ simplecov
56
+ test-unit
57
+ webmock
@@ -0,0 +1,22 @@
1
+ Copyright (c) 2014 Gene Drabkin
2
+
3
+ MIT License
4
+
5
+ Permission is hereby granted, free of charge, to any person obtaining
6
+ a copy of this software and associated documentation files (the
7
+ "Software"), to deal in the Software without restriction, including
8
+ without limitation the rights to use, copy, modify, merge, publish,
9
+ distribute, sublicense, and/or sell copies of the Software, and to
10
+ permit persons to whom the Software is furnished to do so, subject to
11
+ the following conditions:
12
+
13
+ The above copyright notice and this permission notice shall be
14
+ included in all copies or substantial portions of the Software.
15
+
16
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
17
+ EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
18
+ MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
19
+ NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
20
+ LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
21
+ OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
22
+ WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
@@ -0,0 +1,91 @@
1
+ # Plaider
2
+ [![Build Status](https://travis-ci.org/cloocher/plaider.png)](https://travis-ci.org/cloocher/plaider)
3
+ [![Coverage Status](https://coveralls.io/repos/cloocher/plaider/badge.png?branch=master)](https://coveralls.io/r/cloocher/plaider)
4
+ [![Gem Version](https://badge.fury.io/rb/plaider.png)](http://badge.fury.io/rb/plaider)
5
+
6
+ Plaid API client
7
+
8
+ ## Installation
9
+
10
+ Plaider is available through [Rubygems](http://rubygems.org/gems/plaider) and can be installed via:
11
+
12
+ ```
13
+ $ gem install plaider
14
+ ```
15
+
16
+ or add it to your Gemfile like this:
17
+
18
+ ```
19
+ gem 'plaider'
20
+ ```
21
+
22
+ ## Start Guide
23
+
24
+ Register for [Plaid](https://plaid.com/account/signup).
25
+
26
+ ## Usage
27
+
28
+ ```ruby
29
+ require 'plaider'
30
+
31
+ # Plaider global configuration
32
+ Plaider.configure do |config|
33
+ config.client_id = 'client id'
34
+ config.secret = 'secret'
35
+ end
36
+
37
+ # alternatively, specify configuration options when instantiating an Aggcat::Client
38
+ client = Plaider::Client.new(
39
+ client_id: 'client id',
40
+ secret: 'secret',
41
+ access_token: 'scope for all requests'
42
+ )
43
+
44
+ # create an scoped client by customer_id
45
+ client = Aggcat.scope(customer_id)
46
+
47
+ # get all supported financial institutions
48
+ client.institutions
49
+
50
+ # get details for Chase
51
+ client.institution('5301a99504977c52b60000d0')
52
+
53
+ # add new financial account to aggregate from Chase
54
+ response = client.add_user('chase', username, password, email)
55
+
56
+ # in case MFA is required
57
+ questions = response[:mfa]
58
+ answer = 'answer'
59
+ client.user_confirmation(answer)
60
+
61
+ # get already aggregated financial accounts and transactions
62
+ client.transactions
63
+
64
+ # get all aggregated account balances
65
+ client.balance
66
+
67
+ # get account transactions
68
+ start_date = Date.today - 30
69
+ end_date = Date.today # optional
70
+ pending = true # include pending transactions
71
+ client.transactions(account_id, start_date, end_date, pending)
72
+
73
+ # update user credentials
74
+ client.update_user(new_username, new_password)
75
+
76
+ # you can set scope inline for any request
77
+ Aggcat.scope(access_request).transactions
78
+
79
+ # delete user
80
+ client.delete_user
81
+ ```
82
+
83
+ ## Requirements
84
+
85
+ * Ruby 1.9.3 or higher
86
+
87
+ ## Copyright
88
+ Copyright (c) 2014 Gene Drabkin.
89
+ See [LICENSE][] for details.
90
+
91
+ [license]: LICENSE.md
@@ -0,0 +1,10 @@
1
+ require 'bundler/gem_tasks'
2
+ require 'rake/testtask'
3
+
4
+ Rake::TestTask.new(:test) do |t|
5
+ t.libs << 'lib' << 'test'
6
+ t.pattern = 'test/*/*_test.rb'
7
+ t.verbose = true
8
+ end
9
+
10
+ task default: :test
@@ -0,0 +1,29 @@
1
+ require 'plaider/version'
2
+ require 'plaider/configurable'
3
+ require 'plaider/client'
4
+
5
+ module Plaider
6
+ class << self
7
+ include Plaider::Configurable
8
+
9
+ def scope(access_token = nil)
10
+ if !defined?(@access_token) || @access_token != access_token
11
+ @access_token = access_token
12
+ @client = Plaider::Client.new(options.merge({access_token: access_token}))
13
+ end
14
+ @client
15
+ end
16
+
17
+ def client
18
+ @client ||= Plaider::Client.new(options)
19
+ end
20
+
21
+ private
22
+
23
+ def method_missing(method_name, *args, &block)
24
+ return super unless client.respond_to?(method_name)
25
+ client.send(method_name, *args, &block)
26
+ end
27
+
28
+ end
29
+ end
@@ -0,0 +1,146 @@
1
+ require 'net/https'
2
+ require 'json'
3
+
4
+ module Plaider
5
+ class Client
6
+
7
+ BASE_URL = 'https://tartan.plaid.com'
8
+
9
+ DATE_FORMAT = '%Y-%m-%d'
10
+
11
+ OPEN_TIMEOUT = 15
12
+ READ_TIMEOUT = 120
13
+
14
+ def initialize(options={})
15
+ options[:open_timeout] ||= OPEN_TIMEOUT
16
+ options[:read_timeout] ||= READ_TIMEOUT
17
+ options[:verbose] ||= false
18
+ Plaider::Configurable::KEYS.each do |key|
19
+ instance_variable_set(:"@#{key}", !options[key].nil? ? options[key] : Plaider.instance_variable_get(:"@#{key}"))
20
+ end
21
+ end
22
+
23
+ def institutions
24
+ get('/institutions')
25
+ end
26
+
27
+ def institution(institution_id)
28
+ validate(institution_id: institution_id)
29
+ get("/institutions/#{institution_id}")
30
+ end
31
+
32
+ def categories
33
+ get('/categories')
34
+ end
35
+
36
+ def category(category_id)
37
+ validate(category_id: category_id)
38
+ get("/categories/#{category_id}")
39
+ end
40
+
41
+ def entity(entity_id)
42
+ validate(entity_id: entity_id)
43
+ get("/entities/#{entity_id}")
44
+ end
45
+
46
+ def balance
47
+ post('/balance')
48
+ end
49
+
50
+ def add_user(institution_type, username, password, email)
51
+ validate(institution_type: institution_type, username: username, password: password, email: email)
52
+ response = post('/connect', {type: institution_type, username: username, password: password, email: email})
53
+ status_code = response[:status_code].to_i
54
+ @access_token = response[:result][:access_token] if [200, 201].include?(status_code)
55
+ response
56
+ end
57
+
58
+ def user_confirmation(mfa)
59
+ validate(mfa: mfa)
60
+ post('/connect/step', {mfa: mfa})
61
+ end
62
+
63
+ def transactions(account_id = nil, start_date = nil, end_date = nil, pending = false)
64
+ params = {}
65
+ params[:account_id] = account_id if account_id
66
+ params[:gte] = format_date(start_date)
67
+ params[:lte] = format_date(end_date)
68
+ params[:pending] = account_id if pending
69
+ post('/connect/get', params)
70
+ end
71
+
72
+ def update_user(username, password)
73
+ validate(username: username, password: password)
74
+ patch('/connect', {username: username, password: password})
75
+ end
76
+
77
+ def delete_user
78
+ response = delete('/connect')
79
+ @access_token = nil
80
+ response
81
+ end
82
+
83
+ protected
84
+
85
+ def get(path)
86
+ process(Net::HTTP::Get.new(path))
87
+ end
88
+
89
+ def post(path, params = {})
90
+ request = Net::HTTP::Post.new(path)
91
+ params.merge!(credentials)
92
+ params.merge!(access_token: @access_token)
93
+ request.set_form_data(params)
94
+ process(request)
95
+ end
96
+
97
+ def patch(path, params = {})
98
+ request = Net::HTTP::Patch.new(path)
99
+ params.merge!(credentials)
100
+ params.merge!(access_token: @access_token)
101
+ request.set_form_data(params)
102
+ process(request)
103
+ end
104
+
105
+ def delete(path)
106
+ request = Net::HTTP::Delete.new(path)
107
+ request.set_form_data(credentials.merge(access_token: @access_token))
108
+ puts request.inspect
109
+ process(request)
110
+ end
111
+
112
+ private
113
+
114
+ def validate(args)
115
+ args.each do |name, value|
116
+ if value.nil? || value.to_s.empty?
117
+ raise ArgumentError.new("#{name} is required")
118
+ end
119
+ end
120
+ end
121
+
122
+ def credentials
123
+ @credentials ||= {client_id: @client_id, secret: @secret}
124
+ end
125
+
126
+ def http
127
+ unless defined?(@http)
128
+ uri = URI.parse(BASE_URL)
129
+ @http = Net::HTTP.new(uri.host, uri.port)
130
+ @http.use_ssl = true
131
+ @http.verify_mode = OpenSSL::SSL::VERIFY_NONE
132
+ end
133
+ @http
134
+ end
135
+
136
+ def process(request)
137
+ response = http.request(request)
138
+ {status_code: response.code, result: JSON.parse(response.body, {symbolize_names: true})}
139
+ end
140
+
141
+ def format_date(date)
142
+ !!date ? date.strftime(DATE_FORMAT) : date
143
+ end
144
+ end
145
+
146
+ end
@@ -0,0 +1,20 @@
1
+ module Plaider
2
+ module Configurable
3
+
4
+ KEYS = [:client_id, :secret, :access_token, :open_timeout, :read_timeout]
5
+
6
+ attr_writer *KEYS
7
+
8
+ def configure
9
+ yield self
10
+ self
11
+ end
12
+
13
+ private
14
+
15
+ def options
16
+ Plaider::Configurable::KEYS.inject({}) { |hash, key| hash[key] = instance_variable_get(:"@#{key}"); hash }
17
+ end
18
+
19
+ end
20
+ end
@@ -0,0 +1,3 @@
1
+ module Plaider
2
+ VERSION = '0.1.0'
3
+ end
@@ -0,0 +1,24 @@
1
+ # coding: utf-8
2
+ lib = File.expand_path('../lib', __FILE__)
3
+ $LOAD_PATH.unshift(lib) unless $LOAD_PATH.include?(lib)
4
+ require 'plaider/version'
5
+
6
+ Gem::Specification.new do |spec|
7
+ spec.name = 'plaider'
8
+ spec.version = Plaider::VERSION
9
+ spec.authors = ['Gene Drabkin']
10
+ spec.email = ['gene.drabkin@gmail.com']
11
+ spec.description = %q{Wraps Plaid API in a simple client}
12
+ spec.summary = %q{Ruby client for Plaid API}
13
+ spec.homepage = 'https://github.com/cloocher/plaider'
14
+ spec.license = 'MIT'
15
+ spec.files = `git ls-files -z`.split("\x0")
16
+ spec.executables = spec.files.grep(%r{^bin/}) { |f| File.basename(f) }
17
+ spec.test_files = spec.files.grep(%r{^(test|spec|features)/})
18
+ spec.require_paths = ['lib']
19
+
20
+ spec.required_ruby_version = '>= 1.9.3'
21
+
22
+ spec.add_development_dependency 'bundler', '~> 1.6'
23
+ spec.add_development_dependency 'json', '~> 1.8'
24
+ end