Class: ISO8583::Message
- Inherits:
-
Object
- Object
- ISO8583::Message
- Defined in:
- lib/iso8583/message.rb
Overview
The class ‘Message` defines functionality to describe classes representing different type of messages, or message families. A message family consists of a number of possible message types that are allowed, and a way of naming and encoding the bitmaps allowed in the messages.
To create your own message, start by subclassing Message:
class MyMessage < Message
(...)
end
the subtyped message should be told how the MTI is encoded:
class MyMessage < Message
mti_format N, :length => 4
(...)
end
‘N` above is an instance of Field which encodes numbers into their ASCII representations in a fixed length field. The option `length=>4` indicates the length of the fixed field.
Next, the allowed message types are specified:
class MyMessage < Message
(...)
mti 1100, "Authorization Request Acquirer Gateway"
mti 1110, "Authorization Request Response Issuer Gateway"
(...)
end
This basically defines to message types, 1100 and 1110 which may be accessed later either via their name or value:
mes = MyMessage.new 1100
or
mes = MyMessage.new "Authorization Request Acquirer Gateway"
or
mes = MyMessage.new
mes.mti = 1110 # or Auth. Req. Acq. Gateway ...
Finally the allowed bitmaps, their names and the encoding rules are specified:
class MyMessage < Message
(...)
bmp 2, "Primary Account Number (PAN)", LLVAR_N, :max => 19
bmp 3, "Processing Code", N, :length => 6
bmp 4, "Amount (Transaction)", N, :length => 12
bmp 6, "Amount, Cardholder Billing" , N, :length => 12
(...)
end
The example above defines four bitmaps (2,3,4 and 6), and provides their bitmap number and description. The PAN field is variable length encoded (LL length indicator, ASCII, contents numeric, ASCII) and the maximum length of the field is limited to 19 using options.
The other fields are fixed length numeric ASCII fields (the length of the fields is indicated by the ‘:length` options.)
This message may be used as follows in order to interpret a received message.:
mes = MyMessage.parse inputData
puts mes[2] # prints the PAN from the message.
Constructing own messages works as follows:
mes = MyMessage.new 1100
mes[2]= 474747474747
# Alternatively
mes["Primary Account Number (PAN)"]= 4747474747
mes[3] = 1234 # padding is added by the Field en/decoder
mes["Amount (Transaction)"] = 100
mes[6] = 200
the convenience method bmp_alias may be used in defining the class in order to provide direct access to fields using methods:
class MyMessage < Message
(...)
bmp 2, "Primary Account Number (PAN)", LLVAR_N, :max => 19
(...)
bmp_alias 2, :pan
end
this allows accessing fields in the following manner:
mes = MyMessage.new 1100
mes.pan = 474747474747
puts mes.pan
# Identical functionality to:
mes[2]= 474747474747
# or:
mes["Primary Account Number (PAN)"]= 4747474747
Most of the work in implementing a new set of message type lays in figuring out the correct fields to use defining the Message class via bmp.
Direct Known Subclasses
Instance Attribute Summary collapse
-
#mti ⇒ Object
The value of the MTI (Message Type Indicator) of this message.
Class Method Summary collapse
-
._definitions ⇒ Object
Access the field definitions of this class, this is a hash containing [bmp_number, BMP] and [bitmap_name, BMP] pairs.
-
._handle_opts(field, opts) ⇒ Object
Modifies the field definitions of the fields passed in through the ‘bmp` and `mti_format` class methods.
-
._mti_definitions ⇒ Object
access the mti definitions applicable to the Message.
-
._mti_format ⇒ Object
Returns the field definition to format the mti.
-
.bmp(bmp, name, field, opts = nil) ⇒ Object
Define a bitmap in the message ===Params: * bmp : bitmap number * name : human readable form * field : field for encoding/decoding * opts : options to pass to the field, e.g.
-
.bmp_alias(bmp, aliaz) ⇒ Object
Create an alias to access bitmaps directly using a method.
-
.mti(value, name) ⇒ Object
Defines the message types allowed for this type of message and gives them names.
-
.mti_format(field, opts) ⇒ Object
Defines how the message type indicator is encoded into bytes.
-
.parse(str) ⇒ Object
Parse the bytes ‘str` returning a message of the defined type.
Instance Method Summary collapse
-
#[](key) ⇒ Object
Retrieve the decoded value of the contents of a bitmap described either by the bitmap number or name.
-
#[]=(key, value) ⇒ Object
Set a field in this message, ‘key` is either the bmp number or it’s name.
-
#_body ⇒ Object
Returns an array of two byte arrays: [bitmap_bytes, message_bytes].
-
#_get_definition(key) ⇒ Object
:nodoc:.
-
#_get_mti_definition(key) ⇒ Object
return [mti_num, mti_value] for key being either mti_num or mti_value.
-
#initialize(mti = nil) ⇒ Message
constructor
Instantiate a new instance of this type of Message optionally specifying an mti.
-
#to_b ⇒ Object
Retrieve the byte representation of the bitmap.
-
#to_s ⇒ Object
Returns a nicely formatted representation of this message.
Constructor Details
#initialize(mti = nil) ⇒ Message
Instantiate a new instance of this type of Message optionally specifying an mti.
117 118 119 120 121 122 123 |
# File 'lib/iso8583/message.rb', line 117 def initialize(mti = nil) # values is an internal field used to collect all the # bmp number | bmp name | field en/decoders | values # which are set in this message. @values = {} self.mti = mti if mti end |
Instance Attribute Details
#mti ⇒ Object
The value of the MTI (Message Type Indicator) of this message.
113 114 115 |
# File 'lib/iso8583/message.rb', line 113 def mti @mti end |
Class Method Details
._definitions ⇒ Object
Access the field definitions of this class, this is a hash containing [bmp_number, BMP] and [bitmap_name, BMP] pairs.
374 375 376 |
# File 'lib/iso8583/message.rb', line 374 def _definitions @defs end |
._handle_opts(field, opts) ⇒ Object
Modifies the field definitions of the fields passed in through the ‘bmp` and `mti_format` class methods.
391 392 393 394 395 396 397 398 399 400 |
# File 'lib/iso8583/message.rb', line 391 def _handle_opts(field, opts) opts.each_pair {|key, value| key = (key.to_s+"=").to_sym if field.respond_to?(key) field.send(key, value) else warn "unknown option #{key} for #{field.name}" end } end |
._mti_definitions ⇒ Object
access the mti definitions applicable to the Message
returns a pair of hashes containing:
mti_value => mti_name
mti_name => mti_value
366 367 368 |
# File 'lib/iso8583/message.rb', line 366 def _mti_definitions [@mtis_v, @mtis_n] end |
._mti_format ⇒ Object
Returns the field definition to format the mti.
379 380 381 |
# File 'lib/iso8583/message.rb', line 379 def _mti_format @mti_format end |
.bmp(bmp, name, field, opts = nil) ⇒ Object
Define a bitmap in the message
Params:
-
bmp : bitmap number
-
name : human readable form
-
field : field for encoding/decoding
-
opts : options to pass to the field, e.g. length for fxed len fields.
Example
class MyMessage < Message
bmp 2, "PAN", LLVAR_N, :max =>19
(...)
end
creates a class MyMessage that allows for a bitmap 2 which is named “PAN” and encoded by an LLVAR_N Field. The maximum length of the value is 19. This class may be used as follows:
mes = MyMessage.new
mes[2] = 474747474747 # or mes["PAN"] = 4747474747
299 300 301 302 303 304 305 306 307 308 309 310 311 |
# File 'lib/iso8583/message.rb', line 299 def bmp(bmp, name, field, opts = nil) @defs ||= {} field = field.dup field.name = name field.bmp = bmp _handle_opts(field, opts) if opts bmp_def = BMP.new bmp, name, field @defs[bmp] = bmp_def @defs[name] = bmp_def end |
.bmp_alias(bmp, aliaz) ⇒ Object
Create an alias to access bitmaps directly using a method. Example:
class MyMessage < Message
(...)
bmp 2, "PAN", LLVAR_N
(...)
bmp_alias 2, :pan
end #class
would allow you to access the PAN like this:
mes.pan = 1234
puts mes.pan
instead of:
mes[2] = 1234
331 332 333 334 335 336 337 338 339 340 341 342 343 |
# File 'lib/iso8583/message.rb', line 331 def bmp_alias(bmp, aliaz) define_method (aliaz) { bmp_ = @values[bmp] bmp_ ? bmp_.value : nil } define_method ("#{aliaz}=") {|value| self[bmp] = value # bmp_def = _get_definition(bmp) # bmp_def.value= value # @values[bmp] = bmp_def } end |
.mti(value, name) ⇒ Object
Defines the message types allowed for this type of message and gives them names
Example
class MyMessage < Message
(...)
mti 1100, "Authorization Request Acquirer Gateway"
end
mes = MyMessage.new
mes.mti = 1100 # or mes.mti = "Authorization Request Acquirer Gateway"
See Also: mti_format
271 272 273 274 275 276 |
# File 'lib/iso8583/message.rb', line 271 def mti(value, name) @mtis_v ||= {} @mtis_n ||= {} @mtis_v[value] = name @mtis_n[name] = value end |
.mti_format(field, opts) ⇒ Object
Defines how the message type indicator is encoded into bytes.
Params:
-
field : the decoder/encoder for the MTI
-
opts : the options to pass to this field
Example
class MyMessage < Message
mti_format N, :length =>4
(...)
end
encodes the mti of this message using the ‘N` field (fixed length, plain ASCII) and sets the fixed lengh to 4 bytes.
See also: mti
252 253 254 255 256 |
# File 'lib/iso8583/message.rb', line 252 def mti_format(field, opts) f = field.dup _handle_opts(f, opts) @mti_format = f end |
.parse(str) ⇒ Object
Parse the bytes ‘str` returning a message of the defined type.
346 347 348 349 350 351 352 353 354 355 356 |
# File 'lib/iso8583/message.rb', line 346 def parse(str) = self.new .mti, rest = _mti_format.parse(str) bmp,rest = Bitmap.parse(rest) bmp.each {|bit| bmp_def = _definitions[bit] value, rest = bmp_def.field.parse(rest) [bit] = value } end |
Instance Method Details
#[](key) ⇒ Object
Retrieve the decoded value of the contents of a bitmap described either by the bitmap number or name.
Example
mes = BlaBlaMessage.parse someMessageBytes
mes[2] # bmp 2 is generally the PAN
mes["Primary Account Number"] # if thats what you called the field in Message.bmp.
167 168 169 170 171 |
# File 'lib/iso8583/message.rb', line 167 def [](key) bmp_def = _get_definition key bmp = @values[bmp_def.bmp] bmp ? bmp.value : nil end |
#[]=(key, value) ⇒ Object
Set a field in this message, ‘key` is either the bmp number or it’s name.
Example
mes = BlaBlaMessage.new
mes[2]=47474747 # bmp 2 is generally the PAN
mes["Primary Account Number"]=47474747 # if thats what you called the field in Message.bmp.
149 150 151 152 153 154 155 156 157 |
# File 'lib/iso8583/message.rb', line 149 def []=(key, value) if value.nil? @values.delete(key) else bmp_def = _get_definition key bmp_def.value = value @values[bmp_def.bmp] = bmp_def end end |
#_body ⇒ Object
Returns an array of two byte arrays:
- bitmap_bytes, message_bytes
203 204 205 206 207 208 209 210 211 212 |
# File 'lib/iso8583/message.rb', line 203 def _body bitmap = Bitmap.new = "" @values.keys.sort.each do |bmp_num| bitmap.set(bmp_num) enc_value = @values[bmp_num].encode << enc_value end [ bitmap.to_bytes, ] end |
#_get_definition(key) ⇒ Object
:nodoc:
214 215 216 217 218 219 220 |
# File 'lib/iso8583/message.rb', line 214 def _get_definition(key) #:nodoc: b = self.class._definitions[key] unless b raise ISO8583Exception.new "no definition for field: #{key}" end b.dup end |
#_get_mti_definition(key) ⇒ Object
return [mti_num, mti_value] for key being either mti_num or mti_value
224 225 226 227 228 229 230 231 232 233 |
# File 'lib/iso8583/message.rb', line 224 def _get_mti_definition(key) num_hash,name_hash = self.class._mti_definitions if num_hash[key] [key, num_hash[key]] elsif name_hash[key] [name_hash[key], key] else raise ISO8583Exception.new("MTI: #{key} not allowed!") end end |
#to_b ⇒ Object
Retrieve the byte representation of the bitmap.
174 175 176 177 178 |
# File 'lib/iso8583/message.rb', line 174 def to_b raise ISO8583Exception.new "no MTI set!" unless mti mti_enc = self.class._mti_format.encode(mti) mti_enc << _body.join end |
#to_s ⇒ Object
Returns a nicely formatted representation of this message.
182 183 184 185 186 187 188 189 190 191 192 193 194 195 |
# File 'lib/iso8583/message.rb', line 182 def to_s _mti_name = _get_mti_definition(mti)[1] str = "MTI:#{mti} (#{_mti_name})\n\n" _max = @values.values.max {|a,b| a.name.length <=> b.name.length } _max_name = _max.name.length @values.keys.sort.each{|bmp_num| _bmp = @values[bmp_num] str += ("%03d %#{_max_name}s : %s\n" % [bmp_num, _bmp.name, _bmp.value]) } str end |