参考自 https://blog.csdn.net/a1036645146/article/details/100585393
chinapay不是银联支付 , chinapay不是银联支付, chinapay不是银联支付
重要的事情说三遍, chinapay 是银联的一部分 接口对接方式相仿但完全是另一套操作流程
此文主要为记录最后的注意点 代码次要,
公共方法:
// 验签
@Override
public Boolean verifyNotify(Map<String, String> notifyMap, PayTypeEnum payTypeEnum) throws Exception {
SecssUtil secssUtil = ChinaPayUtil.secssUtil;
try {
//验签
String sign = notifyMap.get("Signature");
if (!StringUtils.isEmpty(sign)) {
secssUtil.verify(notifyMap);//入参:返回商户报文中的所有参数
}
if (!SecssConstants.SUCCESS.equals(secssUtil.getErrCode())) {
log.error(secssUtil.getErrCode() + "=" + secssUtil.getErrMsg());
log.info("ChinaPay返回的应答数据【验签】失败:{}", secssUtil.getErrMsg());
return false;
}
return true;
} catch (Exception e) {
e.printStackTrace();
}
return null;
}
/**
* @Description 获取签名
* @param paramMap 发送请求时携带的参数
**/
private void getSign(Map<String,Object> paramMap) {
//签名
SecssUtil secssUtil = ChinaPayUtil.secssUtil;
secssUtil.sign(paramMap);
if (!SecssConstants.SUCCESS.equals(secssUtil.getErrCode())) {
log.error("ChinaPay签名失败:" + secssUtil.getErrCode() + "=" + secssUtil.getErrMsg());
throw new ValidateException("签名失败:" + secssUtil.getErrCode() + "=" + secssUtil.getErrMsg());
}
String signature = secssUtil.getSign();
paramMap.put("Signature", signature);
}
/**
* @Description 接口返回参数转map
* @param resp response返回参数
**/
private Map<String, String> getRespMap(String resp) {
if (resp == null) {
return new HashMap();
}
// log.info("################交易查询结果, 解码后:{}", respDec);
Map<String, String> resultMap = new TreeMap<String, String>();
for (String str : resp.split("&", -1)) {
String[] keyValues = str.split("=", -1);
if (keyValues.length < 2) {
continue;
}
String key = keyValues[0];
String value = keyValues[1];
if (StringUtils.isEmpty(value)) {
continue;
}
//响应字段解码
try {
value = URLDecoder.decode(value, "UTF-8");
} catch (UnsupportedEncodingException e) {
e.printStackTrace();
}
resultMap.put(key, value);
}
return resultMap;
}
/**
* @Description 将有卡交易信息域 加密
* @param cardTranData 有卡交易信息域数据
**/
private String encryptCardTranData(JSONObject cardTranData ){
// 有卡交易信息域 base64编码后 RSA加密
String cardTranDataStr = cardTranData.toJSONString();
String cardTranDataBase64 = Base64.getEncoder().encodeToString((cardTranDataStr == null ? "" : cardTranDataStr).getBytes());
ChinaPayUtil.secssUtil.encryptData(cardTranDataBase64);
return ChinaPayUtil.secssUtil.getEncValue();
}
/**
* @Description 将返回的有卡交易信息域 解密
* @param cardTranData 有卡交易信息域数据
**/
private JSONObject decryptCardTranData(String cardTranData){
// 有卡交易信息域 在应答中获取我司返回的该字段后,采用 RSA 解密,再 Base64 解码,解密时
// 调用方法 decryptData,调用 getDecValue 获取解密后的结果
// 文档中上面两句话是在 噗噗噗 不用管
log.info("有卡交易信息域 解密 前参数: " + cardTranData);
String value = null;
ChinaPayUtil.secssUtil.decryptData(cardTranData);
if (SecssConstants.SUCCESS.equals(ChinaPayUtil.secssUtil.getErrCode())) {
value = ChinaPayUtil.secssUtil.getDecValue();
} else {
throw new ValidateException(ChinaPayUtil.secssUtil.getErrMsg());
}
log.info("有卡交易信息域 解密 后参数: " + value);
return JSONObject.parseObject(value);
}
private static RequestConfig requestConfig;
private static PoolingHttpClientConnectionManager connMgr;
/**
* 发送 SSL POST 请求(HTTPS),K-V形式
*
* @param apiUrl API接口URL
* @param params 参数map
*/
public static String doPostSSL(String apiUrl, Map<String, Object> params, Map<String, String> headers) {
CloseableHttpClient httpClient = HttpClients.custom().setSSLSocketFactory(createSSLConnSocketFactory())
.setConnectionManager(connMgr).setDefaultRequestConfig(requestConfig).build();
HttpPost httpPost = new HttpPost(apiUrl);
CloseableHttpResponse response = null;
String httpStr = null;
try {
List<NameValuePair> pairList = new ArrayList<NameValuePair>(params.size());
for (Map.Entry<String, Object> entry : params.entrySet()) {
NameValuePair pair = new BasicNameValuePair(entry.getKey(), entry.getValue().toString());
pairList.add(pair);
}
httpPost.setEntity(new UrlEncodedFormEntity(pairList, StandardCharsets.UTF_8));
if (headers != null) {
for (String key : headers.keySet()) {
httpPost.setHeader(key, headers.get(key));
}
}
response = httpClient.execute(httpPost);
int statusCode = response.getStatusLine().getStatusCode();
if (statusCode != HttpStatus.SC_OK) {
return null;
}
HttpEntity entity = response.getEntity();
if (entity == null) {
return null;
}
httpStr = EntityUtils.toString(entity, "utf-8");
} catch (Exception e) {
log.error(e.getMessage(), e);
} finally {
if (response != null) {
try {
EntityUtils.consume(response.getEntity());
} catch (IOException e) {
log.error(e.getMessage(), e);
}