What is wrong in computing header for ISO8583?

100 views Asked by At

I need to implement or integrate the ISO8583, using Java. I am using jpos for the implementation. In code, everything seems fine; but at server level it's identified the format is not as per expectations. Where network team is saying header is not their.

The code is as below (updated):

   // Load the ISO 8583 packager from the resources folder
                InputStream is = ISO8583MessageHandler.class.getClassLoader().getResourceAsStream("iso93ascii.xml");
                if (is == null) {
                    throw new IllegalArgumentException("iso8583.xml is not found in resources!");
                }
                // Load the ISO 8583 packager
                GenericPackager packager = new GenericPackager(ISO8583MessageHandler.class.getClassLoader().getResourceAsStream("iso93ascii.xml"));
                packager.setLogger(LOGGER, "client");

                // PostChannel for 2 bytes header
                PostChannel channel = new PostChannel(serverIP, serverPort, packager);
                channel.setLogger(LOGGER, "client");

                ISOMsg isoMsg = new ISOMsg();
                isoMsg.setPackager(packager);
                isoMsg.setMTI("1804");
                isoMsg.set(11, TransactionUtils.generateSTAN()); // Unique STAN
                isoMsg.set(12, new SimpleDateFormat("yyMMddHHmmss").format(new Date())); // yyMMddHHmmss
                isoMsg.set(24, "831"); // Function code

                // Serialize the message once
                isoMsg.recalcBitMap();
                byte[] packedMessage = isoMsg.pack();


                // Prepare the header
                /*byte[] header = new byte[2];
                int length = (packedMessage.length);
                System.out.println("Length " + length);
                header[0] = (byte) (length >> 8); // High byte
                header[1] = (byte) (length);      // Low byte

                isoMsg.setHeader(header);
                byte[] finalPackedMessage = isoMsg.pack();*/

                // Now dump the full message
                System.out.println("Message Hex Dump:: ");
                System.out.println(ISOUtil.hexString(packedMessage));
                System.out.println("Message ASCII Dump:: ");
                System.out.println(TransactionUtils.hexToAscii(ISOUtil.hexString(packedMessage)));
//            System.out.println("Full Message Hex Dump:: ");
//            System.out.println(TransactionUtils.toFormattedHexDump(fullMessage));

                channel.connect();
                channel.send(isoMsg);

                System.out.println("ISO Network Management Call Sent...");

                ISOMsg response = channel.receive();
                System.out.println("Received Network Management Response from the Server!");
                printISOMessage(response);

The code above is for Network Management call (sing-on). As per the integration document the protocol requirement is something like: enter image description here

The header requirement:

enter image description here

The iso93ascii.xml file:

    <?xml version="1.0" encoding="UTF-8" standalone="no"?>
<!DOCTYPE isopackager SYSTEM "genericpackager.dtd">

<!-- ISO 8583:1993 (ASCII) field descriptions for GenericPackager -->

<isopackager headerLength="2">
  <isofield
      id="0"
      length="4"
      name="Message Type Indicator"
      class="org.jpos.iso.IFA_NUMERIC"/>
  <isofield
      id="1"
      length="64"
      name="Bitmap"
      class="org.jpos.iso.IFA_BITMAP"/>
  <isofield
      id="2"
      length="24"
      name="Primary Account number"
      class="org.jpos.iso.IFA_LLNUM"/>
  <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="5"
      length="12"
      name="Amount, Reconciliation"
      class="org.jpos.iso.IFA_NUMERIC"/>
  <isofield
      id="6"
      length="12"
      name="Amount, Cardholder billing"
      class="org.jpos.iso.IFA_NUMERIC"/>
  <isofield
      id="7"
      length="10"
      name="Date and time, transmission"
      class="org.jpos.iso.IFA_NUMERIC"/>
  <isofield
      id="8"
      length="8"
      name="Amount, Cardholder billing fee"
      class="org.jpos.iso.IFA_NUMERIC"/>
  <isofield
      id="9"
      length="8"
      name="Conversion rate, Reconciliation"
      class="org.jpos.iso.IFA_NUMERIC"/>
  <isofield
      id="10"
      length="8"
      name="Conversion rate, Cardholder billing"
      class="org.jpos.iso.IFA_NUMERIC"/>
  <isofield
      id="11"
      length="6"
      name="Systems trace audit number"
      class="org.jpos.iso.IFA_NUMERIC"/>
  <isofield
      id="12"
      length="12"
      name="Date and time, Local transaction"
      class="org.jpos.iso.IFA_NUMERIC"/>
  <isofield
      id="13"
      length="4"
      name="Date, Effective"
      class="org.jpos.iso.IFA_NUMERIC"/>
  <isofield
      id="14"
      length="4"
      name="Date, Expiration"
      class="org.jpos.iso.IFA_NUMERIC"/>
  <isofield
      id="15"
      length="6"
      name="Date, Settlement"
      class="org.jpos.iso.IFA_NUMERIC"/>
  <isofield
      id="16"
      length="4"
      name="Date, Conversion"
      class="org.jpos.iso.IFA_NUMERIC"/>
  <isofield
      id="17"
      length="4"
      name="Date, Capture"
      class="org.jpos.iso.IFA_NUMERIC"/>
  <isofield
      id="18"
      length="4"
      name="Merchant type"
      class="org.jpos.iso.IFA_NUMERIC"/>
  <isofield
      id="19"
      length="3"
      name="Country code, Acquiring institution"
      class="org.jpos.iso.IFA_NUMERIC"/>
  <isofield
      id="20"
      length="3"
      name="Country code, Primary account number"
      class="org.jpos.iso.IFA_NUMERIC"/>
  <isofield
      id="21"
      length="3"
      name="Country code, Forwarding institution"
      class="org.jpos.iso.IFA_NUMERIC"/>
  <isofield
      id="22"
      length="12"
      name="Point of service data code"
      class="org.jpos.iso.IF_CHAR"/>
  <isofield
      id="23"
      length="3"
      name="Card sequence number"
      class="org.jpos.iso.IFA_NUMERIC"/>
  <isofield
      id="24"
      length="3"
      name="Function code"
      class="org.jpos.iso.IFA_NUMERIC"/>
  <isofield
      id="25"
      length="4"
      name="Message reason code"
      class="org.jpos.iso.IFA_NUMERIC"/>
  <isofield
      id="26"
      length="4"
      name="Card acceptor business code"
      class="org.jpos.iso.IFA_NUMERIC"/>
  <isofield
      id="27"
      length="1"
      name="Approval code length"
      class="org.jpos.iso.IFA_NUMERIC"/>
  <isofield
      id="28"
      length="6"
      name="Date, Reconciliation"
      class="org.jpos.iso.IFA_NUMERIC"/>
  <isofield
      id="29"
      length="3"
      name="Reconciliation indicator"
      class="org.jpos.iso.IFA_NUMERIC"/>
  <isofield
      id="30"
      length="24"
      name="Amounts, original"
      class="org.jpos.iso.IFA_NUMERIC"/>
  <isofield
      id="31"
      length="99"
      name="Acquirer reference data"
      class="org.jpos.iso.IFA_LLCHAR"/>
  <isofield
      id="32"
      length="11"
      name="Acquirer institution identification code"
      class="org.jpos.iso.IFA_LLNUM"/>
  <isofield
      id="33"
      length="11"
      name="Forwarding institution identification code"
      class="org.jpos.iso.IFA_LLNUM"/>
  <isofield
      id="34"
      length="28"
      name="Primary account number, extended"
      class="org.jpos.iso.IFA_LLCHAR"/>
  <isofield
      id="35"
      length="37"
      name="Track 2 data"
      class="org.jpos.iso.IFA_LLCHAR"/>
  <isofield
      id="36"
      length="104"
      name="Track 3 data"
      class="org.jpos.iso.IFA_LLLCHAR"/>
  <isofield
      id="37"
      length="12"
      name="Retrieval reference number"
      class="org.jpos.iso.IF_CHAR"/>
  <isofield
      id="38"
      length="6"
      name="Approval code"
      class="org.jpos.iso.IF_CHAR"/>
  <isofield
      id="39"
      length="3"
      name="Action code"
      class="org.jpos.iso.IFA_NUMERIC"/>
  <isofield
      id="40"
      length="3"
      name="Service code"
      class="org.jpos.iso.IFA_NUMERIC"/>
  <isofield
      id="41"
      length="8"
      name="Card acceptor terminal identification"
      class="org.jpos.iso.IF_CHAR"/>
  <isofield
      id="42"
      length="15"
      name="Card acceptor identification code"
      class="org.jpos.iso.IF_CHAR"/>
  <isofield
      id="43"
      length="99"
      name="Card acceptor name/location"
      class="org.jpos.iso.IFA_LLCHAR"/>
  <isofield
      id="44"
      length="99"
      name="Additional response data"
      class="org.jpos.iso.IFA_LLCHAR"/>
  <isofield
      id="45"
      length="76"
      name="Track 1 data"
      class="org.jpos.iso.IFA_LLCHAR"/>
  <isofield
      id="46"
      length="204"
      name="Amounts, Fees"
      class="org.jpos.iso.IFA_LLLCHAR"/>
  <isofield
      id="47"
      length="999"
      name="Additional data - national"
      class="org.jpos.iso.IFA_LLLCHAR"/>
  <isofield
      id="48"
      length="999"
      name="Additional data - private"
      class="org.jpos.iso.IFA_LLLCHAR"/>
  <isofield
      id="49"
      length="3"
      name="Currency code, Transaction"
      class="org.jpos.iso.IF_CHAR"/>
  <isofield
      id="50"
      length="3"
      name="Currency code, Reconciliation"
      class="org.jpos.iso.IF_CHAR"/>
  <isofield
      id="51"
      length="3"
      name="Currency code, Cardholder billing"
      class="org.jpos.iso.IF_CHAR"/>
  <isofield
      id="52"
      length="8"
      name="Personal identification number [PIN] data"
      class="org.jpos.iso.IFA_BINARY"/>
  <isofield
      id="53"
      length="48"
      name="Security related control information"
      class="org.jpos.iso.IFA_LLBINARY"/>
  <isofield
      id="54"
      length="120"
      name="Amounts, additional"
      class="org.jpos.iso.IFA_LLLCHAR"/>
  <isofield
      id="55"
      length="255"
      name="IC card system related data"
      class="org.jpos.iso.IFA_LLLBINARY"/>
  <isofield
      id="56"
      length="35"
      name="Original data elements"
      class="org.jpos.iso.IFA_LLNUM"/>
  <isofield
      id="57"
      length="3"
      name="Authorization life cycle code"
      class="org.jpos.iso.IFA_NUMERIC"/>
  <isofield
      id="58"
      length="11"
      name="Authorizing agent institution Id Code"
      class="org.jpos.iso.IFA_LLNUM"/>
  <isofield
      id="59"
      length="999"
      name="Transport data"
      class="org.jpos.iso.IFA_LLLCHAR"/>
  <isofield
      id="60"
      length="999"
      name="Reserved for national use"
      class="org.jpos.iso.IFA_LLLCHAR"/>
  <isofield
      id="61"
      length="999"
      name="Reserved for national use"
      class="org.jpos.iso.IFA_LLLCHAR"/>
  <isofield
      id="62"
      length="999"
      name="Reserved for private use"
      class="org.jpos.iso.IFA_LLLCHAR"/>
  <isofield
      id="63"
      length="999"
      name="Reserved for private use"
      class="org.jpos.iso.IFA_LLLCHAR"/>
  <isofield
      id="64"
      length="8"
      name="Message authentication code field"
      class="org.jpos.iso.IFA_BINARY"/>
  <isofield
      id="65"
      length="8"
      name="Reserved for ISO use"
      class="org.jpos.iso.IFA_BINARY"/>
  <isofield
      id="66"
      length="204"
      name="Amounts, original fees"
      class="org.jpos.iso.IFA_LLLCHAR"/>
  <isofield
      id="67"
      length="2"
      name="Extended payment data"
      class="org.jpos.iso.IFA_NUMERIC"/>
  <isofield
      id="68"
      length="3"
      name="Country code, receiving institution"
      class="org.jpos.iso.IFA_NUMERIC"/>
  <isofield
      id="69"
      length="3"
      name="Country code, settlement institution"
      class="org.jpos.iso.IFA_NUMERIC"/>
  <isofield
      id="70"
      length="3"
      name="Country code, authorizing agent Inst."
      class="org.jpos.iso.IFA_NUMERIC"/>
  <isofield
      id="71"
      length="8"
      name="Message number"
      class="org.jpos.iso.IFA_NUMERIC"/>
  <isofield
      id="72"
      length="999"
      name="Data record"
      class="org.jpos.iso.IFA_LLLCHAR"/>
  <isofield
      id="73"
      length="6"
      name="Date, action"
      class="org.jpos.iso.IFA_NUMERIC"/>
  <isofield
      id="74"
      length="10"
      name="Credits, number"
      class="org.jpos.iso.IFA_NUMERIC"/>
  <isofield
      id="75"
      length="10"
      name="Credits, reversal number"
      class="org.jpos.iso.IFA_NUMERIC"/>
  <isofield
      id="76"
      length="10"
      name="Debits, number"
      class="org.jpos.iso.IFA_NUMERIC"/>
  <isofield
      id="77"
      length="10"
      name="Debits, reversal number"
      class="org.jpos.iso.IFA_NUMERIC"/>
  <isofield
      id="78"
      length="10"
      name="Transfer, number"
      class="org.jpos.iso.IFA_NUMERIC"/>
  <isofield
      id="79"
      length="10"
      name="Transfer, reversal number"
      class="org.jpos.iso.IFA_NUMERIC"/>
  <isofield
      id="80"
      length="10"
      name="Inquiries, number"
      class="org.jpos.iso.IFA_NUMERIC"/>
  <isofield
      id="81"
      length="10"
      name="Authorizations, number"
      class="org.jpos.iso.IFA_NUMERIC"/>
  <isofield
      id="82"
      length="10"
      name="Inquiries, reversal number"
      class="org.jpos.iso.IFA_NUMERIC"/>
  <isofield
      id="83"
      length="10"
      name="Payments, number"
      class="org.jpos.iso.IFA_NUMERIC"/>
  <isofield
      id="84"
      length="10"
      name="Payments, reversal number"
      class="org.jpos.iso.IFA_NUMERIC"/>
  <isofield
      id="85"
      length="10"
      name="Fee collections, number"
      class="org.jpos.iso.IFA_NUMERIC"/>
  <isofield
      id="86"
      length="16"
      name="Credits, amount"
      class="org.jpos.iso.IFA_NUMERIC"/>
  <isofield
      id="87"
      length="16"
      name="Credits, reversal amount"
      class="org.jpos.iso.IFA_NUMERIC"/>
  <isofield
      id="88"
      length="16"
      name="Debits, amount"
      class="org.jpos.iso.IFA_NUMERIC"/>
  <isofield
      id="89"
      length="16"
      name="Debits, reversal amount"
      class="org.jpos.iso.IFA_NUMERIC"/>
  <isofield
      id="90"
      length="10"
      name="Authorizations, reversal number"
      class="org.jpos.iso.IFA_NUMERIC"/>
  <isofield
      id="91"
      length="3"
      name="Country code, transaction Dest. Inst."
      class="org.jpos.iso.IFA_NUMERIC"/>
  <isofield
      id="92"
      length="3"
      name="Country code, transaction Orig. Inst."
      class="org.jpos.iso.IFA_NUMERIC"/>
  <isofield
      id="93"
      length="11"
      name="Transaction Dest. Inst. Id code"
      class="org.jpos.iso.IFA_LLNUM"/>
  <isofield
      id="94"
      length="11"
      name="Transaction Orig. Inst. Id code"
      class="org.jpos.iso.IFA_LLNUM"/>
  <isofield
      id="95"
      length="99"
      name="Card issuer reference data"
      class="org.jpos.iso.IFA_LLCHAR"/>
  <isofield
      id="96"
      length="999"
      name="Key management data"
      class="org.jpos.iso.IFA_LLLBINARY"/>
  <isofield
      id="97"
      length="17"
      name="Amount, Net reconciliation"
      class="org.jpos.iso.IFA_AMOUNT"/>
  <isofield
      id="98"
      length="25"
      name="Payee"
      class="org.jpos.iso.IF_CHAR"/>
  <isofield
      id="99"
      length="11"
      name="Settlement institution Id code"
      class="org.jpos.iso.IFA_LLCHAR"/>
  <isofield
      id="100"
      length="11"
      name="Receiving institution Id code"
      class="org.jpos.iso.IFA_LLNUM"/>
  <isofield
      id="101"
      length="17"
      name="File name"
      class="org.jpos.iso.IFA_LLCHAR"/>
  <isofield
      id="102"
      length="28"
      name="Account identification 1"
      class="org.jpos.iso.IFA_LLCHAR"/>
  <isofield
      id="103"
      length="28"
      name="Account identification 2"
      class="org.jpos.iso.IFA_LLCHAR"/>
  <isofield
      id="104"
      length="100"
      name="Transaction description"
      class="org.jpos.iso.IFA_LLLCHAR"/>
  <isofield
      id="105"
      length="16"
      name="Credits, Chargeback amount"
      class="org.jpos.iso.IFA_NUMERIC"/>
  <isofield
      id="106"
      length="16"
      name="Debits, Chargeback amount"
      class="org.jpos.iso.IFA_NUMERIC"/>
  <isofield
      id="107"
      length="10"
      name="Credits, Chargeback number"
      class="org.jpos.iso.IFA_NUMERIC"/>
  <isofield
      id="108"
      length="10"
      name="Debits, Chargeback number"
      class="org.jpos.iso.IFA_NUMERIC"/>
  <isofield
      id="109"
      length="84"
      name="Credits, Fee amounts"
      class="org.jpos.iso.IFA_LLCHAR"/>
  <isofield
      id="110"
      length="84"
      name="Debits, Fee amounts"
      class="org.jpos.iso.IFA_LLCHAR"/>
  <isofield
      id="111"
      length="999"
      name="Reserved for ISO use"
      class="org.jpos.iso.IFA_LLLCHAR"/>
  <isofield
      id="112"
      length="999"
      name="Reserved for ISO use"
      class="org.jpos.iso.IFA_LLLCHAR"/>
  <isofield
      id="113"
      length="999"
      name="Reserved for ISO use"
      class="org.jpos.iso.IFA_LLLCHAR"/>
  <isofield
      id="114"
      length="999"
      name="Reserved for ISO use"
      class="org.jpos.iso.IFA_LLLCHAR"/>
  <isofield
      id="115"
      length="999"
      name="Reserved for ISO use"
      class="org.jpos.iso.IFA_LLLCHAR"/>
  <isofield
      id="116"
      length="999"
      name="Reserved for national use"
      class="org.jpos.iso.IFA_LLLCHAR"/>
  <isofield
      id="117"
      length="999"
      name="Reserved for national use"
      class="org.jpos.iso.IFA_LLLCHAR"/>
  <isofield
      id="118"
      length="999"
      name="Reserved for national use"
      class="org.jpos.iso.IFA_LLLCHAR"/>
  <isofield
      id="119"
      length="999"
      name="Reserved for national use"
      class="org.jpos.iso.IFA_LLLCHAR"/>
  <isofield
      id="120"
      length="999"
      name="Reserved for national use"
      class="org.jpos.iso.IFA_LLLCHAR"/>
  <isofield
      id="121"
      length="999"
      name="Reserved for national use"
      class="org.jpos.iso.IFA_LLLCHAR"/>
  <isofield
      id="122"
      length="999"
      name="Reserved for national use"
      class="org.jpos.iso.IFA_LLLCHAR"/>
  <isofield
      id="123"
      length="999"
      name="Reserved for private use"
      class="org.jpos.iso.IFA_LLLCHAR"/>
  <isofield
      id="124"
      length="999"
      name="Reserved for private use"
      class="org.jpos.iso.IFA_LLLCHAR"/>
  <isofield
      id="125"
      length="999"
      name="Reserved for private use"
      class="org.jpos.iso.IFA_LLLCHAR"/>
  <isofield
      id="126"
      length="999"
      name="Reserved for private use"
      class="org.jpos.iso.IFA_LLLCHAR"/>
  <isofield
      id="127"
      length="999"
      name="Reserved for private use"
      class="org.jpos.iso.IFA_LLLCHAR"/>
  <isofield
      id="128"
      length="8"
      name="Message authentication code field"
      class="org.jpos.iso.IFA_BINARY"/>
</isopackager>

And the logs are:

<log realm="client" at="2024-01-02T14:43:40.881" lifespan="7ms">
  <pack>
    3138303430303330303130303030303030303030313134383339323430313032313434333430383331
  </pack>
</log>
Message Hex Dump:: 
3138303430303330303130303030303030303030313134383339323430313032313434333430383331
Message ASCII Dump:: 
18040030010000000000114839240102144340831
<log realm="client/172.20.30.50:6320" at="2024-01-02T14:43:41.005" lifespan="119ms">
  <connect>
    Try 0 172.xx.xx.xx:63xx
      Connection established to 172.xx.xx.xx:63xx
  </connect>
</log>
<log realm="client" at="2024-01-02T14:43:41.005">
  <pack>
    3138303430303330303130303030303030303030313134383339323430313032313434333430383331
  </pack>
</log>
<log realm="client/172.xx.xx.xx:63xx" at="2024-01-02T14:43:41.005">
  <send>
    <isomsg direction="outgoing">
      <!-- org.jpos.iso.packager.GenericPackager -->
      <field id="0" value="1804"/>
      <field id="11" value="114839"/>
      <field id="12" value="240102144340"/>
      <field id="24" value="831"/>
    </isomsg>
  </send>
</log>

What am I actually doing wrong, your suport in this regards highly appreciated.

1

There are 1 answers

13
Andrés Alcarraz On

The channel handles the length header for you. What you are actually setting with

        // Prepare the header
        byte[] header = new byte[2];
        int length = packedMessage.length + 2;
        header[0] = (byte) (length >> 8); // High byte
        header[1] = (byte) (length);      // Low byte

Is the message header, which is a header that goes after the length header, an it seems it is not needed as per the shared spec.

It seems you need a PostChannel, the code would be something like this:

        // Load the ISO 8583 packager
        ISOPackager packager = new GenericPackager("jar:iso93ascii.xml"); //jPOS can load the packager for you

        // Create an ASCIIChannel (use appropriate channel as per your requirement) the appropriate channel seems to be PostChannel

        ISOChannel channel = new PostChannel(serverIP, serverPort, packager);

        // Connect to the server
        channel.connect();
        System.out.println("Connected to server: " + serverIP + ":" + serverPort);

        // Sending Network Management Request
        ISOMsg isoMsg = new ISOMsg();
        //channel will set the packager
        isoMsg.setMTI("1804");
        String stan = TransactionUtils.generateSTAN();
        System.out.println(stan + " -> length : " + stan.length() );
        isoMsg.set(11, stan); // Unique STAN
        String datetime = new SimpleDateFormat("yyMMddHHmmss").format(new Date());
        System.out.println(datetime + " -> length : " + datetime.length());
        isoMsg.set(12, datetime); // yyMMddHHmmss
        isoMsg.set(24, "831"); // Function code

        channel.send(isoMsg);
        System.out.println("ISO Network Management Call Sent...");

        ISOMsg response = channel.receive();
        System.out.println("Received Network Management Response from the Server!");
        printISOMessage(response);

If you want to know what goes over the TCP/IP stream you better use a sniffer like tcpdump or Wireshark. You can set a logger to the packager to check the packaged message.

I'm on mobile and will expand later, but you also should consider using Q2 to configure the channel.