/* * 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..."); } }