yodlee_wrap 0.0.2 → 0.0.4
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/.DS_Store +0 -0
- data/README.md +22 -118
- data/lib/yodlee_wrap/response.rb +38 -1
- data/lib/yodlee_wrap/version.rb +1 -1
- data/lib/yodlee_wrap/yodlee_api.rb +20 -6
- data/yodlee_wrap-0.0.1.gem +0 -0
- metadata +3 -2
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA1:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 91be96e289ac0ed16b7bb328865c95c56b1e64e3
|
4
|
+
data.tar.gz: 6a39f206131d80dcc265bc1e86aded6606c299e5
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 8d05e183c36aabe3ba06fb028f276d4916a9cb1a3663f95d3335878f3b158e5cd818bcfceaa4654d504ccc78762fc482a00ec0b41a99a74bb9dcde7165e47168
|
7
|
+
data.tar.gz: e582b194c5a90822fd4e5ebb6c9ec37194b0b37c014ea11e13b73ca2e5cc52ae94325d284dd2db8a9d67a03b52903a0d840392c42dcc9c65ee325a3bf24aa9b2
|
data/.DS_Store
CHANGED
Binary file
|
data/README.md
CHANGED
@@ -1,40 +1,39 @@
|
|
1
1
|
|
2
|
-
# Yodlee
|
3
|
-
[![Gem Version](https://badge.fury.io/rb/yodlee-icious.svg)](http://badge.fury.io/rb/yodlee-icious) [![Code Climate](https://codeclimate.com/repos/556dcf7fe30ba00903005872/badges/9398ac76dbcae2084eeb/gpa.svg)](https://codeclimate.com/repos/556dcf7fe30ba00903005872/feed) [![Test Coverage](https://codeclimate.com/repos/556dcf7fe30ba00903005872/badges/9398ac76dbcae2084eeb/coverage.svg)](https://codeclimate.com/repos/556dcf7fe30ba00903005872/coverage)
|
4
|
-
[ ![Codeship Status for liftforward/yodlee-icious](https://codeship.com/projects/71603f00-9393-0132-dcd0-1a9a253548c0/status?branch=master)](https://codeship.com/projects/62288)
|
2
|
+
# Yodlee Wrap
|
5
3
|
|
6
|
-
Yodlee-icious (formally Yodlicious) is a ruby gem wrapping the Yodlee REST(ish) API. We had to build this for our integration with Yodlee which was somewhat more painful than it should have been so we figured we share to be a good neighbor.
|
7
4
|
|
8
|
-
|
5
|
+
Yodlee Wrap is a ruby gem wrapping the new Yodlee REST API (2016). It is built on the roots of the Yodlee-icious gem, but works with the newly named endpoints and resource names.
|
6
|
+
|
9
7
|
|
10
8
|
## Installation
|
11
9
|
|
12
10
|
Add this line to your application's Gemfile:
|
13
11
|
|
14
12
|
```ruby
|
15
|
-
gem '
|
13
|
+
gem 'yodlee_wrap'
|
16
14
|
```
|
17
15
|
|
18
|
-
|
16
|
+
Then:
|
19
17
|
|
20
18
|
$ bundle install
|
21
19
|
|
22
|
-
Or
|
20
|
+
Or, outside Rails:
|
23
21
|
|
24
|
-
$ gem install
|
22
|
+
$ gem install yodlee_wrap
|
25
23
|
|
26
24
|
## Usage
|
27
25
|
|
28
26
|
### Configuration
|
29
27
|
|
30
|
-
|
28
|
+
Like Yodleeicious, you can continue to use the app from within Rails or externally. Outside of rails (even in an irb session)
|
31
29
|
|
32
30
|
```ruby
|
33
|
-
require "
|
31
|
+
require "yodlee_wrap"
|
34
32
|
|
35
33
|
config = {
|
36
34
|
cobranded_username: your_username,
|
37
|
-
cobranded_password: your_password
|
35
|
+
cobranded_password: your_password,
|
36
|
+
webhook_endpoint: your_webhook_endpoint
|
38
37
|
}
|
39
38
|
|
40
39
|
yodlee_api = YodleeWrap::YodleeApi.new(config)
|
@@ -44,118 +43,34 @@ When in a Rails app it can be more convenient to use a global default configurat
|
|
44
43
|
|
45
44
|
```ruby
|
46
45
|
#/<myproject>/config/initializers/yodleeicious.rb
|
47
|
-
require '
|
46
|
+
require 'yodlee_wrap'
|
48
47
|
|
49
48
|
#setting default configurations for Yodleeicious
|
50
|
-
|
51
|
-
|
52
|
-
|
49
|
+
YodleeWrap::Config.base_url = ENV['YODLEE_BASE_URL']
|
50
|
+
YodleeWrap::Config.cobranded_username = ENV['YODLEE_COBRANDED_USERNAME']
|
51
|
+
YodleeWrap::Config.cobranded_password = ENV['YODLEE_COBRANDED_PASSWORD']
|
52
|
+
YodleeWrap::Config.webhook_endpoint = ENV['YODLEE_WEBHOOK_ENDPOINT']
|
53
53
|
|
54
54
|
#setting yodleeicious logger to use the Rails logger
|
55
|
-
|
55
|
+
YodleeWrap::Config.logger = Rails.logger
|
56
56
|
```
|
57
57
|
and wherever you want to use the api simply create a new one and it will pickup the global defaults.
|
58
58
|
|
59
59
|
```ruby
|
60
|
-
yodlee_api =
|
60
|
+
yodlee_api = YodleeWrap::YodleeApi.new
|
61
61
|
```
|
62
62
|
If for any reason you need to, you can pass a hash into the constructor and it will use any provided hash values over the defaults. Note this is done on each value not the entire hash.
|
63
63
|
|
64
|
-
You can also update an existing instances of the YodleeApi's configuration with the configure method. For example:
|
65
|
-
|
66
|
-
```ruby
|
67
64
|
|
68
|
-
|
65
|
+
## TODO: Documentation
|
69
66
|
|
70
|
-
|
67
|
+
For right now, check the source code for documentation. I'll document when there is more time.
|
71
68
|
|
72
|
-
|
73
|
-
```
|
74
|
-
will output
|
75
|
-
|
76
|
-
```
|
77
|
-
https://secure.yodlee.com/blablabla
|
78
|
-
```
|
79
|
-
|
80
|
-
### Configuring the proxy
|
81
|
-
|
82
|
-
If you're Yodlee account is like ours Yodlee will whitelist certain IPs for access and you'll need to proxy all of your API requests through that IP. You can set the proxy with the proxy_url key. Currently the proxy supports, http, https, and socks proxies. Simply set the proxy_url property in the config hash passed to YodleeApi and it should begin using the proxy. For example:
|
83
|
-
|
84
|
-
```
|
85
|
-
config = {
|
86
|
-
base_url: "https://consolidatedsdk.yodlee.com/yodsoap/srest/my-cobranded-path/v1.0",
|
87
|
-
cobranded_username: "my-cobranded-user",
|
88
|
-
cobranded_password: "my-cobranded-password",
|
89
|
-
proxy_url: "https://my-proxy-server-on-the-whitelist:my=proxy-port/"
|
90
|
-
}
|
69
|
+
For endpoints that are not currently included, you can call them directly on your yodlee_wrap object using
|
91
70
|
|
92
|
-
yodlee_api
|
71
|
+
``` yodlee_api.user_execute_api(:http_method, endpoint)
|
93
72
|
```
|
94
73
|
|
95
|
-
## Working with the API
|
96
|
-
|
97
|
-
The Yodlee Api responses are somewhat varied (especially the errors) and as such we build Yodleeicious as a pretty thin layer around their request/response model. We didn't attempt to map all their JSON responses into models or anything fancy like that. Instead we simply created a method for each API endpoint which takes the required parameters and return a response object. That said, Response object does provide some conveniences to make up for the inconsistent delivery of errors from Yodlee's APIs.
|
98
|
-
|
99
|
-
### Starting your cobranded session
|
100
|
-
|
101
|
-
Once you've configured an instance of the YodleeAPI the first thing you must do is start a Yodlee cobranded session. This is also a good rails console test to see if everything is configured correctly:
|
102
|
-
|
103
|
-
```ruby
|
104
|
-
pry(main)> yodlee_api = Yodleeicious::YodleeApi.new
|
105
|
-
pry(main)> response = yodlee_api.cobranded_login
|
106
|
-
pry(main)> response.success?
|
107
|
-
=> true
|
108
|
-
```
|
109
|
-
As you probably suspect the call to cobranded_login wraps the ```/authenticate/coblogin``` endpoint call. If this is a success the YodleeApi instance will cache the cobranded session id yodlee returned and use it on all subsequent api calls. You can also access this value if desired with YodleeApi#cobranded_session_token.
|
110
|
-
|
111
|
-
```
|
112
|
-
pry(main)> yodlee_api.cobranded_session_token
|
113
|
-
=> "12162013_1:a0b1ac3e32a2e656f8f5bd21de23ae1721ffd9dab8bee9f29811f5959bbf102f16c98354eba252bb030dc96e267bd2489a40562f18e09ee8ba9038d19280cc43"
|
114
|
-
```
|
115
|
-
At this point something has probably gone wrong for you and you want to see the response json from ```/authenticate/coblogin```. To do this simply use ```response#body```.
|
116
|
-
|
117
|
-
```
|
118
|
-
pry(main)> response.body
|
119
|
-
=> {"Error"=>[{"errorDetail"=>"Invalid Cobrand Credentials"}]}
|
120
|
-
```
|
121
|
-
|
122
|
-
### Starting a user session
|
123
|
-
|
124
|
-
Once the cobranded session is active a number of API endpoints will work however most of the interesting ones require you to register or login under a user account. It is within these accounts that you can add the user's bank accounts and whatnot to aggregate their financial data. There are 3 methods offered to allow you to #register_user, #login_user, or do either #login_or_register_user. After executing any of these the user session will be started and the user's session token will be cached in the YodleeApi instance and used on subsequent calls to api endpoints. As with all api calls if the call was not successful you'll need to look at the body of the response to determine what went wrong.
|
125
|
-
|
126
|
-
### Registering a new user
|
127
|
-
|
128
|
-
```
|
129
|
-
pry(main)> response = yodlee_api.register_user 'my-username', 'my-password123', 'my-email@my-domain.com'
|
130
|
-
pry(main)> yodlee_api.user_session_token
|
131
|
-
=> "12162013_1:69761d51a4010e6382ccb49b854513dbccad0f835a873d37884b68826acefaa5b8d41b634f4cc83d97d86e7df861f70860a4e4d8a3f08d5b5440eae504af5f19"
|
132
|
-
```
|
133
|
-
|
134
|
-
### Login existing user
|
135
|
-
|
136
|
-
```
|
137
|
-
pry(main)> response = yodlee_api.login_user 'my-username', 'my-password123'
|
138
|
-
pry(main)> yodlee_api.user_session_token
|
139
|
-
=> "12162013_1:69761d51a4010e6382ccb49b854513dbccad0f835a873d37884b68826acefaa5b8d41b634f4cc83d97d86e7df861f70860a4e4d8a3f08d5b5440eae504af5f19"
|
140
|
-
```
|
141
|
-
|
142
|
-
### Convenience for doing both
|
143
|
-
|
144
|
-
In case you have a situation where you don't know if the user is already registered there is #login_or_register_user
|
145
|
-
|
146
|
-
```
|
147
|
-
pry(main)> response = yodlee_api.login_or_register_user 'my-username', 'my-password123', 'my-email@my-domain.com'
|
148
|
-
pry(main)> yodlee_api.user_session_token
|
149
|
-
=> "12162013_1:69761d51a4010e6382ccb49b854513dbccad0f835a873d37884b68826acefaa5b8d41b634f4cc83d97d86e7df861f70860a4e4d8a3f08d5b5440eae504af5f19"
|
150
|
-
```
|
151
|
-
### other API methods
|
152
|
-
|
153
|
-
TODO
|
154
|
-
|
155
|
-
## Why the rename from Yodlicious?
|
156
|
-
|
157
|
-
Rubygems.org's search apparently only indexes the gem name not the description or summary. This meant that if you searched for Yodlee in there Yodlicous didn't show up. Now it does.
|
158
|
-
|
159
74
|
## Contributing
|
160
75
|
|
161
76
|
1. Fork it ( https://github.com/liftforward/yodlee-icious/fork )
|
@@ -163,14 +78,3 @@ Rubygems.org's search apparently only indexes the gem name not the description o
|
|
163
78
|
3. Commit your changes (`git commit -am 'Add some feature'`)
|
164
79
|
4. Push to the branch (`git push origin my-new-feature`)
|
165
80
|
5. Create a new Pull Request
|
166
|
-
|
167
|
-
### Running the integration suite
|
168
|
-
|
169
|
-
To run the Yodlee-icious integration tests you'll need an approved yodlee account. This is more than the one offered here [https://devnow.yodlee.com/user/register]. (Some of the integration suite will work against the devnow APIs but not all. On my todo list is to separate them out to make testing easier.) The integration suite expects these values to be set in the following environment variables:
|
170
|
-
|
171
|
-
```
|
172
|
-
YODLEE_BASE_URL="https://consolidatedsdk.yodlee.com/yodsoap/srest/my-cobranded-path/v1.0"
|
173
|
-
YODLEE_COBRANDED_USERNAME="my-cobranded-user"
|
174
|
-
YODLEE_COBRANDED_PASSWORD="my-cobranded-password"
|
175
|
-
YODLEEICIOUS_PROXY_URL="https://my-proxy-server-on-the-whitelist:my=proxy-port/"
|
176
|
-
```
|
data/lib/yodlee_wrap/response.rb
CHANGED
@@ -17,14 +17,51 @@ module YodleeWrap
|
|
17
17
|
body.is_a?(Hash) && !(body.fetch('errorCode', nil)).nil?
|
18
18
|
end
|
19
19
|
|
20
|
+
# Determine if the PROVIDER has mfa
|
20
21
|
def mfa?
|
21
22
|
if body.is_a?(Hash) && body['provider'] && body['provider'].length == 1
|
22
|
-
body['provider'].first['mfaType']
|
23
|
+
body['provider'].first['mfaType'].present?
|
23
24
|
end
|
24
25
|
end
|
25
26
|
|
26
27
|
def mfa_type
|
28
|
+
return nil unless body['provider']
|
27
29
|
body['provider'].first['mfaType'] if mfa?
|
28
30
|
end
|
31
|
+
|
32
|
+
def refresh_status
|
33
|
+
return nil unless body['providerAccount']
|
34
|
+
body['providerAccount']['refreshInfo']['status']
|
35
|
+
end
|
36
|
+
|
37
|
+
def additional_status
|
38
|
+
return nil unless body['providerAccount']
|
39
|
+
body['providerAccount']['refreshInfo']['additionalStatus']
|
40
|
+
end
|
41
|
+
|
42
|
+
def add_in_progress?
|
43
|
+
return false unless body['providerAccount']
|
44
|
+
refresh_status == 'IN_PROGRESS' && additional_status == 'USER_INPUT_REQUIRED'
|
45
|
+
end
|
46
|
+
|
47
|
+
def mfa_available?
|
48
|
+
return false unless body['providerAccount']
|
49
|
+
body['providerAccount']['loginForm'] && body['providerAccount']['loginForm']['formType'] != 'login'
|
50
|
+
end
|
51
|
+
|
52
|
+
def add_successful?
|
53
|
+
return false unless body['providerAccount']
|
54
|
+
['SUCCESS', 'PARTIAL_SUCCESS'].include? refresh_status
|
55
|
+
end
|
56
|
+
|
57
|
+
def add_failed?
|
58
|
+
return false unless body['providerAccount']
|
59
|
+
refresh_status == 'FAILED'
|
60
|
+
end
|
61
|
+
|
62
|
+
def provider_account_id
|
63
|
+
return nil unless body['providerAccount']
|
64
|
+
body['providerAccount']['id']
|
65
|
+
end
|
29
66
|
end
|
30
67
|
end
|
data/lib/yodlee_wrap/version.rb
CHANGED
@@ -1,4 +1,5 @@
|
|
1
1
|
require 'json'
|
2
|
+
require 'byebug'
|
2
3
|
|
3
4
|
module YodleeWrap
|
4
5
|
class YodleeApi
|
@@ -97,7 +98,6 @@ module YodleeWrap
|
|
97
98
|
else
|
98
99
|
info_log response.error_message
|
99
100
|
end
|
100
|
-
|
101
101
|
@user_auth = response.success? ? response.body : nil
|
102
102
|
|
103
103
|
response
|
@@ -107,12 +107,20 @@ module YodleeWrap
|
|
107
107
|
user_session_execute_api(:get, "/v1/transactions")
|
108
108
|
end
|
109
109
|
|
110
|
+
def get_accounts_for(provider_account_id, container_name)
|
111
|
+
user_session_execute_api(:get, "/v1/accounts?providerAccountId=#{provider_account_id}&container=&#{container_name}")
|
112
|
+
end
|
113
|
+
|
114
|
+
def get_account(account_id)
|
115
|
+
user_session_execute_api(:get, "v1/accounts/#{account_id}")
|
116
|
+
end
|
117
|
+
|
110
118
|
def get_provider_details(provider_id)
|
111
119
|
user_session_execute_api(:get, "/v1/providers/#{provider_id}")
|
112
120
|
end
|
113
121
|
|
114
122
|
def add_provider_account(provider_id, provider_params)
|
115
|
-
user_session_execute_api(:post, "/v1/providers
|
123
|
+
user_session_execute_api(:post, "/v1/providers/providerAccounts?providerId=#{provider_id}", provider_params)
|
116
124
|
end
|
117
125
|
|
118
126
|
def delete_provider_account(provider_account_id)
|
@@ -121,8 +129,9 @@ module YodleeWrap
|
|
121
129
|
|
122
130
|
# After an account has been added, use the returned provider_account_id
|
123
131
|
# to get updates about the provider account.
|
132
|
+
# default to getting mfa questions if they are available.
|
124
133
|
def get_provider_account_status(provider_account_id)
|
125
|
-
user_session_execute_api(:get, "/v1/providers/providerAccounts/#{provider_account_id}")
|
134
|
+
user_session_execute_api(:get, "/v1/providers/providerAccounts/#{provider_account_id}?include=credentials")
|
126
135
|
end
|
127
136
|
|
128
137
|
# Get all provider accounts for the currently logged in user.
|
@@ -130,6 +139,10 @@ module YodleeWrap
|
|
130
139
|
user_session_execute_api(:get, '/v1/providers/providerAccounts')
|
131
140
|
end
|
132
141
|
|
142
|
+
def get_statements
|
143
|
+
user_session_execute_api(:get, '/v1/statements')
|
144
|
+
end
|
145
|
+
|
133
146
|
def update_provider_account(provider_account_id, provider_params)
|
134
147
|
user_session_execute_api(:put, "/v1/providers/providerAccounts?providerAccountIds=#{provider_account_id}", provider_params)
|
135
148
|
end
|
@@ -150,7 +163,7 @@ module YodleeWrap
|
|
150
163
|
cobranded_auth_header + ",userSession=#{user_session_token}"
|
151
164
|
end
|
152
165
|
|
153
|
-
def execute_api(method, url, params, auth_header =
|
166
|
+
def execute_api(method, url, params, auth_header = '')
|
154
167
|
debug_log "calling #{url} with #{params}"
|
155
168
|
ssl_opts = { verify: false }
|
156
169
|
connection = Faraday.new(url: base_url, ssl: ssl_opts, request: { proxy: [] })
|
@@ -160,8 +173,9 @@ module YodleeWrap
|
|
160
173
|
request.body = params.to_json unless params.empty?
|
161
174
|
request.headers['Content-Type'] = 'application/json' unless params.empty?
|
162
175
|
end
|
163
|
-
|
164
|
-
|
176
|
+
body = JSON.parse(response.body.blank? ? '{}' : response.body)
|
177
|
+
debug_log "response=#{response.status} success?=#{response.success?} body=#{body}"
|
178
|
+
Response.new(body, response.status)
|
165
179
|
end
|
166
180
|
|
167
181
|
def cobranded_session_token
|
Binary file
|
metadata
CHANGED
@@ -1,14 +1,14 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: yodlee_wrap
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 0.0.
|
4
|
+
version: 0.0.4
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Shannon Byrne
|
8
8
|
autorequire:
|
9
9
|
bindir: bin
|
10
10
|
cert_chain: []
|
11
|
-
date: 2016-06
|
11
|
+
date: 2016-07-06 00:00:00.000000000 Z
|
12
12
|
dependencies:
|
13
13
|
- !ruby/object:Gem::Dependency
|
14
14
|
name: bundler
|
@@ -121,6 +121,7 @@ files:
|
|
121
121
|
- spec/unit/yodlee_wrap/yodlee_api_spec.rb
|
122
122
|
- spec/unit/yodleeicious/config_spec.rb
|
123
123
|
- todo.md
|
124
|
+
- yodlee_wrap-0.0.1.gem
|
124
125
|
- yodlee_wrap.gemspec
|
125
126
|
- yodlicious.png
|
126
127
|
homepage: ''
|