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 +4 -4
- data/.gitignore +1 -0
- data/README +1 -1
- data/USAGE +17 -0
- data/lib/ofx/1.0.2/banking_message_set.rb +5 -3
- data/lib/ofx/1.0.2/credit_card_statement_message_set.rb +18 -14
- data/lib/ofx/1.0.2/header.rb +1 -1
- data/lib/ofx/1.0.2/serializer.rb +31 -7
- data/lib/ofx/1.0.2/signon_message_set.rb +1 -1
- data/lib/ofx/1.0.2/signup_message_set.rb +26 -3
- data/lib/ofx/financial_client.rb +14 -4
- data/lib/ofx/financial_institution.rb +213 -10
- data/lib/ofx/http/cacert.pem +2629 -2703
- data/lib/ofx/http/ofx_http_client.rb +14 -5
- data/lib/ofx/version.rb +1 -1
- data/lib/ofx_for_ruby.rb +60 -0
- data/ofx_for_ruby.gemspec +3 -2
- metadata +38 -39
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA1:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: f5ff318155e5d3faeab49209d7492b3f9ba36400
|
4
|
+
data.tar.gz: 049c7b99734a9da7a0fcedf0f34dd2b051c63d29
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 0574c03c81ba22a20babfbbba79a4d821ed7f6a5e0a131ed6d4a87f0bbfa6f31d5e3e7ee6fdb8e255fa8d9a9fa4c02755b4412ab08b94d75e905933662ea3231
|
7
|
+
data.tar.gz: 81a52f06bfc3bcd1280b2057302e0e0882c6b9a468ffcd7e73485a8ae8ad776285c4fa46e7c587fa665059d2961bc12a60c2fff8a82f05aa09b7bb085ee78da6
|
data/.gitignore
CHANGED
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/
|
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
|
-
|
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
|
-
"
|
98
|
-
"
|
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
|
-
|
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
|
-
|
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
|
-
|
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
|
data/lib/ofx/1.0.2/header.rb
CHANGED
@@ -37,7 +37,7 @@ module OFX
|
|
37
37
|
header = OFX::Header.new
|
38
38
|
|
39
39
|
header_pattern = /^(\w+)\:(.*)$/
|
40
|
-
header_string.split(
|
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
|
data/lib/ofx/1.0.2/serializer.rb
CHANGED
@@ -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
|
93
|
-
|
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
|
-
|
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
|
data/lib/ofx/financial_client.rb
CHANGED
@@ -42,11 +42,21 @@ module OFX
|
|
42
42
|
return nil
|
43
43
|
end
|
44
44
|
|
45
|
-
def application_identification
|
46
|
-
|
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/
|
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://
|
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
|