The objective of this protocol is to transmit information for payment processing through a network, usually using TCP/IP sockets. An ISO8583 message can have up to 63 or 127 fields and is processed in a linear way, that is, the message can be processed as it is being read.
A simple ISO8583 is comprised of the following:
The first field is a special field and contains a secondary bitmap. If the first bit of the primary bitmap is on, then the first field after the bitmap is another bitmap, also 64 bits long, indicating additional fields from 65 to 128.
From the second field to the last one, the message contains only "normal" fields, which can have the following datatypes:
000000001500
.The most common message types are:
0200 | Request for payment, credit card charge, etc. |
0210 | Response to payment, credit card charge, etc. |
0400 | Request for reversal of payment, credit card charge, etc. |
0410 | Response to reversal of payment, credit card charge, etc. |
0600 | Query |
0610 | Response to query |
0800 | Echo request |
0810 | Echo response |
ISO8583 messages can be encoded as ASCII or binary; ASCII is more common. In this format, the message type is 4 bytes long, because the characters for it are sent as text, ie. "0200". In binary encoding, the message type is 2 bytes long, for example message type 0200 is encoded as byte 0x02 and byte 0x00.
In ASCII encoding, the bitmap is sent using hex encoding, so it's 16 characters long; that is, every 4 bits are a hex digit. For example, if the message includes fields 1 and 3 but not 2 or 4, then the first 4 bits are 1010 which is 0xA. In binary encoding, the bitmap is sent as 8 bytes, without encoding them in any way.
Numeric and alpha fields in ASCII have the same length in bytes as they do in characters or digits; numeric fields are sent as text, for example "000012".
In binary encoding, numeric fields are encoded using BCD (Binary Coded Digits), which means taking 2 digits and encoding them as hex, that is, the number 12 is encoded as 0x12; this way, a byte can always contain 2 digits. Numbers with an odd number of digits (such as the length header for a LLLVAR field) will have a zero to the left, for example 128 is encoded as two bytes: 0x1 and 0x28.
ASCII-encoded LLVAR and LLLVAR fields will have 2 or 3 character headers.
Binary encoded LLVAR and LLLVAR fields will have 1 or 2 byte headers; LLVAR fields have their header as a 1-byte BCD number, for example if the header is 0x57 it means that the field is 57 bytes long. LLLVAR fields have 2-byte BCD headers but the first digit is always 0; for example if the header is 0x128 it means the field contents are 128 bytes long.
Date and amount fields, being numeric, are encoded as any other numeric field. For example a full date field will be 10 characters long in ASCII encoding but only 5 bytes long in binary encoding.
In some implementations, messages must include a header before the message type. This is implementation-specific and the headers usually vary only by message type.
Additionally, it is very common to include a header with the length of the message when sending ISO8583 over a network. The header is usually 2 bytes long and is a binary unsigned integer with the length of the full message, thus making the reading on the other side easier, since the process consists of reading 2 bytes, interpreting them as a length, and then reading that many bytes. The byte order is usually most significant byte first, but it can vary in certain implementations.
Sometimes there is also a message terminator, which can be included in the length or not, depending on implementation. Message terminators are usually just 1 byte long.
Here are some examples of ISO8583 messages, along with the XML definition to parse them with the j8583 framework. ASCII encoding is being used for these.
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE j8583-config PUBLIC "-//J8583//DTD CONFIG 1.0//EN"
"http://j8583.sourceforge.net/j8583.dtd">
<j8583-config>
<!-- These are the ISO headers to be prepended to the message types specified -->
<header type="0200">ISO015000050</header>
<header type="0210">ISO015000055</header>
<header type="0400">ISO015000050</header>
<header type="0410">ISO015000055</header>
<header type="0800">ISO015000015</header>
<header type="0810">ISO015000015</header>
<!-- The client example uses this to create requests -->
<template type="0200">
<field num="3" type="NUMERIC" length="6">650000</field>
<field num="32" type="LLVAR">456</field>
<field num="35" type="LLVAR">4591700012340000=</field>
<field num="43" type="ALPHA" length="40">SOLABTEST TEST-3 DF MX
<field num="49" type="ALPHA" length="3">484</field>
<field num="60" type="LLLVAR">B456PRO1+000</field>
<field num="61" type="LLLVAR"> 1234P</field>
<field num="100" type="LLVAR">999</field>
<field num="102" type="LLVAR">ABCD</field>
</template>
<!-- The server example uses this to create the responses
we only need a few fields because the rest are copied from the request -->
<template type="0210">
<field num="60" type="LLLVAR">Fixed data from template</field>
<field num="70" type="ALPHA" length="3">ABC</field>
<field num="90" type="ALPHA" length="42">Field of length 42</field>
<field num="100" type="LLVAR">Fixed field</field>
<field num="102" type="LLVAR">Another fixed field</field>
<field num="126" type="LLLVAR">...and yet another fixed field.</field>
</template>
<!-- The server example uses this to read the requests -->
<parse type="0200">
<field num="3" type="NUMERIC" length="6" />
<field num="4" type="AMOUNT" />
<field num="7" type="DATE10" />
<field num="11" type="NUMERIC" length="6" />
<field num="12" type="TIME" />
<field num="13" type="DATE4" />
<field num="15" type="DATE4" />
<field num="17" type="DATE_EXP" />
<field num="32" type="LLVAR" />
<field num="35" type="LLVAR" />
<field num="37" type="NUMERIC" length="12" />
<field num="41" type="ALPHA" length="16" />
<field num="43" type="ALPHA" length="40" />
<field num="48" type="LLLVAR" />
<field num="49" type="ALPHA" length="3" />
<field num="60" type="LLLVAR" />
<field num="61" type="LLLVAR" />
<field num="100" type="LLVAR" />
<field num="102" type="LLVAR" />
</parse>
<!-- The client example uses this to read the responses -->
<parse type="0210">
<field num="3" type="NUMERIC" length="6" />
<field num="4" type="AMOUNT" />
<field num="7" type="DATE10" />
<field num="11" type="NUMERIC" length="6" />
<field num="12" type="TIME" />
<field num="13" type="DATE4" />
<field num="15" type="DATE4" />
<field num="17" type="DATE_EXP" />
<field num="32" type="LLVAR" />
<field num="35" type="LLVAR" />
<field num="37" type="NUMERIC" length="12" />
<field num="38" type="NUMERIC" length="6" />
<field num="39" type="NUMERIC" length="2" />
<field num="41" type="ALPHA" length="16" />
<field num="43" type="ALPHA" length="40" />
<field num="48" type="LLLVAR" />
<field num="49" type="ALPHA" length="3" />
<field num="60" type="LLLVAR" />
<field num="61" type="LLLVAR" />
<field num="70" type="ALPHA" length="3" />
<field num="90" type="ALPHA" length="42" />
<field num="100" type="LLVAR" />
<field num="102" type="LLVAR" />
<field num="126" type="LLLVAR" />
</parse>
</j8583-config>
Request:
ISO0150000500200B23A800128A180180000000014000000650000000000002050042813271000057813271004280428042803456174591700012340000=000000230579A1B2C3D4E5 SOLABTEST TEST-3 DF MX010abcdefghij484012B456PRO1+000013 1234P0399904ABCD
Field | Value |
---|---|
ISO header | ISO015000050 |
Message type | 0200 |
Primary bitmap | B23A800128A18018 |
Secondary bitmap | 0000000014000000 |
3 (proc code) | 650000 |
4 (amount) | 000000002050 ($20.50) |
7 (date) | 0428132710 (Abril 28 13:27:10) |
11 (trace) | 000578 |
12 (time) | 132710 (13:27:10) |
13 (date issued) | 0428 (28 de abril) |
15 (limit date) | 0428 (28 de abril) |
17 (expiration date) | 0804 (Abril 2008) |
32 | 456 |
35 | 4591700012340000= |
37 (reference) | 000000230579 |
41 (term id) | A1B2C3D4E5 |
43 | SOLABTEST TEST-3 DF MX |
48 | abcdefghij |
49 (currency) | 484 |
60 | B456PRO1+000 |
61 | 1234P |
100 | 999 |
102 | ABCD |
Response:
ISO0150000550210B23A80012EA180180400004014000004650000000000002050042813271000057813271004280428060403456174591700012340000=00000023057923104300A1B2C3D4E5 SOLABTEST TEST-3 DF MX010abcdefghij484012B456PRO1+000054Dynamic data generated at Mon Apr 28 13:27:11 CDT 2008ABCField of length 42 0399904ABCD031...and yet another fixed field.
Field | Value |
---|---|
ISO header | ISO015000055 |
Message type | 0210 |
Primary bitmap | B23A80012EA18018 |
Secondary bitmap | 0400004014000004 |
3 (proc code) | 650000 |
4 (amount) | 000000002050 ($20.50) |
7 (transaction date) | 0428132710 (Abril 28 13:27:10) |
11 (trace) | 000578 |
12 (time) | 132710 (13:27:10) |
13 (date issued) | 0428 (28 de abril) |
15 (limit date) | 0428 (28 de abril) |
17 (expiration date) | 0804 (Abril 2008) |
32 | 456 |
35 | 4591700012340000= |
37 (reference) | 000000230579 |
38 (confirmation number) | 231043 |
39 (result code) | 00 |
41 (term id) | A1B2C3D4E5 |
43 | SOLABTEST TEST-3 DF MX |
48 | abcdefghij |
49 (currency) | 484 |
60 | B456PRO1+000 |
61 | Dynamic data generated at Mon Apr 28 13:27:11 CDT 2008 |
70 | ABC |
90 | Field of length 42 |
100 | 999 |
102 | ABCD |
126 | ...and yet another fixed field. |