intuit_ids_aggcat 0.0.5 → 0.0.7

Sign up to get free protection for your applications and to get access to all the features.
data/README.markdown CHANGED
@@ -1,15 +1,23 @@
1
1
  intuit_ids_aggcat - A wrapper for Intuit's Aggregation & Categorization Data Services
2
2
  ==================================================================
3
- **Important Note: This gem is still under active development for its first release. Features are missing or imcomplete. It is released under the Apache 2.0 license "as-is" without warranty.**
3
+ **Important Note: This gem is still under active development. Some features provided by Intuit may be missing or imcomplete in this gem. It is released under the Apache 2.0 license "as-is" without warranty.**
4
+
5
+ Notice for Ruby 1.8.7 and Rails 2.x users: This gem has been tested with Ruby 1.9.2 and 1.9.3 and Rails 3.2.x. There are some known problems with the syntax used for hashes and with a lack of millisecond time formats that prevent the gem from working with Ruby 1.8.7 currently. Thanks to Vinh Pham for pointing this out.
4
6
 
5
7
  Configuration
6
8
  -----------------
7
- While the first release of this gem is being developed, it will not be included in gem directories. Installation of the gem can be accomplished by cloning the code from Github and installing manually:
9
+ While the first release of this gem is being developed, newer versions may be available on Github that have not yet been pushed to the RubyGems repository. Installation of the gem from RubyGems can be done by running:
10
+ `gem install intuit_ids_aggcat`
11
+
12
+ or the latest version can be cloned from Github and installing manually:
8
13
  `git clone https://github.com/rewardsummit/intuit_ids_aggcat.git`
9
- `gem build intuit_ids_aggcat.gemspec && gem install intuit_ids_aggcat-0.0.1.gem`
14
+ `gem build intuit_ids_aggcat.gemspec && gem install intuit_ids_aggcat-0.0.x.gem`
10
15
 
11
16
  ... or in a Rails environment using bundler by adding this to your Gemfile:
12
- `gem 'quicken_parser', :git => 'https://github.com/rewardsummit/intuit_ids_aggcat.git'`
17
+ `gem 'intuit_ids_aggcat', :git => 'https://github.com/rewardsummit/intuit_ids_aggcat.git'`
18
+ for the latest development version in Github or:
19
+ `gem 'intuit_ids_aggcat'`
20
+ for the version in the RubyGems repository that should be production-ready.
13
21
 
14
22
  Once installed, you can manually configure the gem at runtime (e.g. in a pure Ruby environment) by doing:
15
23
  `require "intuit_ids_aggcat"`
@@ -64,7 +72,7 @@ The gem currently provides the following helper class methods from IntuitIdsAggc
64
72
 
65
73
  - get_institutions(oauth_token_info, consumer_key, consumer_secret): all arguments optional, a "default" user context will be used for the request and consumer_key and consumer_secret will be pulled from the gem configuration if not specified. Returns an XML document with institution data.
66
74
  - get_institution_detail(id, oauth_token_info, consumer_key, consumer_secret): id is required and is the institution ID for which the detail is retrieved, all other arguments optional, a "default" user context will be used for the request and consumer_key and consumer_secret will be pulled from the gem configuration if not specified. Returns institution detail XML document.
67
- - discover_and_add_accounts_with_credentials institution_id, username, creds_hash, oauth_token_info, consumer_key, consumer_secret, timeout): Discovers and adds accounts from institution in the context of username or using the auth_tokens provided using the key/value pairs in creds_hash to populate the credentials/credential elements of the login request message. If no oauth_token_info is provided, new tokens will be provisioned using username. consumer_key, consumer_secret are optional and will be pulled from the gem configuration. timeout is optional, default is 30 seconds. **Currently only supports FIs that do NOT use MFA. Still under development!**
75
+ - discover_and_add_accounts_with_credentials institution_id, username, creds_hash, oauth_token_info, consumer_key, consumer_secret, timeout): Discovers and adds accounts from institution in the context of username or using the auth_tokens provided using the key/value pairs in creds_hash to populate the credentials/credential elements of the login request message. If no oauth_token_info is provided, new tokens will be provisioned using username. consumer_key, consumer_secret are optional and will be pulled from the gem configuration. timeout is optional, default is 30 seconds
68
76
  - delete_customer(username, oauth_token_info, consumer_key, consumer_secret): Deletes a customer from aggregation in the context of username or using the oauth_tokens provided.
69
77
 
70
78
  Return values from all methods except get_institutions and get_institution_detail are a hash with a response_code key with the HTTP response code value and a response_xml key containing a REXML::Document object.
@@ -87,7 +95,7 @@ Return values from all methods except get_institutions and get_institution_detai
87
95
 
88
96
  Testing
89
97
  ----------
90
- In order to thoroughly test the Intuit integration, many of the RSpec tests included with this gem make live calls to the Intuit services and use Intuit's test financial institutions/customers/accounts. In order for this to work, real OAuth tokens and the corresponding private key and issuer ID need to be used. To configure these the tests assume there is a YAML configuration in spec/config/real_config.yml in the following format:
98
+ In order to thoroughly test the Intuit integration, many of the RSpec tests included with this gem make live calls to the Intuit services and use Intuit's test financial institutions/customers/accounts. In order for this to work, real OAuth tokens and the corresponding private key and issuer ID need to be used. To configure these the tests assume there is a YAML configuration in spec/config/real_config.yml in the following format:
91
99
 
92
100
  `certificate_path: key_file`
93
101
  `issuer_id: issuer_id`
@@ -98,6 +106,11 @@ Note that the tests do create a test user to validate the integration and this w
98
106
 
99
107
  The .gitignore file contains spec/config/real_config.yml and spec/config/real_cert.key to prevent sensitive information from being checked in. Note that if you change the names, or .gitignore is modified, this may not hold true. Exercise caution when commiting code to public repos.
100
108
 
109
+ Changelog
110
+ -----------------
111
+ 0.0.7: Added support for updating institution login information with IntuitIdsAggcat::Client::Services.update_institution_login_with_credentials
112
+
113
+
101
114
  Contributing
102
115
  -----------------
103
116
  Feel free to fork this repo, make changes and submit a pull request.
@@ -4,7 +4,7 @@ class DateTimeNode < XML::Mapping::SingleAttributeNode
4
4
  path,*args = super(*args)
5
5
  @path = XML::XXPath.new(path)
6
6
  args
7
- end
7
+ end #
8
8
 
9
9
  def extract_attr_value(xml)
10
10
  # without millisecs
@@ -39,6 +39,9 @@ module IntuitIdsAggcat
39
39
  class Account; end
40
40
  class BankingAccount < Account; end
41
41
  class CreditAccount < Account; end
42
+ class InvestmentAccount < Account; end
43
+ class LoanAccount < Account; end
44
+ class OtherAccount < Account; end
42
45
  class Choice; end
43
46
  class Transaction; end
44
47
  class BankingTransaction < Transaction; end
@@ -173,14 +176,14 @@ module IntuitIdsAggcat
173
176
  include XML::Mapping
174
177
  array_node :banking_accounts, "BankingAccount", :class => BankingAccount, :default_value => nil
175
178
  array_node :credit_accounts, "CreditAccount", :class => CreditAccount, :default_value => nil
176
- #array_node :loan_accounts, "LoanAccount", :default_value => nil
177
- #array_node :investment_accounts, "InvestmentAccount", :default_value => nil
179
+ array_node :loan_accounts, "LoanAccount", :class => LoanAccount, :default_value => nil
180
+ array_node :investment_accounts, "InvestmentAccount", :class => InvestmentAccount, :default_value => nil
178
181
  #array_node :rewards_accounts, "RewardsAccount", :default_value => nil
179
- #array_node :other_accounts, "OtherAccount", :default_value => nil
182
+ array_node :other_accounts, "OtherAccount", :class => OtherAccount, :default_value => nil
180
183
  end
181
184
 
182
185
  class Account
183
- include XML::Mapping
186
+ include XML::Mapping
184
187
  numeric_node :account_id, "accountId", :default_value => nil
185
188
  text_node :status, "status", :default_value => nil
186
189
  text_node :account_number, "accountNumber", :default_value => nil
@@ -198,7 +201,7 @@ module IntuitIdsAggcat
198
201
  date_time_node :aggregation_attempt_date, "aggrAttemptDate", :default_value => nil
199
202
  text_node :currency_code, "currencyCode", :default_value => nil
200
203
  text_node :bank_id, "bankId", :default_value => nil
201
- numeric_node :institution_login_id, "institutionLongId", :default_value => nil
204
+ numeric_node :institution_login_id, "institutionLoginId", :default_value => nil
202
205
  end
203
206
 
204
207
  class BankingAccount < Account
@@ -217,6 +220,95 @@ module IntuitIdsAggcat
217
220
  numeric_node :maturity_amount, "maturityAmount", :default_value => nil
218
221
  end
219
222
 
223
+ class OtherAccount < Account
224
+ include XML::Mapping
225
+ use_mapping :_default
226
+ end
227
+
228
+ class InvestmentAccount < Account
229
+ include XML::Mapping
230
+
231
+ text_node :investment_account_type, "investmentAccountType", :default_value => nil
232
+ numeric_node :interest_margin_balance, "interestMarginBalance", :default_value => nil
233
+ numeric_node :short_balance, "shortBalance", :default_value => nil
234
+ numeric_node :available_cash_balance, "availableCashBalance", :default_value => nil
235
+ numeric_node :current_balance, "currentBalance", :default_value => nil
236
+ numeric_node :maturity_value_amount, "maturityValueAmount", :default_value => nil
237
+ numeric_node :unvested_balance, "unvestedBalance", :default_value => nil
238
+ numeric_node :emp_match_defer_amount, "empMatchDeferAmount", :default_value => nil
239
+ numeric_node :emp_match_defer_amount_ytd, "empMatchDeferAmountYtd", :default_value => nil
240
+ numeric_node :emp_match_amount, "empMatchAmount", :default_value => nil
241
+ numeric_node :emp_match_amount_ytd, "empMatchAmountYtd", :default_value => nil
242
+ numeric_node :emp_pre_tax_contrib_amount, "empPretaxContribAmount", :default_value => nil
243
+ numeric_node :emp_pre_tax_contrib_amount_ytd, "empPretaxContribAmountYtd", :default_value => nil
244
+ numeric_node :rollover_itd, "rollover_itd", :default_value => nil
245
+ numeric_node :cash_balance_amount, "cashBalanceAmount", :default_value => nil
246
+ numeric_node :initial_loan_balance, "initialLoanBalance", :default_value => nil
247
+ date_time_node :loan_start_date, "loanStartDate", :default_value => nil
248
+ numeric_node :current_loan_balance, "currentLoanBalance", :default_value => nil
249
+ numeric_node :loan_rate, "loanRate", :default_value => nil
250
+
251
+ end
252
+
253
+ class LoanAccount < Account
254
+ include XML::Mapping
255
+ text_node :loan_type, "loanType", :default_value => nil
256
+ date_time_node :posted_date, "postedDate", :default_value => nil
257
+ text_node :term, "term", :default_value => nil
258
+ text_node :holder_name, "holderName", :default_value => nil
259
+ numeric_node :late_fee_amount, "lateFeeAmount", :default_value => nil
260
+ numeric_node :payoff_amount, "payoffAmount", :default_value => nil
261
+ date_time_node :payoff_amount_date, "payoffAmountDate", :default_value => nil
262
+ text_node :reference_number, "referenceNumber", :default_value => nil
263
+ date_time_node :original_maturity_date, "originalMaturityDate", :default_value => nil
264
+ text_node :tax_payee_name, "taxPayeeName", :default_value => nil
265
+ numeric_node :principal_balance, "principalBalance", :default_value => nil
266
+ numeric_node :escrow_balance, "escrowBalance", :default_value => nil
267
+ numeric_node :interest_rate, "interestRate", :default_value => nil
268
+ text_node :interest_period, "interestPeriod", :default_value => nil
269
+ numeric_node :initial_amount, "initialAmount", :default_value => nil
270
+ date_time_node :initial_date, "initialDate", :default_value => nil
271
+ numeric_node :next_payment_principal_amount, "nextPaymentPrincipalAmount", :default_value => nil
272
+ numeric_node :next_payment_interest_amount, "nextPaymentInterestAmount", :default_value => nil
273
+ numeric_node :next_payment, "nextPayment", :default_value => nil
274
+ date_time_node :next_payment_date, "nextPaymentDate", :default_value => nil
275
+ date_time_node :next_payment_due_date, "nextPaymentDueDate", :default_value => nil
276
+ date_time_node :next_payment_receive_date, "nextPaymentReceiveDate", :default_value => nil
277
+ numeric_node :last_payment_amount, "lastPaymentAmount", :default_value => nil
278
+ numeric_node :last_payment_principal_amount, "lastPaymentPrincipalAmount", :default_value => nil
279
+ numeric_node :last_payment_interest_amount, "lastPaymentInterestAmount", :default_value => nil
280
+ numeric_node :last_payment_escrow_amount, "lastPaymentEscrowAmount", :default_value => nil
281
+ numeric_node :last_payment_last_fee_amount, "lastPaymentLastFeeAmount", :default_value => nil
282
+ numeric_node :last_payment_late_charge, "lastPaymentLateCharge", :default_value => nil
283
+ numeric_node :principal_paid_ytd, "principalPaidYTD", :default_value => nil
284
+ numeric_node :interest_paid_ytd, "interestPaidYTD", :default_value => nil
285
+ numeric_node :insurance_paid_ytd, "insurancePaidYTD", :default_value => nil
286
+ numeric_node :tax_paid_ytd, "taxPaidYTD", :default_value => nil
287
+ boolean_node :auto_pay_enrolled, "autoPayEnrolled", :default_value => nil
288
+ text_node :collateral, "collateral", :default_value => nil
289
+ text_node :current_school, "currentSchool", :default_value => nil
290
+ date_time_node :first_payment_date, "firstPaymentDate", :default_value => nil
291
+ text_node :guarantor, "guarantor", :default_value => nil
292
+ boolean_node :first_mortgage, "firstMortgage", :default_value => nil
293
+ text_node :loan_payment_freq, "loanPaymentFreq", :default_value => nil
294
+ numeric_node :payment_min_amount, "paymentMinAmount", :default_value => nil
295
+ text_node :original_school, "originalSchool", :default_value => nil
296
+ numeric_node :recurring_payment_amount, "recurringPaymentAmount", :default_value => nil
297
+ text_node :lender, "lender", :default_value => nil
298
+ numeric_node :ending_balance_amount, "endingBalanceAmount", :default_value => nil
299
+ numeric_node :available_balance_amount, "availableBalanceAmount", :default_value => nil
300
+ text_node :loan_term_type, "loanTermType", :default_value => nil
301
+ numeric_node :no_of_payments, "noOfPayments", :default_value => nil
302
+ numeric_node :balloon_amount, "balloonAmount", :default_value => nil
303
+ numeric_node :projected_interest, "projectedInterest", :default_value => nil
304
+ numeric_node :interest_paid_ltd, "interestPaidLtd", :default_value => nil
305
+ text_node :interest_rate_type, "interestRateType", :default_value => nil
306
+ text_node :loan_payment_type, "loanPaymentType", :default_value => nil
307
+ numeric_node :remainingPayments, "remainingPayments", :default_value => nil
308
+
309
+ end
310
+
311
+
220
312
  class CreditAccount < Account
221
313
  include XML::Mapping
222
314
  text_node :credit_account_type, "creditAccountType", :default_value => nil
@@ -244,12 +336,16 @@ module IntuitIdsAggcat
244
336
  class Common
245
337
  include XML::Mapping
246
338
  text_node :normalized_payee_name, "normalizedPayeeName", :default_value => nil
339
+ text_node :merchant, "merchant", :default_value => nil
340
+ text_node :sic_code, "sic", :default_value => nil
247
341
  end
248
342
 
249
343
  class Context
250
344
  include XML::Mapping
251
345
  text_node :source, "source", :default_value => nil
252
346
  text_node :category_name, "categoryName", :default_value => nil
347
+ text_node :context_type, "contextType", :default_value => nil
348
+ text_node :schedule_c_code, "scheduleC", :default_value => nil
253
349
  end
254
350
 
255
351
  class Categorization
@@ -285,7 +381,6 @@ module IntuitIdsAggcat
285
381
  date_time_node :available_date, "availableDate", :default_value => nil
286
382
  numeric_node :amount, "amount", :default_value => nil
287
383
  numeric_node :running_balance_amount, "runningBalanceAmount", :default_value => nil
288
- numeric_node :sic, "sic", :default_value => nil
289
384
  boolean_node :pending, "pending", "true", "false", :default_value => nil
290
385
  object_node :categorization, "categorization", :class => Categorization, :default_value => nil
291
386
  end
@@ -393,4 +488,4 @@ module IntuitIdsAggcat
393
488
  array_node :investment_transactions, "InvestmentTransaction", :class => InvestmentTransaction, :default_value => nil
394
489
  array_node :rewards_transactions, "RewardsTransaction", :class => RewardsTransaction, :default_value => nil
395
490
  end
396
- end
491
+ end
@@ -111,13 +111,7 @@ EOF_XML
111
111
  end
112
112
 
113
113
  def get_tokens username, issuer_id = IntuitIdsAggcat.config.issuer_id, oauth_consumer_key = IntuitIdsAggcat.config.oauth_consumer_key, oauth_consumer_secret = IntuitIdsAggcat.config.oauth_consumer_secret, certificate_path = IntuitIdsAggcat.config.certificate_path, certificate_string = IntuitIdsAggcat.config.certificate_string, certificate_password = IntuitIdsAggcat.config.certificate_password
114
- #if !IntuitIdsAggcat.config.oauth_token_info.nil? && !IntuitIdsAggcat.config.oauth_token_info[:oauth_token].nil? && IntuitIdsAggcat.config.oauth_token_info[:token_expiry] > (Time.now + 2)
115
- # IntuitIdsAggcat.config.oauth_token_info
116
- #else
117
114
  oauth_token_info = get_oauth_info issuer_id, username, oauth_consumer_key, oauth_consumer_secret, certificate_path, certificate_string, certificate_password
118
- # IntuitIdsAggcat.config(:oauth_token_info => oauth_token_info)
119
- # oauth_token_info
120
- #end
121
115
  end
122
116
 
123
117
  end
@@ -20,8 +20,12 @@ module IntuitIdsAggcat
20
20
  # consumer_key and consumer_secret will be retrieved from the Configuration class if not provided
21
21
  def get_institutions oauth_token_info = IntuitIdsAggcat::Client::Saml.get_tokens("default"), consumer_key = IntuitIdsAggcat.config.oauth_consumer_key, consumer_secret = IntuitIdsAggcat.config.oauth_consumer_secret
22
22
  response = oauth_get_request "https://financialdatafeed.platform.intuit.com/rest-war/v1/institutions", oauth_token_info, consumer_key, consumer_secret
23
- institutions = Institutions.load_from_xml(response[:response_xml].root)
24
- institutions.institutions
23
+ if response[:response_code] == "200"
24
+ institutions = Institutions.load_from_xml(response[:response_xml].root)
25
+ institutions.institutions
26
+ else
27
+ return nil
28
+ end
25
29
  end
26
30
 
27
31
  ##
@@ -33,6 +37,15 @@ module IntuitIdsAggcat
33
37
  institutions
34
38
  end
35
39
 
40
+ ##
41
+ # Get a specific account for a customer from aggregation at Intuit.
42
+ # username and account ID must be provided, if no oauth_token_info is provided, new tokens will be provisioned using username
43
+ def get_account username, account_id, oauth_token_info = IntuitIdsAggcat::Client::Saml.get_tokens(username), consumer_key = IntuitIdsAggcat.config.oauth_consumer_key, consumer_secret = IntuitIdsAggcat.config.oauth_consumer_secret
44
+ url = "https://financialdatafeed.platform.intuit.com/rest-war/v1/accounts/#{account_id}"
45
+ oauth_get_request url, oauth_token_info
46
+ end
47
+
48
+
36
49
  ##
37
50
  # Deletes the customer's accounts from aggregation at Intuit.
38
51
  # username must be provided, if no oauth_token_info is provided, new tokens will be provisioned using username
@@ -66,7 +79,9 @@ module IntuitIdsAggcat
66
79
  # challenge_session_id: challenge session ID to pass to challenge_response if this is a challenge
67
80
  # challenge_node_id : challenge node ID to pass to challenge_response if this is a challenge
68
81
  # description : text description of the result of the discover request
82
+
69
83
  def discover_and_add_accounts_with_credentials institution_id, username, creds_hash, oauth_token_info = IntuitIdsAggcat::Client::Saml.get_tokens(username), consumer_key = IntuitIdsAggcat.config.oauth_consumer_key, consumer_secret = IntuitIdsAggcat.config.oauth_consumer_secret, timeout = 30
84
+
70
85
  url = "https://financialdatafeed.platform.intuit.com/rest-war/v1/institutions/#{institution_id}/logins"
71
86
  credentials_array = []
72
87
  creds_hash.each do |k,v|
@@ -102,11 +117,49 @@ module IntuitIdsAggcat
102
117
  ##
103
118
  # Gets all accounts for a customer
104
119
  def get_customer_accounts username, oauth_token_info = IntuitIdsAggcat::Client::Saml.get_tokens(username), consumer_key = IntuitIdsAggcat.config.oauth_consumer_key, consumer_secret = IntuitIdsAggcat.config.oauth_consumer_secret
105
- url = "https://financialdatafeed.platform.intuit.com/rest-war/v1/accounts/"
120
+ url = "https://financialdatafeed.platform.intuit.com/v1/accounts/"
121
+ response = oauth_get_request url, oauth_token_info
122
+ accounts = AccountList.load_from_xml(response[:response_xml].root)
123
+ end
124
+
125
+ ##
126
+ # Gets accounts for a specific customer login_id
127
+ def get_login_accounts login_id, username, oauth_token_info = IntuitIdsAggcat::Client::Saml.get_tokens(username), consumer_key = IntuitIdsAggcat.config.oauth_consumer_key, consumer_secret = IntuitIdsAggcat.config.oauth_consumer_secret
128
+ url = "https://financialdatafeed.platform.intuit.com/v1/logins/#{login_id}/accounts"
106
129
  response = oauth_get_request url, oauth_token_info
107
130
  accounts = AccountList.load_from_xml(response[:response_xml].root)
108
131
  end
109
132
 
133
+ ##
134
+ # Updates an existing customer account with new credentials at an institution
135
+ # Response can include an MFA challenge; see the return values for discover_and_add_accounts_with_credentials for
136
+ # more information on possible responses
137
+ def update_institution_login_with_credentials login_id, username, creds_hash, oauth_token_info = IntuitIdsAggcat::Client::Saml.get_tokens(username), consumer_key = IntuitIdsAggcat.config.oauth_consumer_key, consumer_secret = IntuitIdsAggcat.config.oauth_consumer_secret
138
+ url = "https://financialdatafeed.platform.intuit.com/v1/logins/#{login_id}?refresh=true"
139
+ credentials_array = []
140
+ creds_hash.each do |k,v|
141
+ c = Credential.new
142
+ c.name = k
143
+ c.value = v
144
+ credentials_array.push c
145
+ end
146
+ creds = Credentials.new
147
+ creds.credential = credentials_array
148
+ il = InstitutionLogin.new
149
+ il.credentials = creds
150
+ response = oauth_put_request url, oauth_token_info, il.save_to_xml.to_s
151
+ update_credentials_data_to_hash response
152
+ end
153
+
154
+ ##
155
+ # Explicitly refreshes the customer account with new credentials at an institution
156
+ def update_institution_login_explicit_refresh login_id, username, oauth_token_info = IntuitIdsAggcat::Client::Saml.get_tokens(username), consumer_key = IntuitIdsAggcat.config.oauth_consumer_key, consumer_secret = IntuitIdsAggcat.config.oauth_consumer_secret
157
+ url = "https://financialdatafeed.platform.intuit.com/v1/logins/#{login_id}?refresh=true"
158
+ body = InstitutionLogin.new.save_to_xml.to_s
159
+ response = oauth_put_request url, oauth_token_info, body
160
+ return response
161
+ end
162
+
110
163
  ##
111
164
  # Get transactions for a specific account and timeframe
112
165
  def get_account_transactions username, account_id, start_date, end_date = nil, oauth_token_info = IntuitIdsAggcat::Client::Saml.get_tokens(username), consumer_key = IntuitIdsAggcat.config.oauth_consumer_key, consumer_secret = IntuitIdsAggcat.config.oauth_consumer_secret
@@ -121,6 +174,39 @@ module IntuitIdsAggcat
121
174
  tl = IntuitIdsAggcat::TransactionList.load_from_xml xml.root
122
175
  end
123
176
 
177
+ ##
178
+ # Helper method for parsing discover credential update response data
179
+ def update_credentials_data_to_hash daa
180
+ challenge_type = "none"
181
+ if daa[:response_code] == "200"
182
+ # return account list
183
+ accounts = AccountList.load_from_xml(daa[:response_xml].root)
184
+ { update_response: daa, challenge_type: challenge_type, challenge: nil, description: "Account information updated." }
185
+ elsif daa[:response_code] == "401" && daa[:challenge_session_id]
186
+ # return challenge
187
+ challenge = Challenges.load_from_xml(daa[:response_xml].root)
188
+ challenge_type = "unknown"
189
+ if challenge.save_to_xml.to_s.include?("<choice>")
190
+ challenge_type = "choice"
191
+ elsif challenge.save_to_xml.to_s.include?("image")
192
+ challenge_type ="image"
193
+ else
194
+ challenge_type = "text"
195
+ end
196
+ { update_response: daa, accounts: nil, challenge_type: challenge_type, challenge: challenge, challenge_session_id: daa[:challenge_session_id], challenge_node_id: daa[:challenge_node_id], description: "Multi-factor authentication required to update credentials." }
197
+ elsif daa[:response_code] == "404"
198
+ { update_response: daa, accounts: nil, challenge_type: challenge_type, challenge: nil, description: "Login ID not found." }
199
+ elsif daa[:response_code] == "408"
200
+ { update_response: daa, accounts: nil, challenge_type: challenge_type, challenge: nil, description: "Timed out." }
201
+ elsif daa[:response_code] == "500"
202
+ { update_response: daa, accounts: nil, challenge_type: challenge_type, challenge: nil, description: "Internal server error." }
203
+ elsif daa[:response_code] == "503"
204
+ { update_response: daa, accounts: nil, challenge_type: challenge_type, challenge: nil, description: "Problem at the finanical institution." }
205
+ else
206
+ { update_response: daa, accounts: nil, challenge_type: challenge_type, challenge: nil, description: "Unknown error." }
207
+ end
208
+ end
209
+
124
210
  ##
125
211
  # Helper method for parsing discover account response data
126
212
  def discover_account_data_to_hash daa
@@ -187,8 +273,34 @@ module IntuitIdsAggcat
187
273
  options = options.merge({ :proxy => IntuitIdsAggcat.config.proxy}) if !IntuitIdsAggcat.config.proxy.nil?
188
274
  consumer = OAuth::Consumer.new(consumer_key, consumer_secret, options)
189
275
  access_token = OAuth::AccessToken.new(consumer, oauth_token, oauth_token_secret)
190
- response = access_token.get(url, { "Content-Type"=>'application/xml', 'Host' => 'financialdatafeed.platform.intuit.com' })
191
- response_xml = REXML::Document.new response.body
276
+ begin
277
+ response = access_token.get(url, { "Content-Type"=>'application/xml', 'Host' => 'financialdatafeed.platform.intuit.com' })
278
+ response_xml = REXML::Document.new response.body
279
+ rescue REXML::ParseException => msg
280
+ #Rails.logger.error "REXML Parse Exception"
281
+ return nil
282
+ end
283
+ { :response_code => response.code, :response_xml => response_xml }
284
+ end
285
+
286
+ ##
287
+ # Helper method to issue put requests
288
+ def oauth_put_request url, oauth_token_info, body = nil, consumer_key = IntuitIdsAggcat.config.oauth_consumer_key, consumer_secret = IntuitIdsAggcat.config.oauth_consumer_secret, timeout = 120
289
+ oauth_token = oauth_token_info[:oauth_token]
290
+ oauth_token_secret = oauth_token_info[:oauth_token_secret]
291
+
292
+ options = { :request_token_path => 'https://financialdatafeed.platform.intuit.com', :timeout => timeout, :http_method => :put }
293
+ options = options.merge({ :proxy => IntuitIdsAggcat.config.proxy}) if !IntuitIdsAggcat.config.proxy.nil?
294
+ consumer = OAuth::Consumer.new(consumer_key, consumer_secret, options)
295
+ access_token = OAuth::AccessToken.new(consumer, oauth_token, oauth_token_secret)
296
+ begin
297
+ response = access_token.put(url, body, { "Content-Type"=>'application/xml', 'Host' => 'financialdatafeed.platform.intuit.com' })
298
+ response_xml = REXML::Document.new response.body
299
+ rescue REXML::ParseException => msg
300
+ #Rails.logger.error "REXML Parse Exception"
301
+ #Rails.logger.error msg
302
+ return nil
303
+ end
192
304
  { :response_code => response.code, :response_xml => response_xml }
193
305
  end
194
306
 
@@ -80,7 +80,7 @@ module IntuitIdsAggcat
80
80
  # Configures gem to log to the Rails default logger.
81
81
  # @return [nil]
82
82
  def self.log_to_rails_logger
83
- AWS.config(:logger => rails_logger)
83
+ # AWS.config(:logger => rails_logger)
84
84
  nil
85
85
  end
86
86
 
@@ -1,3 +1,3 @@
1
1
  module IntuitIdsAggcat
2
- VERSION = "0.0.5"
2
+ VERSION = "0.0.7"
3
3
  end
data/spec/saml_spec.rb CHANGED
@@ -21,5 +21,22 @@ describe IntuitIdsAggcat::Client::Saml do
21
21
  tokens[:oauth_token].should_not be_nil
22
22
  tokens[:token_expiry].should_not be_nil
23
23
  end
24
+
25
+ it "should return different tokens for different usernames" do
26
+ path = Pathname.new("spec/config/real_config.yml")
27
+ config = YAML::load(ERB.new(File.read(path)).result)
28
+ IntuitIdsAggcat.config(config)
29
+ tokens = IntuitIdsAggcat::Client::Saml.get_tokens "test"
30
+ tokens[:oauth_token_secret].should_not be_nil
31
+ tokens[:oauth_token].should_not be_nil
32
+ tokens[:token_expiry].should_not be_nil
33
+ tokens2 = IntuitIdsAggcat::Client::Saml.get_tokens "test2"
34
+ tokens2[:oauth_token_secret].should_not be_nil
35
+ tokens2[:oauth_token].should_not be_nil
36
+ tokens2[:token_expiry].should_not be_nil
37
+ tokens[:oauth_token_secret].should_not eql(tokens2[:oauth_token_secret])
38
+ tokens[:oauth_token].should_not eql(tokens2[:oauth_token])
39
+ end
40
+
24
41
  end
25
42
 
@@ -63,13 +63,20 @@ describe IntuitIdsAggcat::Client::Services do
63
63
  x.should_not be_nil
64
64
  x.banking_accounts.count.should be > 2
65
65
 
66
+ # get the login ID to use later in the test
67
+ login_id = x.banking_accounts[0].institution_login_id
68
+
66
69
  # get transactions from 90 days ago until current
67
70
  start = Time.now - (90 * 24 * 60 * 60)
68
- y = IntuitIdsAggcat::Client::Services.get_account_transactions 1, x.banking_accounts[0].account_id, start
71
+ y = IntuitIdsAggcat::Client::Services.get_account_transactions "9cj2hbjfgh47cna72", x.banking_accounts[0].account_id, start
69
72
  y.should_not be_nil
70
73
  y.banking_transactions[0].id.should_not be_nil
71
74
  y.banking_transactions[0].amount.should_not be_nil
72
75
 
76
+ # refresh credentials and confirm we get accounts back again
77
+ x = IntuitIdsAggcat::Client::Services.update_institution_login_with_credentials login_id, "9cj2hbjfgh47cna72", { "Banking Userid" => "direct", "Banking Password" => "anyvalue" }
78
+ x[:update_response][:response_code].should == "200"
79
+
73
80
  # delete customer
74
81
  x = IntuitIdsAggcat::Client::Services.delete_customer "9cj2hbjfgh47cna72"
75
82
  x[:response_code].should == "200"
metadata CHANGED
@@ -1,121 +1,135 @@
1
- --- !ruby/object:Gem::Specification
1
+ --- !ruby/object:Gem::Specification
2
2
  name: intuit_ids_aggcat
3
- version: !ruby/object:Gem::Version
4
- prerelease: false
5
- segments:
6
- - 0
7
- - 0
8
- - 5
9
- version: 0.0.5
3
+ version: !ruby/object:Gem::Version
4
+ version: 0.0.7
5
+ prerelease:
10
6
  platform: ruby
11
- authors:
7
+ authors:
12
8
  - Chris Hart
13
9
  autorequire:
14
10
  bindir: bin
15
11
  cert_chain: []
16
-
17
- date: 2012-12-02 00:00:00 -05:00
18
- default_executable:
19
- dependencies:
20
- - !ruby/object:Gem::Dependency
12
+ date: 2013-07-03 00:00:00.000000000 Z
13
+ dependencies:
14
+ - !ruby/object:Gem::Dependency
21
15
  name: rspec
22
- prerelease: false
23
- requirement: &id001 !ruby/object:Gem::Requirement
24
- requirements:
16
+ requirement: !ruby/object:Gem::Requirement
17
+ none: false
18
+ requirements:
25
19
  - - ~>
26
- - !ruby/object:Gem::Version
27
- segments:
28
- - 2
29
- - 11
30
- version: "2.11"
20
+ - !ruby/object:Gem::Version
21
+ version: '2.11'
31
22
  type: :development
32
- version_requirements: *id001
33
- - !ruby/object:Gem::Dependency
34
- name: vcr
35
23
  prerelease: false
36
- requirement: &id002 !ruby/object:Gem::Requirement
37
- requirements:
24
+ version_requirements: !ruby/object:Gem::Requirement
25
+ none: false
26
+ requirements:
38
27
  - - ~>
39
- - !ruby/object:Gem::Version
40
- segments:
41
- - 2
42
- - 2
43
- version: "2.2"
28
+ - !ruby/object:Gem::Version
29
+ version: '2.11'
30
+ - !ruby/object:Gem::Dependency
31
+ name: vcr
32
+ requirement: !ruby/object:Gem::Requirement
33
+ none: false
34
+ requirements:
35
+ - - ~>
36
+ - !ruby/object:Gem::Version
37
+ version: '2.2'
44
38
  type: :development
45
- version_requirements: *id002
46
- - !ruby/object:Gem::Dependency
47
- name: fakeweb
48
39
  prerelease: false
49
- requirement: &id003 !ruby/object:Gem::Requirement
50
- requirements:
40
+ version_requirements: !ruby/object:Gem::Requirement
41
+ none: false
42
+ requirements:
43
+ - - ~>
44
+ - !ruby/object:Gem::Version
45
+ version: '2.2'
46
+ - !ruby/object:Gem::Dependency
47
+ name: fakeweb
48
+ requirement: !ruby/object:Gem::Requirement
49
+ none: false
50
+ requirements:
51
51
  - - ~>
52
- - !ruby/object:Gem::Version
53
- segments:
54
- - 1
55
- - 3
56
- version: "1.3"
52
+ - !ruby/object:Gem::Version
53
+ version: '1.3'
57
54
  type: :development
58
- version_requirements: *id003
59
- - !ruby/object:Gem::Dependency
60
- name: oauth
61
55
  prerelease: false
62
- requirement: &id004 !ruby/object:Gem::Requirement
63
- requirements:
56
+ version_requirements: !ruby/object:Gem::Requirement
57
+ none: false
58
+ requirements:
59
+ - - ~>
60
+ - !ruby/object:Gem::Version
61
+ version: '1.3'
62
+ - !ruby/object:Gem::Dependency
63
+ name: oauth
64
+ requirement: !ruby/object:Gem::Requirement
65
+ none: false
66
+ requirements:
64
67
  - - ~>
65
- - !ruby/object:Gem::Version
66
- segments:
67
- - 0
68
- - 4
69
- version: "0.4"
68
+ - !ruby/object:Gem::Version
69
+ version: '0.4'
70
70
  type: :runtime
71
- version_requirements: *id004
72
- - !ruby/object:Gem::Dependency
73
- name: nokogiri
74
71
  prerelease: false
75
- requirement: &id005 !ruby/object:Gem::Requirement
76
- requirements:
72
+ version_requirements: !ruby/object:Gem::Requirement
73
+ none: false
74
+ requirements:
75
+ - - ~>
76
+ - !ruby/object:Gem::Version
77
+ version: '0.4'
78
+ - !ruby/object:Gem::Dependency
79
+ name: nokogiri
80
+ requirement: !ruby/object:Gem::Requirement
81
+ none: false
82
+ requirements:
77
83
  - - ~>
78
- - !ruby/object:Gem::Version
79
- segments:
80
- - 1
81
- - 5
82
- version: "1.5"
84
+ - !ruby/object:Gem::Version
85
+ version: '1.5'
83
86
  type: :runtime
84
- version_requirements: *id005
85
- - !ruby/object:Gem::Dependency
86
- name: xml-mapping
87
87
  prerelease: false
88
- requirement: &id006 !ruby/object:Gem::Requirement
89
- requirements:
90
- - - ">="
91
- - !ruby/object:Gem::Version
92
- segments:
93
- - 0
94
- version: "0"
88
+ version_requirements: !ruby/object:Gem::Requirement
89
+ none: false
90
+ requirements:
91
+ - - ~>
92
+ - !ruby/object:Gem::Version
93
+ version: '1.5'
94
+ - !ruby/object:Gem::Dependency
95
+ name: xml-mapping
96
+ requirement: !ruby/object:Gem::Requirement
97
+ none: false
98
+ requirements:
99
+ - - ! '>='
100
+ - !ruby/object:Gem::Version
101
+ version: '0'
95
102
  type: :runtime
96
- version_requirements: *id006
97
- - !ruby/object:Gem::Dependency
98
- name: activesupport
99
103
  prerelease: false
100
- requirement: &id007 !ruby/object:Gem::Requirement
101
- requirements:
102
- - - ">="
103
- - !ruby/object:Gem::Version
104
- segments:
105
- - 0
106
- version: "0"
104
+ version_requirements: !ruby/object:Gem::Requirement
105
+ none: false
106
+ requirements:
107
+ - - ! '>='
108
+ - !ruby/object:Gem::Version
109
+ version: '0'
110
+ - !ruby/object:Gem::Dependency
111
+ name: activesupport
112
+ requirement: !ruby/object:Gem::Requirement
113
+ none: false
114
+ requirements:
115
+ - - ! '>='
116
+ - !ruby/object:Gem::Version
117
+ version: '0'
107
118
  type: :runtime
108
- version_requirements: *id007
119
+ prerelease: false
120
+ version_requirements: !ruby/object:Gem::Requirement
121
+ none: false
122
+ requirements:
123
+ - - ! '>='
124
+ - !ruby/object:Gem::Version
125
+ version: '0'
109
126
  description: Provides a wrapped for the IPP AggCat interfaces
110
- email:
127
+ email:
111
128
  - chris@rewardsummit.com
112
129
  executables: []
113
-
114
130
  extensions: []
115
-
116
131
  extra_rdoc_files: []
117
-
118
- files:
132
+ files:
119
133
  - README.markdown
120
134
  - LICENSE.txt
121
135
  - lib/intuit_ids_aggcat/client/intuit_xml_mappings.rb
@@ -126,37 +140,38 @@ files:
126
140
  - lib/intuit_ids_aggcat/rails.rb
127
141
  - lib/intuit_ids_aggcat/version.rb
128
142
  - lib/intuit_ids_aggcat.rb
129
- has_rdoc: true
130
- homepage: ""
143
+ - spec/config/intuit_ids_aggcat.yml
144
+ - spec/config/test.crt
145
+ - spec/configuration_spec.rb
146
+ - spec/rails_spec.rb
147
+ - spec/saml_spec.rb
148
+ - spec/services_spec.rb
149
+ - spec/spec_helper.rb
150
+ homepage: ''
131
151
  licenses: []
132
-
133
152
  post_install_message:
134
153
  rdoc_options: []
135
-
136
- require_paths:
154
+ require_paths:
137
155
  - lib
138
- required_ruby_version: !ruby/object:Gem::Requirement
139
- requirements:
140
- - - ">="
141
- - !ruby/object:Gem::Version
142
- segments:
143
- - 0
144
- version: "0"
145
- required_rubygems_version: !ruby/object:Gem::Requirement
146
- requirements:
147
- - - ">="
148
- - !ruby/object:Gem::Version
149
- segments:
150
- - 0
151
- version: "0"
156
+ required_ruby_version: !ruby/object:Gem::Requirement
157
+ none: false
158
+ requirements:
159
+ - - ! '>='
160
+ - !ruby/object:Gem::Version
161
+ version: '0'
162
+ required_rubygems_version: !ruby/object:Gem::Requirement
163
+ none: false
164
+ requirements:
165
+ - - ! '>='
166
+ - !ruby/object:Gem::Version
167
+ version: '0'
152
168
  requirements: []
153
-
154
169
  rubyforge_project: intuit_ids_aggcat
155
- rubygems_version: 1.3.6
170
+ rubygems_version: 1.8.25
156
171
  signing_key:
157
172
  specification_version: 3
158
173
  summary: Integration for Intuit's aggregation and categorization services
159
- test_files:
174
+ test_files:
160
175
  - spec/config/intuit_ids_aggcat.yml
161
176
  - spec/config/test.crt
162
177
  - spec/configuration_spec.rb