How To Parse ISO8583 Message Using JPOS

In this case, I create simple UI to input ISO8583 message then parse the message using jpos. The result will be displayed on the text area.

isodecoder

Here are the code and explanation.

1. Packager.dtd
Packager file will be used to pack and unpack message into one of ISOMsg. If you have spesific case for your iso message, you have to work on this file.


<?xml version="1.0" encoding="UTF-8"?>

<!ELEMENT isopackager (isofield+,isofieldpackager*)*>
<!ATTLIST isopackager maxValidField CDATA #IMPLIED>
<!ATTLIST isopackager bitmapField CDATA #IMPLIED>
<!ATTLIST isopackager firstField CDATA #IMPLIED>
<!ATTLIST isopackager emitBitmap (true|false) #IMPLIED>
<!ATTLIST isopackager headerLength CDATA #IMPLIED>

<!-- isofield -->
<!ELEMENT isofield (#PCDATA)>
<!ATTLIST isofield id CDATA #REQUIRED>
<!ATTLIST isofield length CDATA #REQUIRED>
<!ATTLIST isofield name CDATA #REQUIRED>
<!ATTLIST isofield class NMTOKEN #REQUIRED>
<!ATTLIST isofield token CDATA #IMPLIED>
<!ATTLIST isofield pad (true|false) #IMPLIED>

<!-- isofieldpackager -->
<!ELEMENT isofieldpackager (isofield+,isofieldpackager*)*>
<!ATTLIST isofieldpackager id CDATA #REQUIRED>
<!ATTLIST isofieldpackager name CDATA #REQUIRED>
<!ATTLIST isofieldpackager length CDATA #REQUIRED>
<!ATTLIST isofieldpackager class NMTOKEN #REQUIRED>
<!ATTLIST isofieldpackager token CDATA #IMPLIED>
<!ATTLIST isofieldpackager pad (true|false) #IMPLIED>
<!ATTLIST isofieldpackager packager NMTOKEN #REQUIRED>
<!ATTLIST isofieldpackager emitBitmap (true|false) #IMPLIED>
<!ATTLIST isofieldpackager maxValidField CDATA #IMPLIED>
<!ATTLIST isofieldpackager bitmapField CDATA #IMPLIED>
<!ATTLIST isofieldpackager firstField CDATA #IMPLIED>
<!ATTLIST isofieldpackager headerLength CDATA #IMPLIED>

2. ISOMSG.xml
In this file you have to define the length of bit, name, ID, and type of the data.
Example:
<isofield id=”3″ length=”6″ name=”PROCESSING CODE” class=”org.jpos.iso.IFA_NUMERIC”/>
those means that bit3 have length 6 and the name is processing code which has numeric data only.

<?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="16"
      name="BIT MAP"
      class="org.jpos.iso.IFA_BITMAP"/>
  <isofield
      id="2"
      length="19"
      name="SECRET ID"
      class="org.jpos.iso.IFA_LLNUM"/>
  <isofield
      id="3"
      length="6"
      name="PROCESSING CODE"
      class="org.jpos.iso.IFA_NUMERIC"/>

	<!-- etc -->

  <isofield
      id="127"
      length="999"
      name="RESERVED PRIVATE USE"
      class="org.jpos.iso.IFA_LLLCHAR"/>
  <isofield
      id="128"
      length="8"
      name="MAC 2"
      class="org.jpos.iso.IFA_BINARY"/>
</isopackager>

3. ISOProcessor.java


package com.ariestania.isodecoder.main;

import org.jpos.iso.ISOException;
import org.jpos.iso.ISOMsg;
import org.jpos.iso.packager.GenericPackager;

/**
 *
 * @author ariestania.winda
 */
public class ISOProcess {

    private static String findBitMaps(String msg) {
        String firstBitmap = msg.substring(4, 20);
        String binFirstBitMap = hexToBinary(firstBitmap);
        boolean hasSecondary = (binFirstBitMap.charAt(0)) == '1';
        if (!hasSecondary) {
            return firstBitmap;
        }
        return msg.substring(4,36);
    }

    public static String processIsoMsg(String msg) {
        String isoMsgResult = "";
        String error = "";
        try {
            GenericPackager packager = new GenericPackager("ISOMSG.xml");
            ISOMsg isoMsg = new ISOMsg();
            isoMsg.setPackager(packager);
            isoMsg.unpack(msg.getBytes());

            isoMsgResult = logISOMsg(isoMsg, findBitMaps(msg));
        } catch (ISOException ex) {
            error = ex.getMessage();
        }
        return isoMsgResult + "\n" + error;
    }

    private static String logISOMsg(ISOMsg msg, String bitmaps) {
        StringBuilder sb = new StringBuilder();
        StringBuilder activeBit = new StringBuilder();

        String error = "";
        sb.append("----ISO MESSAGE-----\n");
        activeBit.append("Active Bit: ");
        try {
            sb.append("  MTI : ").append(msg.getMTI()).append("\n");
            sb.append("  Bitmaps : ").append(bitmaps).append("\n\n");
            for (int i = 1; i <= msg.getMaxField(); i++) {
                if (msg.hasField(i)) {
                    activeBit.append(i);
                    sb.append("    Bit-").append(i).append(" : ").append(msg.getString(i)).append("\n");
                    if (i < msg.getMaxField()) {
                        activeBit.append(", ");
                    } else {
                        activeBit.append("\n\n");
                    }
                }
            }
        } catch (ISOException e) {
            error = e.getMessage();
        } finally {
            sb.append("--------------------\n");
        }
        return activeBit.toString() + sb.toString() + error;
    }

    private static String HexToBinary(char Hex) {
        String[] staticLookup = new String[]{"0000", "0001", "0010", "0011", "0100", "0101", "0110", "0111", "1000", "1001", "1010", "1011", "1100", "1101", "1110", "1111"};
        return staticLookup[Integer.parseInt(Character.toString(Hex), 16)];
    }

    private static String hexToBinary(String s) {
        String result = "";

        for (int i = 0; i < s.length(); i++) {
            result = result + HexToBinary(s.charAt(i));
        }

        return result;
    }

}

4. Form

public class MainForm extends javax.swing.JFrame {

	//some code

	private void btnProcessActionPerformed(java.awt.event.ActionEvent evt) {
        // TODO add your handling code here:
        txtResult.setText("");
        String msg = txtIsoMsg.getText();
        if (msg == null || msg.length() == 0) {
            txtResult.setText("ISO MESSAGE NULL..!!");
            return;
        }
        String headerString = "";
        if (chkHasHeader.isEnabled()) {
            String headerLength = txtHeaderLength.getText();
            if (headerLength != null &amp;&amp; !"".equals(headerLength)) {
                int headerLg = Integer.parseInt(headerLength);
                headerString = msg.substring(0, headerLg);
                msg = msg.substring(headerLg);
            }
        }

        String resultMsg = ISOProcess.processIsoMsg(msg);
        if (!"".equals(headerString)) {
            headerString = "Header MSG : " + headerString + "\n\n";
        }
        txtResult.setText(headerString + resultMsg);
    }

	//some code

}

If you want to see the full code and download it, you can go to my github. Hope this article can help 🙂

Leave a Reply

Fill in your details below or click an icon to log in:

WordPress.com Logo

You are commenting using your WordPress.com account. Log Out /  Change )

Google photo

You are commenting using your Google account. Log Out /  Change )

Twitter picture

You are commenting using your Twitter account. Log Out /  Change )

Facebook photo

You are commenting using your Facebook account. Log Out /  Change )

Connecting to %s