Module: ISO8583

Includes:
DaFunk::Helper
Defined in:
lib/iso8583/util.rb,
lib/iso8583/codec.rb,
lib/iso8583/field.rb,
lib/iso8583/bitmap.rb,
lib/iso8583/fields.rb,
lib/iso8583/message.rb,
lib/iso8583/version.rb,
lib/iso8583/exception.rb,
lib/iso8583/file_parser.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, Bitmap, Codec, Field, FileParser, 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
A_Codec =
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")
HhmmssCodec =
_date_codec("%H%M%S")
YYMMDDhhmmssCodec =
_date_codec("%y%m%d%H%M%S")
YYMMCodec =
_date_codec("%y%m")
MMDDCodec =
_date_codec("%m%d")
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
Z =

Two byte variable length ASCII numeral, payload Track2 data

Field.new
LLVAR_AN =

Two byte variable length ASCII numeral, payload ASCII, fixed length, zeropadded (right)

Field.new
LLVAR_ANS =

Two byte variable length ASCII numeral, payload ASCII+special

Field.new
LLLVAR_Z =

Thre byte variable length ASCII numeral, payload Track2 data

Field.new
LLLVAR_AN =

Three byte variable length ASCII numeral, payload ASCII, fixed length, zeropadded (right)

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
XN =
BCDField.new
N_BCD =
BCDField.new
PADDING_LEFT_JUSTIFIED_SPACES =
lambda {|val, len|
  sprintf "%-#{len}s", val
}
A =

Fixed length ASCII letters [A-Za-z]

Field.new
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
MMDD =
Field.new
Hhmmss =
Field.new
UNKNOWN =

Unknown

Field.new
VERSION =
"0.1.6"

Class Method Summary collapse

Instance Method Summary collapse

Class Method Details

._date_codec(fmt) ⇒ Object



168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
# File 'lib/iso8583/codec.rb', line 168

def self._date_codec(fmt)
  c = Codec.new
  c.encoder = lambda {|date|
    enc = case date
          when DateTime, Date, Time
            date.strftime(fmt)
          when String
            begin
              dt = DateTime.strptime(date, fmt)
              dt.strftime(fmt)
            rescue => e
              msg = "Invalid format encoding: #{date}, must be #{fmt}."
              ContextLog.exception(e, e.backtrace, msg) if Object.defined?(:ContextLog)
              raise ISO8583Exception.new(msg)
            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 => e
      msg = "Invalid format decoding: #{str}, must be #{fmt}."
      ContextLog.exception(e, e.backtrace, msg) if Object.defined?(:ContextLog)
      raise ISO8583Exception.new(msg)
    end
  }

  c
end

Instance Method Details

#_conv(str, mapping) ⇒ Object



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

def _conv(str, mapping)
  _str = String.new("", encoding: "ASCII-8BIT")
  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/iso8583/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/iso8583/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/iso8583/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/iso8583/util.rb', line 25

def hex2b(hex_string)
  string = hex_string.to_s.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