解析银联55域

import java.util.HashMap;
import java.util.Map;

/**
 * Created by zn on 2018/5/8.
 */
public class ISO8583Util {
    /**
     * 解析IC卡55域(银联、POS通用)
     *
     * @param f55
     * @return Map
     * @throws Exception 关于55域
     *                   1、tag:1~2字节,左边第一字节的右5bit 为 11111,则tag占2字节,否则占1字节 (两字节一般格式 xFxx)
     *                   2、leng:1~3字节,左边字节最左bit为0,则剩下的7bit表示长度,范围 1~127
     *                   左边字节最左bit为1,则剩下的7bit表示长度的长度,如 10000001,表示后面还有1个字节的长度,范围 128~255
     *                   现在最多leng是3个字节,也就是左边字节只能是 0x80(右1字节长度)、0x81(右2字节长度)
     *                   3、value:
     */
    public static Map decodeF55(byte[] f55) throws Exception {
        Map map = new HashMap<>();
        int offset = 0;
        while (offset < f55.length) {
            /* step 1: 取tag */
            int tagLength = (f55[offset] & 0x1F) == 0x1F ? 2 : 1; // 第1个字节后5bit全为1,则tag占2字节,否则占1字节
            byte[] tag = new byte[tagLength];
            System.arraycopy(f55, offset, tag, 0, tagLength);
            offset += tagLength;
            /* step 2: 取数据长度 */
            int valueLength = 0;
            if (f55[offset] >= 0) { // 判断最左bit为0时,长度占1个字节,后续7个bit表示长度, 1~127 (当最左bit为0时,比较时自动转换成int为非负数)
                valueLength = f55[offset++]; // 只用后7bit,不用处理符号位;支持长度为0的情况。
            } else if (f55[offset] == 0xffffff81) { // 1000 0001,后面1个字节表示长度,128~255
                valueLength = f55[offset + 1] & 0xFF; // 因为可以表示255,所以byte要转成无符号的
                offset += 2;
            } else if (f55[offset] == 0xffffff82) { // 1000 0010,后面2个字节表示长度
                valueLength = (f55[offset + 1] & 0xFF) << 8 | f55[offset + 2] & 0xFF; // 转成无符号
                offset += 3;
            } else { // 其他长度格式暂不支持
                throw new Exception("value length error!");
            }
            /* step 3: 取值 */
            byte[] value = null;
            if (0 != valueLength) {
                value = new byte[valueLength];
                System.arraycopy(f55, offset, value, 0, valueLength);
                offset += valueLength;
            }
            /* step 4: tag - value */
            map.put(hexBytesToStr(tag), hexBytesToStr(value));
        }
        return map;
    }

    /**
     * 十六进制的字符串 --> byte[] ("FF" --> 0xFF)
     *
     * @param str
     * @return
     */
    public static byte[] hexStrToBytes(String str) {
        if (null == str || str.trim().length() == 0) {
            return null;
        }
        byte[] bytes = new byte[str.length() / 2];
        for (int i = 0; i < str.length() / 2; i++) {
            String subStr = str.substring(i * 2, i * 2 + 2);
            bytes[i] = (byte) Integer.parseInt(subStr, 16);
        }
        return bytes;
    }

    /**
     * byte[] --> 十六进制的字符串 (0xFF --> "FF")
     *
     * @param bytes
     * @return
     */
    public static String hexBytesToStr(byte[] bytes) {
        if (null == bytes) {
            return null;
        }
        StringBuilder buf = new StringBuilder(bytes.length * 2);
        for (byte b : bytes) {
            buf.append(String.format("%02X", new Integer(b & 0xff)));
        }
        return buf.toString();
    }

    public static void main(String[] args) throws Exception {
        StringBuilder sF55 = new StringBuilder();
        // 测试一下长度为0的情况
        sF55.append("9F00").append("00");
        // 测试一下长度为2字节的情况
        sF55.append("9F01").append("81fa").append("01234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789");
        // 测试一下长度为3字节的情况
        sF55.append("9F02").append("820100").append("01234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901");
        byte[] bF55 = hexStrToBytes(sF55.toString());
        Map mapF55 = decodeF55(bF55);
        System.out.println(mapF55);
    }
}

你可能感兴趣的:(银联POS相关)