Jimmy’s Blog – ISO 8583 Tutorial – Build and Parse ISO Message using JPOS library
by jimmy on Jul.26, 2011, under English, Java, Programming
[Switch to Mobile Edition]ISO 8583 Tutorial article
In the beginning
OK after my article about ISO 8583 let’s go deeper into programming using Java + JPOS library.
Quote from JPOS website:
jPOS is a Java® platform-based, mission-critical, ISO-8583 based financial transaction library/framework that can be customized and extended in order to implement financial interchanges.
So first thing to do is download JPOS from it website.
Then we setup our development environment by creating Java Project using your favorites IDE. Add to the project all jar in JPOS library.
Here’s my Eclipse package explorer looks like.
Create Data Elements (DE) types XML
Like I said that ISO 8583 is a ’standard’ which mean can be different between one implementation and another ![]()
To put it simple, although there’s a (some) standard for DE list sometime we need to change it.
Either way, we need to tell JPOS how our DE will be formatted or packaged.
Since in the complete XML there’s 128 DE, I’ll quote only the DE # we used. Full xml can be downloaded here (basic.xml)
<?xml version="1.0" encoding="UTF-8" standalone="no"?> <!DOCTYPE isopackager SYSTEM "genericpackager.dtd"> <isopackager> <isofield id="0" length="4" name="MESSAGE TYPE INDICATOR" class="org.jpos.iso.IFA_NUMERIC"/> <isofield id="1" length="64" name="BIT MAP" class="org.jpos.iso.IFA_BITMAP"/> <isofield id="3" length="6" name="PROCESSING CODE" class="org.jpos.iso.IFA_NUMERIC"/> <isofield id="4" length="12" name="AMOUNT, TRANSACTION" class="org.jpos.iso.IFA_NUMERIC"/> <isofield id="7" length="10" name="TRANSMISSION DATE AND TIME" class="org.jpos.iso.IFA_NUMERIC"/> <isofield id="11" length="6" name="SYSTEM TRACE AUDIT NUMBER" class="org.jpos.iso.IFA_NUMERIC"/> <isofield id="44" length="25" name="ADITIONAL RESPONSE DATA" class="org.jpos.iso.IFA_LLCHAR"/> <isofield id="105" length="999" name="RESERVED ISO USE" class="org.jpos.iso.IFA_LLLCHAR"/> </isopackager>
The XML should easily understand in each isofield tag we define:
- id : the DE number
- length : the max/fixed length of the DE
- name : yes, it’s the name or description
- class : this define the type of the DE, which in this case represent by the JPOS class. You can see the whole class list here. I only list some of it.
- IFA_NUMERIC : Numeric – Left padder with zeros.
- IFA_BITMAP : For ISO Bitmap
- IFA_LLCHAR : ASCII variable len CHAR – 2 digit length info
- IFA_LLLCHAR : ASCII variable len CHAR – 3 digit length info
So this XML will be used for build (pack) ISO Message or parse (unpack) ISO Message.
You will need the XML data schema (genericpackager.dtd) to be put on same directory with basic.xml
Build (pack) ISO Message
Below is the code. The code is quite straight forward, review it first and I’ll discuss a bit afterward.
package gnu.jimmod.iso8583.utility; import java.io.IOException; import org.jpos.iso.ISOException; import org.jpos.iso.ISOMsg; import org.jpos.iso.packager.GenericPackager; public class BuildISOMessage { public static void main(String[] args) throws IOException, ISOException { // Create Packager based on XML that contain DE type GenericPackager packager = new GenericPackager("basic.xml"); // Create ISO Message ISOMsg isoMsg = new ISOMsg(); isoMsg.setPackager(packager); isoMsg.setMTI("0200"); isoMsg.set(3, "201234"); isoMsg.set(4, "10000"); isoMsg.set(7, "110722180"); isoMsg.set(11, "123456"); isoMsg.set(44, "A5DFGR"); isoMsg.set(105, "ABCDEFGHIJ 1234567890"); // print the DE list logISOMsg(isoMsg); // Get and print the output result byte[] data = isoMsg.pack(); System.out.println("RESULT : " + new String(data)); } private static void logISOMsg(ISOMsg msg) { System.out.println("----ISO MESSAGE-----"); try { System.out.println(" MTI : " + msg.getMTI()); for (int i=1;i<=msg.getMaxField();i++) { if (msg.hasField(i)) { System.out.println(" Field-"+i+" : "+msg.getString(i)); } } } catch (ISOException e) { e.printStackTrace(); } finally { System.out.println("--------------------"); } } }
The output:
----ISO MESSAGE-----
MTI : 0200
Field-3 : 201234
Field-4 : 10000
Field-7 : 110722180
Field-11 : 123456
Field-44 : A5DFGR
Field-105 : ABCDEFGHIJ 1234567890
--------------------
RESULT : 0200B2200000001000000000000000800000201234000000010000011072218012345606A5DFGR021ABCDEFGHIJ 1234567890
The program flow:
- Create ISO packager based on the xml file.
- Set the DE values. I use the previous article examples.
- Print the DE values set.
- Pack the message.
- Print the formatted ISO message. As you can see the result is the same with the previous article examples.
Parse (unpack) ISO Message
On this case it’s reversed. We have the ISO Message, and we need to see the DE values of it.
Like the previous code this one also similar and should be easy to understand.
package gnu.jimmod.iso8583.utility; import java.io.IOException; import org.jpos.iso.ISOException; import org.jpos.iso.ISOMsg; import org.jpos.iso.packager.GenericPackager; public class ParseISOMessage { public static void main(String[] args) throws IOException, ISOException { // Create Packager based on XML that contain DE type GenericPackager packager = new GenericPackager("basic.xml"); // Print Input Data String data = "0200B2200000001000000000000000800000201234000000010000011072218012345606A5DFGR021ABCDEFGHIJ 1234567890"; System.out.println("DATA : " + data); // Create ISO Message ISOMsg isoMsg = new ISOMsg(); isoMsg.setPackager(packager); isoMsg.unpack(data.getBytes()); // print the DE list logISOMsg(isoMsg); } private static void logISOMsg(ISOMsg msg) { System.out.println("----ISO MESSAGE-----"); try { System.out.println(" MTI : " + msg.getMTI()); for (int i=1;i<=msg.getMaxField();i++) { if (msg.hasField(i)) { System.out.println(" Field-"+i+" : "+msg.getString(i)); } } } catch (ISOException e) { e.printStackTrace(); } finally { System.out.println("--------------------"); } } }
The output:
DATA : 0200B2200000001000000000000000800000201234000000010000011072218012345606A5DFGR021ABCDEFGHIJ 1234567890
----ISO MESSAGE-----
MTI : 0200
Field-3 : 201234
Field-4 : 000000010000
Field-7 : 0110722180
Field-11 : 123456
Field-44 : A5DFGR
Field-105 : ABCDEFGHIJ 1234567890
--------------------
The program flow:
- Create ISO packager based on the xml file.
- Set ISO Message.
- Print the ISO Message.
- Unpack the message.
- Print the DE values. As you can see the result is correct, just like the DE set in first example.
In the end
Ok, like always I hope I make it clear for you.
This might not (yet) a tutorial to make you able the whole financial platform or a bank platform ![]()
But everyone need to start somewhere.
I see this code example as the implementation of my previous article (ISO 8583 introduction)
Just leave comment if you have questions.
Related posts:

February 26th, 2013 on 10:45 pm
I need to implement this application in android. I got error.
org.jpos.iso.ISOException: java.lang.ClassNotFoundException: org.apache.crimson.parser.XMLReaderImpl in loader dalvik.system.PathClassLoader[/data/app/com.sample.androidisomessage-1.apk] (java.lang.ClassNotFoundException: org.apache.crimson.parser.XMLReaderImpl in loader dalvik.system.PathClassLoader[/data/app/com.sample.androidisomessage-1.apk])
Please help me.
@Sanjay did you get solution. Please guide me
March 4th, 2013 on 1:36 pm
@Piraba I have the soultion too. Just mail me and I’ll send you the code.If you want to do it yourself override Generic packager with your own class that implements SAX Parser instead of default Crimson parser.
March 11th, 2013 on 2:06 pm
Hi,
I have a one small doubt i need to send a message to iso server like u show in the above. Can u assist me how to connect the server using ip and port number.
Thanks in Advance
praveenkumar
March 11th, 2013 on 5:18 pm
client = new Socket(serverName, port);
if(client.isConnected())
{
System.out.println(”Connected T0″
+ client.getRemoteSocketAddress());
OutputStream outToServer = client.getOutputStream();
DataOutputStream out = new DataOutputStream(outToServer);
out.writeUTF(new String(JPOS_PACKET));
InputStream inFromServer = client.getInputStream();
DataInputStream in =
new DataInputStream(inFromServer);
response = in.readUTF();
//Print Response
System.out.println(”Server says ” + response);
client.close();
March 12th, 2013 on 5:18 pm
Thanks a lot for your response
March 12th, 2013 on 6:45 pm
Please provide sample example for Cash withdrawal partial reversal(Message type 400). Also let me know the significance of the field 95 in ISO 8583.
Thanks in advance.
March 18th, 2013 on 4:57 am
please tell me what all is required to make an ATM device work ( including client application interface with all programming modules, ISO 8583 message implementation, encrypting user’s input at the terminal and connection to bank switches )
March 18th, 2013 on 5:04 am
also tell me that once the client establishes connection to its own bank switch ,then how do the that client’s request for transaction is routed to the issuer bank through acquirer bank. i mean who does that, is it the bank’s job or we need to write the code for that process( as an ATM developer).
March 18th, 2013 on 2:23 pm
@piraba : could u please answer to my questions!
March 18th, 2013 on 3:28 pm
@Deepak
First you send data to your switch using JPOS or by making a custom packet (eg for balance Enquiry)
public LinkedHashMap getBalanceEnquiry(Context context,String accountNumber,String trackValue){
LinkedHashMap balanceEnquiry = new LinkedHashMap();
balanceEnquiry.put(”003″,”311000″);
balanceEnquiry.put(”004″,”000000000000″);
balanceEnquiry.put(”007″,ProjectUtil.getTransacDateTimeStamp());
balanceEnquiry.put(”011″,ProjectUtil.getStanNumber(context));
balanceEnquiry.put(”012″,ProjectUtil.getTransacTimeStamp());
balanceEnquiry.put(”013″,ProjectUtil.getTransacDateStamp());
balanceEnquiry.put(”015″,ProjectUtil.getTransacDateStamp());
balanceEnquiry.put(”018″,”6011″);
balanceEnquiry.put(”041″,ProjectUtil.getTermID(context));
balanceEnquiry.put(”048″,”0130″+trackValue);
balanceEnquiry.put(”049″,”356″);
balanceEnquiry.put(”123″,”015210101213146002″);
return balanceEnquiry;
}
Then your switch connects to the bank’s CBS which is based on the agreement between the bank and the organization.
March 18th, 2013 on 9:33 pm
Thanks @mihir for the kind response.I am a beginner. Kindly elaborate/explain some blocks of the code you provided( precisely the class definition, LinkedHashMap, ProjectUtil class).
Also Mihir, i wanted to know the flow beyond the acquirer bank’s CBS, like how the above message is forwarded to issuer bank(in case of inter-bank transactions) , i mean whether my message will be automatically forwarded to the issuer bank or will i have to write some code for that too.