[[iso8583]]

== An ISO-8583 primer

This section contains general information about the ISO-8583 International Standard. 

=== International standard ISO 8583

*Financial transaction card-originated messages Interchange message specifications*.

You have to read it, period. And you have to read the correct one
(1987/1993/2003) for your particular interchange.  And you also have to read
your vendor-specific interchange specs as well. 

But while you manage to gather all that information, let's have a look at this
brief introduction. When talking about ISO-8583, we have to be aware of the difference between:

* message format (its binary representation),
* wire protocol (how a  message is transmitted over the wire), and
* message flow (e.g., send  request for authorization, wait for response, retransmit, reversal, etc.). 



[[iso8583_message_structure]]

=== Message format

ISO-8583 messages are composed by fields, which are represented in different ways. Basically we have the following structure: 

.ISO-8583 message structure
[cols="1,5", options="header"]
|========================================================================
|Field #    |Description
|0 - MTI    |Message Type Indicator
|1 - Bitmap |64 (or 128) bits indicating presence/absence of other fields
|2 .. 128   |Other fields as specified in bitmap
|========================================================================

[NOTE]
The bitmaps are encoded in network byte order, with the most significant bit (leftmost bit) of the first
byte indicating presence of a secondary bitmap. Then, the next bit towards the right indicates presence
of field 2, the next one refers to field 3, and so on.



So let's have a look at a simple example: 

.Sample 0800 message
[cols="2,5,3,3", options="header"]
|========================================================================
|#|Name|Value|Hex Value
|0 |MTI|0800|08 00
|1 |PRIMARY BITMAP|Indicates presence of fields 3, 11 and 41|20 20 00 00 00 80 00 00
|3 |PROCESSING CODE|000000|00 00 00
|11|SYSTEM TRACE AUDIT NUMBER|000001|00 00 01
|41|TERMINAL ID|29110001|32 39 31 31 30 30 30 31
|========================================================================

Here is the binary representation of our 0800 message: 

----
   080020200000008000000000000000013239313130303031
----


In the previous example, 0800 is the  *message type indicator ('MTI')*; 
The first position represents ISO-8583 version number: 

* 0 for version 1987
* 1 for version 1993
* 2 for version 2003
* 3-7 reserved for ISO use
* 8 is reserved for national use
* 9 is reserved for private use

The second position represents *message class*: 

* 0 is reserved for ISO use
* 1 authorization
* 2 financial
* 3 file update
* 4 reversals and chargebacks
* 5 reconciliation
* 6 administrative
* 7 fee collection
* 8 network management
* 9 reserved for ISO use

The third position is the *message function*: 

* 0 request
* 1 request response
* 2 advice
* 3 advice response
* 4 notification
* 5-9 reserved for ISO use

And the last position is used to indicate the *transaction originator*: 

* 0 acquirer
* 1 acquirer repeat
* 2 card issuer
* 3 card issuer repeat
* 4 other
* 5 other repeat
* 6-9 reserved for ISO use
 

So "0800" is a 'version 1987 network management request'. 

Next we have field 1, the primary bitmap: 


.Primary Bitmap
[cols="2,2,2,4", options="header"]
|==============================
|byte|hex value|bit value|field #
|0|20|0010 0000|3
|1|20|0010 0000|11
|2|00|0000 0000|
|3|00|0000 0000|
|4|00|0000 0000|
|5|80|1000 0000|41
|6|00|0000 0000|
|7|00|0000 0000|
|==============================

So now that we've parsed the MTI (0800) and bitmap (2020000000800000), 
we know that fields 3, 11 and 41 are present. 
So our next field is number 3.  


[[iso8583_fieldtypes]]

==== ISO-8583 fields

There are many field types:

* Fixed length 
** Numeric
** Alphanumeric
** Binary

* Variable length with a max length 99
** Numeric
** Alphanumeric
** Binary

* Variable length with a max length 999
** Numeric
** Alphanumeric
** Binary

* Variable length with a max length 9999 (available starting in ISO-8583 version 2003)
** Numeric
** Alphanumeric
** Binary

* Nested message 


So far, so good, this is very simple stuff, isn't it? 
The problem is not complexity but diversity, ISO-8583 is not specific about how 
a given field is represented, so you can have a numeric field represented as a 
sequence of ASCII characters, EBCDIC characters, BCD, etc. 

Variable length fields have a prefix specifying its length, but how this is represented 
is not defined. Different vendors use different representations (e.g., BCD, EBCDIC, 
binary value). 

In our example, field #3 is using a BCD representation in network byte order, so a value of "000000" 
is represented with just three bytes whose hex values are "00 00 00". 
Same goes for field #11 whose value is "000001" - it is represented as "00 00 01". 
In our example, field #41 is an eight-byte alphanumeric field represented as eight ASCII characters 

----

     Message: 08002020 00000080 00000000 00000001
              32393131 30303031

         MTI: 0800
      Bitmap: 20200000 00800000
    Field 03: 000000
    Field 11: 000001
    field 41: 3239313130303031 (ASCII for "29110001")
   
----

Let's have a look at another sample message: 

.Another 0800 message
[cols="2,4,6,3", options="header"]
|===============
|#|Name|Value|Hex Value
|0
|MTI
|0800
|+08 00+

|1.
|PRIMARY BITMAP
|Indicates presence of secondary bitmap plus fields 3, 11, 41 and 60
|+A0 20 00 00 00 80 00 10+

|1
|SECONDARY BITMAP
|Indicates presence of field 70
|+04 00 00 00 00 00 00 00+

|3
|PROCESSING CODE
|000000
|+00 00 00+

|11
|SYSTEM TRACE AUDIT NUMBER
|000001
|+00 00 01+

|41
|TERMINAL ID
|29110001
|+32 39 31 31 30 30 30 31+

|60
|RESERVED FOR PRIVATE USE
|jPOS 1.9.1
|+00 10 6A 50 4F 53 20 31 2E 39 2E 31+

|70
|NETWORK MANAGEMENT INFORMATION CODE
|301
|+03 01+
|===============



Two new fields are present: #60 and #70. Here is our message representation: 

----

         Message: 0800A020 00000080 00100400 00000000
                  00000000 00000001 32393131 30303031
                  00106A50 4F532031 2E392E31 0301

             MTI: 0800
  Primary bitmap: A0200000 00800010 
Secondary bitmap: 04000000 00000000
        Field 03: 000000
        Field 11: 000001
        Field 41: 3239313130303031 (ASCII for "29110001")
        Field 60: 0010 6A504F5320312E392E31 (length=10, value="jPOS 1.9.1") <1>
        Field 70: 0301
 
----

<1> In this example, the length prefix in field 60 is expressed as a 2-byte BCD number; therefore, a length of 10 is encoded as 0010 in hexadecimal.

Let's break down this bitmap: 

.Primary Bitmap
[cols="2,2,2,4", options="header"]
|====
|byte|hex value|bit value|field #
|0|A0|1010 0000|secondary bitmap present plus #3
|1|20|0010 0000|11
|2|00|0000 0000|
|3|00|0000 0000|
|4|00|0000 0000|
|5|80|1000 0000|41
|6|00|0000 0000|
|7|10|0001 0000|60
|====

.Secondary Bitmap
[cols="2,2,2,4", options="header"]
|====
|byte|hex value|bit value|field #
|0|04|0000 0100|70
|1|00|0000 0000|
|2|00|0000 0000|
|3|00|0000 0000|
|4|00|0000 0000|
|5|00|0000 0000|
|6|00|0000 0000|
|7|00|0000 0000|
|====


To make things more complex to developers, different vendors choose different padding 
styles when handling odd-length BCD fields. So in order to represent "003" one 
vendor may use two bytes with the values +"00 03"+ while others may use +"00 30"+ 
or even +"00 3F"+. 

Same goes for variable-length fields: field length as well as field values can
be padded to the left or to the right (that's not defined by ISO-8583, it's
just a matter of fact of different implementations). 

Then we have nested fields - some implementations use "reserved for private
use" fields to carry other ISO-8583 messages. These messages are usually packed
as variable-length binary fields as seen by the outer message. 

[TIP]
=====
You will see that jPOS handles this problem in a very simple way so you
don't have to worry about this low-level stuff.  
=====

[[iso8583_wire_protocol]]

=== Wire protocol

Once we have a binary representation of a given ISO-8583 message, we have to
transmit it over the wire using some communication protocol (e.g., TCP/IP,
UDP, X.25, SDLC, SNA, ASYNC, QTP, SSL, HTTP, you name it). 

That communication protocol is not part of the ISO-8583 standard, so different
vendors have chosen different protocols. 

Many implementations (especially the older ones) require support for some kind 
of routing information (e.g., a CICS transaction name), so they use different sorts 
of +headers+. 

A few of them (especially stream-based ones) require some kind of trailers as well. 

So, the wire protocol is composed by: 

* An optional header / message boundary delimiter
* ISO-8583 message data
* An optional trailer (sometimes used as a message boundary delimiter)

A TCP/IP-based implementation may use a couple of bytes to indicate message
length, so our 0800 example described earlier would be sent as: 


----

  00 46 08 00 A0 20 00 00  00 80 00 10 04 00 00 00
  00 00 00 00 00 00 00 00  00 01 32 39 31 31 30 30
  30 31 00 10 6A 50 4F 53  20 31 2E 34 2E 31 03 01
  
----

0046 being the message length expressed in network byte order. 

But this is just one way of specifying message length. Other implementations may choose to send 
four ASCII bytes, e.g.:  

----

  30 30 34 36 08 00 A0 20  00 00 00 80 00 10 04 00
  00 00 00 00 00 00 00 00  00 00 00 01 32 39 31 31
  30 30 30 31 00 10 6A 50  4F 53 20 31 2E 34 2E 31
  03 01
----

+30 30 34 36+ being the ASCII representation of "0046". 

[NOTE]
======
Some implementations count the size of the message length indicator -- in the
previous example the four bytes "0046" -- so instead of sending "0046" they would
send "0050".
======

A few of them perform odd things with those headers, flagging rejected messages
(e.g., you send a 0100 and instead of receiving a 0110 with a suitable response
code you get back your own 0100 with some proprietary flag in the header
indicating for example a temporarily failure such as destination unreachable).  

[TIP]
====
It's very important to read your interchange specification(s) 
as early as possible during your development.
====


jPOS deals with the wire protocol by using a set of classes called 
*channels* that implement the 
http://jpos.org/doc/javadoc/org/jpos/iso/ISOChannel.html[ISOChannel] interface
that hides the wire protocol details.

[[iso8583_message_flow]]

=== Message flow

Message flow will vary depending on your particular interchange specification. 
But let's have a look at a simple example: 

.Sample authorization
[cols="2,2,2,4", options="header"]
|===============
|Time|Acquirer|Issuer|Description
|t~0~|0100 --&gt; ||authorization request
|t~1~|| &lt;-- 0110|authorization response
|===============


While this is the typical case (you send a request, you get a response),
sometimes there are temporary failures, and you don't get a response.  You have
to reverse the previously transmitted transaction and then either retry your
authorization request, abort that transaction or get an authorization approval
by other means (e.g., by phone) and send an advice. 

.Authorization timeout
[cols="2,2,2,4", options="header"]
|===============
|Time|Acquirer|Issuer|Description
|t~0~|0100 --&gt; ||authorization request
|t~1~|||no response
|t~2~|0400 --&gt; ||reverse previous authorization
|t~3~|| &lt;-- 0410|reverse received
|t~4~|0120 --&gt; ||authorization advice
|t~5~|| &lt;-- 0130|advice received
|===============

Depending on your particular implementation, you may be able to send
retransmissions as well (e.g., 0101 after an unanswered 0100). Some
implementations use private messages (e.g., 9600)  to request extended time to
process a transaction. So you can see  it is very important to become familiar
with your interchange specifications and its expected message flow as early 
as possible. 

jPOS provides tools to deal with message structure, wire protocol and message
flow, but it's the responsibility of your higher-level application to interface
the message flow  with your business logic. 

A real example may help you get the idea of what kind of information is
exchanged during an authorization request and response. See below: 


.Sample authorization request
[cols="1,3,4,4", options="header"]
|===============
|Fld #|Description|Value|Comments
|0|MTI|0100|Authorization request
|2|Primary Account Number|4321123443211234|
|3|Processing Code|000000|
|4|Amount transaction|000000012300|e.g., 123.00
|7|Transmission data/time|0304054133|MMYYHHMMSS
|11|System trace audit number|001205|
|14|Expiration date|0205|YYMM
|18|Merchant Type|5399|
|22|POS Entry Mode|022|Swiped Card
|25|POS Condition Code|00|
|35|Track 2|4321123443211234=0205..|
|37|Retrieval Reference Number|206305000014|
|41|Terminal ID|29110001|
|42|Merchant ID|1001001|
|49|Currency|840|US Dollars
|===============

.Sample authorization response
[cols="1,3,4,4", options="header"]
|===============
|Fld #|Description|Value|Comments
|0|MTI|0110|Authorization response
|2|Primary Account Number|4321123443211234|
|3|Processing Code|000000|
|4|Amount transaction|000000012300|e.g., 123.00
|7|Transmission data/time|0304054133|MMYYHHMMSS
|11|System trace audit number|001205|
|14|Expiration date|0205|YYMM
|18|Merchant Type|5399|
|22|POS Entry Mode|022|Swiped Card
|25|POS Condition Code|00|
|35|Track 2|4321123443211234=0205..|
|37|Retrieval Reference Number|206305000014|
|38|Authorization number|010305|
|39|Response code|00|Approved
|41|Terminal ID|29110001|
|42|Merchant ID|1001001|
|49|Currency|840|US Dollars
|===============

