pos 8583报文我的解决方案

2017-06-08  本文已影响0人  华先生_a70a

最近公司在做pos业务,以前直接是pos接我们后台c,后台c去对接支付pos支付通道,现在打算用android系统pos机器,完成原pos机的业务,下面出2个图
传统pos和android系统pos


相信对支付业务了解的同学,都知道8583报文,我这个业务也是都是用是8583报文交互的,我们先来看看8583报文的组成

1,报文头
12,交易类型
3,位图
4,报文域
8583报文讲解网上一堆,我这主要是针对,8583组装和解析,已经常见的c传过来的数据转换位java字符串
8583报文是这样的下面举个例子:

60000000006016011603240210702406C022C09A111662257575445226840000000000000001000000102012051000100006326225757544522684D201220111172543433138383331303935323838383132303135383131303030303135365CB9C8D88C010844260000000000000001309F2608C26F69BE24700A5E9F2701809F101307010103A0B802010A010000000000BB1B528B9F37047A4DFFAC9F36020094950500880470009A031706089C01009F02060000000001005F2A02015682027C009F1A0201569F03060000000000009F3303E0E9C89F34034203009F3501229F1E0830303030303930359F4104000000100014220000010006204533383936303641

首先我们知道报文是16进制的一段数字串,可是通道c和我们前台java是scoket通信,scoket通信数据交互是byte数组,所以首先我们先要有byte[]
转化为16进制字符串的方法
* @param b 10进制byte数组
* @return 返回16进制的字符串
*/
public static String byte2Hex(byte[] b) {
String hs = "";
String stmp = "";
for (int n = 0; n < b.length; n++) {
stmp = (Integer.toHexString(b[n] & 0XFF));
if (stmp.length() == 1) {
hs = hs + "0" + stmp;
} else {
hs = hs + stmp;
}
if (n < b.length - 1)
hs = hs;
}
return hs.toUpperCase();
}

我们pos交易,常见的都是2个步骤

计算报文的长度
/**
* @param length 传入报文长度
* @ 计算报文长度转换为byte格式
*/
private static byte[] length(int length) {
byte[] result = new byte[2];
int[] key = {length / 256, length % 256};
for (int i = 0; i < key.length; i++) {
StringBuffer sb = new StringBuffer("0");
String str = key[i] < 10 ? sb.append(key[i]).toString() :
String.valueOf(key[i]);
result[i] = Integer.valueOf(str).byteValue();
}
return result;
}

通过上面的方法我们可以轻松组装一个报文,下面举个例子

                LinkedHashMap<String, String> data_consumer = new LinkedHashMap<String, String>();
                data_consumer.put("2", cardBean.getCardNo());
                data_consumer.put("3", "数据");
                data_consumer.put("4", 数据);  //金额  55域9f02相等
                data_consumer.put("11", 数据);
                data_consumer.put("11", "数据");
                data_consumer.put("14", "数据");
                data_consumer.put("22", "数据");  
                data_consumer.put("23", 数据);
                data_consumer.put("25", "数据");
                data_consumer.put("26", "数据");
                data_consumer.put("35", 数据);
                data_consumer.put("41", 数据);
                data_consumer.put("42", 数据);
                data_consumer.put("49", "数据")
                data_consumer.put("52", "密码加密数据");
                data_consumer.put("53", "数据");
                data_consumer.put("55", 数据)
                data_consumer.put("60", "数据");
                String yu64 = BWTools.get64yu(数据)));
                data_consumer.put("64", 数据);
                byte[] xf_consumer = BWTools.makeBW(data_consumer, Common.Consumer, Common.consume_bitmap);
            一个list集合传入对应的数据直接是string就行,会最后通道我们的makeBW方法返回一个byte[]数组可以直接用scoket传给通道,  
}

下面讲解通道返回的byte[]如何转换为我们看的懂得数据即解析8583报文

public static LinkedHashMap<String, String> analyzeBW(String bwdata) {
     LinkedHashMap<String, String> filedMap = new LinkedHashMap<>();
    String bwString = bwdata;
    String temp1 = bwString.substring(0, 2);
    String temp2 = bwString.substring(2, 4);
    int int1 = Integer.parseInt(temp1, 16);
    int int2 = Integer.parseInt(temp2, 16);
    int data = int1 * 256 + int2;
    String bw_result = bwString.substring(4, data * 2 + 4);
    Log.d("serve返回的报文不含长度", bw_result);
    String bitmap = bw_result.substring(26, 42);
    String yu_data = bw_result.substring(42);
    String bitMap128Str = hexString2binaryString(bitmap);
    for (int i = 1; i < bitMap128Str.length(); i++) {
        if (bitMap128Str.charAt(i) == '1') {
            String filedValue = "";// 字段值
            String filedName = "" + (i + 1);// FIELD005
            // 获取域定义信息
            String defLen = map2().get(filedName);
            boolean isFixLen = true;// 是否是变成
            if (defLen.startsWith("LL")) {
                isFixLen = false;
            }
            // 截取域信息
            if (!isFixLen) {// 变长域
                int defLen1 = 0;
                int start_point = 0;
                if (defLen.startsWith("LLVAR")) {
                    defLen = yu_data.substring(0, 2);
                    defLen1 = Integer.valueOf(defLen);
                    start_point = 2;
                }
                if (defLen.startsWith("LLLVAR")) {
                    defLen = yu_data.substring(0, 4);
                    int temp = Integer.parseInt(defLen);
                    String temp3 = defLen.substring(0, 2);
                    String temp4 = defLen.substring(2, 4);
                    int int3 = Integer.parseInt(temp3);
                    int int4 = Integer.parseInt(temp4);
                    //                        defLen1 = int3 * 256 + int4;
                    defLen1 = temp;
                    start_point = 4;
                    //报文长度是长度x2,bcd不需要乘以2
                }
                String type = map1().get(filedName);
                if (filedName.equals("55")) {
                    //此处55域
                    filedValue = yu_data.substring(start_point, start_point + defLen1 * 2);
                        yu_data = yu_data.substring(start_point + defLen1 * 2);
                } else if (type.startsWith("BCD")) {
                    filedValue = yu_data.substring(start_point, start_point + defLen1);
                    if (defLen1 % 2 != 0) {
                        yu_data = yu_data.substring(start_point + defLen1 + 1);
                    } else {
                        yu_data = yu_data.substring(start_point + defLen1);
                    }
                } else {
                    filedValue = hexTolLetter(yu_data.substring(start_point, start_point + defLen1 * 2));
                    yu_data = yu_data.substring(start_point + defLen1 * 2);
                }
            } else {// 不变长域
                int defLen2 = Integer.parseInt(map2().get(filedName));
                String type2 = map1().get(filedName);
                if (filedName.equals("64")) {//64不关心类型 2位变一位  同理ascii
                    filedValue = hexTolLetter(yu_data.substring(0, defLen2 * 2));
                } else if (type2.startsWith("BCD")) {
                    filedValue = yu_data.substring(0, defLen2);
                    if (defLen2 % 2 != 0) {
                        yu_data = yu_data.substring(defLen2 + 1);
                    } else {
                        yu_data = yu_data.substring(defLen2);
                    }
                } else {
                    filedValue = hexTolLetter(yu_data.substring(0, defLen2 * 2));
                    yu_data = yu_data.substring(defLen2 * 2);
                }
            }
            filedMap.put(filedName, filedValue);
        }
    }
    return filedMap;
}

方法有点吧通告放回的byte[]数组转化为16进制的8583报文string类型作为参数传入即可,其实就是一个循环判断便利报文根据类型解析的方法,这个方法需要确定报文每个域的类型和长度所有需要2个配置集合

private static HashMap<String, String> map1() {
    HashMap<String, String> map1 = new HashMap<>();
    map1.put("head", "BCD");
    map1.put("type", "BCD");
    map1.put("map", "BCD");
    map1.put("2", "BCD");
    map1.put("3", "BCD");
    map1.put("4", "BCD");
    map1.put("11", "BCD");
    map1.put("12", "BCD");
    map1.put("13", "BCD");
    map1.put("14", "BCD");
    map1.put("15", "BCD");
    map1.put("22", "BCD");
    map1.put("23", "BCD");
    map1.put("25", "BCD");
    map1.put("26", "BCD");
    map1.put("32", "BCD");
    map1.put("35", "BCD");
    map1.put("36", "BCD");
    map1.put("37", "ASCII");
    map1.put("38", "ASCII");
    map1.put("39", "ASCII");
    map1.put("41", "ASCII");
    map1.put("42", "ASCII");
    map1.put("44", "ASCII");
    map1.put("49", "ASCII");
    map1.put("52", "BCD");
    map1.put("53", "BCD");
    map1.put("55", "BCD");
    map1.put("54", "ASCII");
    map1.put("60", "BCD");
    map1.put("61", "BCD");
    map1.put("62", "ASCII");
    map1.put("63", "ASCII");
    map1.put("64", "ASCII");  //判断是binary
    return map1;
}
private static HashMap<String, String> map2() {
    HashMap<String, String> map2 = new HashMap<>();
    map2.put("head", "22");
    map2.put("type", "4");
    map2.put("map", "16");
    map2.put("2", "LLVAR019");
    map2.put("3", "6");
    map2.put("4", "12");
    map2.put("5", "12");
    map2.put("6", "12");
    map2.put("7", "10");
    map2.put("9", "8");
    map2.put("10", "8");
    map2.put("11", "6");
    map2.put("12", "6");
    map2.put("13", "4");
    map2.put("14", "4");
    map2.put("15", "4");
    map2.put("16", "4");
    map2.put("18", "4");
    map2.put("19", "3");
    map2.put("22", "3");
    map2.put("23", "3");
    map2.put("25", "2");
    map2.put("26", "2");
    map2.put("32", "LLVAR011");
    map2.put("33", "LLVAR011");
    map2.put("35", "LLVAR037");
    map2.put("36", "LLLVAR104");
    map2.put("37", "12");
    map2.put("38", "6");
    map2.put("39", "2");
    map2.put("41", "8");
    map2.put("42", "15");
    map2.put("43", "40");
    map2.put("44", "LLVAR25");
    map2.put("45", "LLVAR79");
    map2.put("48", "LLLVAR512");
    map2.put("49", "3");
    map2.put("50", "3");
    map2.put("51", "3");
    map2.put("52", "16"); // 64bit的二进制数
    map2.put("53", "16");
    map2.put("55", "LLLVAR255");
    map2.put("54", "LLLVAR040");
    map2.put("60", "LLLVAR100");
    map2.put("61", "LLLVAR29");
    map2.put("62", "LLLVAR200");
    map2.put("63", "LLLVAR63");
    map2.put("64", "8");
    return map2;
}

map1确定报文的类型map2确定报文的长度,最终返回一个list的集合 key是域的地址,value就是string明文数据
下面贴出几个上面用得方法

/**
 * 位图操作
 * <p>
 * 把16位图的字节数组转化成128位01字符串
 */
private static String get16BitMapStr(byte[] bitMap16) {
    String bitMap128 = "";
    // 16位图转2进制位图128位字符串
    for (int i = 0; i < bitMap16.length; i++) {
        int bc = bitMap16[i];
        bc = (bc < 0) ? (bc + 256) : bc;
        String bitnaryStr = Integer.toBinaryString(bc);// 二进制字符串
        // 左补零,保证是8位
        String rightBitnaryStr = strCopy("0", Math.abs(8 - bitnaryStr.length())) + bitnaryStr;// 位图二进制字符串
        // 先去除多余的零,然后组装128域二进制字符串
        bitMap128 += rightBitnaryStr;
    }
    return bitMap128;
}

/**
 * 复制字符
 *
 * @param str
 * @param count
 * @return
 */
private static String strCopy(String str, int count) {
    StringBuffer sb = new StringBuffer();
    for (int i = 0; i < count; i++) {
        sb.append(str);
    }
    return sb.toString();
}

// 返回字段号码,例如005
public static String getNumThree(int i) {
    String len = "";
    String iStr = String.valueOf(i);
    len = strCopy("0", 3 - iStr.length()) + iStr;
    return len;
}

/**
 * 16进制转化为字母
 *
 * @param hex 要转化的16进制数,用逗号隔开 如:536861646f77
 * @return
 */
private static String hexTolLetter(String hex) {
    StringBuilder sb = new StringBuilder();
    while (hex.length() > 0) {
        String temp = hex.substring(0, 2);
        int i = Integer.parseInt(temp, 16);
        sb.append((char) i);
        hex = hex.substring(2);
    }
    return sb.toString();
}

/**
 * ascii
 * 字符串中每个字母转化为16进制
 *
 * @param letter
 * @return
 */
public static String letterToH(String letter) {
    StringBuilder sb = new StringBuilder();
    for (int i = 0; i < letter.length(); i++) {
        char c = letter.charAt(i);
        String s = Integer.toHexString(c);
        if (s.length() == 1) {
            s = "0" + s;
        }
        sb.append(s);
        System.out.println(s);
    }
    //        sb.deleteCharAt(sb.length() - 2);
    return sb.toString();
}

/**
 * 16进制转二进制
 *
 * @param hexString
 * @return
 */
public static String hexString2binaryString(String hexString) {
    if (hexString == null || hexString.length() % 2 != 0)
        return null;
    String bString = "", tmp;
    for (int i = 0; i < hexString.length(); i++) {
        tmp = "0000" + Integer.toBinaryString(Integer.parseInt(hexString.substring(i, i + 1), 16));
        bString += tmp.substring(tmp.length() - 4);
    }
    return bString;
}

/**
 * 二进制转16进制
 *
 * @param bString
 * @return
 */
private static String binaryString2hexString(String bString) {
    if (bString == null || bString.equals("") || bString.length() % 8 != 0)
        return null;
    StringBuffer tmp = new StringBuffer();
    int iTmp = 0;
    for (int i = 0; i < bString.length(); i += 4) {
        iTmp = 0;
        for (int j = 0; j < 4; j++) {
            iTmp += Integer.parseInt(bString.substring(i + j, i + j + 1)) << (4 - j - 1);
        }
        tmp.append(Integer.toHexString(iTmp));
    }
    return tmp.toString();
}

下面讲讲密钥的加解密,没有ping和mac是组装不了52和64的
下面讲讲,tmk终端主密钥,主密钥由传输密钥保护,所以需要先拿到传输密钥一般pos的初始化都是拿主密钥,不过初始化可能会分几步,我拿我们平台举例,初始化分3步
初始化——握手(第一步)
62域返回一次性的临时随机数Ans…6(LLLVAR) 6位的随机数RANDOM-NUM。
初始化——获取临时密钥(第二步)
62域
返回一次性的临时密钥TMPKEY(单倍长密钥)的密文ans…12(LLLVAR);前8个字节是密文,后4个字节是checkvalue。
该密钥使用随机数Ans…6(LLLVAR) 6位的随机数RANDOM-NUM后补00,对TMPKEY做DES加密产生。
初始化——获取POS主密钥(第三步)
62域
返回POS主密钥MASTERKEY(双倍长密钥)的密文ans…16(LLLVAR);
该密钥使用主密钥受TMPKEY保护,做DES加密产生。
那我们就根据要去一步一步获取吧
首先先通道scoket拿到random_num和tmpkey
开始解析传输密钥密文下面是代码逻辑

                byte[] bytes_handData2 = ParseTMPKEY(rando_num);
                byte[] tempkey = new byte[8];//建立一个长度为8的数组放传输密钥密文
                System.arraycopy(bytes_handData2, 0, tempkey, 0, 8);
                byte[] decrypt_tmpkey = DesUtils.decrypt(tempkey, radom);  //临时密钥解密后的数据
                byte[] encrypt = DesUtils.encrypt(ParseTMPKEY("0000000000000000"),decrypt_tmpkey);//密钥     明文都是16进制的,此次的16个0为16进制
                String check1 = BWTools.byte2Hex(encrypt).substring(0, 8);//传输密钥明文对16个0做des加密的前8位和checkvalue对比一样说checkvalue校验正确
                String check2= handData2.substring(16, 24);
                LogUtils.i("初始化第二步校验checkvalue——1,计算得到",check1);
                LogUtils.i("初始化第二步校验checkvalue——2==16进制",check2);
                int i = check1.compareToIgnoreCase(check2);
                if (i == 0) {
                    Utils.runOnUIThread(new Runnable() {
                        @Override
                        public void run() {
                            ToastUtil.showToast("checkvalue检查正确");
                        }
                    });
                }

下面解密主密钥和校验checkvalue

                final byte[] masterkey = ParseTMPKEY(主密钥密文);
                byte[] masterkey1 = new byte[8];
                byte[] masterkey2 = new byte[8];
                System.arraycopy(masterkey, 0, masterkey1, 0, 8);
                System.arraycopy(masterkey, 8, masterkey2, 0, 8);
                byte[] decrypt_masterkey1 = DesUtils.decrypt(masterkey1, decrypt_tmpkey);
                byte[] decrypt_masterkey2 = DesUtils.decrypt(masterkey2, decrypt_tmpkey);
                byte[] result_master = new byte[16];
                System.arraycopy(decrypt_masterkey1, 0, result_master, 0, 8);
                System.arraycopy(decrypt_masterkey2, 0, result_master, 8, result_master.length - 8);
                String master_key = byte2Hex(result_master);//获得终端主密钥的明文

就是根据文档做加解密
下面是签到交易获取工作密钥的密文

          String s = BWTools.analyzeBW(byte2Hex(d)).get("62");//获取工作密钥密文
                String result = BWTools.letterToH(s);//密文转化为ascii转16进制
                LogUtils.d("签到原始", result);
                final int resultlength = result.length();
                LogUtils.d("goRegister", "resultlength:" + resultlength);
                if (resultlength < 72) {
                    Utils.runOnUIThread(new Runnable() {
                        @Override
                        public void run() {
                            ToastUtil.showToast("签到62域长度问题,长度为" + resultlength);
                        }
                    });
                    return;
                }
                String ping = result.substring(0, 32);
                String ping_checkvalue = result.substring(32, 40);
                Log.d("ping", ping);
                String mac = result.substring(40, 72);
                String mac_checkvalue = result.substring(72, 80);
                byte[] bytes_ping = DesUtils.ThreeDecrypt(result_master_bytes, ParseTMPKEY(ping));
                byte[] bytes_mac = DesUtils.ThreeDecrypt(result_master_bytes, ParseTMPKEY(mac));
                String ping_des = zm(bytes_ping, "ping密钥解密后");
                String mac_des = zm(bytes_mac, "mac密钥解密后");
                String ping_checkvalue_js = (BWTools.byte2Hex(DesUtils.ThreeEncryptt(ParseTMPKEY(ping_des),ParseTMPKEY("00000000000000000000000000000000")))).substring(0,8);
                LogUtils.d("ping_checkvalue1",ping_checkvalue);
                LogUtils.d("ping_checkvalue2",ping_checkvalue_js);
                String mac_checkvalue_js = (BWTools.byte2Hex(DesUtils.encrypt(ParseTMPKEY("0000000000000000"),ParseTMPKEY(mac_des)))).substring(0,8);
                LogUtils.d("mac_checkvalue1",mac_checkvalue);
                LogUtils.d("mac_checkvalue2",mac_checkvalue_js);
                int i = ping_checkvalue.compareToIgnoreCase(ping_checkvalue_js);
                int i1 = mac_checkvalue.compareToIgnoreCase(mac_checkvalue_js);
                if (i == 0 && i1 == 0) {
                    Utils.runOnUIThread(new Runnable() {
                        @Override
                        public void run() {
                            ToastUtil.showToast("工作密钥checkvalue检测正确");
                        }
                    });
                }

下面贴出部分方法

/**
 * ascii
 * 字符串中每个字母转化为16进制
 *
 * @param letter
 * @return
 */
public static String letterToH(String letter) {
    StringBuilder sb = new StringBuilder();
    for (int i = 0; i < letter.length(); i++) {
        char c = letter.charAt(i);
        String s = Integer.toHexString(c);
        if (s.length() == 1) {
            s = "0" + s;
        }
        sb.append(s);
        System.out.println(s);
    }
    //        sb.deleteCharAt(sb.length() - 2);
    return sb.toString();
}

到此就获得了ping和mac明文下面可以愉快的加密52和64啦
先讲52,52域很简单 首先需要银行卡号,我的方法是直接传入35域数据,根据自己需要可以改为直接传银行卡
银行卡从倒数第2位先前截取13个前面不0000和("06"+密码+"FFFFFFFF")做异或,异或的结果用ping密文做3des加密下面是方法
/**
* 52yu获取
* @param yu35data
* @param ping_des
* @param pwd
* @return
/
public static String get52yu(String yu35data, String ping_des, String pwd) {
String[] ds = yu35data.split("D");
String s1 = "0000"+ds[0].substring(ds[0].length()-13,ds[0].length()-1);
String s2 = "06"+pwd+"FFFFFFFF";
String xor = Tools.xor(s1, s2);
Log.d("Tools52_s1", s1);
Log.d("Tools52_s2", s2);
Log.d("Tools52_xor", xor);
byte[] threeEncryptt = DesUtils.ThreeEncryptt(ParseTMPKEY(ping_des),ParseTMPKEY(xor+"0000000000000000"));
Log.d("Tools3des加密后的数值", byte2Hex(threeEncryptt).substring(0, 16));
return byte2Hex(threeEncryptt).substring(0,16);
}
下面讲解64域mac的值计算方法
mac比较复杂,用伪代码解释下
将type_63域的报文数据(16进制数据)分成8位1组,前后异或下去等到的结果是16位ascii转换32位(16进制字符)
加入前16位a1后后16位a2,a1和mac密钥做des加密(或者3des看通道要求)得到的结果 b1,然后b1和a2做异或运算得到c,最后c和mac做des加密或者3des加密,结果就是mac
下面是方法
/
*
* 获取64域mac
* @param bw type-63域报文
* @param mac mac密钥
* @return
/
public static String getMac(String bw, String mac) {
// type-63域报文先分成16个一组前后异或下去
String xor_result = Tools.xor_result(bw);
//将 报文每8位结果异或结果的16位转32位(将ASC字符串转16进制字符)
String xor_result_2_hex = Tools.xor_result_2_hex(xor_result);
//System.out.println(xor_result_2_hex);
String result1 = xor_result_2_hex.substring(0, 16);
String result2 = xor_result_2_hex.substring(16);
//System.out.println(result1);
// System.out.println(result2);
//byte[] bytes = DesUtils.ThreeEncryptt(ParseUtils.ParseTMPKEY(mac), ParseUtils.ParseTMPKEY(result1 + "0000000000000000")); 3des
byte[] bytes = DesUtils.encrypt(ParseTMPKEY(result1 + "0000000000000000"), ParseTMPKEY(mac.substring(0,16)));
String s = byte2Hex(bytes);
String substring = s.substring(0, 16);
// System.out.println(substring);
String xor = Tools.xor(substring, result2);
// System.out.println(xor);
//byte[] bytes2 = DesUtils.ThreeEncryptt(ParseUtils.ParseTMPKEY(mac), ParseUtils.ParseTMPKEY(xor + "0000000000000000")); 3des
byte[] bytes2 = DesUtils.encrypt(ParseTMPKEY(xor + "0000000000000000"), ParseTMPKEY(mac.substring(0,16)));
String s2 = byte2Hex(bytes2);
Log.d("mac__64为截取", s2);
return s2.substring(0, 8);
}
下面贴出部分方法
/
*将报文每8位结果异或结果的16转32
* 将ASC字符串转16进制字符
*
* @param asc
* @return
*/
private static String xor_result_2_hex(String asc) {
StringBuffer hex = new StringBuffer();
try {
byte[] bs = asc.toUpperCase().getBytes("UTF-8");
for (byte b : bs) {
hex.append(Integer.toHexString(new Byte(b).intValue()));
}
} catch (UnsupportedEncodingException e) {
e.printStackTrace();
}
return hex.toString();
}

//报文异或结果
private static String xor_result(String bw) {
    List<String> bw_sub = sub(bw);
    //System.out.println(bw_sub.toString());
    String temp = bw_sub.get(0);
    for (int i = 1; i < bw_sub.size(); i++) {
        temp = xor(temp, bw_sub.get(i));
        //System.out.println("第"+i+"次"+temp);
    }
    return temp;
}

//string截取为16位一组的数据 不足补0
private static List<String> sub(String bw) {
    List<String> listdata = new ArrayList();
    while (bw.length() > 16) {
        String substring = bw.substring(0, 16);
        listdata.add(substring);
        bw = bw.substring(16);
    }
    if (bw.length() == 16
            ) {
        listdata.add(bw);
    }
    if (bw.length() < 16) {
        int i = 16 - bw.length();
        for (int i1 = 0; i1 < i; i1++) {
            bw = bw + "0";
        }
        listdata.add(bw);
    }
    return listdata;
}

//2个16进制的string异或
public static String xor(String string, String string2) {
    int[] i = toInterger(string);
    int[] j = toInterger(string2);
    int length = i.length == j.length ? i.length : 0;
    int[] result = new int[length];
    StringBuffer sb = new StringBuffer();
    for (int k = 0; k < result.length; k++) {
        int data = i[k] ^ j[k];
        sb.append(Integer.toHexString(data));
    }
    return sb.toString().toUpperCase();
}

//16进制string转int
private static int[] toInterger(String string) {

    int length = string.length();
    int[] result = new int[length];
    for (int i = 0; i < length; i++) {
        String str = string.substring(i, i + 1);
        int k = Integer.valueOf(str, 16);
        result[i] = k;
    }
    return result;
}

public static String getBankCardNum(String cardNum) {
    StringBuilder sb = new StringBuilder();
    sb.append(cardNum.substring(0, 6));
    sb.append("*******");
    sb.append(cardNum.substring(cardNum.length() - 4));
    return sb.toString();
}

最后贴出我的64域获取方法,可根据需求自定义修改
/**
* 获取64mac
*
* @param data type-63域
* @param mac_des
* @return
*/
public static String get64yu(LinkedHashMap<String, String> data, String type, String bitmap, String mac_des) {
List<byte[]> result = new ArrayList<>();
//tpdu+MSGHEAD +type+bitmap
//Common.Messagehead=tpdu+MSGHEAD
String msghead = type + PartsUtils.GroupOfBitMap(bitmap);
byte[] bytes1 = PartsUtils.GroupOfBCD(msghead);
Log.d("BWTools", "bytes1:" + Arrays.toString(bytes1));
result.add(bytes1);
for (Map.Entry<String, String> entry : data.entrySet()) {
String key = entry.getKey();
String value = entry.getValue();
String yuType = map1().get(key);
String yuLength = map2().get(key);
byte[] bytes = null;
if (yuLength.startsWith("LLVAR")) {//变长
if (yuType.startsWith("BCD")) {
bytes = PartsUtils.GroupOfLLVar(value, Common.BCD);
} else {
bytes = PartsUtils.GroupOfLLVar(value, Common.ASCII);
}
} else if (yuLength.startsWith("LLLVAR")) {
if (yuType.startsWith("BCD")) {
bytes = PartsUtils.GroupOfLLLVar(value, Common.BCD);
} else {
bytes = PartsUtils.GroupOfLLLVar(value, Common.ASCII);
}
} else {//定长
if (yuType.startsWith("BCD")) {
bytes = PartsUtils.GroupOfBCD(value);
} else {
bytes = PartsUtils.GroupOfASCII(value);
}
}
result.add(bytes);

    }
    byte[] bw_result = PartsUtils.ArrayMerge64(result);
    String s = byte2Hex(bw_result);
    String mac = Tools.getMac(s, mac_des);
    return mac;
}

任然不明白的,可以留言!大家一起进步

上一篇下一篇

猜你喜欢

热点阅读