/*
* 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 headers = new HashMap();
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 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 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 headers = new HashMap();
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 params) {
// 设置默认请求头
Map headers = new HashMap();
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 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 headers, Map 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 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 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...");
}
}