public class Field55Test {
private static final String LINE_SP = System.getProperty("line.separator");
//测试报文55域
public static final byte[] BYTES = new byte[] { (byte) 0x9F, 0x10, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, (byte) 0x9A, 0x03, 0x11,
0x12,
0x08, //
(byte) 0x9C, 0x01, 0x00, (byte) 0x9F, 0x02, 0x06, 0x00, 0x00, 0x00, 0x10, 0x00, 0x00, 0x5F, 0x2A,
0x02,
0x01, //
0x11, 0x71, (byte) 0x81, (byte) 0xC8, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, //
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, //
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, //
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, //
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, //
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, //
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, //
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, //
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, //
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, //
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, //
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, //
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 };
//获取55域中的TAG
private static byte[] getTag(int index, byte[] source) {
byte tag1 = source[index];
if ((tag1 & 0x1f) == 0x1f) {
return new byte[] { source[index], source[index + 1] };
} else {
return new byte[] { source[index] };
}
}
//获取域名中得TAG长度
private static byte[] getLen(int index, byte[] source) {
byte len1 = source[index];
if ((len1 & 0x80) == 0x00) {
return new byte[] { source[index] };
} else {
byte len2 = (byte) (len1 & 0x7f);
len2++;
byte[] len = new byte[len2];
System.arraycopy(source, index, len, 0, len2);
return len;
}
}
//获取55域中得TAG值
private static byte[] getValue(int index, byte[] source, int len) {
byte[] value = new byte[len];
System.arraycopy(source, index, value, 0, len);
return value;
}
static void printHex(byte[] bytes) {
String info = "";
for (int i = 0; i < bytes.length; i++) {
String s = Integer.toHexString(bytes[i] < 0 ? bytes[i] + 256 : bytes[i]);
if (s.length() == 1) {
s = "0" + s;
}
info += s;
info += " ";
if ((i + 1) % 16 == 0) {
info += LINE_SP;
}
}
System.out.print(info);
}
/**
* @param args
*/
public static void main(String[] args) {
int index = 0;
//循环读取所有TAG
while (index < BYTES.length) {
byte[] tag = getTag(index, BYTES);
index += tag.length;
byte[] len = getLen(index, BYTES);
index += len.length;
int iLen;
if (len.length == 1) {
iLen = len[0];
} else {
iLen = len[1] < 0 ? len[1] + 256 : len[1];
}
byte[] val = getValue(index, BYTES, iLen);
index += val.length;
System.out.print("tag:");
printHex(tag);
System.out.print("len:");
printHex(len);
System.out.print("val:");
printHex(val);
System.out.println();
}
}
}
/**
* 银联55域
*
* 本域将根据不同的交易种类包含不同的子域。银联处理中心仅在受理方和发卡方之间传递这些适用于IC卡交易的特有数据,而不对它们进行任何修改和处理。
* 为适应该子域需要不断变化的情况
* ,本域采用TLV(tag-length-value)的表示方式,即每个子域由tag标签(T),子域取值的长度(L)和子域取值(V)构成。
* tag标签的属性为bit
* ,由16进制表示,占1~2个字节长度。例如,"9F33"为一个占用两个字节的tag标签。而"95"为一个占用一个字节的tag标签
* 。若tag标签的第一个字节
* (注:字节排序方向为从左往右数,第一个字节即为最左边的字节。bit排序规则同理。)的后五个bit为"11111",则说明该tag占两个字节
* ,例如"9F33";否则占一个字节,例如"95"。 子域长度(即L本身)的属性也为bit,占1~3个字节长度。具体编码规则如下: a)
* 当L字段最左边字节的最左bit位(即bit8)为0,表示该L字段占一个字节,它的后续7个bit位(即bit7~bit1)表示子域取值的长度,
* 采用二进制数表示子域取值长度的十进制数
* 。例如,某个域取值占3个字节,那么其子域取值长度表示为"00000011"。所以,若子域取值的长度在1~127
* 字节之间,那么该L字段本身仅占一个字节。 b)
* 当L字段最左边字节的最左bit位(即bit8)为1,表示该L字段不止占一个字节,那么它到底占几个字节由该最左字节的后续7个bit位
* (即bit7~bit1)的十进制取值表示。例如,若最左字节为10000010,表示L字段除该字节外,后面还有两个字节。其后续字节
* 的十进制取值表示子域取值的长度。例如,若L字段为"1000 0001 1111 1111",表示该子域取值占255个字节。
* 所以,若子域取值的长度在128~255字节之间,那么该L字段本身需占两个字节
*
*/