ofx_for_ruby 0.1.1
Sign up to get free protection for your applications and to get access to all the features.
- data/.externalToolBuilders/Rebuild parsers.launch +10 -0
- data/.gitignore +9 -0
- data/.loadpath +5 -0
- data/.project +27 -0
- data/COPYING +674 -0
- data/Gemfile +2 -0
- data/README +47 -0
- data/RELEASE_NOTES +45 -0
- data/Rakefile +63 -0
- data/lib/ofx.rb +60 -0
- data/lib/ofx/1.0.2/banking_message_set.rb +261 -0
- data/lib/ofx/1.0.2/credit_card_statement_message_set.rb +269 -0
- data/lib/ofx/1.0.2/document.rb +34 -0
- data/lib/ofx/1.0.2/email_message_set.rb +34 -0
- data/lib/ofx/1.0.2/financial_institution_profile_message_set.rb +155 -0
- data/lib/ofx/1.0.2/header.rb +48 -0
- data/lib/ofx/1.0.2/interbank_funds_transfer_message_set.rb +30 -0
- data/lib/ofx/1.0.2/investment_security_list_message_set.rb +30 -0
- data/lib/ofx/1.0.2/investment_statement_message_set.rb +30 -0
- data/lib/ofx/1.0.2/lexer.rb +135 -0
- data/lib/ofx/1.0.2/message_set.rb +165 -0
- data/lib/ofx/1.0.2/ofx_102.racc +90 -0
- data/lib/ofx/1.0.2/ofx_102.rex +65 -0
- data/lib/ofx/1.0.2/parser.rb +215 -0
- data/lib/ofx/1.0.2/payment_message_set.rb +30 -0
- data/lib/ofx/1.0.2/serializer.rb +114 -0
- data/lib/ofx/1.0.2/signon_message_set.rb +121 -0
- data/lib/ofx/1.0.2/signup_message_set.rb +186 -0
- data/lib/ofx/1.0.2/statements.rb +54 -0
- data/lib/ofx/1.0.2/status.rb +30 -0
- data/lib/ofx/1.0.2/wire_funds_transfer_message_set.rb +30 -0
- data/lib/ofx/banking_message_set.rb +125 -0
- data/lib/ofx/credit_card_statement_message_set.rb +104 -0
- data/lib/ofx/document.rb +30 -0
- data/lib/ofx/email_message_set.rb +42 -0
- data/lib/ofx/file_unique_identifier.rb +28 -0
- data/lib/ofx/financial_client.rb +76 -0
- data/lib/ofx/financial_institution.rb +83 -0
- data/lib/ofx/financial_institution_profile_message_set.rb +67 -0
- data/lib/ofx/header.rb +115 -0
- data/lib/ofx/http/cacert.pem +3509 -0
- data/lib/ofx/http/ofx_http_client.rb +84 -0
- data/lib/ofx/interbank_funds_transfer_message_set.rb +33 -0
- data/lib/ofx/investment_security_list_message_set.rb +33 -0
- data/lib/ofx/investment_statement_message_set.rb +33 -0
- data/lib/ofx/message_set.rb +78 -0
- data/lib/ofx/payment_message_set.rb +33 -0
- data/lib/ofx/serializer.rb +39 -0
- data/lib/ofx/signon_message_set.rb +141 -0
- data/lib/ofx/signup_message_set.rb +84 -0
- data/lib/ofx/statements.rb +49 -0
- data/lib/ofx/status.rb +100 -0
- data/lib/ofx/transaction_unique_identifier.rb +28 -0
- data/lib/ofx/version.rb +82 -0
- data/lib/ofx/wire_funds_transfer_message_set.rb +33 -0
- data/ofx_for_ruby.gemspec +25 -0
- data/planning/OFX Specification completion.ods +0 -0
- data/test/capital_one/capital_one_helper.rb +77 -0
- data/test/capital_one/fixtures/README +10 -0
- data/test/capital_one/fixtures/fipid-5599.xml +98 -0
- data/test/capital_one/test_banking_statement.rb +108 -0
- data/test/capital_one/test_financial_institution_profile.rb +295 -0
- data/test/capital_one/test_ofx_http_client.rb +72 -0
- data/test/capital_one/test_signup_account_information.rb +100 -0
- data/test/citi/citi_helper.rb +77 -0
- data/test/citi/fixtures/README +9 -0
- data/test/citi/fixtures/fipid-6642.xml +98 -0
- data/test/citi/test_credit_card_statement.rb +159 -0
- data/test/citi/test_financial_institution_profile.rb +231 -0
- data/test/citi/test_ofx_http_client.rb +71 -0
- data/test/citi/test_signup_account_information.rb +85 -0
- data/test/test_helper.rb +4 -0
- data/test/test_ofx_version.rb +141 -0
- metadata +210 -0
@@ -0,0 +1,65 @@
|
|
1
|
+
# Copyright © 2007 Chris Guidry <chrisguidry@gmail.com>
|
2
|
+
#
|
3
|
+
# This file is part of OFX for Ruby.
|
4
|
+
#
|
5
|
+
# OFX for Ruby is free software; you can redistribute it and/or modify
|
6
|
+
# it under the terms of the GNU General Public License as published by
|
7
|
+
# the Free Software Foundation; either version 3 of the License, or
|
8
|
+
# (at your option) any later version.
|
9
|
+
#
|
10
|
+
# OFX for Ruby is distributed in the hope that it will be useful,
|
11
|
+
# but WITHOUT ANY WARRANTY; without even the implied warranty of
|
12
|
+
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
13
|
+
# GNU General Public License for more details.
|
14
|
+
#
|
15
|
+
# You should have received a copy of the GNU General Public License
|
16
|
+
# along with this program. If not, see <http://www.gnu.org/licenses/>.
|
17
|
+
|
18
|
+
module OFX
|
19
|
+
module OFX102
|
20
|
+
class Parser
|
21
|
+
option
|
22
|
+
|
23
|
+
macro
|
24
|
+
TAG_IN \<
|
25
|
+
TAG_OUT \>
|
26
|
+
ETAG_IN \<\/
|
27
|
+
|
28
|
+
rule
|
29
|
+
|
30
|
+
# [:state] pattern [actions]
|
31
|
+
{ETAG_IN} { state = :TAG; [:etag_in, text] }
|
32
|
+
{TAG_IN} { state = :TAG; [:tag_in, text] }
|
33
|
+
|
34
|
+
:TAG {TAG_OUT} { state = nil; [:tag_out, text] }
|
35
|
+
|
36
|
+
:TAG [\w\-\.]+ { [:element, text] }
|
37
|
+
|
38
|
+
|
39
|
+
\s+(?=\S)
|
40
|
+
.*?(?=({TAG_IN}|{ETAG_IN})+?) { [:text, text] }
|
41
|
+
.*\S(?=\s*$) { [:text, text] }
|
42
|
+
\s+(?=$)
|
43
|
+
|
44
|
+
inner
|
45
|
+
|
46
|
+
end
|
47
|
+
|
48
|
+
end # module OFX102
|
49
|
+
end # module OFX
|
50
|
+
|
51
|
+
=begin
|
52
|
+
if __FILE__ == $0
|
53
|
+
exit if ARGV.size != 1
|
54
|
+
filename = ARGV.shift
|
55
|
+
rex = OFX::OFX102::Parser.new
|
56
|
+
begin
|
57
|
+
rex.load_file filename
|
58
|
+
while token = rex.next_token
|
59
|
+
p token
|
60
|
+
end
|
61
|
+
rescue
|
62
|
+
$stderr.printf "%s:%d:%s\n", rex.filename, rex.lineno, $!.message
|
63
|
+
end
|
64
|
+
end
|
65
|
+
=end
|
@@ -0,0 +1,215 @@
|
|
1
|
+
#
|
2
|
+
# DO NOT MODIFY!!!!
|
3
|
+
# This file is automatically generated by Racc 1.4.6
|
4
|
+
# from Racc grammer file "".
|
5
|
+
#
|
6
|
+
|
7
|
+
require 'racc/parser.rb'
|
8
|
+
|
9
|
+
#
|
10
|
+
# generated by racc
|
11
|
+
#
|
12
|
+
require File.dirname(__FILE__) + '/lexer'
|
13
|
+
|
14
|
+
module OFX
|
15
|
+
module OFX102
|
16
|
+
class Parser < Racc::Parser
|
17
|
+
|
18
|
+
module_eval(<<'...end ofx_102.racc/module_eval...', 'ofx_102.racc', 48)
|
19
|
+
|
20
|
+
attr :documents
|
21
|
+
attr :ofx_hashes
|
22
|
+
|
23
|
+
def initialize
|
24
|
+
@documents = []
|
25
|
+
@ofx_hashes = []
|
26
|
+
|
27
|
+
@tags_stack = []
|
28
|
+
end
|
29
|
+
|
30
|
+
private
|
31
|
+
def start_tag(tag_name)
|
32
|
+
# push an empty aggregate/value tag
|
33
|
+
@tags_stack.push({ tag_name => {} })
|
34
|
+
end
|
35
|
+
|
36
|
+
def data_value(value)
|
37
|
+
# pop the most recent tag, and use it's name as the key in the next higher tag's hash
|
38
|
+
tag = @tags_stack.pop
|
39
|
+
@tags_stack.last[@tags_stack.last.keys[0]][tag.keys[0]] = CGI::unescapeHTML(value)
|
40
|
+
end
|
41
|
+
|
42
|
+
def end_tag(tag_name)
|
43
|
+
# pop the most recent tag, stop and recognize this as a full document if this is the last tag; otherwise,
|
44
|
+
# use this tag's naem as the key in the next higher tag's hash
|
45
|
+
tag = @tags_stack.pop
|
46
|
+
if (@tags_stack.empty?)
|
47
|
+
@ofx_hashes << tag
|
48
|
+
@documents << OFX::Document.from_ofx_102_hash(tag)
|
49
|
+
else
|
50
|
+
previous = @tags_stack.last[@tags_stack.last.keys[0]][tag.keys[0]]
|
51
|
+
if previous == nil
|
52
|
+
@tags_stack.last[@tags_stack.last.keys[0]][tag.keys[0]] = tag[tag.keys[0]]
|
53
|
+
elsif previous.kind_of?(Array)
|
54
|
+
previous << tag[tag.keys[0]]
|
55
|
+
else
|
56
|
+
@tags_stack.last[@tags_stack.last.keys[0]][tag.keys[0]] = [previous, tag[tag.keys[0]]]
|
57
|
+
end
|
58
|
+
end
|
59
|
+
end
|
60
|
+
|
61
|
+
...end ofx_102.racc/module_eval...
|
62
|
+
##### State transition tables begin ###
|
63
|
+
|
64
|
+
racc_action_table = [
|
65
|
+
1, 6, 1, 14, 15, 14, 15, 8, 9, 5,
|
66
|
+
17, 19, 20, 1 ]
|
67
|
+
|
68
|
+
racc_action_check = [
|
69
|
+
18, 2, 7, 18, 18, 7, 7, 5, 6, 1,
|
70
|
+
14, 16, 17, 0 ]
|
71
|
+
|
72
|
+
racc_action_pointer = [
|
73
|
+
11, 6, 1, nil, nil, 3, 8, 0, nil, nil,
|
74
|
+
nil, nil, nil, nil, 7, nil, 5, 8, -2, nil,
|
75
|
+
nil, nil ]
|
76
|
+
|
77
|
+
racc_action_default = [
|
78
|
+
-1, -13, -13, -2, -6, -13, -13, -13, -4, 22,
|
79
|
+
-3, -7, -9, -10, -13, -8, -6, -13, -13, -12,
|
80
|
+
-5, -11 ]
|
81
|
+
|
82
|
+
racc_goto_table = [
|
83
|
+
7, 4, 10, 3, 2, nil, nil, nil, nil, nil,
|
84
|
+
nil, nil, 18, 21 ]
|
85
|
+
|
86
|
+
racc_goto_check = [
|
87
|
+
4, 3, 5, 2, 1, nil, nil, nil, nil, nil,
|
88
|
+
nil, nil, 4, 5 ]
|
89
|
+
|
90
|
+
racc_goto_pointer = [
|
91
|
+
nil, 4, 3, 1, -4, -5, nil, nil, nil ]
|
92
|
+
|
93
|
+
racc_goto_default = [
|
94
|
+
nil, nil, nil, 16, nil, nil, 11, 12, 13 ]
|
95
|
+
|
96
|
+
racc_reduce_table = [
|
97
|
+
0, 0, :racc_error,
|
98
|
+
0, 8, :_reduce_none,
|
99
|
+
1, 8, :_reduce_none,
|
100
|
+
3, 9, :_reduce_none,
|
101
|
+
3, 10, :_reduce_4,
|
102
|
+
3, 12, :_reduce_5,
|
103
|
+
0, 11, :_reduce_none,
|
104
|
+
2, 11, :_reduce_none,
|
105
|
+
1, 13, :_reduce_none,
|
106
|
+
1, 13, :_reduce_none,
|
107
|
+
1, 13, :_reduce_none,
|
108
|
+
3, 14, :_reduce_none,
|
109
|
+
2, 15, :_reduce_12 ]
|
110
|
+
|
111
|
+
racc_reduce_n = 13
|
112
|
+
|
113
|
+
racc_shift_n = 22
|
114
|
+
|
115
|
+
racc_token_table = {
|
116
|
+
false => 0,
|
117
|
+
:error => 1,
|
118
|
+
:tag_in => 2,
|
119
|
+
:element => 3,
|
120
|
+
:tag_out => 4,
|
121
|
+
:etag_in => 5,
|
122
|
+
:text => 6 }
|
123
|
+
|
124
|
+
racc_nt_base = 7
|
125
|
+
|
126
|
+
racc_use_result_var = true
|
127
|
+
|
128
|
+
Racc_arg = [
|
129
|
+
racc_action_table,
|
130
|
+
racc_action_check,
|
131
|
+
racc_action_default,
|
132
|
+
racc_action_pointer,
|
133
|
+
racc_goto_table,
|
134
|
+
racc_goto_check,
|
135
|
+
racc_goto_default,
|
136
|
+
racc_goto_pointer,
|
137
|
+
racc_nt_base,
|
138
|
+
racc_reduce_table,
|
139
|
+
racc_token_table,
|
140
|
+
racc_shift_n,
|
141
|
+
racc_reduce_n,
|
142
|
+
racc_use_result_var ]
|
143
|
+
|
144
|
+
Racc_token_to_s_table = [
|
145
|
+
"$end",
|
146
|
+
"error",
|
147
|
+
"tag_in",
|
148
|
+
"element",
|
149
|
+
"tag_out",
|
150
|
+
"etag_in",
|
151
|
+
"text",
|
152
|
+
"$start",
|
153
|
+
"target",
|
154
|
+
"ofx_body",
|
155
|
+
"tag_from",
|
156
|
+
"contents",
|
157
|
+
"tag_to",
|
158
|
+
"content",
|
159
|
+
"aggregate",
|
160
|
+
"value" ]
|
161
|
+
|
162
|
+
Racc_debug_parser = false
|
163
|
+
|
164
|
+
##### State transition tables end #####
|
165
|
+
|
166
|
+
# reduce 0 omitted
|
167
|
+
|
168
|
+
# reduce 1 omitted
|
169
|
+
|
170
|
+
# reduce 2 omitted
|
171
|
+
|
172
|
+
# reduce 3 omitted
|
173
|
+
|
174
|
+
module_eval(<<'.,.,', 'ofx_102.racc', 25)
|
175
|
+
def _reduce_4(val, _values, result)
|
176
|
+
start_tag(val[1])
|
177
|
+
result
|
178
|
+
end
|
179
|
+
.,.,
|
180
|
+
|
181
|
+
module_eval(<<'.,.,', 'ofx_102.racc', 26)
|
182
|
+
def _reduce_5(val, _values, result)
|
183
|
+
end_tag(val[1])
|
184
|
+
result
|
185
|
+
end
|
186
|
+
.,.,
|
187
|
+
|
188
|
+
# reduce 6 omitted
|
189
|
+
|
190
|
+
# reduce 7 omitted
|
191
|
+
|
192
|
+
# reduce 8 omitted
|
193
|
+
|
194
|
+
# reduce 9 omitted
|
195
|
+
|
196
|
+
# reduce 10 omitted
|
197
|
+
|
198
|
+
# reduce 11 omitted
|
199
|
+
|
200
|
+
module_eval(<<'.,.,', 'ofx_102.racc', 36)
|
201
|
+
def _reduce_12(val, _values, result)
|
202
|
+
data_value(val[1])
|
203
|
+
result
|
204
|
+
end
|
205
|
+
.,.,
|
206
|
+
|
207
|
+
def _reduce_none(val, _values, result)
|
208
|
+
val[0]
|
209
|
+
end
|
210
|
+
|
211
|
+
end # class Parser
|
212
|
+
end # module OFX102
|
213
|
+
end # module OFX
|
214
|
+
|
215
|
+
|
@@ -0,0 +1,30 @@
|
|
1
|
+
# Copyright © 2007 Chris Guidry <chrisguidry@gmail.com>
|
2
|
+
#
|
3
|
+
# This file is part of OFX for Ruby.
|
4
|
+
#
|
5
|
+
# OFX for Ruby is free software; you can redistribute it and/or modify
|
6
|
+
# it under the terms of the GNU General Public License as published by
|
7
|
+
# the Free Software Foundation; either version 3 of the License, or
|
8
|
+
# (at your option) any later version.
|
9
|
+
#
|
10
|
+
# OFX for Ruby is distributed in the hope that it will be useful,
|
11
|
+
# but WITHOUT ANY WARRANTY; without even the implied warranty of
|
12
|
+
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
13
|
+
# GNU General Public License for more details.
|
14
|
+
#
|
15
|
+
# You should have received a copy of the GNU General Public License
|
16
|
+
# along with this program. If not, see <http://www.gnu.org/licenses/>.
|
17
|
+
|
18
|
+
module OFX
|
19
|
+
class PaymentMessageSet < MessageSet
|
20
|
+
end
|
21
|
+
|
22
|
+
class PaymentMessageSetProfile < MessageSetProfile
|
23
|
+
def self.from_ofx_102_hash(message_set_description_hash)
|
24
|
+
profile = OFX::PaymentMessageSetProfile.new
|
25
|
+
profile.message_set_class = OFX::PaymentMessageSet
|
26
|
+
profile.from_ofx_102_hash(message_set_description_hash)
|
27
|
+
profile
|
28
|
+
end
|
29
|
+
end
|
30
|
+
end
|
@@ -0,0 +1,114 @@
|
|
1
|
+
# Copyright © 2007 Chris Guidry <chrisguidry@gmail.com>
|
2
|
+
#
|
3
|
+
# This file is part of OFX for Ruby.
|
4
|
+
#
|
5
|
+
# OFX for Ruby is free software; you can redistribute it and/or modify
|
6
|
+
# it under the terms of the GNU General Public License as published by
|
7
|
+
# the Free Software Foundation; either version 3 of the License, or
|
8
|
+
# (at your option) any later version.
|
9
|
+
#
|
10
|
+
# OFX for Ruby is distributed in the hope that it will be useful,
|
11
|
+
# but WITHOUT ANY WARRANTY; without even the implied warranty of
|
12
|
+
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
13
|
+
# GNU General Public License for more details.
|
14
|
+
#
|
15
|
+
# You should have received a copy of the GNU General Public License
|
16
|
+
# along with this program. If not, see <http://www.gnu.org/licenses/>.
|
17
|
+
|
18
|
+
require File.dirname(__FILE__) + '/document'
|
19
|
+
require File.dirname(__FILE__) + '/header'
|
20
|
+
require File.dirname(__FILE__) + '/message_set'
|
21
|
+
require File.dirname(__FILE__) + '/status'
|
22
|
+
require File.dirname(__FILE__) + '/statements'
|
23
|
+
|
24
|
+
require File.dirname(__FILE__) + '/signon_message_set'
|
25
|
+
require File.dirname(__FILE__) + '/signup_message_set'
|
26
|
+
require File.dirname(__FILE__) + '/banking_message_set'
|
27
|
+
require File.dirname(__FILE__) + '/credit_card_statement_message_set'
|
28
|
+
require File.dirname(__FILE__) + '/investment_statement_message_set'
|
29
|
+
require File.dirname(__FILE__) + '/interbank_funds_transfer_message_set'
|
30
|
+
require File.dirname(__FILE__) + '/wire_funds_transfer_message_set'
|
31
|
+
require File.dirname(__FILE__) + '/payment_message_set'
|
32
|
+
require File.dirname(__FILE__) + '/email_message_set'
|
33
|
+
require File.dirname(__FILE__) + '/investment_security_list_message_set'
|
34
|
+
require File.dirname(__FILE__) + '/financial_institution_profile_message_set'
|
35
|
+
|
36
|
+
require File.dirname(__FILE__) + '/parser'
|
37
|
+
|
38
|
+
module OFX
|
39
|
+
module OFX102
|
40
|
+
class Serializer
|
41
|
+
def to_http_post_body(document)
|
42
|
+
body = ""
|
43
|
+
|
44
|
+
body += document.header.to_ofx_102_s
|
45
|
+
body += "\n"
|
46
|
+
body += "<OFX>\n"
|
47
|
+
document.message_sets.each do |message_set|
|
48
|
+
body += message_set.to_ofx_102_s
|
49
|
+
end
|
50
|
+
body += "</OFX>\n"
|
51
|
+
|
52
|
+
#print body
|
53
|
+
|
54
|
+
body
|
55
|
+
end
|
56
|
+
|
57
|
+
def from_http_response_body(body)
|
58
|
+
header_pattern = /(\w+\:.*\n)+/
|
59
|
+
header_match = header_pattern.match(body)
|
60
|
+
|
61
|
+
body = header_match.post_match
|
62
|
+
header = Header.from_ofx_102_s(header_match[0].strip)
|
63
|
+
|
64
|
+
parser = OFX::OFX102::Parser.new
|
65
|
+
parser.scan_str body
|
66
|
+
|
67
|
+
if parser.documents.length > 1
|
68
|
+
raise NotImplementedError, "Multiple response documents"
|
69
|
+
end
|
70
|
+
|
71
|
+
#require 'pp'
|
72
|
+
#print body
|
73
|
+
#pp parser.ofx_hashes[0]
|
74
|
+
|
75
|
+
document = parser.documents[0]
|
76
|
+
document.header = header
|
77
|
+
document
|
78
|
+
end
|
79
|
+
end
|
80
|
+
end
|
81
|
+
end
|
82
|
+
|
83
|
+
require 'date'
|
84
|
+
class Date
|
85
|
+
def to_ofx_102_s
|
86
|
+
strftime('%Y%m%d')
|
87
|
+
end
|
88
|
+
end
|
89
|
+
class DateTime
|
90
|
+
def to_ofx_102_s
|
91
|
+
strftime('%Y%m%d%H%M%S')
|
92
|
+
end
|
93
|
+
end
|
94
|
+
class String
|
95
|
+
def to_date
|
96
|
+
Date.parse(self)
|
97
|
+
end
|
98
|
+
def to_datetime
|
99
|
+
DateTime.parse(self)
|
100
|
+
end
|
101
|
+
def to_time
|
102
|
+
('-47120101' + self).to_datetime
|
103
|
+
end
|
104
|
+
end
|
105
|
+
class TrueClass
|
106
|
+
def to_ofx_102_s
|
107
|
+
'Y'
|
108
|
+
end
|
109
|
+
end
|
110
|
+
class FalseClass
|
111
|
+
def to_ofx_102_s
|
112
|
+
'Y'
|
113
|
+
end
|
114
|
+
end
|
@@ -0,0 +1,121 @@
|
|
1
|
+
# Copyright © 2007 Chris Guidry <chrisguidry@gmail.com>
|
2
|
+
#
|
3
|
+
# This file is part of OFX for Ruby.
|
4
|
+
#
|
5
|
+
# OFX for Ruby is free software; you can redistribute it and/or modify
|
6
|
+
# it under the terms of the GNU General Public License as published by
|
7
|
+
# the Free Software Foundation; either version 3 of the License, or
|
8
|
+
# (at your option) any later version.
|
9
|
+
#
|
10
|
+
# OFX for Ruby is distributed in the hope that it will be useful,
|
11
|
+
# but WITHOUT ANY WARRANTY; without even the implied warranty of
|
12
|
+
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
13
|
+
# GNU General Public License for more details.
|
14
|
+
#
|
15
|
+
# You should have received a copy of the GNU General Public License
|
16
|
+
# along with this program. If not, see <http://www.gnu.org/licenses/>.
|
17
|
+
|
18
|
+
module OFX
|
19
|
+
class SignonMessageSet < MessageSet
|
20
|
+
def ofx_102_message_set_name
|
21
|
+
'SIGNON'
|
22
|
+
end
|
23
|
+
|
24
|
+
def self.from_ofx_102_hash(message_set_hash)
|
25
|
+
message_set = SignonMessageSet.new
|
26
|
+
|
27
|
+
message_set_hash.each_pair() do |response_or_request_name, response_or_request_hash|
|
28
|
+
case response_or_request_name
|
29
|
+
when "SONRQ" then message_set.requests << SignonRequest.from_ofx_102_hash(response_or_request_hash)
|
30
|
+
when "SONRS" then message_set.responses << SignonResponse.from_ofx_102_hash(response_or_request_hash)
|
31
|
+
else raise NotImplementedError, response_or_request_name
|
32
|
+
end
|
33
|
+
end
|
34
|
+
|
35
|
+
return message_set
|
36
|
+
end
|
37
|
+
end
|
38
|
+
|
39
|
+
class SignonMessageSetProfile < MessageSetProfile
|
40
|
+
def self.from_ofx_102_hash(message_set_description_hash)
|
41
|
+
profile = OFX::SignonMessageSetProfile.new
|
42
|
+
profile.message_set_class = OFX::SignonMessageSet
|
43
|
+
profile.from_ofx_102_hash(message_set_description_hash)
|
44
|
+
profile
|
45
|
+
end
|
46
|
+
end
|
47
|
+
|
48
|
+
class SignonRequest < Request
|
49
|
+
def ofx_102_name
|
50
|
+
'SON'
|
51
|
+
end
|
52
|
+
def ofx_102_request_body
|
53
|
+
" <DTCLIENT>#{date.to_ofx_102_s}\n" +
|
54
|
+
user_identification.to_ofx_102_s + "\n" +
|
55
|
+
(" <GENUSERKEY>#{generate_user_key}\n" if generate_user_key).to_s +
|
56
|
+
" <LANGUAGE>#{language}\n" +
|
57
|
+
financial_institution_identification.to_ofx_102_s + "\n" +
|
58
|
+
(" <SESSCOOKIE>#{session_cookie}\n" if session_cookie).to_s +
|
59
|
+
application_identification.to_ofx_102_s
|
60
|
+
end
|
61
|
+
def self.from_ofx_102_hash(request_hash)
|
62
|
+
raise NotImplementedError
|
63
|
+
end
|
64
|
+
end
|
65
|
+
class UserCredentials
|
66
|
+
def to_ofx_102_s
|
67
|
+
" <USERID>#{user_identification}\n" +
|
68
|
+
" <USERPASS>#{password}"
|
69
|
+
end
|
70
|
+
end
|
71
|
+
class UserKey
|
72
|
+
def to_ofx_102_s
|
73
|
+
" <USERKEY>#{user_key}"
|
74
|
+
end
|
75
|
+
end
|
76
|
+
|
77
|
+
class FinancialInstitutionIdentification
|
78
|
+
def to_ofx_102_s
|
79
|
+
" <FI>\n" +
|
80
|
+
" <ORG>#{organization}\n" +
|
81
|
+
" <FID>#{financial_institution_identifier}\n" +
|
82
|
+
" </FI>"
|
83
|
+
end
|
84
|
+
def self.from_ofx_102_hash(fi_hash)
|
85
|
+
return FinancialInstitutionIdentification.new(fi_hash['ORG'],
|
86
|
+
fi_hash['FID'])
|
87
|
+
end
|
88
|
+
end
|
89
|
+
|
90
|
+
class ApplicationIdentification
|
91
|
+
def to_ofx_102_s
|
92
|
+
" <APPID>#{application_identification}\n" +
|
93
|
+
" <APPVER>#{application_version}"
|
94
|
+
end
|
95
|
+
end
|
96
|
+
|
97
|
+
class SignonResponse < Response
|
98
|
+
def ofx_102_name
|
99
|
+
'SON'
|
100
|
+
end
|
101
|
+
|
102
|
+
def ofx_102_response_body
|
103
|
+
raise NotImplementedError
|
104
|
+
end
|
105
|
+
|
106
|
+
def self.from_ofx_102_hash(response_hash)
|
107
|
+
response = SignonResponse.new
|
108
|
+
|
109
|
+
response.status = OFX::Status.from_ofx_102_hash(response_hash['STATUS'])
|
110
|
+
response.date = response_hash['DTSERVER'].to_datetime if response_hash['DTSERVER']
|
111
|
+
#TODO: @user_key
|
112
|
+
response.language = response_hash['LANGUAGE']
|
113
|
+
response.date_of_last_profile_update = response_hash['DTPROFUP'].to_datetime if response_hash['DTPROFUP']
|
114
|
+
response.date_of_last_account_update = response_hash['DTACCTUP'].to_datetime if response_hash['DTACCTUP']
|
115
|
+
response.financial_institution_identification = OFX::FinancialInstitutionIdentification.from_ofx_102_hash(response_hash['FI'])
|
116
|
+
#TODO: @session_cookie
|
117
|
+
|
118
|
+
response
|
119
|
+
end
|
120
|
+
end
|
121
|
+
end
|