iso8583 0.1.1 → 0.1.3

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.
@@ -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
-