Custom jPOS Channel binary bitmap Active Bit Indicator

Today, i have implement new Custom jPOS Channel binary bitmap Active Bit Indicator for communicate between some bank with goverment tax system.

there are strange ISO 8583 message structure like this [ISO HEADER] [BODY], there are no message length indicator, and tail. The strange occure in the body message, they are not using hexa format for the ‘active bit indicator’ or we call it bitmap (primary/secondary/tertiary bitmap), but in binary format. So, i create Custom jPOS Channel binary bitmap Active Bit Indicator that can fit that requirment called BinaryX25Channel.

The main idea is to replace the active bit indicator on binary to hexa format right before the channel packed/unpacked the message.
First, for match [ISO HEADER] [BODY] o can use PADChannel, from jPOS programmer guide PADChannel’s explanation is,

Stream-based channel reads messages on-the-fly without using any kind of message boundary indicator.

But, i think it would be easier if i use X25Channel, because it have streamReceive() method there.

X25 is similar to PADChannel but uses a slightly different strategy. Instead of pulling an ISO-8583 from a stream, unpacking it on the fly, X25Channel attempts to read full TCP/IP packets by specifying a small timeout value. Whenever possible, PADChannel seems like a better solution; however, certain X.25 packet assembler/disassemblers sometimes send garbage over the wire (i.e. ETXs) which might confuse PADChannel.

for normal case, PADChannel seems like a better solution. But in my case, i have to read full TCP/IP packet, and change the active bit indicator from hexa to binary format (when sending) and vice versa. The channel implementation is like:


[java]
package com.didikhari.channel;

import java.io.EOFException;
import java.io.IOException;
import java.util.Vector;

import org.jpos.iso.ISOException;
import org.jpos.iso.ISOUtil;
import org.jpos.iso.ISOFilter.VetoException;
import org.jpos.iso.ISOMsg;
import org.jpos.iso.channel.X25Channel;
import org.jpos.util.LogEvent;
import org.jpos.util.Logger;

import com.didikhari.util.JposUtil;

/**
* Channel jPOS for communicate with binary format for ‘active bit indicator’
* main process is replace ‘active bit indicator’ from hex to bit and vice versa right before message is packed/unpacked
* @author Didik Hari
* @since 04-March-2015
*/
public class BinaryX25Channel extends X25Channel {

public BinaryX25Channel() {
super();
}

/**
* @return a byte array with the received message
* @exception IOException
*/
protected byte[] streamReceive() throws IOException {
int c, k=0, len = 1;
Vector v = new Vector();

c = serverIn.read();
if (c == -1)
throw new EOFException (“connection closed”);
byte[] b = new byte[1];
b[0] = (byte) c;
v.addElement (b);

// Wait for packets until timeout
while ((c = serverIn.available()) > 0) {
b = new byte[c];
if (serverIn.read (b) != c)
throw new EOFException (“connection closed”);
v.addElement (b);
len += c;
try {
Thread.sleep (50);
} catch (InterruptedException e) { }
}

byte[] d = new byte[len];
for (int i=0; i When receive message, the streamReceive() methods will be invoked right before message stream be unpack on receive() methods, so i manipulate the received message stream from binary to hexa format, so the ISOMsg.unpack(byte[]) not getting error. and when the channel send the message stream, method send(ISOMsg) will be invoked, and right before channel send the stream over network, i change the active bit indicator from hexa (jpos pack result) to binary format so the receiver can understand the message.

and the channel implementation is:
[xml]


[/xml]

i use 24 length for header is because i use “ISO123456789″.getByte(), if you are useing ISOUtil.hex2byte(header) for set the header, you need to change the implementation to header=”000000000000”.

And here the JposUtil implementation is like this:

[java]
package com.didikhari.util;

import org.jpos.iso.ISOException;

/**
* JposUtil is improvement of ISOUtil, String, and common static methods
* @author Didik Hari
* @since 04-March-2015
*/
public class JposUtil {

/**
* NPE save for splitting string
* @param string
* @param splitter
* @return
* @throws ISOException
*/
public static String[] split(String string, String splitter) throws ISOException{
if (string == null || splitter == null) {
throw new ISOException(“string or splitter cannot be null”);
}
return string.split(splitter);
}

/**
* NPE save for substring a given string between start and end index
* @param string
* @param start
* @param end
* @return
* @throws ISOException
*/
public static String subString(String string, int start, int end) throws ISOException{
if (string == null) {
throw new ISOException(“String value cannot be null”);
}
return string.substring(start, end);
}

/**
* NPE save for subString a given string between start index and end of string
* @param string
* @param start
* @return
* @throws ISOException
*/
public static String subString(String string, int start) throws ISOException{
if (string == null) {
throw new ISOException(“String value cannot be null”);
}
return string.substring(start);
}

/**
* Convert Decimal to Hex
* @param decimalNumber
* @return
*/
public static String decimalToHexa(Long decimalNumber) {
return Long.toHexString(decimalNumber);
}

/**
* Convert Decimal To Binary Type
* @param decimalNumber
* @return
*/
public static String decimalToBinary(Long decimalNumber) {
StringBuilder binaryNumber = new StringBuilder();
StringBuilder sbBinary = new StringBuilder();
String binaryString = Long.toBinaryString(decimalNumber);
char[] binary = binaryString.toCharArray();
int counter = 0;
for (int i=binary.length-1; i>=0; i–) {
counter++;
sbBinary.append(binary[i]);
if (counter == 4) counter = 0;
}

for (int i=0; i<4-counter; i++) { if (counter > 0) sbBinary.append(“0”);
}

for (int i=sbBinary.length()-1; i>=0;i–) {
binaryNumber.append(sbBinary.toString().charAt(i));
}

return binaryNumber.toString();
}

/**
* Convert Binary to Decimal
* @param binaryNumber
* @return
*/
public static Long binaryToDecimal(String binaryNumber) {
return Long.parseLong(binaryNumber, 2);
}

/**
* Convert Binary to Hex
* @param binaryNumber
* @return
*/
public static String binaryToHexa(String binaryNumber) {
return decimalToHexa(binaryToDecimal(binaryNumber));
}

/**
* Convert Hex to Decimal
* @param hexaNumber
* @return
*/
public static Long hexaToDecimal(String hexaNumber) {
return Long.parseLong(hexaNumber, 16);
}

/**
* Convert Hex to Binary
* @param hexaNumber
* @return
*/
public static String hexaToBinary(String hexaNumber) {
return decimalToBinary(hexaToDecimal(hexaNumber));
}

/**
* Split String every ‘n’ digit
* @param string
* @param interval
* @return
* @see Aske B. answere
*/
public static String[] splitStringEvery(String s, int interval) {
int arrayLength = (int) Math.ceil(((s.length() / (double)interval)));
String[] result = new String[arrayLength];

int j = 0;
int lastIndex = result.length – 1;
for (int i = 0; i < lastIndex; i++) { result[i] = s.substring(j, j + interval); j += interval; } //Add the last bit result[lastIndex] = s.substring(j); return result; } } [/java]

And thats it the Custom jPOS Channel binary bitmap Active Bit Indicator implementation. feel free to give comment bellow, and thank you for coming to my blog. regards.

11 responses to “Custom jPOS Channel binary bitmap Active Bit Indicator”

  1. Joe Avatar
    Joe

    Is there a JPOS channel with noheader? I’m trying to send an isoMsg using ISO87APackagerBBitmap.
    When the data is passed I see that the message is prepended with header. Server where we are sending the message does not want the header.
    Channels that i have tried sends the message like this:
    ..0200.:.Q……

    but the server wants it like this:
    0200ò.ÄQ……..

    1. Didik H Avatar

      did you mean length indicator? what channel you use right now?

      1. Joe Avatar
        Joe

        I have used PostChannel, RawChannel… I have pretty much tried most of the channels.. nothing works.

        1. Joe Avatar
          Joe

          Here is my sample code:

          import org.jpos.iso.*;
          import org.jpos.util.*;
          import org.jpos.iso.channel.*;
          import org.jpos.iso.packager.*;
          public class Test {
          public static void main (String[] args) throws Exception {
          Logger logger = new Logger();
          logger.addListener (new SimpleLogListener (System.out));
          ISOChannel channel = new PostChannel (“xxx.xx.xx.xxx”, 12345, new ISO87APackagerBBitmap());
          ((LogSource)channel).setLogger (logger, “test-channel”);
          channel.connect ();
          ISOMsg m = new ISOMsg ();
          m.setMTI(“0200″);
          m.set(2,”1111110000000395″);
          m.set(3,”319600″);
          m.set(4,”000000000000″);
          m.set(7,”0609064610″);
          m.set(11,”791138″);
          m.set(12,”214610″);
          m.set(13,”0608″);
          m.set(15,”0609″);
          m.set(17,”0609″);
          m.set(18,”6011″);
          m.set(22,”021″);
          m.set(26,”12″);
          m.set(28,”C00000000″);
          m.set(32,”1840298043″);
          m.set(37,”516100303374″);
          m.set(41,”24155901″);
          m.set(43,”201NORTHNELLISBLVDLASVEGASNVUS”);
          m.set(49,”840″);
          m.set(111,”EB007151006″);
          channel.send (m);
          ISOMsg r = channel.receive ();
          channel.disconnect ();
          }
          }

      2. Joe Avatar
        Joe

        Yes, I meant the length indicator.

  2. Joe Avatar
    Joe

    One more thing that I forgot to mention is that when looking at the server config I found the following settings:

    Server side settings:
    “Etx”: -1,
    “BitmapPacking”: true,
    “MessagePacking”: false,
    “CharacterEncoding”: “ASCII”,

    1. Didik H Avatar

      So, the server is not using jPOS?

      have you try using PADChannel or X25Channel, from the docs, these channel does not use length indicator.

      1. Joe Avatar
        Joe

        Thanks for your reply Didik. Message indeed had a header attached to it. However their raw message output does not display those. Used wireshark and it showed that the length was part of the header. Used NAC channel and it all works now. Thanks for your time and input.

        1. Didik H Avatar

          great! thanks for visiting my blog Joe.

  3. Rully Avatar
    Rully

    Nice explanation , but I’m getting error on response from channel.receive() from DJP on financial message but in network management message all done well . Many thanks btw

    1. Rully Avatar
      Rully

      Sorry , all fine now , mistake from reading spec

Leave a Reply

Your email address will not be published. Required fields are marked *