银商TMS平台秘钥下载工具

时间:2022-07-22
本文章向大家介绍银商TMS平台秘钥下载工具,主要内容包括其使用实例、应用技巧、基本知识点总结和需要注意事项,具有一定的参考价值,需要的朋友可以参考一下。
/*
 * To change this license header, choose License Headers in Project Properties.
 * To change this template file, choose Tools | Templates
 * and open the template in the editor.
 */
package javaapplication3.utils;

import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.JSONObject;
import java.util.HashMap;
import java.util.Map;
import static javaapplication3.utils.DesUtil.DES_decrypt_3;
import static javaapplication3.utils.DesUtil.DES_encrypt_3;
import static javaapplication3.utils.HttpClientUtil.sendPost;
import static javaapplication3.utils.MyUtil.bytesToHexString;
import static javaapplication3.utils.MyUtil.hexStringToBytes;
import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;

/**
 *
 * @author yangyongzhen 2018.11.12 
 * 连接银联商务TMS平台,进行秘钥激活,参数下载,和主秘钥下载功能 
 * 秘钥激活:功能是通过主控秘钥分量1获取主控秘钥分量2并解密出分量2的明文 
 * 参数下载:功能是使用主控秘钥分量2加密请求,获取商户号,终端号等信息
 * 主秘钥下载:功能是下载银商通信的主秘钥
 */
public class TmsUtil {

    public static Log log = LogFactory.getLog(HttpClientUtil.class);

    //TMS地址 秘钥激活
    public static String url_keyactive = "http://xx.xx.x.x../TMSWebService/nostandard/xxxx";
    //TMS地址 主控秘钥下载
    public static String url_keydownload = "http://xxxxxx/TMSWebService/nostandard/xxxx";
    //TMS地址 参数更新检查
    public static String url_updatecheck = "http://xxxxxx/TMSWebService/nostandard/xxxx";

    public static String fid = "xxx";
    public static String mid = "xxxx";
    //硬件序列号(终端poscode)
    //String sn  = "xxx18030710022";
    public static String sn = "xxxxxx710023";
    //随机数
    public static String random = "5183683762638030";
    //秘钥分量1,通过银商的串口工具获取。
    //String tmskey1 = "xxxxxxFDExx7E60D692AEC878E047D";
    public static String tmskey1 = "xxxxxx3EAFCD367D4A4C1E";
    //秘钥分量2,通过访问TMS系统接口的秘钥激活,获取密文,并用分量1解密得到。
    public static String tmskey2 = "";
    //交易类型
    public static String transcode = "";

    /**
     * 异或运算
     *
     * @param src
     * @param dest
     * @param size
     */
    private static void dataXor(byte[] src, byte[] dest, int size) {
        for (int i = 0; i < size; i++) {
            src[i] = (byte) ((dest[i] & 0xff) ^ (src[i] & 0xff));
        }
    }

    /**
     * 接入TMS平台报文头的认证信息计算
     *
     * @param random 随机数
     * @param fid 厂商号
     * @param mid 机器型号
     * @param sn 硬件序列号(终端号)
     * @param tmskey1 主控秘钥分量1(从银商提供的串口工具中获得)
     * @return
     */
    public static String calcAuthInfo(String random, String fid, String mid, String sn, String tmskey1) {

        //计算认证信息
        String auinfo = fid + mid + sn;
        //使用认证密钥对厂商标识+终端型号标识+终端硬件序列号(使用 0x00 补足 8 的倍数长度)进行 CBC 运算得到加密结果(8 字节)
        int auinfolen = auinfo.length();
        int auinfoloop = auinfolen / 8;
        if ((auinfolen % 8) > 0) {
            auinfoloop++;
        }

        byte[] aubuf = new byte[auinfoloop * 8];
        System.arraycopy(auinfo.getBytes(), 0, aubuf, 0, auinfolen);
        byte[] authkey = DES_encrypt_3(random.getBytes(), hexStringToBytes(tmskey1));

        byte[] auinfoI = new byte[8];
        byte[] auinfoD = new byte[8];
        for (int i = 0; i < auinfoloop; i++) {
            System.arraycopy(aubuf, i * 8, auinfoD, 0, 8);
            dataXor(auinfoI, auinfoD, 8);
            auinfoI = DES_encrypt_3(auinfoI, authkey);
        }
        String authinfo = EncryptionUtils.base64Encode(auinfoI);

        return authinfo;
    }

    public static void main(String[] args) {

        log.debug("Begin TMS test...");
        Map<String, String> headers = new HashMap<String, String>();
        JSONObject data = null;

        headers.put("VER", "01");
        headers.put("Encoding", "UTF8");
        headers.put("content-type", "application/json");
        headers.put("FID", fid);
        headers.put("MID", mid);
        headers.put("SN", sn);
        headers.put("Random", random);
        
        //1.===========================秘钥激活测试
        log.debug("1.==================秘钥激活");
        String authinfo = "";
        transcode = "020";
        authinfo = calcAuthInfo(random, fid, mid, sn, tmskey1);
        headers.put("AuthInfo", authinfo);
        headers.put("TransCode", transcode);
        
        String out = sendPost(url_keyactive, headers, data);
        log.debug(out);
        JSONObject jbt = JSONObject.parseObject(out);
        String rcode = "";
        rcode = jbt.getString("ReturnCode");
        if (rcode.equals("00")) {
            log.debug("秘钥激活成功!");
            log.debug(jbt);
            String key2 = jbt.getString("MKey2");
            log.debug("秘钥分量2密文: " + key2);
            //使用主控秘钥分量1对其进行解密
            byte[] outkey = DES_decrypt_3(hexStringToBytes(key2), hexStringToBytes(tmskey1));
            tmskey2 = bytesToHexString(outkey);
            log.debug("秘钥分量2明文: " + tmskey2);

            //2.===========================参数更新检查,参数下载(商户号,终端号等参数在里面)
            log.debug("2.==================参数更新检查");
            String poststr = "{"
                    + ""APPCount":1,"
                    + ""APP1":"
                    + "{"APPID":"NC_B503","APPVer":"V0.02.13","APPIndex":"1","APPState":"1","
                    + ""ParameterUp":{"04000001":"1"},"
                    + ""Parameter":["01000001","01000002","01000005","02000002","03000012","04000001","04000002","04000003","04000006","04000007","04000008","04000012","04000013","04000014","04000015","04000016","04000017","04000022","04000023","04000026","04000028","04000029","04000030","04000031","04000038","04000039","04000051","04000054","04000055","04000056","deptcode"]}}";

            transcode = "010";
            //使用tmskey2计算认证信息,tmskey1则只在第一步的秘钥激活中有用
            authinfo = calcAuthInfo(random, fid, mid, sn, tmskey2);

            headers.remove("TransCode");
            headers.remove("AuthInfo");
            headers.put("TransCode", transcode);
            headers.put("AuthInfo", authinfo);
            log.debug("poststr:" + poststr);
            data = JSON.parseObject(poststr);
            log.debug("data:" + data);
            out = sendPost(url_updatecheck, headers, data);
            jbt = JSONObject.parseObject(out);
            rcode = jbt.getString("ReturnCode");
            if (rcode.equals("00")) {
                log.debug("参数更新检查成功!");
                log.debug(jbt);
            } else {
                log.debug("参数更新检查失败!");
                log.debug(jbt);
            }

        } else {
            log.debug("秘钥激活失败!");
            log.debug(jbt);
        }
        //3.===========================银商主秘钥下载
        log.debug("3.==================主秘钥下载");
        transcode = "030";
        //使用tmskey2计算认证信息,tmskey1则只在第一步的秘钥激活中有用
        authinfo = calcAuthInfo(random, fid, mid, sn, tmskey2);

        headers.remove("TransCode");
        headers.remove("AuthInfo");
        headers.put("TransCode", transcode);
        headers.put("AuthInfo", authinfo);
        out = sendPost(url_keydownload, headers, data);
        jbt = JSONObject.parseObject(out);
        rcode = jbt.getString("ReturnCode");
        if (rcode.equals("00")) {
            log.debug("主秘钥下载成功!");
            log.debug(jbt);
            //使用秘钥分量2,解密出主秘钥
            
        } else {
            log.debug("主秘钥下载失败!");
            log.debug(jbt);
        }

    }

}
/*
 * To change this license header, choose License Headers in Project Properties.
 * To change this template file, choose Tools | Templates
 * and open the template in the editor.
 */
package javaapplication3.utils;

import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.JSONObject;
import java.net.URI;
import java.util.HashMap;
import java.util.Map;
import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
import org.apache.http.Header;
import org.apache.http.HttpStatus;
import org.apache.http.client.methods.CloseableHttpResponse;
import org.apache.http.client.methods.HttpGet;
import org.apache.http.client.methods.HttpPost;
import org.apache.http.client.utils.URIBuilder;
import org.apache.http.entity.StringEntity;
import org.apache.http.impl.client.CloseableHttpClient;
import org.apache.http.impl.client.HttpClients;
import org.apache.http.message.BasicHeader;
import org.apache.http.util.EntityUtils;

/**
 * @ClassName: HttpClientUtil
 * @Description: TODO(HttpClient工具类)
 * @author wangxy
 * @date 2018年5月8日 下午5:23:39
 * @version 1.0
 */
public class HttpClientUtil {

    // 默认字符集
    private static final String ENCODING = "UTF-8";
    public static Log log = LogFactory.getLog(HttpClientUtil.class);

    /**
     * @Title: sendPost
     * @Description: TODO(发送post请求)
     * @param url 请求地址
     * @param headers 请求头
     * @param data 请求实体
     * @param encoding 字符集
     * @author wangxy
     * @return String
     * @date 2018年5月10日 下午4:36:17
     * @throws
     */
    public static String sendPost(String url, Map<String, String> headers, JSONObject data, String encoding) {
        log.info("进入post请求方法...");
        log.info("请求入参:URL= " + url);
        log.info("请求入参:headers=" + JSON.toJSONString(headers));
        log.info("请求入参:data=" + JSON.toJSONString(data));
        // 请求返回结果
        String resultJson = null;
        // 创建Client
        CloseableHttpClient client = HttpClients.createDefault();
        // 创建HttpPost对象
        HttpPost httpPost = new HttpPost();

        try {
            // 设置请求地址
            httpPost.setURI(new URI(url));
            // 设置请求头
            if (headers != null) {
                Header[] allHeader = new BasicHeader[headers.size()];
                int i = 0;
                for (Map.Entry<String, String> entry : headers.entrySet()) {
                    allHeader[i] = new BasicHeader(entry.getKey(), entry.getValue());
                    i++;
                }
                httpPost.setHeaders(allHeader);
            }
            // 设置实体
            httpPost.setEntity(new StringEntity(JSON.toJSONString(data)));
            // 发送请求,返回响应对象
            CloseableHttpResponse response = client.execute(httpPost);
            // 获取响应状态
            int status = response.getStatusLine().getStatusCode();
            if (status == HttpStatus.SC_OK) {
                // 获取响应结果
                resultJson = EntityUtils.toString(response.getEntity(), encoding);
            } else {
                log.error("响应失败,状态码:" + status);
            }

        } catch (Exception e) {
            log.error("发送post请求失败", e);
        } finally {
            httpPost.releaseConnection();
        }
        return resultJson;
    }

    /**
     * @Title: sendPost
     * @Description: TODO(发送post请求,请求数据默认使用json格式,默认使用UTF-8编码)
     * @param url 请求地址
     * @param data 请求实体
     * @author wangxy
     * @return String
     * @date 2018年5月10日 下午4:37:28
     * @throws
     */
    public static String sendPost(String url, JSONObject data) {
        // 设置默认请求头
        Map<String, String> headers = new HashMap<String, String>();
        headers.put("content-type", "application/json");

        return sendPost(url, headers, data, ENCODING);
    }

    /**
     * @Title: sendPost
     * @Description: TODO(发送post请求,请求数据默认使用json格式,默认使用UTF-8编码)
     * @param url 请求地址
     * @param params 请求实体
     * @author wangxy
     * @return String
     * @date 2018年5月10日 下午6:11:05
     * @throws
     */
    public static String sendPost(String url, Map<String, Object> params) {
        // 设置默认请求头
        Map<String, String> headers = new HashMap<String, String>();
        headers.put("content-type", "application/json");
        // 将map转成json
        JSONObject data = JSONObject.parseObject(JSON.toJSONString(params));
        return sendPost(url, headers, data, ENCODING);
    }

    /**
     * @Title: sendPost
     * @Description: TODO(发送post请求,请求数据默认使用UTF-8编码)
     * @param url 请求地址
     * @param headers 请求头
     * @param data 请求实体
     * @author wangxy
     * @return String
     * @date 2018年5月10日 下午4:39:03
     * @throws
     */
    public static String sendPost(String url, Map<String, String> headers, JSONObject data) {
        return sendPost(url, headers, data, ENCODING);
    }

    /**
     * @Title: sendPost
     * @Description:(发送post请求,请求数据默认使用UTF-8编码)
     * @param url 请求地址
     * @param headers 请求头
     * @param params 请求实体
     * @author wangxy
     * @return String
     * @date 2018年5月10日 下午5:58:40
     * @throws
     */
    public static String sendPost(String url, Map<String, String> headers, Map<String, String> params) {
        // 将map转成json
        JSONObject data = JSONObject.parseObject(JSON.toJSONString(params));
        return sendPost(url, headers, data, ENCODING);
    }

    /**
     * @Title: sendGet
     * @Description: TODO(发送get请求)
     * @param url 请求地址
     * @param params 请求参数
     * @param encoding 编码
     * @author wangxy
     * @return String
     * @date 2018年5月14日 下午2:39:01
     * @throws
     */
    public static String sendGet(String url, Map<String, Object> params, String encoding) {
        log.info("进入get请求方法...");
        log.info("请求入参:URL= " + url);
        log.info("请求入参:params=" + JSON.toJSONString(params));
        // 请求结果
        String resultJson = null;
        // 创建client
        CloseableHttpClient client = HttpClients.createDefault();
        // 创建HttpGet
        HttpGet httpGet = new HttpGet();
        try {
            // 创建uri
            URIBuilder builder = new URIBuilder(url);
            // 封装参数
            if (params != null) {
                for (String key : params.keySet()) {
                    builder.addParameter(key, params.get(key).toString());
                }
            }
            URI uri = builder.build();
            log.info("请求地址:" + uri);
            // 设置请求地址
            httpGet.setURI(uri);
            // 发送请求,返回响应对象
            CloseableHttpResponse response = client.execute(httpGet);
            // 获取响应状态
            int status = response.getStatusLine().getStatusCode();
            if (status == HttpStatus.SC_OK) {
                // 获取响应数据
                resultJson = EntityUtils.toString(response.getEntity(), encoding);
            } else {
                log.error("响应失败,状态码:" + status);
            }
        } catch (Exception e) {
            log.error("发送get请求失败", e);
        } finally {
            httpGet.releaseConnection();
        }
        return resultJson;
    }

    /**
     * @Title: sendGet
     * @Description: TODO(发送get请求)
     * @param url 请求地址
     * @param params 请求参数
     * @author wangxy
     * @return String
     * @date 2018年5月14日 下午2:32:39
     * @throws
     */
    public static String sendGet(String url, Map<String, Object> params) {
        return sendGet(url, params, ENCODING);
    }

    /**
     * @Title: sendGet
     * @Description: TODO(发送get请求)
     * @param url 请求地址
     * @author wangxy
     * @return String
     * @date 2018年5月14日 下午2:33:45
     * @throws
     */
    public static String sendGet(String url) {
        return sendGet(url, null, ENCODING);
    }

    public static void main(String[] args) {

        log.debug("Begin Http test...");
    }

}