yodlee_wrap 0.0.0
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +7 -0
- data/.DS_Store +0 -0
- data/.gitignore +15 -0
- data/.rspec +4 -0
- data/Gemfile +16 -0
- data/Guardfile +16 -0
- data/LICENSE.txt +22 -0
- data/README.md +176 -0
- data/Rakefile +2 -0
- data/lib/yodlee_wrap/config.rb +14 -0
- data/lib/yodlee_wrap/parameter_translator.rb +27 -0
- data/lib/yodlee_wrap/response.rb +20 -0
- data/lib/yodlee_wrap/version.rb +3 -0
- data/lib/yodlee_wrap/yodlee_api.rb +183 -0
- data/lib/yodlee_wrap.rb +27 -0
- data/log/.gitkeep +0 -0
- data/spec/integration/integration_spec.rb +534 -0
- data/spec/spec_helper.rb +22 -0
- data/spec/unit/yodleeicious/config_spec.rb +65 -0
- data/spec/unit/yodleeicious/parameter_translator_spec.rb +80 -0
- data/spec/unit/yodleeicious/response_spec.rb +61 -0
- data/spec/unit/yodleeicious/yodlee_api_spec.rb +341 -0
- data/todo.md +8 -0
- data/yodlee_wrap.gemspec +31 -0
- data/yodlicious.png +0 -0
- metadata +156 -0
checksums.yaml
ADDED
@@ -0,0 +1,7 @@
|
|
1
|
+
---
|
2
|
+
SHA1:
|
3
|
+
metadata.gz: 333e83243a0aa385ef387bdcdea95b1b6e8d3d93
|
4
|
+
data.tar.gz: 46f43b8085cf36b894ad595788b3b15367d325de
|
5
|
+
SHA512:
|
6
|
+
metadata.gz: 378bae78d518fa9311b3ca23f2aee56e8f0ad5aa32dcc22d5c10e58ac191bb686ec4bf749730f4f6ca7988347bb1a10baf1848d0faacc9f04931508b953dfcd7
|
7
|
+
data.tar.gz: 87d2975006769dd6f8070a994ea3cdbeb6c5a31865380f50869e1667da86d11c14a569d6a55d3406104682a3ef6c10c5326f0e21885ea09cd5c499a354c3947b
|
data/.DS_Store
ADDED
Binary file
|
data/.gitignore
ADDED
data/.rspec
ADDED
data/Gemfile
ADDED
@@ -0,0 +1,16 @@
|
|
1
|
+
source 'https://rubygems.org'
|
2
|
+
|
3
|
+
# Specify your gem's dependencies in yodleeicious.gemspec
|
4
|
+
gemspec
|
5
|
+
|
6
|
+
gem 'faraday', '0.9.1'
|
7
|
+
gem 'faraday_middleware', '~>0.9.1'
|
8
|
+
gem 'socksify', '~>1.6.0'
|
9
|
+
gem 'dotenv'
|
10
|
+
gem 'byebug'
|
11
|
+
|
12
|
+
group :development, :test do
|
13
|
+
gem "codeclimate-test-reporter"
|
14
|
+
gem "guard-rspec"
|
15
|
+
gem 'rspec-its'
|
16
|
+
end
|
data/Guardfile
ADDED
@@ -0,0 +1,16 @@
|
|
1
|
+
# A sample Guardfile
|
2
|
+
# More info at https://github.com/guard/guard#readme
|
3
|
+
|
4
|
+
# Note: The cmd option is now required due to the increasing number of ways
|
5
|
+
# rspec may be run, below are examples of the most common uses.
|
6
|
+
# * bundler: 'bundle exec rspec'
|
7
|
+
# * bundler binstubs: 'bin/rspec'
|
8
|
+
# * spring: 'bin/rsspec' (This will use spring if running and you have
|
9
|
+
# installed the spring binstubs per the docs)
|
10
|
+
# * zeus: 'zeus rspec' (requires the server to be started separetly)
|
11
|
+
# * 'just' rspec: 'rspec'
|
12
|
+
guard :rspec, cmd: "bundle exec rspec" do
|
13
|
+
watch(%r{^spec/(.+)_spec\.rb$})
|
14
|
+
watch('spec/spec_helper.rb') { "spec" }
|
15
|
+
watch(%r{^lib/(.+)\.rb$}) { |m| "spec/unit/#{m[1]}_spec.rb" }
|
16
|
+
end
|
data/LICENSE.txt
ADDED
@@ -0,0 +1,22 @@
|
|
1
|
+
Copyright (c) 2015 Drew Nichols
|
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.
|
data/README.md
ADDED
@@ -0,0 +1,176 @@
|
|
1
|
+
|
2
|
+
# Yodlee-icious
|
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)
|
5
|
+
|
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
|
+
|
8
|
+
![image of yodleeicious](https://github.com/liftforward/yodlee-icious/blob/master/yodlicious.png)
|
9
|
+
|
10
|
+
## Installation
|
11
|
+
|
12
|
+
Add this line to your application's Gemfile:
|
13
|
+
|
14
|
+
```ruby
|
15
|
+
gem 'yodlee-icious'
|
16
|
+
```
|
17
|
+
|
18
|
+
And then execute:
|
19
|
+
|
20
|
+
$ bundle install
|
21
|
+
|
22
|
+
Or install it yourself as:
|
23
|
+
|
24
|
+
$ gem install yodlee-icious
|
25
|
+
|
26
|
+
## Usage
|
27
|
+
|
28
|
+
### Configuration
|
29
|
+
|
30
|
+
We needed to use the Yodlee API both within a rails app and outside with multiple Yodlee connections concurrently. As such we provided both the option for a global default configuration and a instance specific configuration. For instance specific:
|
31
|
+
|
32
|
+
```ruby
|
33
|
+
require "yodleeicious"
|
34
|
+
|
35
|
+
config = {
|
36
|
+
cobranded_username: your_username,
|
37
|
+
cobranded_password: your_password
|
38
|
+
}
|
39
|
+
|
40
|
+
yodlee_api = YodleeWrap::YodleeApi.new(config)
|
41
|
+
|
42
|
+
```
|
43
|
+
When in a Rails app it can be more convenient to use a global default configuration. To use global defaults:
|
44
|
+
|
45
|
+
```ruby
|
46
|
+
#/<myproject>/config/initializers/yodleeicious.rb
|
47
|
+
require 'yodleeicious'
|
48
|
+
|
49
|
+
#setting default configurations for Yodleeicious
|
50
|
+
Yodleeicious::Config.base_url = ENV['YODLEE_BASE_URL']
|
51
|
+
Yodleeicious::Config.cobranded_username = ENV['YODLEE_COBRANDED_USERNAME']
|
52
|
+
Yodleeicious::Config.cobranded_password = ENV['YODLEE_COBRANDED_PASSWORD']
|
53
|
+
|
54
|
+
#setting yodleeicious logger to use the Rails logger
|
55
|
+
Yodleeicious::Config.logger = Rails.logger
|
56
|
+
```
|
57
|
+
and wherever you want to use the api simply create a new one and it will pickup the global defaults.
|
58
|
+
|
59
|
+
```ruby
|
60
|
+
yodlee_api = Yodleeicious::YodleeApi.new
|
61
|
+
```
|
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
|
+
|
64
|
+
You can also update an existing instances of the YodleeApi's configuration with the configure method. For example:
|
65
|
+
|
66
|
+
```ruby
|
67
|
+
|
68
|
+
yodlee_api = Yodleeicious::YodleeApi.new { base_url: 'http://yodlee.com/blablabla' }
|
69
|
+
|
70
|
+
yodlee_api.configure { base_url: 'https://secure.yodlee.com/blablabla }
|
71
|
+
|
72
|
+
puts yodlee_api.base_url
|
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
|
+
}
|
91
|
+
|
92
|
+
yodlee_api = Yodleeicious::YodleeApi.new(config)
|
93
|
+
```
|
94
|
+
|
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.user_login '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
|
+
## Contributing
|
160
|
+
|
161
|
+
1. Fork it ( https://github.com/liftforward/yodlee-icious/fork )
|
162
|
+
2. Create your feature branch (`git checkout -b my-new-feature`)
|
163
|
+
3. Commit your changes (`git commit -am 'Add some feature'`)
|
164
|
+
4. Push to the branch (`git push origin my-new-feature`)
|
165
|
+
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/Rakefile
ADDED
@@ -0,0 +1,14 @@
|
|
1
|
+
|
2
|
+
|
3
|
+
module YodleeWrap
|
4
|
+
class Config
|
5
|
+
class << self
|
6
|
+
attr_accessor :cobranded_username, :cobrand_name, :cobranded_password,
|
7
|
+
:proxy_url, :logger, :webhook_endpoint
|
8
|
+
end
|
9
|
+
|
10
|
+
self.logger = Logger.new(STDOUT)
|
11
|
+
self.logger.level = Logger::WARN
|
12
|
+
|
13
|
+
end
|
14
|
+
end
|
@@ -0,0 +1,27 @@
|
|
1
|
+
module YodleeWrap
|
2
|
+
class ParameterTranslator
|
3
|
+
def site_login_form_to_add_site_account_params site_login_form
|
4
|
+
|
5
|
+
params = { "credentialFields.enclosedType" => "com.yodlee.common.FieldInfoSingle" }
|
6
|
+
|
7
|
+
i = 0
|
8
|
+
site_login_form['componentList'].each { |field|
|
9
|
+
# puts "field=#{field}"
|
10
|
+
params["credentialFields[#{i}].displayName"] = field['displayName']
|
11
|
+
params["credentialFields[#{i}].fieldType.typeName"] = field['fieldType']['typeName']
|
12
|
+
params["credentialFields[#{i}].helpText"] = field['helpText']
|
13
|
+
params["credentialFields[#{i}].maxlength"] = field['maxlength']
|
14
|
+
params["credentialFields[#{i}].name"] = field['name']
|
15
|
+
params["credentialFields[#{i}].size"] = field['size']
|
16
|
+
params["credentialFields[#{i}].value"] = field['value']
|
17
|
+
params["credentialFields[#{i}].valueIdentifier"] = field['valueIdentifier']
|
18
|
+
params["credentialFields[#{i}].valueMask"] = field['valueMask']
|
19
|
+
params["credentialFields[#{i}].isEditable"] = field['isEditable']
|
20
|
+
params["credentialFields[#{i}].value"] = field['fieldValue']
|
21
|
+
|
22
|
+
i += 1
|
23
|
+
}
|
24
|
+
params
|
25
|
+
end
|
26
|
+
end
|
27
|
+
end
|
@@ -0,0 +1,20 @@
|
|
1
|
+
module YodleeWrap
|
2
|
+
class Response
|
3
|
+
attr_accessor :body, :status, :error_code, :error_message
|
4
|
+
|
5
|
+
def initialize(body, status)
|
6
|
+
@body = body
|
7
|
+
@status = status
|
8
|
+
@error_code = body.fetch('errorCode') if fail?
|
9
|
+
@error_message = body.fetch('errorMessage') if fail?
|
10
|
+
end
|
11
|
+
|
12
|
+
def success?
|
13
|
+
!fail?
|
14
|
+
end
|
15
|
+
|
16
|
+
def fail?
|
17
|
+
body.is_a?(Hash) && !(body.fetch('errorCode', nil)).nil?
|
18
|
+
end
|
19
|
+
end
|
20
|
+
end
|
@@ -0,0 +1,183 @@
|
|
1
|
+
require 'json'
|
2
|
+
|
3
|
+
module YodleeWrap
|
4
|
+
class YodleeApi
|
5
|
+
attr_reader :base_url, :cobranded_username, :cobranded_password, :proxy_url,
|
6
|
+
:logger, :cobranded_auth, :user_auth, :cobrand_name, :webhook_endpoint
|
7
|
+
|
8
|
+
def initialize(config = {})
|
9
|
+
configure(config)
|
10
|
+
end
|
11
|
+
|
12
|
+
def configure(config = {})
|
13
|
+
validate(config)
|
14
|
+
@cobrand_name = config[:cobrand_name] || YodleeWrap::Config.cobrand_name || 'restserver'
|
15
|
+
@cobranded_username = config[:cobranded_username] || YodleeWrap::Config.cobranded_username
|
16
|
+
@cobranded_password = config[:cobranded_password] || YodleeWrap::Config.cobranded_password
|
17
|
+
@webhook_endpoint = config[:webhook_endpoint] || YodleeWrap::Config.webhook_endpoint
|
18
|
+
@logger = config[:logger] || YodleeWrap::Config.logger
|
19
|
+
|
20
|
+
info_log "YodleeApi configured with base_url=#{base_url} cobranded_username=#{cobranded_username} logger=#{logger}"
|
21
|
+
end
|
22
|
+
|
23
|
+
def validate(config)
|
24
|
+
[:cobranded_username, :cobranded_password, :logger].each do |key|
|
25
|
+
if config.key?(key) && config[key].nil?
|
26
|
+
fail 'Invalid config provided to YodleeApi. Values may not be nil/blank.'
|
27
|
+
end
|
28
|
+
end
|
29
|
+
end
|
30
|
+
|
31
|
+
def cobranded_login
|
32
|
+
params = {
|
33
|
+
cobrand: {
|
34
|
+
cobrandLogin: cobranded_username,
|
35
|
+
cobrandPassword: cobranded_password,
|
36
|
+
locale: "en_US"
|
37
|
+
}
|
38
|
+
}
|
39
|
+
response = execute_api('/v1/cobrand/login', params)
|
40
|
+
|
41
|
+
@cobranded_auth = response.success? ? response.body : nil
|
42
|
+
|
43
|
+
response
|
44
|
+
end
|
45
|
+
|
46
|
+
def user_params(username, password)
|
47
|
+
{
|
48
|
+
user: {
|
49
|
+
loginName: username,
|
50
|
+
password: password,
|
51
|
+
locale: 'en_US'
|
52
|
+
}
|
53
|
+
}
|
54
|
+
end
|
55
|
+
|
56
|
+
def user_login(username:, password:)
|
57
|
+
params = user_params(username, password)
|
58
|
+
response = cobranded_session_execute_api('/v1/user/login', params)
|
59
|
+
@user_auth = response.success? ? response.body : nil
|
60
|
+
response
|
61
|
+
end
|
62
|
+
|
63
|
+
def register_user(username:, password:, options: {}, subscribe: true)
|
64
|
+
params = user_params(username, password).merge(options)
|
65
|
+
response = cobranded_session_execute_api('/v1/user/register', params)
|
66
|
+
@user_auth = response.success? ? response.body : nil
|
67
|
+
subscribe_user_to_refresh if response.success? && subscribe
|
68
|
+
response
|
69
|
+
end
|
70
|
+
|
71
|
+
# subscribe user to webhook refresh notifications
|
72
|
+
def subscribe_user_to_refresh
|
73
|
+
params = {
|
74
|
+
event: {
|
75
|
+
callbackUrl: webhookEndpoint
|
76
|
+
}
|
77
|
+
}
|
78
|
+
user_session_execute_api('v1/cobrand/config/notifications/events/REFRESH', params)
|
79
|
+
end
|
80
|
+
|
81
|
+
def unregister_user
|
82
|
+
response = user_session_execute_api('v1/user/unregister')
|
83
|
+
@user_auth = nil if response.success?
|
84
|
+
end
|
85
|
+
|
86
|
+
def logout_user
|
87
|
+
user_session_execute_api('/v1/user/logout')
|
88
|
+
end
|
89
|
+
|
90
|
+
def login_or_register_user(username:, password:, subscribe: true)
|
91
|
+
info_log "Attempting to log in #{username}"
|
92
|
+
response = user_login(username: username, password: password)
|
93
|
+
|
94
|
+
# TODO: look into what other errors could occur here
|
95
|
+
if response.fail? && response.error_code == 'Y002'
|
96
|
+
info_log "Invalid credentials for #{username}. Attempting to register"
|
97
|
+
response = register_user(username: username, password: password, subscribe: subscribe)
|
98
|
+
else
|
99
|
+
info_log response.error_message
|
100
|
+
end
|
101
|
+
|
102
|
+
@user_auth = response.success? ? response.body : nil
|
103
|
+
|
104
|
+
response
|
105
|
+
end
|
106
|
+
|
107
|
+
def get_provider_details(provider_id)
|
108
|
+
user_session_execute_api("/v1/providers/#{provider_id}")
|
109
|
+
end
|
110
|
+
|
111
|
+
def add_provider_account(provider_id, provider_params)
|
112
|
+
user_session_execute_api("v1/providers/#{provider_id}", provider_params)
|
113
|
+
end
|
114
|
+
|
115
|
+
def delete_provider_account(provider_account_id)
|
116
|
+
user_session_execute_api("v1/providers/providerAccounts/#{provider_account_id}")
|
117
|
+
end
|
118
|
+
|
119
|
+
# After an account has been added, use the returned provider_account_id
|
120
|
+
# to get updates about the provider account.
|
121
|
+
def get_provider_account_status(provider_account_id)
|
122
|
+
user_session_execute_api("v1/providers/#{provider_account_id}")
|
123
|
+
end
|
124
|
+
|
125
|
+
def update_provider_account(provider_account_id, provider_params)
|
126
|
+
user_session_execute_api("v1/providers/providerAccounts?providerAccountIds=#{provider_account_id}", provider_params)
|
127
|
+
end
|
128
|
+
|
129
|
+
def cobranded_session_execute_api(url, params = {})
|
130
|
+
|
131
|
+
execute_api(url, params, cobranded_auth_header)
|
132
|
+
end
|
133
|
+
|
134
|
+
def user_session_execute_api(url, params = {})
|
135
|
+
|
136
|
+
execute_api(url, params, user_auth_header)
|
137
|
+
end
|
138
|
+
|
139
|
+
def cobranded_auth_header
|
140
|
+
"cobSession=#{cobranded_session_token}"
|
141
|
+
end
|
142
|
+
|
143
|
+
def user_auth_header
|
144
|
+
cobranded_auth_header + "userSession=#{user_session_token}"
|
145
|
+
end
|
146
|
+
|
147
|
+
def execute_api(url, params, auth_header = "")
|
148
|
+
debug_log "calling #{url} with #{params}"
|
149
|
+
ssl_opts = { verify: false }
|
150
|
+
connection = Faraday.new(url: base_url, ssl: ssl_opts, request: { proxy: [] })
|
151
|
+
response = connection.post do |request|
|
152
|
+
request.url "#{base_url}#{url}"
|
153
|
+
request.headers['Content-Type'] = 'application/json'
|
154
|
+
request.headers['Authorization'] = auth_header
|
155
|
+
request.body = params.to_json
|
156
|
+
end
|
157
|
+
debug_log "response=#{response.status} success?=#{response.success?} body=#{response.body}"
|
158
|
+
Response.new(JSON.parse(response.body), response.status)
|
159
|
+
end
|
160
|
+
|
161
|
+
def cobranded_session_token
|
162
|
+
return nil if cobranded_auth.nil?
|
163
|
+
cobranded_auth.fetch('session', {}).fetch('cobSession', nil)
|
164
|
+
end
|
165
|
+
|
166
|
+
def user_session_token
|
167
|
+
return nil if user_auth.nil?
|
168
|
+
user_auth.fetch('session', {}).fetch('userSession', nil)
|
169
|
+
end
|
170
|
+
|
171
|
+
def debug_log(msg)
|
172
|
+
logger.debug(msg)
|
173
|
+
end
|
174
|
+
|
175
|
+
def info_log(msg)
|
176
|
+
logger.info(msg)
|
177
|
+
end
|
178
|
+
|
179
|
+
def base_url
|
180
|
+
"https://developer.api.yodlee.com/ysl/#{cobrand_name}"
|
181
|
+
end
|
182
|
+
end
|
183
|
+
end
|
data/lib/yodlee_wrap.rb
ADDED
@@ -0,0 +1,27 @@
|
|
1
|
+
require 'rubygems'
|
2
|
+
require 'logger'
|
3
|
+
require 'faraday'
|
4
|
+
require 'socksify'
|
5
|
+
require 'socksify/http'
|
6
|
+
|
7
|
+
require File.dirname(__FILE__) + "/yodlee_wrap/version"
|
8
|
+
require File.dirname(__FILE__) + "/yodlee_wrap/config"
|
9
|
+
require File.dirname(__FILE__) + "/yodlee_wrap/parameter_translator"
|
10
|
+
require File.dirname(__FILE__) + "/yodlee_wrap/response"
|
11
|
+
require File.dirname(__FILE__) + "/yodlee_wrap/yodlee_api"
|
12
|
+
|
13
|
+
class Faraday::Adapter::NetHttp
|
14
|
+
def net_http_connection(env)
|
15
|
+
if !(proxy = env[:request][:proxy]).empty?
|
16
|
+
if proxy[:socks]
|
17
|
+
# TCPSocket.socks_username = proxy[:user] if proxy[:user]
|
18
|
+
# TCPSocket.socks_password = proxy[:password] if proxy[:password]
|
19
|
+
Net::HTTP::SOCKSProxy(proxy[:uri].host, proxy[:uri].port)
|
20
|
+
else
|
21
|
+
Net::HTTP::Proxy(proxy[:uri].host, proxy[:uri].port, proxy[:uri].user, proxy[:uri].password)
|
22
|
+
end
|
23
|
+
else
|
24
|
+
Net::HTTP
|
25
|
+
end.new(env[:url].host, env[:url].port)
|
26
|
+
end
|
27
|
+
end
|
data/log/.gitkeep
ADDED
File without changes
|