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
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
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.
Leave a Reply