iso8583 0.1.1 → 0.1.3

Sign up to get free protection for your applications and to get access to all the features.
@@ -0,0 +1,22 @@
1
+ require 'lib/8583'
2
+ require 'lib/8583/berlin'
3
+ require 'test/unit'
4
+
5
+ include ISO8583
6
+
7
+ class SeperateTest < Test::Unit::TestCase
8
+
9
+
10
+
11
+ def test_test_separate_messages
12
+ mes1=BerlinMessage.new
13
+ mes1[2]="1234567890"
14
+ assert_equal(mes1[2], "1234567890")
15
+ mes2=BerlinMessage.new
16
+ mes2[2]="0987654321"
17
+ assert_equal(mes2[2], "0987654321")
18
+ # test that the original value of field 2 in mes1 hasn't changed
19
+ assert_equal(mes1[2], "1234567890") # this will fail, as the field 2 in mes1 has changed value too!!
20
+ end
21
+
22
+ end
data/test/test_util.rb ADDED
@@ -0,0 +1,32 @@
1
+ require 'lib/iso8583'
2
+ require 'test/unit'
3
+
4
+ include ISO8583
5
+
6
+ class UtilTest < Test::Unit::TestCase
7
+ def test_hex2b
8
+ assert_equal "\xab\xcd\x12", hex2b("abcd12")
9
+ assert_equal "\xab\xcd\x12", hex2b("a b c d 1 2")
10
+ assert_equal "\xab\xcd\x12", hex2b("ABCD12")
11
+ assert_raise(ISO8583Exception){
12
+ # non hex
13
+ hex2b("ABCDEFGH")
14
+ }
15
+ assert_raise(ISO8583Exception){
16
+ # odd num digits
17
+ hex2b("ABCDEF0")
18
+ }
19
+ end
20
+
21
+ def test_b2hex
22
+ assert_equal "abcd12", b2hex("\xab\xcd\x12")
23
+ end
24
+
25
+ def test_ebcdic2ascii
26
+ assert_equal "0123456789", ebcdic2ascii("\xf0\xf1\xf2\xf3\xf4\xf5\xf6\xf7\xf8\xf9")
27
+ end
28
+
29
+ def test_ascii2ebcdic
30
+ assert_equal "\xf0\xf1\xf2\xf3\xf4\xf5\xf6\xf7\xf8\xf9", ascii2ebcdic("0123456789")
31
+ end
32
+ end
metadata CHANGED
@@ -1,20 +1,25 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: iso8583
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.1.1
4
+ version: 0.1.3
5
5
  platform: ruby
6
6
  authors:
7
7
  - Tim Becker
8
+ - Slava Kravchenko
8
9
  autorequire:
9
10
  bindir: bin
10
11
  cert_chain: []
11
12
 
12
- date: 2009-08-15 00:00:00 +02:00
13
+ date: 2010-09-29 00:00:00 +02:00
13
14
  default_executable:
14
15
  dependencies: []
15
16
 
16
- description: Ruby implementation of ISO 8583 financial messaging
17
- email: tim.becker@kuriositaet.de
17
+ description: |
18
+ Ruby implementation of ISO 8583 financial messaging
19
+
20
+ email:
21
+ - tim.becker@kuriositaet.de
22
+ - cordawyn@gmail.com
18
23
  executables: []
19
24
 
20
25
  extensions: []
@@ -22,14 +27,16 @@ extensions: []
22
27
  extra_rdoc_files: []
23
28
 
24
29
  files:
25
- - lib/berlin.rb
26
- - lib/bitmap.rb
27
- - lib/codec.rb
28
- - lib/exception.rb
29
- - lib/field.rb
30
- - lib/fields.rb
30
+ - lib/8583/berlin.rb
31
+ - lib/8583/bitmap.rb
32
+ - lib/8583/codec.rb
33
+ - lib/8583/exception.rb
34
+ - lib/8583/field.rb
35
+ - lib/8583/fields.rb
36
+ - lib/8583/message.rb
37
+ - lib/8583/util.rb
38
+ - lib/8583.rb
31
39
  - lib/iso8583.rb
32
- - lib/message.rb
33
40
  - AUTHORS
34
41
  - CHANGELOG
35
42
  - LICENSE
@@ -40,8 +47,12 @@ files:
40
47
  - test/message_test.rb
41
48
  - test/test_codec.rb
42
49
  - test/test_fields.rb
50
+ - test/test_seperate_msg.rb
51
+ - test/test_util.rb
43
52
  has_rdoc: true
44
- homepage: http://iso8583.rubyforge.org/
53
+ homepage: http://github.com/a2800276/8583/
54
+ licenses: []
55
+
45
56
  post_install_message:
46
57
  rdoc_options: []
47
58
 
@@ -62,9 +73,9 @@ required_rubygems_version: !ruby/object:Gem::Requirement
62
73
  requirements:
63
74
  - none
64
75
  rubyforge_project: iso8583
65
- rubygems_version: 1.3.1
76
+ rubygems_version: 1.3.5
66
77
  signing_key:
67
- specification_version: 2
78
+ specification_version: 3
68
79
  summary: "iso8583: Ruby implementation of ISO 8583 financial messaging"
69
80
  test_files: []
70
81
 
data/lib/berlin.rb DELETED
@@ -1,79 +0,0 @@
1
- # Copyright 2009 by Tim Becker (tim.becker@kuriostaet.de)
2
- # MIT License, for details, see the LICENSE file accompaning
3
- # this distribution
4
-
5
- require 'lib/iso8583'
6
-
7
-
8
- # Example of a protocol specification based on:
9
- # http://www.berlin-group.org/documents/BG_Authorisation_3.0.pdf
10
- # The Berlin Groups Authorisation Interface specification.
11
- # No gurantees are made that this is an accurate implemenation.
12
- # It currently serves as an example only.
13
-
14
-
15
- class BerlinMessage < Message
16
- mti_format N, :length=>4
17
- mti 1100, "Authorization Request Acquirer Gateway"
18
- mti 1110, "Authorization Request Response Issuer Gateway"
19
- mti 1420, "Reversal Advice Acquirer Gateway"
20
- mti 1421, "Reversal Advice Repeat Acquirer Gateway"
21
- mti 1430, "Reversal Advice Response Issuer Gateway"
22
- mti 1804, "Network Management Request Acquirer Gateway or Issuer Gateway"
23
- mti 1814, "Network Management Request Response Issuer Gateway or Acquirer Gateway"
24
-
25
- bmp 2, "Primary Account Number (PAN)", LLVAR_N, :max => 19
26
- bmp 3, "Processing Code", N, :length => 6
27
- bmp 4, "Amount (Transaction)", N, :length => 12
28
- bmp 6, "Amount, Cardholder Billing" , N, :length => 12
29
- bmp 7, "Date and Time, Transmission" , MMDDhhmmss
30
- bmp 10, "Conversion Rate, Cardholder Billing", N, :length => 8
31
- bmp 11, "System Trace Audit Number (STAN)", N, :length => 6
32
- bmp 12, "Date and Time, Local Transaction", YYMMDDhhmmss
33
- bmp 14, "Date, Expiration", YYMM
34
- bmp 22, "POS Data Code", AN, :length => 12
35
- bmp 23, "Card Sequence Number", N, :length => 3
36
- bmp 24, "Function Code", N, :length => 3
37
- bmp 25, "Message Reason Code", N, :length => 4
38
- bmp 26, "Card Acceptor Business Code", N, :length => 4
39
- bmp 30, "Amounts, Original", N, :length => 24
40
- bmp 32, "Acquiring Institution Identification Code", LLVAR_N, :max => 11
41
- bmp 35, "Track 2 Data", LLVAR_Z, :max => 37
42
- bmp 37, "Retrieval Reference Number", ANP, :length => 12
43
- bmp 38, "Approval Code", ANP, :length => 6
44
- bmp 39, "Action Code", N, :length => 3
45
- bmp 41, "Card Acceptor Terminal Identification", ANS, :length => 8
46
- bmp 42, "Card Acceptor Identification Code", ANS, :length => 15
47
- bmp 43, "Card Acceptor Name/Location", LLVAR_ANS, :max => 56
48
- bmp 49, "Currency Code, Transaction", N, :length => 3
49
- bmp 51, "Currency Code, Cardholder Billing", N, :length => 3
50
- bmp 52, "Personal Identification Number (PIN) Data", B, :length => 8
51
- bmp 53, "Security Related Control Information", LLVAR_B, :max => 48
52
- bmp 54, "Amounts, Additional", LLLVAR_ANS,:max => 40
53
-
54
- bmp 55, "Integrated Circuit Card (ICC) System Related Data", LLLVAR_B, :max => 255
55
- bmp 56, "Original Data Elements", LLVAR_N, :max => 35
56
- bmp 58, "Authorizing Agent Institution Identification Code", LLVAR_N, :max => 11
57
- bmp 59, "Additional Data - Private", LLLVAR_ANS, :max => 67
58
- bmp 64, "Message Authentication Code (MAC) Field", B, :length => 8
59
-
60
- bmp_alias 2, :pan
61
- bmp_alias 3, :proc_code
62
- bmp_alias 4, :amount
63
- bmp_alias 12, :exp_date
64
- end
65
-
66
- if __FILE__==$0
67
- mes = BerlinMessage.new
68
- mes.mti = 1110
69
- mes[2] = 474747474747
70
- mes["Processing Code"] = "123456"
71
-
72
- pan = mes["Primary Account Number (PAN)"]
73
- #mes.pan = 47474747474747
74
-
75
- #puts mes.pan
76
- puts mes.to_b
77
- puts mes.to_s
78
- #mes2 = BerlinMessage.parse input
79
- end
data/lib/bitmap.rb DELETED
@@ -1,117 +0,0 @@
1
- # Copyright 2009 by Tim Becker (tim.becker@kuriostaet.de)
2
- # MIT License, for details, see the LICENSE file accompaning
3
- # this distribution
4
-
5
- # This class constructs an object for handling bitmaps
6
- # with which ISO8583 messages typically begin.
7
- # Bitmaps are either 8 or 16 bytes long, an extended length
8
- # bitmap is indicated by the first bit being set.
9
- # In all likelyhood, you won't be using this class much, it's used
10
- # transparently by the Message class.
11
- class Bitmap
12
-
13
-
14
- # create a new Bitmap object. In case an iso message
15
- # is passed in, that messages bitmap will be parsed. If
16
- # not, this initializes and empty bitmap.
17
-
18
- def initialize message=nil
19
- @bmp = Array.new(128,false)
20
- if !message
21
-
22
- else
23
- initialize_from_message message
24
- end
25
- end
26
-
27
- # yield once with the number of each set field.
28
- def each #:yields: each bit set in the bitmap.
29
- @bmp.each_with_index {|set,i| yield i+i if set}
30
- end
31
-
32
- # Returns whether the bit is set or not.
33
- def [] i
34
- @bmp[i-1]
35
- end
36
-
37
- # Set the bit to the indicated value. Only `true` sets the
38
- # bit, any other value unsets it.
39
- def []= i,value
40
- if i > 128
41
- raise ISO8583Exception.new("Bits > 128 are not permitted.")
42
- elsif i < 2
43
- raise ISO8583Exception.new("Bits < 2 are not permitted (continutation bit is set automatically)")
44
- end
45
- @bmp[i-1]=(value==true)
46
- end
47
-
48
- # Sets bit #i
49
- def set i
50
- self[i]=true
51
- end
52
-
53
- # Unsets bit #i
54
- def unset i
55
- self[i]=false
56
- end
57
-
58
- # Generate the bytes representing this bitmap.
59
- def to_bytes
60
- arr=[self.to_s]
61
- # tricky and ugly, setting bit[1] only when generating to_s...
62
- count = self[1] ? 128 : 64
63
- arr.pack("B#{count}")
64
- end
65
- alias_method :to_b, :to_bytes
66
-
67
- # Generate a String representation of this bitmap in the form:
68
- # 01001100110000011010110110010100100110011000001101011011001010
69
- def to_s
70
- #check whether any `high` bits are set
71
- @bmp[0]=false
72
- 65.upto(128) { |i|
73
- if self[i]
74
- # if so, set continuation bit
75
- @bmp[0]=true
76
- break
77
- end
78
- }
79
- str = ""
80
- 1.upto(self[1] ? 128 : 64) {|i|
81
- str << (self[i] ? "1" : "0")
82
- }
83
- str
84
- end
85
-
86
- private
87
- def initialize_from_message message
88
- bmp = message.unpack("B64")[0]
89
- if bmp[0,1] == "1"
90
- bmp = message.unpack("B128")[0]
91
- end
92
-
93
- 0.upto(bmp.length-1) do |i|
94
- @bmp[i] = bmp[i,1]=="1"
95
- end
96
-
97
-
98
- end
99
-
100
- class << self
101
- # Parse the bytes in string and return the Bitmap and bytes remaining in `str`
102
- # after the bitmap is taken away.
103
- def parse str
104
- bmp = Bitmap.new(str)
105
- rest = bmp[1] ? str[16,str.length] : str[8,str.length]
106
- return [bmp,rest]
107
- end
108
- end
109
-
110
- end
111
-
112
- if __FILE__==$0
113
-
114
- mp = ISO8583::Bitmap.new
115
- 20.step(128,7) {|i| mp.set(i)}
116
- print mp.to_bytes
117
- end
data/lib/codec.rb DELETED
@@ -1,173 +0,0 @@
1
- # Copyright 2009 by Tim Becker (tim.becker@kuriostaet.de)
2
- # MIT License, for details, see the LICENSE file accompaning
3
- # this distribution
4
-
5
- require 'date'
6
-
7
- # Codec provides functionality to encode and decode values, codecs are
8
- # used internally by Field instances in order to do character conversions
9
- # and checking for proper values.
10
- # Although they are used internally, you will probably need to write
11
- # your own Codec sooner or later. The codecs used by Field instances are
12
- # typically instances of Codec, it may or may not be usefull to subclass
13
- # Codec.
14
- #
15
- # Say, for example, a text field needs to be encoded in EBCDIC in the
16
- # message, this is how a corresponding codec would be constructed:
17
- #
18
- # EBCDIC_Codec = Codec.new
19
- # EBCDIC_Codec.encoder = lambda {|ascii_str|
20
- # raise ISO8583Exception.new("String (#{ascii_str})not valid!") unless =~ /someregexp/
21
- # ascii2ebcdic ascii_str # implementing ascii_str is left as an excercise
22
- # }
23
- # EBCDIC_Codec.decode = lambda {|ebcdic_str|
24
- # # you may or may not want to raise exceptions at this point ....
25
- # # strip removes any padding...
26
- # ebcdic2ascii(ebcdic_str).strip
27
- # }
28
- #
29
- # This instance of Codec would then be used be the corresponding Field
30
- # encoder/decoder, which may look similar to this:
31
- #
32
- # EBCDIC = Field.new
33
- # EBCDIC.codec = EBCDIC_Codec
34
- # EBCDIC.padding = PADDING_LEFT_JUSTIFIED_SPACES
35
- #
36
- # Notice there is a bit of inconsistancy: the padding is added by the
37
- # field, but removed by the codec. I would like to find a better
38
- # solution to this...
39
- #
40
- # See also: Field, link:files/lib/fields_rb.html
41
- #
42
- # The following codecs are already implemented:
43
- # [+ASCII_Number+] encodes either a Number or String representation of
44
- # a number to the ASCII represenation of the number,
45
- # decodes ASCII numerals to a number
46
- # [+AN_Codec+] passes through ASCII string checking they conform to [A-Za-z0-9]
47
- # during encoding, no validity check during decoding.
48
- # [+ANP_Codec+] passes through ASCII string checking they conform to [A-Za-z0-9 ]
49
- # during encoding, no validity check during decoding.
50
- # [+ANS_Codec+] passes through ASCII string checking they conform to [\x20-\x7E]
51
- # during encoding, no validity check during decoding.
52
- # [+Null_Codec+] passes anything along untouched.
53
- # [<tt>Track2</tt>] rudimentary check that string conforms to Track2
54
- # [+MMDDhhmmssCodec+] encodes Time, Datetime or String to the described date format, checking
55
- # that it is a valid date. Decodes to a DateTime instance, decoding and
56
- # encoding perform validity checks!
57
- # [+YYMMDDhhmmssCodec+] encodes Time, Datetime or String to the described date format, checking
58
- # that it is a valid date. Decodes to a DateTime instance, decoding and
59
- # encoding perform validity checks!
60
- # [+YYMMCodec+] encodes Time, Datetime or String to the described date format (exp date),
61
- # checking that it is a valid date. Decodes to a DateTime instance, decoding
62
- # and encoding perform validity checks!
63
- #
64
- class Codec
65
- attr_accessor :encoder
66
- attr_accessor :decoder
67
-
68
- def decode raw
69
- return decoder.call(raw)
70
- end
71
-
72
- # length is either a fixnum or a lenth encoder.
73
- def encode value
74
- return encoder.call(value)
75
- end
76
- end
77
-
78
- # ASCII_Number
79
- ASCII_Number = Codec.new
80
- ASCII_Number.encoder= lambda{|num|
81
- enc = num.to_s
82
- raise ISO8583Exception.new("Invalid value: #{enc} must be numeric!") unless enc =~ /^[0-9]*$/
83
- enc
84
- }
85
-
86
- ASCII_Number.decoder= lambda{|raw|
87
- raw.to_i
88
- }
89
-
90
- PASS_THROUGH_DECODER = lambda{|str|
91
- str.strip # remove padding
92
- }
93
-
94
- AN_Codec = Codec.new
95
- AN_Codec.encoder = lambda{|str|
96
- raise ISO8583Exception.new("Invalid value: #{str} must be [A-Za-y0-9]") unless str =~ /^[A-Za-z0-9]*$/
97
- str
98
- }
99
- AN_Codec.decoder = PASS_THROUGH_DECODER
100
-
101
- ANP_Codec = Codec.new
102
- ANP_Codec.encoder = lambda{|str|
103
- raise ISO8583Exception.new("Invalid value: #{str} must be [A-Za-y0-9 ]") unless str =~ /^[A-Za-z0-9 ]*$/
104
- str
105
- }
106
- ANP_Codec.decoder = PASS_THROUGH_DECODER
107
-
108
- ANS_Codec = Codec.new
109
- ANS_Codec.encoder = lambda{|str|
110
- raise ISO8583Exception.new("Invalid value: #{str} must be [\x20-\x7E]") unless str =~ /^[\x20-\x7E]*$/
111
- str
112
- }
113
- ANS_Codec.decoder = PASS_THROUGH_DECODER
114
-
115
- Null_Codec = Codec.new
116
- Null_Codec.encoder = lambda {|str|
117
- str
118
- }
119
- Null_Codec.decoder = lambda {|str|
120
- str.gsub(/\000*$/,'')
121
- }
122
-
123
- Track2 = Codec.new
124
- Track2.encoder = lambda{|track2|
125
- #SS | PAN | FS | Expiration Date | Service Code | Discretionary Data | ES | LRC
126
- # SS = ;
127
- # PAN = up to 19 digits (at least 9?)
128
- # FS = '='
129
- # Exp Date = YYMM
130
- # SC: 3 digits or =
131
- # ES = ?
132
- # lrc : 1byte
133
- raise ISO8583Exception.new("Invalid Track2 data: #{track2}") unless track2 =~ /^;*(\d{9,19})=(.*)\?.$/
134
- track2
135
- }
136
- Track2.decoder = PASS_THROUGH_DECODER
137
-
138
- def _date_codec(fmt)
139
- c = Codec.new
140
- c.encoder = lambda {|date|
141
- enc = case date
142
- when Time
143
- when DateTime
144
- date.strftime(fmt)
145
- when String
146
- begin
147
- dt = DateTime.strptime date, fmt
148
- dt.strftime(fmt)
149
- rescue
150
- raise ISO8583Exception.new("Invalid format encoding: #{date}, must be #{fmt}.")
151
- end
152
- else
153
- raise ISO8583Exception.new("Don't know how to encode: #{date.class} to a time.")
154
- end
155
- return enc
156
- }
157
- c.decoder = lambda {|str|
158
- dt = begin
159
- DateTime.strptime str, fmt
160
- rescue
161
- raise ISO8583Exception.new("Invalid format decoding: #{str}, must be MMDDhhmmss.")
162
- end
163
- return dt
164
- }
165
-
166
- return c
167
- end
168
-
169
- MMDDhhmmssCodec = _date_codec("%m%d%H%M%S")
170
- YYMMDDhhmmssCodec = _date_codec("%y%m%d%H%M%S")
171
- YYMMCodec = _date_codec("%y%m")
172
-
173
-