ofx_for_ruby 0.1.3 → 0.1.4

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA1:
3
- metadata.gz: 430b7f5c78f4a4dc08653128f5ec829d34e89079
4
- data.tar.gz: 7a6a023f4882b3f1f04a1e5e8f7d0693f316cdf5
3
+ metadata.gz: f5ff318155e5d3faeab49209d7492b3f9ba36400
4
+ data.tar.gz: 049c7b99734a9da7a0fcedf0f34dd2b051c63d29
5
5
  SHA512:
6
- metadata.gz: cb65456b98851a449e4f2124a461c0c650252565dff75d17cd8e8e0218e2a5f7f35401f437d4d8667f5ba711da233f58487f59b0aa0ace963e0b09722ab527a7
7
- data.tar.gz: 980c88061fa30811e7a1e0c43cd350d4a964498e95d4b3df8b1d818359076e6e70ccec35b26f10261aa9c0fb55abd4d04e7d26eee268874d8c8db9f29042a317
6
+ metadata.gz: 0574c03c81ba22a20babfbbba79a4d821ed7f6a5e0a131ed6d4a87f0bbfa6f31d5e3e7ee6fdb8e255fa8d9a9fa4c02755b4412ab08b94d75e905933662ea3231
7
+ data.tar.gz: 81a52f06bfc3bcd1280b2057302e0e0882c6b9a468ffcd7e73485a8ae8ad776285c4fa46e7c587fa665059d2961bc12a60c2fff8a82f05aa09b7bb085ee78da6
data/.gitignore CHANGED
@@ -7,3 +7,4 @@ test/capital_one/fixtures/capital-one-credentials
7
7
  pkg
8
8
  coverage
9
9
  documentation
10
+ tmp
data/README CHANGED
@@ -1,4 +1,4 @@
1
- This is a fork of the "OFX for Ruby" project developed by Chris Guidry <chrisguidry@gmail.com> and hosted on Rubyforge: http://rubyforge.org/projects/ofxget/. That repository has not been updated since early 2008.
1
+ This is a fork of the "OFX for Ruby" project developed by Chris Guidry <chrisguidry@gmail.com> and hosted on Rubyforge: http://rubyforge.org/projects/ofx/. That repository has not been updated since early 2008.
2
2
 
3
3
  ---------------------------------------
4
4
 
data/USAGE ADDED
@@ -0,0 +1,17 @@
1
+
2
+ An easy way to pull your OFX data is with:
3
+
4
+ fi = OFX::FinancialInstitution.get_institution('Chase')
5
+ fi.set_client(<user>, <pass>)
6
+ id = fi.get_account_id
7
+ resp = fi.send(fi.create_request_document_for_cc_statement(id))
8
+
9
+
10
+ If making changes, please test the following to ensure no regressions.
11
+ That is, the following should return data and no HTTP errors.
12
+
13
+ OFX::FinancialInstitution.get_institution('Capital One').get_anon_profile
14
+ OFX::FinancialInstitution.get_institution('Citi').get_anon_profile
15
+ OFX::FinancialInstitution.get_institution('Chase').get_anon_profile
16
+ OFX::FinancialInstitution.get_institution('AMEX').get_anon_profile
17
+
@@ -206,7 +206,9 @@ module OFX
206
206
 
207
207
  transaction_list_hash = response_hash['BANKTRANLIST']
208
208
  if (transaction_list_hash)
209
- response.transaction_range = transaction_list_hash['DTSTART'].to_datetime..transaction_list_hash['DTEND'].to_datetime
209
+ if transaction_list_hash['DTSTART'] && transaction_list_hash['DTEND']
210
+ response.transaction_range = transaction_list_hash['DTSTART'].to_datetime..transaction_list_hash['DTEND'].to_datetime
211
+ end
210
212
 
211
213
  response.transactions = []
212
214
  transactions = transaction_list_hash['STMTTRN'] if transaction_list_hash['STMTTRN'].kind_of?(Array)
@@ -221,7 +223,7 @@ module OFX
221
223
  transaction.date_initiated = transaction_hash['DTUSER'].to_datetime if transaction_hash['DTUSER']
222
224
  transaction.date_available = transaction_hash['DTAVAIL'].to_datetime if transaction_hash['DTAVAIL']
223
225
 
224
- transaction.amount = transaction_hash['TRNAMT'].to_d
226
+ transaction.amount = transaction_hash['TRNAMT'].to_d if transaction_hash['TRNAMT']
225
227
  transaction.currency = transaction_hash['CURRENCY'] || transaction_hash['ORIGCURRENCY'] || response.default_currency
226
228
 
227
229
  transaction.financial_institution_transaction_identifier = transaction_hash['FITID']
@@ -258,4 +260,4 @@ module OFX
258
260
  response
259
261
  end
260
262
  end
261
- end
263
+ end
@@ -84,22 +84,19 @@ module OFX
84
84
  def ofx_102_name
85
85
  'CCSTMT'
86
86
  end
87
+
87
88
  def ofx_102_request_body
88
89
  body = ""
89
-
90
90
  body += account.to_ofx_102_request_body
91
-
92
91
  body +=
93
- " <INCTRAN>\n" +
94
- " <INCLUDE>#{include_transactions.to_ofx_102_s}\n" if include_transactions
95
-
92
+ " <INCTRAN>\n" if include_transactions
96
93
  body +=
97
- " <DTSTART>#{included_range.begin.to_ofx_102_s}\n" +
98
- " <DTEND>#{included_range.end.to_ofx_102_s}\n" if included_range
99
-
94
+ " <DTSTART>#{included_range.begin.to_ofx_102_s}\n" +
95
+ " <DTEND>#{included_range.end.to_ofx_102_s}\n" if included_range
96
+ body +=
97
+ " <INCLUDE>#{include_transactions.to_ofx_102_s}\n" if include_transactions
100
98
  body +=
101
99
  " </INCTRAN>" if include_transactions
102
-
103
100
  body
104
101
  end
105
102
 
@@ -136,7 +133,9 @@ module OFX
136
133
 
137
134
  transaction_list_hash = response_hash['BANKTRANLIST']
138
135
  if (transaction_list_hash)
139
- response.transaction_range = transaction_list_hash['DTSTART'].to_datetime..transaction_list_hash['DTEND'].to_datetime
136
+ if transaction_list_hash['DTSTART'] && transaction_list_hash['DTEND']
137
+ response.transaction_range = transaction_list_hash['DTSTART'].to_datetime..transaction_list_hash['DTEND'].to_datetime
138
+ end
140
139
 
141
140
  response.transactions = []
142
141
  transactions = transaction_list_hash['STMTTRN'] if transaction_list_hash['STMTTRN'].kind_of?(Array)
@@ -151,7 +150,7 @@ module OFX
151
150
  transaction.date_initiated = transaction_hash['DTUSER'].to_datetime if transaction_hash['DTUSER']
152
151
  transaction.date_available = transaction_hash['DTAVAIL'].to_datetime if transaction_hash['DTAVAIL']
153
152
 
154
- transaction.amount = transaction_hash['TRNAMT'].to_d
153
+ transaction.amount = transaction_hash['TRNAMT'].to_d if transaction_hash['TRNAMT']
155
154
  transaction.currency = transaction_hash['CURRENCY'] || transaction_hash['ORIGCURRENCY'] || response.default_currency
156
155
 
157
156
  transaction.financial_institution_transaction_identifier = transaction_hash['FITID']
@@ -241,7 +240,10 @@ module OFX
241
240
  statement.currency = closing_hash['CURRENCY'] || closing_hash['ORIGCURRENCY'] || response.default_currency
242
241
 
243
242
  statement.finanical_institution_transaction_identifier = closing_hash['FITID']
244
- statement.statement_range = closing_hash['DTOPEN'].to_date..closing_hash['DTCLOSE'].to_date
243
+
244
+ if closing_hash['DTOPEN'] && closing_hash['DTCLOSE']
245
+ statement.statement_range = closing_hash['DTOPEN'].to_date..closing_hash['DTCLOSE'].to_date
246
+ end
245
247
  statement.next_statement_close = closing_hash['DTNEXT'].to_date if closing_hash['DTNEXT']
246
248
 
247
249
  statement.opening_balance = closing_hash['BALOPEN'].to_d if closing_hash['BALOPEN']
@@ -256,7 +258,9 @@ module OFX
256
258
  statement.debit_adjustements = closing_hash['DEBADJ'].to_d if closing_hash['DEBADJ']
257
259
  statement.credit_limit = closing_hash['CREDITLIMIT'].to_d if closing_hash['CREDITLIMIT']
258
260
 
259
- statement.transaction_range = closing_hash['DTPOSTSTART'].to_date..closing_hash['DTPOSTEND'].to_date
261
+ if closing_hash['DTPOSTSTART'] && closing_hash['DTPOSTEND']
262
+ statement.transaction_range = closing_hash['DTPOSTSTART'].to_date..closing_hash['DTPOSTEND'].to_date
263
+ end
260
264
 
261
265
  statement.marketing_information = closing_hash['MKTGINFO']
262
266
 
@@ -266,4 +270,4 @@ module OFX
266
270
  response
267
271
  end
268
272
  end
269
- end
273
+ end
@@ -37,7 +37,7 @@ module OFX
37
37
  header = OFX::Header.new
38
38
 
39
39
  header_pattern = /^(\w+)\:(.*)$/
40
- header_string.split("\n").each do |this_header|
40
+ header_string.split(%r{\r*\n}).each do |this_header|
41
41
  header_match = header_pattern.match(this_header)
42
42
  header[header_match[1]] = header_match[2]
43
43
  end
@@ -20,7 +20,6 @@ require File.dirname(__FILE__) + '/header'
20
20
  require File.dirname(__FILE__) + '/message_set'
21
21
  require File.dirname(__FILE__) + '/status'
22
22
  require File.dirname(__FILE__) + '/statements'
23
-
24
23
  require File.dirname(__FILE__) + '/signon_message_set'
25
24
  require File.dirname(__FILE__) + '/signup_message_set'
26
25
  require File.dirname(__FILE__) + '/banking_message_set'
@@ -32,8 +31,9 @@ require File.dirname(__FILE__) + '/payment_message_set'
32
31
  require File.dirname(__FILE__) + '/email_message_set'
33
32
  require File.dirname(__FILE__) + '/investment_security_list_message_set'
34
33
  require File.dirname(__FILE__) + '/financial_institution_profile_message_set'
35
-
36
34
  require File.dirname(__FILE__) + '/parser'
35
+ require 'date'
36
+ require 'time'
37
37
 
38
38
  module OFX
39
39
  module OFX102
@@ -57,9 +57,14 @@ module OFX
57
57
  def from_http_response_body(body)
58
58
  # puts "Raw response:\n#{body}"
59
59
 
60
- header_pattern = /(\w+\:.*\n)+/
60
+ #header_pattern = /(\w+\:.*\n)+\n/
61
+ header_pattern = /(\w+\:.*\r*\n)+\r*\n/
61
62
  header_match = header_pattern.match(body)
62
-
63
+ if header_match.nil?
64
+ raise NotImplementedError, "OFX server returned unmatched ASCII"
65
+ return body
66
+ end
67
+
63
68
  body = header_match.post_match
64
69
  header = Header.from_ofx_102_s(header_match[0].strip)
65
70
 
@@ -82,15 +87,34 @@ module OFX
82
87
  end
83
88
  end
84
89
 
85
- require 'date'
86
90
  class Date
87
91
  def to_ofx_102_s
88
92
  strftime('%Y%m%d')
89
93
  end
90
94
  end
91
95
  class DateTime
92
- def to_ofx_102_s
93
- strftime('%Y%m%d%H%M%S')
96
+ def to_time
97
+ Time.parse(self.to_s)
98
+ end
99
+
100
+ def to_ofx_102_s_defunct
101
+ strftime('%Y%m%d%H%M%S.') + (sec_fraction * 86400000000).to_i.to_s + '[' + offset.numerator.to_s + ':' + strftime('%Z') + ']'
102
+ end
103
+
104
+ def to_ofx_102_s(extended=true)
105
+ s = strftime('%Y%m%d%H%M%S')
106
+
107
+ if extended
108
+ # some servers need exactly 3 decimal places for sec_fraction
109
+ s = s + '.000'
110
+
111
+ # use Time class to return TZ in correct format for OFX
112
+ # ie. ("EDT" vs. "-07:00")
113
+ tz = to_time.zone
114
+ s = s + '[0:' + tz + ']' if tz
115
+ end
116
+
117
+ return s
94
118
  end
95
119
  end
96
120
  class String
@@ -113,7 +113,7 @@ module OFX
113
113
  response.language = response_hash['LANGUAGE']
114
114
  response.date_of_last_profile_update = response_hash['DTPROFUP'].to_datetime if response_hash['DTPROFUP']
115
115
  response.date_of_last_account_update = response_hash['DTACCTUP'].to_datetime if response_hash['DTACCTUP']
116
- response.financial_institution_identification = OFX::FinancialInstitutionIdentification.from_ofx_102_hash(response_hash['FI'])
116
+ response.financial_institution_identification = OFX::FinancialInstitutionIdentification.from_ofx_102_hash(response_hash['FI']) if response_hash['FI']
117
117
  #TODO: @session_cookie
118
118
 
119
119
  response
@@ -109,7 +109,14 @@ module OFX
109
109
  def ofx_102_response_body
110
110
  raise NotImplementedError
111
111
  end
112
-
112
+
113
+ def account_identifier(account_id=nil)
114
+ account_id = 0 if not account_id
115
+ info = accounts[account_id].account_information if accounts and accounts.size > account_id
116
+ id = info.account.account_identifier if info
117
+ return id
118
+ end
119
+
113
120
  def self.from_ofx_102_hash(transaction_hash)
114
121
  response = AccountInformationResponse.new
115
122
 
@@ -117,7 +124,10 @@ module OFX
117
124
  response.status = OFX::Status.from_ofx_102_hash(transaction_hash['STATUS'])
118
125
 
119
126
  response_hash = transaction_hash['ACCTINFORS']
120
- response.date_of_last_account_update = response_hash['DTACCTUP'].to_datetime
127
+ if not response_hash
128
+ return response
129
+ end
130
+ response.date_of_last_account_update = response_hash['DTACCTUP'].to_datetime if response_hash['DTACCTUP']
121
131
 
122
132
  response.accounts = []
123
133
  account_infos = response_hash['ACCTINFO'] if response_hash['ACCTINFO'].kind_of?(Array)
@@ -173,6 +183,19 @@ module OFX
173
183
  when 'ACTIVE' then :active
174
184
  else raise NotImplementedError
175
185
  end
186
+ elsif account_info_hash['INVACCTINFO']
187
+ cc_acct_info_hash = account_info_hash['INVACCTINFO']
188
+ account_info.account_information = OFX::CreditCardAccountInformation.new
189
+
190
+ acct_from_hash = cc_acct_info_hash['INVACCTFROM']
191
+ account_info.account_information.account = OFX::CreditCardAccount.new
192
+ account_info.account_information.account.account_identifier = acct_from_hash['ACCTID']
193
+ account_info.account_information.status = case cc_acct_info_hash['SVCSTATUS']
194
+ when 'AVAIL' then :available
195
+ when 'PEND' then :pending
196
+ when 'ACTIVE' then :active
197
+ else raise NotImplementedError
198
+ end
176
199
  else
177
200
  raise NotImplementedError
178
201
  end
@@ -183,4 +206,4 @@ module OFX
183
206
  response
184
207
  end
185
208
  end
186
- end
209
+ end
@@ -42,11 +42,21 @@ module OFX
42
42
  return nil
43
43
  end
44
44
 
45
- def application_identification
46
- OFX::ApplicationIdentification.new('OFX', '0010')
45
+ def application_identification(ofx_client_spoof=nil)
46
+ # Reference: http://wiki.mthbuilt.com/Tweaking_OFX_Connections
47
+ case ofx_client_spoof
48
+ when 'Money'
49
+ OFX::ApplicationIdentification.new('Money', '1600')
50
+ when 'Quicken'
51
+ OFX::ApplicationIdentification.new('QWIN', '1700')
52
+ when 'QuickBooks'
53
+ OFX::ApplicationIdentification.new('QBW', '1800')
54
+ else
55
+ OFX::ApplicationIdentification.new('OFX', '0010')
56
+ end
47
57
  end
48
58
 
49
- def create_signon_request_message(financial_institution_id)
59
+ def create_signon_request_message(financial_institution_id, ofx_client_id=nil)
50
60
  signonMessageSet = OFX::SignonMessageSet.new
51
61
 
52
62
  signonRequest = OFX::SignonRequest.new
@@ -56,7 +66,7 @@ module OFX
56
66
  signonRequest.language = "ENG"
57
67
  signonRequest.financial_institution_identification = self.financial_institution_identification_for(financial_institution_id)
58
68
  signonRequest.session_cookie = nil
59
- signonRequest.application_identification = self.application_identification
69
+ signonRequest.application_identification = self.application_identification(ofx_client_id)
60
70
  signonRequest.client_unique_identifier = self.client_unique_identifier
61
71
  signonMessageSet.requests << signonRequest
62
72
 
@@ -20,16 +20,44 @@ require 'uri'
20
20
  module OFX
21
21
  class FinancialInstitution
22
22
 
23
- def self.get_institution(financial_institution_name)
23
+ def self.get_institution(financial_institution_name, ofx_client_id=nil, ssl_version=nil)
24
24
  case financial_institution_name
25
25
  when 'Capital One'
26
26
  FinancialInstitution.new('Capital One',
27
- URI.parse('https://onlinebanking.capitalone.com/scripts/serverext.dll'),
28
- OFX::Version.new("1.0.2"))
27
+ URI.parse('https://onlinebanking.capitalone.com/ofx/process.ofx'),
28
+ OFX::Version.new("1.0.2"),
29
+ 'Hibernia', '1001', '065002030',
30
+ ofx_client_id, ssl_version)
29
31
  when 'Citi'
30
32
  FinancialInstitution.new('Citi',
31
- URI.parse('https://secureofx2.bankhost.com/citi/cgi-forte/ofx_rt?servicename=ofx_rt&pagename=ofx'),
32
- OFX::Version.new("1.0.2"))
33
+ URI.parse('https://www.accountonline.com/cards/svc/CitiOfxManager.do'),
34
+ OFX::Version.new("1.0.2"),
35
+ 'Citigroup', '24909', nil,
36
+ 'Quicken', ssl_version)
37
+ when 'Chase'
38
+ FinancialInstitution.new('Chase',
39
+ URI.parse('https://ofx.chase.com'),
40
+ OFX::Version.new("1.0.3"),
41
+ 'B1', '10898', nil,
42
+ 'Quicken', :TLSv1)
43
+ when 'AMEX'
44
+ FinancialInstitution.new('AMEX',
45
+ URI.parse('https://online.americanexpress.com/myca/ofxdl/desktop/desktopDownload.do?request_type=nl_ofxdownload'),
46
+ OFX::Version.new("1.0.2"),
47
+ 'AMEX', '3101', nil,
48
+ 'Quicken', ssl_version)
49
+ when 'Schwab'
50
+ FinancialInstitution.new('Schwab',
51
+ URI.parse('https://ofx.schwab.com/bankcgi_dev/ofx_server'),
52
+ OFX::Version.new("1.0.2"),
53
+ 'ISC', '101', '121202211',
54
+ 'Quicken', ssl_version)
55
+ when 'Fidelity'
56
+ FinancialInstitution.new('Fidelity',
57
+ URI.parse('https://ofx.fidelity.com/ftgw/OFX/clients/download'),
58
+ OFX::Version.new("1.0.2"),
59
+ 'fidelity.com', '7776', nil,
60
+ 'Quicken', ssl_version)
33
61
  else
34
62
  raise NotImplementedError
35
63
  end
@@ -38,11 +66,39 @@ module OFX
38
66
  attr :name
39
67
  attr :ofx_uri
40
68
  attr :ofx_version
69
+ attr :organization_name
70
+ attr :organization_id
71
+ attr :bank_identifier
72
+ attr :client
41
73
 
42
- def initialize(name, ofx_uri, ofx_version)
74
+ def initialize(name, ofx_uri, ofx_version, org_name, org_id, bank_id=nil, client_id=nil, ssl_version=nil)
43
75
  @name = name
44
76
  @ofx_uri = ofx_uri
45
77
  @ofx_version = ofx_version
78
+ @organization_name = org_name
79
+ @organization_id = org_id
80
+ @bank_identifier = bank_id
81
+ @client = nil
82
+ @ofx_client_id = client_id
83
+ @ofx_ssl_version = ssl_version
84
+ end
85
+
86
+ def set_client(user_name, password, client_uid=nil)
87
+ inst_id = OFX::FinancialInstitutionIdentification.new(
88
+ @organization_name, @organization_id)
89
+ user_cred = OFX::UserCredentials.new(user_name, password)
90
+ @client = OFX::FinancialClient.new([[inst_id, user_cred]])
91
+ # caller can generate one-time with: SecureRandom.hex(16)
92
+ # see: http://wiki.gnucash.org/wiki/Setting_up_OFXDirectConnect_in_GnuCash_2#Chase_.22username_or_password_are_incorrect.22
93
+ @client.client_unique_identifier = client_uid
94
+ @client
95
+ end
96
+
97
+ # anonymous can be used for ProfileRequest
98
+ def set_client_anon
99
+ user_name = "anonymous00000000000000000000000"
100
+ password = "anonymous00000000000000000000000"
101
+ set_client(user_name, password)
46
102
  end
47
103
 
48
104
  def create_request_document()
@@ -62,26 +118,173 @@ module OFX
62
118
  end
63
119
 
64
120
  document.header.security = "NONE"
65
-
66
121
  document.header.content_encoding = "USASCII"
67
122
  document.header.content_character_set = "1252"
68
-
69
123
  document.header.compression = "NONE"
70
-
71
124
  document.header.previous_unique_identifier = "NONE"
72
125
  document.header.unique_identifier = OFX::FileUniqueIdentifier.new
73
126
 
74
127
  document
75
128
  end
76
129
 
130
+ def create_request_document_signon
131
+ return nil if @client.nil?
132
+ requestDocument = self.create_request_document
133
+ requestDocument.message_sets << @client.create_signon_request_message(@organization_id, @ofx_client_id)
134
+ return requestDocument
135
+ end
136
+
137
+ def create_request_document_profile_update(request_date=nil)
138
+ return nil if @client.nil?
139
+ if request_date.nil?
140
+ request_date = DateTime.new(2001, 1, 1)
141
+ end
142
+ profileMessageSet = OFX::FinancialInstitutionProfileMessageSet.new
143
+ profileRequest = OFX::FinancialInstitutionProfileRequest.new
144
+ profileRequest.transaction_identifier = OFX::TransactionUniqueIdentifier.new
145
+ profileRequest.client_routing = 'MSGSET'
146
+ profileRequest.date_of_last_profile_update = request_date
147
+ profileMessageSet.requests << profileRequest
148
+
149
+ requestDocument = self.create_request_document
150
+ requestDocument.message_sets << @client.create_signon_request_message(@organization_id, @ofx_client_id)
151
+ requestDocument.message_sets << profileMessageSet
152
+ return requestDocument
153
+ end
154
+
155
+ def create_request_document_signup(request_date=nil)
156
+ return nil if @client.nil?
157
+ if request_date.nil?
158
+ request_date = DateTime.new(2001, 1, 1)
159
+ end
160
+ signup_message_set = OFX::SignupMessageSet.new
161
+ account_info_request = OFX::AccountInformationRequest.new
162
+ account_info_request.transaction_identifier = OFX::TransactionUniqueIdentifier.new
163
+ account_info_request.date_of_last_account_update = request_date
164
+ signup_message_set.requests << account_info_request
165
+
166
+ requestDocument = self.create_request_document
167
+ requestDocument.message_sets << @client.create_signon_request_message(@organization_id, @ofx_client_id)
168
+ requestDocument.message_sets << signup_message_set
169
+ return requestDocument
170
+ end
171
+
172
+ def create_request_document_for_cc_statement(account_id, date_range=nil, include_trans=true)
173
+ return nil if @client.nil?
174
+ cc_message_set = OFX::CreditCardStatementMessageSet.new
175
+ statement_request = OFX::CreditCardStatementRequest.new
176
+ statement_request.transaction_identifier = OFX::TransactionUniqueIdentifier.new
177
+ statement_request.account = OFX::CreditCardAccount.new
178
+ statement_request.account.account_identifier = account_id
179
+ if include_trans
180
+ statement_request.included_range = date_range
181
+ statement_request.include_transactions = include_trans
182
+ end
183
+ cc_message_set.requests << statement_request
184
+
185
+ requestDocument = self.create_request_document
186
+ requestDocument.message_sets << @client.create_signon_request_message(@organization_id, @ofx_client_id)
187
+ requestDocument.message_sets << cc_message_set
188
+ return requestDocument
189
+ end
190
+
191
+ def create_request_document_for_cc_closing_statement(account_id)
192
+ create_request_document_for_cc_statement(account_id, nil, false)
193
+ end
194
+
195
+ def create_request_document_for_bank_statement(account_id, date_range=nil, account_type = :checking)
196
+ return nil if @client.nil?
197
+ banking_message_set = OFX::BankingMessageSet.new
198
+ statement_request = OFX::BankingStatementRequest.new
199
+ statement_request.transaction_identifier = OFX::TransactionUniqueIdentifier.new
200
+ statement_request.account = OFX::BankingAccount.new
201
+ statement_request.account.bank_identifier = @bank_identifier
202
+ statement_request.account.branch_identifier = nil
203
+ statement_request.account.account_identifier = account_id
204
+ statement_request.account.account_type = account_type
205
+ statement_request.account.account_key = nil
206
+ statement_request.include_transactions = true if date_range
207
+ statement_request.included_range = date_range # example DateRange (start.to_date)..(end.to_date)
208
+ banking_message_set.requests << statement_request
209
+
210
+ requestDocument = self.create_request_document
211
+ requestDocument.message_sets << @client.create_signon_request_message(@organization_id, @ofx_client_id)
212
+ requestDocument.message_sets << banking_message_set
213
+ return requestDocument
214
+ end
215
+
216
+ def create_request_document_for_inv_statement(account_id, date_range=nil)
217
+ return nil if @client.nil?
218
+ inv_message_set = OFX::InvestmentStatementMessageSet.new
219
+ statement_request = OFX::BankingStatementRequest.new
220
+ statement_request.transaction_identifier = OFX::TransactionUniqueIdentifier.new
221
+ statement_request.account = OFX::BankingAccount.new
222
+ statement_request.account.bank_identifier = @bank_identifier
223
+ statement_request.account.branch_identifier = nil
224
+ statement_request.account.account_identifier = account_id
225
+ statement_request.account.account_type = :money_market
226
+ statement_request.account.account_key = nil
227
+ statement_request.include_transactions = true if date_range
228
+ statement_request.included_range = date_range
229
+ inv_message_set.requests << statement_request
230
+
231
+ requestDocument = self.create_request_document
232
+ requestDocument.message_sets << @client.create_signon_request_message(@organization_id, @ofx_client_id)
233
+ requestDocument.message_sets << inv_message_set
234
+ return requestDocument
235
+ end
236
+
237
+ def get_account_id(account_id=nil)
238
+ req = create_request_document_signup
239
+ return nil if req.nil?
240
+ resp = send(req)
241
+ id = resp.message_sets[1].responses[0].account_identifier(account_id) if resp
242
+ return id
243
+ end
244
+
77
245
  def send(document)
78
246
  serializer = OFX::Serializer.get(@ofx_version)
79
247
  request_body = serializer.to_http_post_body(document)
80
248
 
81
249
  client = OFX::HTTPClient.new(@ofx_uri)
82
- response_body = client.send(request_body)
250
+ response_body = client.send(request_body, @ofx_ssl_version)
83
251
 
84
252
  return serializer.from_http_response_body(response_body)
85
253
  end
254
+
255
+ ##
256
+ ## Debugging routines
257
+ ##
258
+ def get_anon_profile
259
+ set_client_anon
260
+ return send(create_request_document_profile_update)
261
+ end
262
+
263
+ def document_to_post_data(document, no_whitespace=false)
264
+ serializer = OFX::Serializer.get(@ofx_version)
265
+ request_body = serializer.to_http_post_body(document)
266
+ if no_whitespace
267
+ request_body.delete! " "
268
+ end
269
+ return request_body
270
+ end
271
+
272
+ def test_send(data, post_data=nil, serial_resp=true, debug_req=false, debug_resp=false)
273
+ serializer = OFX::Serializer.get(@ofx_version)
274
+ if post_data
275
+ request_body = data
276
+ else
277
+ request_body = serializer.to_http_post_body(data)
278
+ end
279
+
280
+ client = OFX::HTTPClient.new(@ofx_uri)
281
+ response_body = client.send(request_body, @ofx_ssl_version, debug_req, debug_resp)
282
+
283
+ if serial_resp
284
+ return serializer.from_http_response_body(response_body)
285
+ else
286
+ return response_body
287
+ end
288
+ end
86
289
  end
87
290
  end