Module: ISO8583

Defined in:
lib/util.rb,
lib/codec.rb,
lib/field.rb,
lib/berlin.rb,
lib/bitmap.rb,
lib/fields.rb,
lib/iso8583.rb,
lib/message.rb,
lib/exception.rb

Overview

Copyright 2009 by Tim Becker ([email protected]) MIT License, for details, see the LICENSE file accompaning this distribution

Defined Under Namespace

Classes: BCDField, BMP, BerlinMessage, Bitmap, Codec, Field, ISO8583Exception, ISO8583ParseException, Message

Constant Summary collapse

US_ASCII2IBM037 =

The charsets supported by iconv aren’t guranteed. At the very least MACs don’t support ebcdic, so providing rudimentary mappings here.

[
 0x00, 0x01, 0x02, 0x03, 0x37, 0x2d, 0x2e, 0x2f, 0x16, 0x05, 0x15, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f,
 0x10, 0x11, 0x12, 0x13, 0x3c, 0x3d, 0x32, 0x26, 0x18, 0x19, 0x3f, 0x27, 0x1c, 0x1d, 0x1e, 0x1f,
 0x40, 0x5a, 0x7f, 0x7b, 0x5b, 0x6c, 0x50, 0x7d, 0x4d, 0x5d, 0x5c, 0x4e, 0x6b, 0x60, 0x4b, 0x61,
 0xf0, 0xf1, 0xf2, 0xf3, 0xf4, 0xf5, 0xf6, 0xf7, 0xf8, 0xf9, 0x7a, 0x5e, 0x4c, 0x7e, 0x6e, 0x6f,
 0x7c, 0xc1, 0xc2, 0xc3, 0xc4, 0xc5, 0xc6, 0xc7, 0xc8, 0xc9, 0xd1, 0xd2, 0xd3, 0xd4, 0xd5, 0xd6,
 0xd7, 0xd8, 0xd9, 0xe2, 0xe3, 0xe4, 0xe5, 0xe6, 0xe7, 0xe8, 0xe9, 0xba, 0xe0, 0xbb, 0xb0, 0x6d,
 0x79, 0x81, 0x82, 0x83, 0x84, 0x85, 0x86, 0x87, 0x88, 0x89, 0x91, 0x92, 0x93, 0x94, 0x95, 0x96,
 0x97, 0x98, 0x99, 0xa2, 0xa3, 0xa4, 0xa5, 0xa6, 0xa7, 0xa8, 0xa9, 0xc0, 0x4f, 0xd0, 0xa1, 0x07,
 0x3f, 0x3f, 0x3f, 0x3f, 0x3f, 0x3f, 0x3f, 0x3f, 0x3f, 0x3f, 0x3f, 0x3f, 0x3f, 0x3f, 0x3f, 0x3f,
 0x3f, 0x3f, 0x3f, 0x3f, 0x3f, 0x3f, 0x3f, 0x3f, 0x3f, 0x3f, 0x3f, 0x3f, 0x3f, 0x3f, 0x3f, 0x3f,
 0x3f, 0x3f, 0x3f, 0x3f, 0x3f, 0x3f, 0x3f, 0x3f, 0x3f, 0x3f, 0x3f, 0x3f, 0x3f, 0x3f, 0x3f, 0x3f,
 0x3f, 0x3f, 0x3f, 0x3f, 0x3f, 0x3f, 0x3f, 0x3f, 0x3f, 0x3f, 0x3f, 0x3f, 0x3f, 0x3f, 0x3f, 0x3f,
 0x3f, 0x3f, 0x3f, 0x3f, 0x3f, 0x3f, 0x3f, 0x3f, 0x3f, 0x3f, 0x3f, 0x3f, 0x3f, 0x3f, 0x3f, 0x3f,
 0x3f, 0x3f, 0x3f, 0x3f, 0x3f, 0x3f, 0x3f, 0x3f, 0x3f, 0x3f, 0x3f, 0x3f, 0x3f, 0x3f, 0x3f, 0x3f,
 0x3f, 0x3f, 0x3f, 0x3f, 0x3f, 0x3f, 0x3f, 0x3f, 0x3f, 0x3f, 0x3f, 0x3f, 0x3f, 0x3f, 0x3f, 0x3f,
 0x3f, 0x3f, 0x3f, 0x3f, 0x3f, 0x3f, 0x3f, 0x3f, 0x3f, 0x3f, 0x3f, 0x3f, 0x3f, 0x3f, 0x3f, 0x3f,
]
IBM0372US_ASCII =
[
 0x00, 0x01, 0x02, 0x03, 0x3f, 0x09, 0x3f, 0x7f, 0x3f, 0x3f, 0x3f, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f,
 0x10, 0x11, 0x12, 0x13, 0x3f, 0x0a, 0x08, 0x3f, 0x18, 0x19, 0x3f, 0x3f, 0x1c, 0x1d, 0x1e, 0x1f,
 0x3f, 0x3f, 0x3f, 0x3f, 0x3f, 0x0a, 0x17, 0x1b, 0x3f, 0x3f, 0x3f, 0x3f, 0x3f, 0x05, 0x06, 0x07,
 0x3f, 0x3f, 0x16, 0x3f, 0x3f, 0x3f, 0x3f, 0x04, 0x3f, 0x3f, 0x3f, 0x3f, 0x14, 0x15, 0x3f, 0x1a,
 0x20, 0x3f, 0x3f, 0x3f, 0x3f, 0x3f, 0x3f, 0x3f, 0x3f, 0x3f, 0x3f, 0x2e, 0x3c, 0x28, 0x2b, 0x7c,
 0x26, 0x3f, 0x3f, 0x3f, 0x3f, 0x3f, 0x3f, 0x3f, 0x3f, 0x3f, 0x21, 0x24, 0x2a, 0x29, 0x3b, 0x3f,
 0x2d, 0x2f, 0x3f, 0x3f, 0x3f, 0x3f, 0x3f, 0x3f, 0x3f, 0x3f, 0x3f, 0x2c, 0x25, 0x5f, 0x3e, 0x3f,
 0x3f, 0x3f, 0x3f, 0x3f, 0x3f, 0x3f, 0x3f, 0x3f, 0x3f, 0x60, 0x3a, 0x23, 0x40, 0x27, 0x3d, 0x22,
 0x3f, 0x61, 0x62, 0x63, 0x64, 0x65, 0x66, 0x67, 0x68, 0x69, 0x3f, 0x3f, 0x3f, 0x3f, 0x3f, 0x3f,
 0x3f, 0x6a, 0x6b, 0x6c, 0x6d, 0x6e, 0x6f, 0x70, 0x71, 0x72, 0x3f, 0x3f, 0x3f, 0x3f, 0x3f, 0x3f,
 0x3f, 0x7e, 0x73, 0x74, 0x75, 0x76, 0x77, 0x78, 0x79, 0x7a, 0x3f, 0x3f, 0x3f, 0x3f, 0x3f, 0x3f,
 0x5e, 0x3f, 0x3f, 0x3f, 0x3f, 0x3f, 0x3f, 0x3f, 0x3f, 0x3f, 0x5b, 0x5d, 0x3f, 0x3f, 0x3f, 0x3f,
 0x7b, 0x41, 0x42, 0x43, 0x44, 0x45, 0x46, 0x47, 0x48, 0x49, 0x3f, 0x3f, 0x3f, 0x3f, 0x3f, 0x3f,
 0x7d, 0x4a, 0x4b, 0x4c, 0x4d, 0x4e, 0x4f, 0x50, 0x51, 0x52, 0x3f, 0x3f, 0x3f, 0x3f, 0x3f, 0x3f,
 0x5c, 0x3f, 0x53, 0x54, 0x55, 0x56, 0x57, 0x58, 0x59, 0x5a, 0x3f, 0x3f, 0x3f, 0x3f, 0x3f, 0x3f,
 0x30, 0x31, 0x32, 0x33, 0x34, 0x35, 0x36, 0x37, 0x38, 0x39, 0x3f, 0x3f, 0x3f, 0x3f, 0x3f, 0x3f,
]
ASCII_Number =

ASCII_Number

Codec.new
PASS_THROUGH_DECODER =
lambda{|str|
  str.strip # remove padding
}
Packed_Number =

Takes a number or str representation of a number and BCD encodes it, e.g. “1234” => “x12x34” 3456 => “x34x56”

right justified with null … (correct to do this? almost certainly not…)

Codec.new
AN_Codec =
Codec.new
ANP_Codec =
Codec.new
ANS_Codec =
Codec.new
Null_Codec =
Codec.new
Track2 =
Codec.new
MMDDhhmmssCodec =
_date_codec("%m%d%H%M%S")
YYMMDDhhmmssCodec =
_date_codec("%y%m%d%H%M%S")
YYMMCodec =
_date_codec("%y%m")
LL =

Special form to de/encode variable length indicators, two bytes ASCII numerals

Field.new
LLL =

Special form to de/encode variable length indicators, three bytes ASCII numerals

Field.new
LL_BCD =
BCDField.new
LLVAR_N =

Two byte variable length ASCII numeral, payload ASCII numerals

Field.new
LLLVAR_N =

Three byte variable length ASCII numeral, payload ASCII numerals

Field.new
LLVAR_Z =

Two byte variable length ASCII numeral, payload Track2 data

Field.new
LLVAR_ANS =

Two byte variable length ASCII numeral, payload ASCII+special

Field.new
LLLVAR_ANS =

Three byte variable length ASCII numeral, payload ASCII+special

Field.new
LLVAR_B =

Two byte variable length binary payload

Field.new
LLLVAR_B =

Three byte variable length binary payload

Field.new
N =

Fixed lengh numerals, repesented in ASCII, padding right justified using zeros

Field.new
N_BCD =
BCDField.new
PADDING_LEFT_JUSTIFIED_SPACES =
lambda {|val, len|
  sprintf "%-#{len}s", val
}
AN =

Fixed lengh ASCII [A-Za-z0-9], padding left justified using spaces.

Field.new
ANP =

Fixed lengh ASCII [A-Za-z0-9] and space, padding left, spaces

Field.new
ANS =

Fixed length ASCII [x20-x7E], padding left, spaces

Field.new
B =

Binary data, padding left using nulls (0x00)

Field.new
MMDDhhmmss =

Date, formatted as described in ASCII numerals

Field.new
YYMMDDhhmmss =

Date, formatted as described in ASCII numerals

Field.new
YYMM =

Date, formatted as described in ASCII numerals

Field.new

Class Method Summary collapse

Instance Method Summary collapse

Class Method Details

._date_codec(fmt) ⇒ Object



156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
# File 'lib/codec.rb', line 156

def self._date_codec(fmt) 
  c = Codec.new
  c.encoder = lambda {|date|
    enc = case date
          when Date, Time
            date.strftime(fmt)
          when String
            begin
              dt = DateTime.strptime(date, fmt)
              dt.strftime(fmt)
            rescue
              raise ISO8583Exception.new("Invalid format encoding: #{date}, must be #{fmt}.")
            end
          else  
            raise ISO8583Exception.new("Don't know how to encode: #{date.class} to a time.")
          end
    return enc
  }
  c.decoder = lambda {|str|
    begin
      DateTime.strptime(str, fmt)
    rescue
      raise ISO8583Exception.new("Invalid format decoding: #{str}, must be #{fmt}.")
    end
  }

  c
end

Instance Method Details

#_conv(str, mapping) ⇒ Object



32
33
34
35
36
37
38
# File 'lib/util.rb', line 32

def _conv(str, mapping)
  _str = ""
  str.each_byte{|byte|
    _str << mapping[byte]
  }
  _str
end

#ascii2ebcdic(ascii) ⇒ Object

Convert a String of ASCII chars to EBCDIC



43
44
45
# File 'lib/util.rb', line 43

def ascii2ebcdic(ascii)
  _conv(ascii, US_ASCII2IBM037)
end

#b2hex(byte_string) ⇒ Object

general utilities

Convert a String of bytes to their hex representation E.g.:

b2hex "\x12\x34\xab" => "1234AB"


14
15
16
17
# File 'lib/util.rb', line 14

def b2hex(byte_string)
  r = byte_string.unpack("H*")[0]
  r.length > 1 ? r : "  "
end

#ebcdic2ascii(ebcdic) ⇒ Object

Convert an EBCDIC String to ASCII



50
51
52
# File 'lib/util.rb', line 50

def ebcdic2ascii(ebcdic)
  _conv(ebcdic, IBM0372US_ASCII)
end

#hex2b(hex_string) ⇒ Object

Convert a String containing hex data to a String containing the corresponding bytes:

hex2b "abcd12" => "\xa\cd\12"

Raises:



25
26
27
28
29
30
# File 'lib/util.rb', line 25

def hex2b(hex_string)
  string = hex_string.gsub(/\s+/, "")
  raise ISO8583Exception.new("Invalid Hex chars: #{hex_string}") unless string =~ /^[A-Fa-f0-9]*$/
  raise ISO8583Exception.new("Uneven number of Hex chars #{hex_string}") unless ( (string.length % 2) == 0)
  [string].pack("H*")
end