记得上下班打卡 | git大法好,push需谨慎

Commit cb347737 authored by anjiabin's avatar anjiabin

提交unionpay代码

parent 97b35e40
...@@ -4,7 +4,9 @@ import lombok.extern.slf4j.Slf4j; ...@@ -4,7 +4,9 @@ import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired; import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.CommandLineRunner; import org.springframework.boot.CommandLineRunner;
import org.springframework.boot.SpringApplication; import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.EnableAutoConfiguration;
import org.springframework.boot.autoconfigure.SpringBootApplication; import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.boot.context.properties.EnableConfigurationProperties;
import org.springframework.core.env.Environment; import org.springframework.core.env.Environment;
import java.net.InetAddress; import java.net.InetAddress;
...@@ -12,6 +14,7 @@ import java.util.Arrays; ...@@ -12,6 +14,7 @@ import java.util.Arrays;
@Slf4j @Slf4j
@SpringBootApplication(scanBasePackages = {"com.liquidnet"}) @SpringBootApplication(scanBasePackages = {"com.liquidnet"})
@EnableConfigurationProperties
public class ServiceDragonApplication implements CommandLineRunner { public class ServiceDragonApplication implements CommandLineRunner {
@Autowired @Autowired
private Environment environment; private Environment environment;
......
...@@ -2,6 +2,7 @@ package com.liquidnet.service.dragon.channel.unionpay.sdk; ...@@ -2,6 +2,7 @@ package com.liquidnet.service.dragon.channel.unionpay.sdk;
import lombok.extern.slf4j.Slf4j; import lombok.extern.slf4j.Slf4j;
import org.apache.commons.codec.binary.Base64; import org.apache.commons.codec.binary.Base64;
import org.springframework.beans.factory.annotation.Autowired;
import java.io.IOException; import java.io.IOException;
import java.security.PublicKey; import java.security.PublicKey;
...@@ -15,6 +16,15 @@ import java.util.Map; ...@@ -15,6 +16,15 @@ import java.util.Map;
*/ */
@Slf4j @Slf4j
public class Acp6Service { public class Acp6Service {
@Autowired
private SDKConfig sdkConfig;
@Autowired
private CertUtil certUtil;
@Autowired
private SDKUtil sdkUtil;
/** /**
* 请求报文签名(使用配置文件中配置的私钥证书或者对称密钥签名)<br> * 请求报文签名(使用配置文件中配置的私钥证书或者对称密钥签名)<br>
* 功能:对请求报文进行签名,并计算赋值certid,signature字段并返回<br> * 功能:对请求报文进行签名,并计算赋值certid,signature字段并返回<br>
...@@ -22,10 +32,10 @@ public class Acp6Service { ...@@ -22,10 +32,10 @@ public class Acp6Service {
* @param encoding 上送请求报文域encoding字段的值<br> * @param encoding 上送请求报文域encoding字段的值<br>
* @return 签名后的map对象<br> * @return 签名后的map对象<br>
*/ */
public static Map<String, String> sign(Map<String, String> reqData,String encoding) { public Map<String, String> sign(Map<String, String> reqData,String encoding) {
return signByCertInfo(reqData, SDKConfig.getConfig().getSignCertPath(), SDKConfig.getConfig().getSignCertPwd(), encoding); return signByCertInfo(reqData, sdkConfig.getSignCertPath(), sdkConfig.getSignCertPwd(), encoding);
} }
/** /**
* 多证书签名(通过传入私钥证书路径和密码签名)<br> * 多证书签名(通过传入私钥证书路径和密码签名)<br>
* 功能:如果有多个商户号接入银联,每个商户号对应不同的证书可以使用此方法:传入私钥证书和密码(并且在acp_sdk.properties中 配置 acpsdk.singleMode=false)<br> * 功能:如果有多个商户号接入银联,每个商户号对应不同的证书可以使用此方法:传入私钥证书和密码(并且在acp_sdk.properties中 配置 acpsdk.singleMode=false)<br>
...@@ -35,7 +45,7 @@ public class Acp6Service { ...@@ -35,7 +45,7 @@ public class Acp6Service {
* @param encoding 上送请求报文域encoding字段的值<br> * @param encoding 上送请求报文域encoding字段的值<br>
* @return 签名后的map对象<br> * @return 签名后的map对象<br>
*/ */
public static Map<String, String> signByCertInfo(Map<String, String> reqData, String certPath, public Map<String, String> signByCertInfo(Map<String, String> reqData, String certPath,
String certPwd, String encoding) { String certPwd, String encoding) {
Map<String, String> data = SDKUtil.filterBlank(reqData); Map<String, String> data = SDKUtil.filterBlank(reqData);
...@@ -43,15 +53,15 @@ public class Acp6Service { ...@@ -43,15 +53,15 @@ public class Acp6Service {
if (SDKUtil.isEmpty(encoding)) { if (SDKUtil.isEmpty(encoding)) {
encoding = "UTF-8"; encoding = "UTF-8";
} }
if (SDKUtil.isEmpty(certPath) || SDKUtil.isEmpty(certPwd)) { if (SDKUtil.isEmpty(certPath) || SDKUtil.isEmpty(certPwd)) {
log.error("CertPath or CertPwd is empty"); log.error("CertPath or CertPwd is empty");
return data; return data;
} }
try { try {
data.put(SDKConstants.param_certId, CertUtil.getCertIdByKeyStoreMap(certPath, certPwd)); data.put(SDKConstants.param_certId, certUtil.getCertIdByKeyStoreMap(certPath, certPwd));
data.put(SDKConstants.param_signature, SDKUtil.signRsa2(data, certPath, certPwd, encoding)); data.put(SDKConstants.param_signature, sdkUtil.signRsa2(data, certPath, certPwd, encoding));
return data; return data;
} catch (Exception e) { } catch (Exception e) {
log.error("Sign Error", e); log.error("Sign Error", e);
...@@ -65,20 +75,20 @@ public class Acp6Service { ...@@ -65,20 +75,20 @@ public class Acp6Service {
* @param encoding 上送请求报文域encoding字段的值<br> * @param encoding 上送请求报文域encoding字段的值<br>
* @return true 通过 false 未通过<br> * @return true 通过 false 未通过<br>
*/ */
public static boolean validate(Map<String, String> data, String encoding) { public boolean validate(Map<String, String> data, String encoding) {
log.info("验签处理开始"); log.info("验签处理开始");
if (SDKUtil.isEmpty(encoding)) { if (SDKUtil.isEmpty(encoding)) {
encoding = "UTF-8"; encoding = "UTF-8";
} }
String certId = data.get(SDKConstants.param_certId); String certId = data.get(SDKConstants.param_certId);
log.info("对返回报文串验签使用的验签公钥序列号:[" + certId + "]"); log.info("对返回报文串验签使用的验签公钥序列号:[" + certId + "]");
PublicKey verifyKey = CertUtil.getValidatePublicKey(certId); PublicKey verifyKey = certUtil.getValidatePublicKey(certId);
if(verifyKey == null) { if(verifyKey == null) {
log.error("未找到此序列号证书。"); log.error("未找到此序列号证书。");
return false; return false;
} }
try { try {
boolean result = SDKUtil.verifyRsa2(data, verifyKey, encoding); boolean result = SDKUtil.verifyRsa2(data, verifyKey, encoding);
log.info("验签" + (result ? "成功" : "失败") + "。"); log.info("验签" + (result ? "成功" : "失败") + "。");
...@@ -94,8 +104,8 @@ public class Acp6Service { ...@@ -94,8 +104,8 @@ public class Acp6Service {
* 更新成功则返回1,无更新返回0,失败异常返回-1<br> * 更新成功则返回1,无更新返回0,失败异常返回-1<br>
* @return * @return
*/ */
public static int updateEncryptCert(String strCert, String certType) { public int updateEncryptCert(String strCert, String certType) {
return SDKUtil.updateEncryptCert(strCert, certType); return sdkUtil.updateEncryptCert(strCert, certType);
} }
/** /**
...@@ -105,9 +115,9 @@ public class Acp6Service { ...@@ -105,9 +115,9 @@ public class Acp6Service {
* @param encoding<br> * @param encoding<br>
* @return 加密的内容<br> * @return 加密的内容<br>
*/ */
public static String encryptPin(String accNo, String pin, String encoding) { public String encryptPin(String accNo, String pin, String encoding) {
byte[] pinblock = SecureUtil.pinblock(accNo, pin); byte[] pinblock = SecureUtil.pinblock(accNo, pin);
return Base64.encodeBase64String(SecureUtil.encrypt(CertUtil.getPinEncryptCert().pubKey, pinblock)); return Base64.encodeBase64String(SecureUtil.encrypt(certUtil.getPinEncryptCert().pubKey, pinblock));
} }
// /** // /**
...@@ -117,41 +127,41 @@ public class Acp6Service { ...@@ -117,41 +127,41 @@ public class Acp6Service {
// * @param encoding<br> // * @param encoding<br>
// * @return 加密的内容<br> // * @return 加密的内容<br>
// */ // */
// public static String encryptPin(String pin, String encoding) { // public String encryptPin(String pin, String encoding) {
// byte[] pinblock = SecureUtil.pinblock(pin); // byte[] pinblock = SecureUtil.pinblock(pin);
// return Base64.encodeBase64String(SecureUtil.encrypt(CertUtil.getPinEncryptCert().pubKey, pinblock)); // return Base64.encodeBase64String(SecureUtil.encrypt(CertUtil.getPinEncryptCert().pubKey, pinblock));
// } // }
/** /**
* 敏感信息加密并做base64(卡号,手机号,cvn2,有效期)<br> * 敏感信息加密并做base64(卡号,手机号,cvn2,有效期)<br>
* @param data 送 phoneNo,cvn2,有效期<br> * @param data 送 phoneNo,cvn2,有效期<br>
* @param encoding<br> * @param encoding<br>
* @return 加密的密文<br> * @return 加密的密文<br>
*/ */
public static String encryptData(String data, String encoding) { public String encryptData(String data, String encoding) {
return AcpService.encryptData(data, encoding); return this.encryptData(data, encoding);
} }
/** /**
* @param data 明文<br> * @param data 明文<br>
* @return 加密的密文<br> * @return 加密的密文<br>
*/ */
public static String encryptData(byte[] data) { public String encryptData(byte[] data) {
try { try {
return Base64.encodeBase64String(SecureUtil.encrypt(CertUtil.getEncryptCert().pubKey, data)); return Base64.encodeBase64String(SecureUtil.encrypt(certUtil.getEncryptCert().pubKey, data));
} catch (Exception e) { } catch (Exception e) {
log.error(e.getMessage(), e); log.error(e.getMessage(), e);
return null; return null;
} }
} }
/** /**
* @param data 明文<br> * @param data 明文<br>
* @return 加密的密文<br> * @return 加密的密文<br>
*/ */
public static String tripleDesEncryptECBPKCS5Padding(byte[] key, byte[] data) { public String tripleDesEncryptECBPKCS5Padding(byte[] key, byte[] data) {
try { try {
return Base64.encodeBase64String(SecureUtil.tripleDesEncryptECBPKCS5Padding(key, SecureUtil.rightPadZero(data, 8))); return Base64.encodeBase64String(SecureUtil.tripleDesEncryptECBPKCS5Padding(key, SecureUtil.rightPadZero(data, 8)));
} catch (Exception e) { } catch (Exception e) {
...@@ -159,17 +169,17 @@ public class Acp6Service { ...@@ -159,17 +169,17 @@ public class Acp6Service {
return null; return null;
} }
} }
/** /**
* 敏感信息解密,使用配置文件acp_sdk.properties解密<br> * 敏感信息解密,使用配置文件acp_sdk.properties解密<br>
* @param base64EncryptedInfo 加密信息<br> * @param base64EncryptedInfo 加密信息<br>
* @param encoding<br> * @param encoding<br>
* @return 解密后的明文<br> * @return 解密后的明文<br>
*/ */
public static String decryptData(String base64EncryptedInfo, String encoding) { public String decryptData(String base64EncryptedInfo, String encoding) {
return AcpService.decryptData(base64EncryptedInfo, encoding); return this.decryptData(base64EncryptedInfo, encoding);
} }
/** /**
* 敏感信息解密,通过传入的私钥解密<br> * 敏感信息解密,通过传入的私钥解密<br>
* @param base64EncryptedInfo 加密信息<br> * @param base64EncryptedInfo 加密信息<br>
...@@ -178,28 +188,28 @@ public class Acp6Service { ...@@ -178,28 +188,28 @@ public class Acp6Service {
* @param encoding<br> * @param encoding<br>
* @return * @return
*/ */
public static String decryptData(String base64EncryptedInfo, String certPath, public String decryptData(String base64EncryptedInfo, String certPath,
String certPwd, String encoding) { String certPwd, String encoding) {
return AcpService.decryptData(base64EncryptedInfo, certPath, certPwd, encoding); return this.decryptData(base64EncryptedInfo, certPath, certPwd, encoding);
} }
/** /**
* 获取敏感信息加密证书的物理序列号<br> * 获取敏感信息加密证书的物理序列号<br>
* @return * @return
*/ */
public static String getEncryptCertId(){ public String getEncryptCertId(){
return CertUtil.getEncryptCert().certId; return certUtil.getEncryptCert().certId;
} }
/** /**
* 获取敏感信息加密证书的物理序列号<br> * 获取敏感信息加密证书的物理序列号<br>
* @return * @return
*/ */
public static String getPinEncryptCertId(){ public String getPinEncryptCertId(){
return CertUtil.getPinEncryptCert().certId; return certUtil.getPinEncryptCert().certId;
} }
/** /**
* 功能:后台交易提交请求报文并接收同步应答报文<br> * 功能:后台交易提交请求报文并接收同步应答报文<br>
* @param reqData 请求报文<br> * @param reqData 请求报文<br>
...@@ -207,13 +217,13 @@ public class Acp6Service { ...@@ -207,13 +217,13 @@ public class Acp6Service {
* @param encoding<br> * @param encoding<br>
* @return 应答http 200返回true ,其他false<br> * @return 应答http 200返回true ,其他false<br>
*/ */
public static Map<String,String> post(Map<String, String> reqData, String reqUrl,String encoding) { public Map<String,String> post(Map<String, String> reqData, String reqUrl,String encoding) {
if(reqData == null || reqUrl == null) { if(reqData == null || reqUrl == null) {
log.error("null input"); log.error("null input");
return null; return null;
} }
log.info("请求银联地址:" + reqUrl + ",请求参数:" + reqData.toString()); log.info("请求银联地址:" + reqUrl + ",请求参数:" + reqData.toString());
if(reqUrl.startsWith("https://") && !SDKConfig.getConfig().isIfValidateRemoteCert()) { if(reqUrl.startsWith("https://") && !sdkConfig.isIfValidateRemoteCert()) {
reqUrl = "u" + reqUrl; reqUrl = "u" + reqUrl;
} }
try{ try{
...@@ -230,7 +240,7 @@ public class Acp6Service { ...@@ -230,7 +240,7 @@ public class Acp6Service {
return null; return null;
} }
} }
/** /**
* 功能:后台交易提交请求报文并接收同步应答报文<br> * 功能:后台交易提交请求报文并接收同步应答报文<br>
* @param reqData 请求报文<br> * @param reqData 请求报文<br>
...@@ -238,13 +248,13 @@ public class Acp6Service { ...@@ -238,13 +248,13 @@ public class Acp6Service {
* @param encoding<br> * @param encoding<br>
* @return 应答http 200返回true ,其他false<br> * @return 应答http 200返回true ,其他false<br>
*/ */
public static String postNotice(Map<String, String> reqData, String reqUrl,String encoding) { public String postNotice(Map<String, String> reqData, String reqUrl,String encoding) {
if(reqData == null || reqUrl == null) { if(reqData == null || reqUrl == null) {
log.error("null input"); log.error("null input");
return null; return null;
} }
log.info("请求银联地址:" + reqUrl + ",请求参数:" + reqData.toString()); log.info("请求银联地址:" + reqUrl + ",请求参数:" + reqData.toString());
if(reqUrl.startsWith("https://") && !SDKConfig.getConfig().isIfValidateRemoteCert()) { if(reqUrl.startsWith("https://") && !sdkConfig.isIfValidateRemoteCert()) {
reqUrl = "u" + reqUrl; reqUrl = "u" + reqUrl;
} }
try{ try{
...@@ -269,7 +279,7 @@ public class Acp6Service { ...@@ -269,7 +279,7 @@ public class Acp6Service {
* @return<br> * @return<br>
* @throws IOException * @throws IOException
*/ */
public static String base64Encode(String rawStr, String encoding){ public String base64Encode(String rawStr, String encoding){
return AcpService.base64Encode(rawStr, encoding); return AcpService.base64Encode(rawStr, encoding);
} }
...@@ -280,7 +290,7 @@ public class Acp6Service { ...@@ -280,7 +290,7 @@ public class Acp6Service {
* @return<br> * @return<br>
* @throws IOException * @throws IOException
*/ */
public static String base64Decode(String base64Str, String encoding){ public String base64Decode(String base64Str, String encoding){
return AcpService.base64Decode(base64Str, encoding); return AcpService.base64Decode(base64Str, encoding);
} }
} }
...@@ -2,6 +2,8 @@ package com.liquidnet.service.dragon.channel.unionpay.sdk; ...@@ -2,6 +2,8 @@ package com.liquidnet.service.dragon.channel.unionpay.sdk;
import lombok.extern.slf4j.Slf4j; import lombok.extern.slf4j.Slf4j;
import org.apache.commons.codec.binary.Base64; import org.apache.commons.codec.binary.Base64;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;
import java.io.*; import java.io.*;
import java.nio.charset.Charset; import java.nio.charset.Charset;
...@@ -18,11 +20,16 @@ import static com.liquidnet.service.dragon.channel.unionpay.sdk.SDKConstants.*; ...@@ -18,11 +20,16 @@ import static com.liquidnet.service.dragon.channel.unionpay.sdk.SDKConstants.*;
/** /**
* @ClassName AcpService * @ClassName AcpService
* @Description acpsdk接口服务类,接入商户集成请可以直接参考使用本类中的方法 * @Description acpsdk接口服务类,接入商户集成请可以直接参考使用本类中的方法
* @date 2016-7-22 下午2:44:37 * @date 2021-11-09 下午2:44:37
*/ */
@Slf4j @Slf4j
@Component
public class AcpService { public class AcpService {
@Autowired
private SDKConfig sdkConfig;
@Autowired
private CertUtil certUtil;
/** /**
* 请求报文签名(使用配置文件中配置的私钥证书或者对称密钥签名)<br> * 请求报文签名(使用配置文件中配置的私钥证书或者对称密钥签名)<br>
* 功能:对请求报文进行签名,并计算赋值certid,signature字段并返回<br> * 功能:对请求报文进行签名,并计算赋值certid,signature字段并返回<br>
...@@ -30,26 +37,26 @@ public class AcpService { ...@@ -30,26 +37,26 @@ public class AcpService {
* @param encoding 上送请求报文域encoding字段的值<br> * @param encoding 上送请求报文域encoding字段的值<br>
* @return 签名后的map对象<br> * @return 签名后的map对象<br>
*/ */
public static Map<String, String> sign(Map<String, String> reqData, String encoding) { public Map<String, String> sign(Map<String, String> reqData, String encoding) {
Map<String, String> data = SDKUtil.filterBlank(reqData); Map<String, String> data = SDKUtil.filterBlank(reqData);
if (SDKUtil.isEmpty(encoding)) { if (SDKUtil.isEmpty(encoding)) {
encoding = "UTF-8"; encoding = "UTF-8";
} }
String signMethod = data.get(param_signMethod); String signMethod = data.get(param_signMethod);
String version = data.get(param_version); String version = data.get(param_version);
if (SDKUtil.isEmpty(signMethod)) { if (SDKUtil.isEmpty(signMethod)) {
signMethod = SIGNMETHOD_RSA; signMethod = SIGNMETHOD_RSA;
} }
try{ try{
if (SIGNMETHOD_RSA.equals(signMethod)) { if (SIGNMETHOD_RSA.equals(signMethod)) {
return signByCertInfo(data, SDKConfig.getConfig().getSignCertPath(), SDKConfig.getConfig().getSignCertPwd(), encoding); return signByCertInfo(data, sdkConfig.getSignCertPath(), sdkConfig.getSignCertPwd(), encoding);
} else if (SIGNMETHOD_SHA256.equals(signMethod)) { } else if (SIGNMETHOD_SHA256.equals(signMethod)) {
return signBySecureKey(data, SDKConfig.getConfig().getSecureKey(), encoding); return signBySecureKey(data, sdkConfig.getSecureKey(), encoding);
} else if (SIGNMETHOD_SM3.equals(signMethod)) { } else if (SIGNMETHOD_SM3.equals(signMethod)) {
return signBySecureKey(data, SDKConfig.getConfig().getSecureKey(), encoding); return signBySecureKey(data, sdkConfig.getSecureKey(), encoding);
} }
log.error("未实现签名方法, version=" + version + ", signMethod=" + signMethod); log.error("未实现签名方法, version=" + version + ", signMethod=" + signMethod);
return data; return data;
...@@ -58,7 +65,7 @@ public class AcpService { ...@@ -58,7 +65,7 @@ public class AcpService {
return data; return data;
} }
} }
/** /**
* 多证书签名(通过传入私钥证书路径和密码签名)<br> * 多证书签名(通过传入私钥证书路径和密码签名)<br>
* 功能:如果有多个商户号接入银联,每个商户号对应不同的证书可以使用此方法:传入私钥证书和密码(并且在acp_sdk.properties中 配置 acpsdk.singleMode=false)<br> * 功能:如果有多个商户号接入银联,每个商户号对应不同的证书可以使用此方法:传入私钥证书和密码(并且在acp_sdk.properties中 配置 acpsdk.singleMode=false)<br>
...@@ -68,7 +75,7 @@ public class AcpService { ...@@ -68,7 +75,7 @@ public class AcpService {
* @param encoding 上送请求报文域encoding字段的值<br> * @param encoding 上送请求报文域encoding字段的值<br>
* @return 签名后的map对象<br> * @return 签名后的map对象<br>
*/ */
public static Map<String, String> signByCertInfo(Map<String, String> reqData, String certPath, public Map<String, String> signByCertInfo(Map<String, String> reqData, String certPath,
String certPwd, String encoding) { String certPwd, String encoding) {
Map<String, String> data = SDKUtil.filterBlank(reqData); Map<String, String> data = SDKUtil.filterBlank(reqData);
...@@ -83,21 +90,21 @@ public class AcpService { ...@@ -83,21 +90,21 @@ public class AcpService {
if (SDKUtil.isEmpty(signMethod)) { if (SDKUtil.isEmpty(signMethod)) {
signMethod = SIGNMETHOD_RSA; signMethod = SIGNMETHOD_RSA;
} }
String version = data.get(SDKConstants.param_version); String version = data.get(SDKConstants.param_version);
try { try {
if(VERSION_5_0_1.equals(version) || VERSION_5_0_0.equals(version)){ if(VERSION_5_0_1.equals(version) || VERSION_5_0_0.equals(version)){
if (SIGNMETHOD_RSA.equals(signMethod)) { if (SIGNMETHOD_RSA.equals(signMethod)) {
data.put(SDKConstants.param_certId, com.liquidnet.service.dragon.channel.unionpay.sdk.CertUtil.getCertIdByKeyStoreMap(certPath, certPwd)); data.put(SDKConstants.param_certId, certUtil.getCertIdByKeyStoreMap(certPath, certPwd));
data.put(SDKConstants.param_signature, SDKUtil.signRsa(data, certPath, certPwd, encoding)); data.put(SDKConstants.param_signature, SDKUtil.signRsa(data, certPath, certPwd, encoding));
return data; return data;
} }
} else if(VERSION_5_1_0.equals(version)){ } else if(VERSION_5_1_0.equals(version)){
if (SIGNMETHOD_RSA.equals(signMethod)) { if (SIGNMETHOD_RSA.equals(signMethod)) {
data.put(SDKConstants.param_certId, com.liquidnet.service.dragon.channel.unionpay.sdk.CertUtil.getCertIdByKeyStoreMap(certPath, certPwd)); data.put(SDKConstants.param_certId, certUtil.getCertIdByKeyStoreMap(certPath, certPwd));
data.put(SDKConstants.param_signature, SDKUtil.signRsa2(data, certPath, certPwd, encoding)); data.put(SDKConstants.param_signature, SDKUtil.signRsa2(data, certPath, certPwd, encoding));
return data; return data;
} }
} }
log.error("未实现签名方法, version=" + version + ", signMethod=" + signMethod); log.error("未实现签名方法, version=" + version + ", signMethod=" + signMethod);
return data; return data;
...@@ -106,7 +113,7 @@ public class AcpService { ...@@ -106,7 +113,7 @@ public class AcpService {
return data; return data;
} }
} }
/** /**
* 多密钥签名(通过传入密钥签名)<br> * 多密钥签名(通过传入密钥签名)<br>
* 功能:如果有多个商户号接入银联,每个商户号对应不同的证书可以使用此方法:传入私钥证书和密码(并且在acp_sdk.properties中 配置 acpsdk.singleMode=false)<br> * 功能:如果有多个商户号接入银联,每个商户号对应不同的证书可以使用此方法:传入私钥证书和密码(并且在acp_sdk.properties中 配置 acpsdk.singleMode=false)<br>
...@@ -151,35 +158,35 @@ public class AcpService { ...@@ -151,35 +158,35 @@ public class AcpService {
* @param encoding 上送请求报文域encoding字段的值<br> * @param encoding 上送请求报文域encoding字段的值<br>
* @return true 通过 false 未通过<br> * @return true 通过 false 未通过<br>
*/ */
public static boolean validate(Map<String, String> data, String encoding) { public boolean validate(Map<String, String> data, String encoding) {
log.info("验签处理开始"); log.info("验签处理开始");
if (SDKUtil.isEmpty(encoding)) { if (SDKUtil.isEmpty(encoding)) {
encoding = "UTF-8"; encoding = "UTF-8";
} }
String signMethod = data.get(SDKConstants.param_signMethod); String signMethod = data.get(SDKConstants.param_signMethod);
if (SDKUtil.isEmpty(signMethod)) { if (SDKUtil.isEmpty(signMethod)) {
signMethod = SIGNMETHOD_RSA; signMethod = SIGNMETHOD_RSA;
} }
String version = data.get(SDKConstants.param_version); String version = data.get(SDKConstants.param_version);
try { try {
if(VERSION_5_1_0.equals(version)){ if(VERSION_5_1_0.equals(version)){
if( SIGNMETHOD_SHA256.equals(signMethod)) if( SIGNMETHOD_SHA256.equals(signMethod))
return SDKUtil.verifySha256(data, SDKConfig.getConfig().getSecureKey(), encoding); return SDKUtil.verifySha256(data, sdkConfig.getSecureKey(), encoding);
else if(SIGNMETHOD_SM3.equals(signMethod)) else if(SIGNMETHOD_SM3.equals(signMethod))
return SDKUtil.verifySm3(data, SDKConfig.getConfig().getSecureKey(), encoding); return SDKUtil.verifySm3(data, sdkConfig.getSecureKey(), encoding);
} }
if(SIGNMETHOD_RSA.equals(signMethod)) { if(SIGNMETHOD_RSA.equals(signMethod)) {
String strCert = data.get(SDKConstants.param_signPubKeyCert); String strCert = data.get(SDKConstants.param_signPubKeyCert);
String certId = data.get(SDKConstants.param_certId); String certId = data.get(SDKConstants.param_certId);
PublicKey verifyKey = null; PublicKey verifyKey = null;
if(!SDKUtil.isEmpty(strCert)) if(!SDKUtil.isEmpty(strCert))
verifyKey = com.liquidnet.service.dragon.channel.unionpay.sdk.CertUtil.verifyAndGetVerifyPubKey(strCert); verifyKey = certUtil.verifyAndGetVerifyPubKey(strCert);
else if(!SDKUtil.isEmpty(certId)){ else if(!SDKUtil.isEmpty(certId)){
log.info("对返回报文串验签使用的验签公钥序列号:[" + certId + "]"); log.info("对返回报文串验签使用的验签公钥序列号:[" + certId + "]");
verifyKey = com.liquidnet.service.dragon.channel.unionpay.sdk.CertUtil.getValidatePublicKey(certId); verifyKey = certUtil.getValidatePublicKey(certId);
} }
if(verifyKey == null) { if(verifyKey == null) {
log.error("未成功获取验签公钥,验签失败。"); log.error("未成功获取验签公钥,验签失败。");
...@@ -193,8 +200,8 @@ public class AcpService { ...@@ -193,8 +200,8 @@ public class AcpService {
boolean result = SDKUtil.verifyRsa2(data, verifyKey, encoding); boolean result = SDKUtil.verifyRsa2(data, verifyKey, encoding);
log.info("验签" + (result? "成功":"失败") + "。"); log.info("验签" + (result? "成功":"失败") + "。");
return result; return result;
} }
} }
log.error("无法判断验签方法,验签失败。version="+version+", signMethod="+signMethod); log.error("无法判断验签方法,验签失败。version="+version+", signMethod="+signMethod);
return false; return false;
} catch (Exception e) { } catch (Exception e) {
...@@ -202,7 +209,7 @@ public class AcpService { ...@@ -202,7 +209,7 @@ public class AcpService {
return false; return false;
} }
} }
/** /**
* 多密钥验签(通过传入密钥签名)<br> * 多密钥验签(通过传入密钥签名)<br>
* @param data 返回报文数据<br> * @param data 返回报文数据<br>
...@@ -240,7 +247,7 @@ public class AcpService { ...@@ -240,7 +247,7 @@ public class AcpService {
return false; return false;
} }
} }
/** /**
* @deprecated 5.1.0开发包已删除此方法,请直接参考5.1.0开发包中的VerifyAppData.java验签。 * @deprecated 5.1.0开发包已删除此方法,请直接参考5.1.0开发包中的VerifyAppData.java验签。
...@@ -248,7 +255,7 @@ public class AcpService { ...@@ -248,7 +255,7 @@ public class AcpService {
* @param jsonData json格式数据,例如:{"sign" : "J6rPLClQ64szrdXCOtV1ccOMzUmpiOKllp9cseBuRqJ71pBKPPkZ1FallzW18gyP7CvKh1RxfNNJ66AyXNMFJi1OSOsteAAFjF5GZp0Xsfm3LeHaN3j/N7p86k3B1GrSPvSnSw1LqnYuIBmebBkC1OD0Qi7qaYUJosyA1E8Ld8oGRZT5RR2gLGBoiAVraDiz9sci5zwQcLtmfpT5KFk/eTy4+W9SsC0M/2sVj43R9ePENlEvF8UpmZBqakyg5FO8+JMBz3kZ4fwnutI5pWPdYIWdVrloBpOa+N4pzhVRKD4eWJ0CoiD+joMS7+C0aPIEymYFLBNYQCjM0KV7N726LA==", "data" : "pay_result=success&tn=201602141008032671528&cert_id=68759585097"} * @param jsonData json格式数据,例如:{"sign" : "J6rPLClQ64szrdXCOtV1ccOMzUmpiOKllp9cseBuRqJ71pBKPPkZ1FallzW18gyP7CvKh1RxfNNJ66AyXNMFJi1OSOsteAAFjF5GZp0Xsfm3LeHaN3j/N7p86k3B1GrSPvSnSw1LqnYuIBmebBkC1OD0Qi7qaYUJosyA1E8Ld8oGRZT5RR2gLGBoiAVraDiz9sci5zwQcLtmfpT5KFk/eTy4+W9SsC0M/2sVj43R9ePENlEvF8UpmZBqakyg5FO8+JMBz3kZ4fwnutI5pWPdYIWdVrloBpOa+N4pzhVRKD4eWJ0CoiD+joMS7+C0aPIEymYFLBNYQCjM0KV7N726LA==", "data" : "pay_result=success&tn=201602141008032671528&cert_id=68759585097"}
* @return 是否成功 * @return 是否成功
*/ */
public static boolean validateAppResponse(String jsonData, String encoding) { public boolean validateAppResponse(String jsonData, String encoding) {
log.info("控件应答信息验签处理开始:[" + jsonData + "]"); log.info("控件应答信息验签处理开始:[" + jsonData + "]");
if (SDKUtil.isEmpty(encoding)) { if (SDKUtil.isEmpty(encoding)) {
encoding = "UTF-8"; encoding = "UTF-8";
...@@ -271,7 +278,7 @@ public class AcpService { ...@@ -271,7 +278,7 @@ public class AcpService {
try { try {
// 验证签名需要用银联发给商户的公钥证书. // 验证签名需要用银联发给商户的公钥证书.
return com.liquidnet.service.dragon.channel.unionpay.sdk.SecureUtil.verifySignature(com.liquidnet.service.dragon.channel.unionpay.sdk.CertUtil return com.liquidnet.service.dragon.channel.unionpay.sdk.SecureUtil.verifySignature(certUtil
.getValidatePublicKey(certId), Base64.decodeBase64(sign), .getValidatePublicKey(certId), Base64.decodeBase64(sign),
SDKUtil.byteArrayToHexString(com.liquidnet.service.dragon.channel.unionpay.sdk.SecureUtil.sha1(data.getBytes(encoding))).getBytes(encoding)); SDKUtil.byteArrayToHexString(com.liquidnet.service.dragon.channel.unionpay.sdk.SecureUtil.sha1(data.getBytes(encoding))).getBytes(encoding));
} catch (UnsupportedEncodingException e) { } catch (UnsupportedEncodingException e) {
...@@ -281,7 +288,7 @@ public class AcpService { ...@@ -281,7 +288,7 @@ public class AcpService {
} }
return false; return false;
} }
/** /**
* 功能:后台交易提交请求报文并接收同步应答报文<br> * 功能:后台交易提交请求报文并接收同步应答报文<br>
* @param reqData 请求报文<br> * @param reqData 请求报文<br>
...@@ -289,14 +296,14 @@ public class AcpService { ...@@ -289,14 +296,14 @@ public class AcpService {
* @param encoding<br> * @param encoding<br>
* @return 应答http 200返回true ,其他false<br> * @return 应答http 200返回true ,其他false<br>
*/ */
public static Map<String,String> post( public Map<String,String> post(
Map<String, String> reqData, String reqUrl, String encoding) { Map<String, String> reqData, String reqUrl, String encoding) {
if(reqData == null || reqUrl == null) { if(reqData == null || reqUrl == null) {
log.error("post err: null input"); log.error("post err: null input");
return null; return null;
} }
log.info("请求银联地址:" + reqUrl + ",请求参数:" + reqData.toString()); log.info("请求银联地址:" + reqUrl + ",请求参数:" + reqData.toString());
if(reqUrl.startsWith("https://") && !SDKConfig.getConfig().isIfValidateRemoteCert()) { if(reqUrl.startsWith("https://") && !sdkConfig.isIfValidateRemoteCert()) {
reqUrl = "u" + reqUrl; reqUrl = "u" + reqUrl;
} }
try{ try{
...@@ -313,20 +320,20 @@ public class AcpService { ...@@ -313,20 +320,20 @@ public class AcpService {
return null; return null;
} }
} }
/** /**
* 功能:http Get方法 便民缴费产品中使用<br> * 功能:http Get方法 便民缴费产品中使用<br>
* @param reqUrl 请求地址<br> * @param reqUrl 请求地址<br>
* @param encoding<br> * @param encoding<br>
* @return * @return
*/ */
public static String get(String reqUrl, String encoding) { public String get(String reqUrl, String encoding) {
if(reqUrl == null) { if(reqUrl == null) {
log.error("null input"); log.error("null input");
return null; return null;
} }
log.info("get请求银联地址:" + reqUrl); log.info("get请求银联地址:" + reqUrl);
if(!SDKConfig.getConfig().isIfValidateRemoteCert()) { if(!sdkConfig.isIfValidateRemoteCert()) {
reqUrl = "u" + reqUrl; reqUrl = "u" + reqUrl;
} }
try{ try{
...@@ -343,8 +350,8 @@ public class AcpService { ...@@ -343,8 +350,8 @@ public class AcpService {
return null; return null;
} }
} }
/** /**
* 功能:前台交易构造HTTP POST自动提交表单<br> * 功能:前台交易构造HTTP POST自动提交表单<br>
* @param reqUrl 表单提交地址<br> * @param reqUrl 表单提交地址<br>
...@@ -379,7 +386,7 @@ public class AcpService { ...@@ -379,7 +386,7 @@ public class AcpService {
return html; return html;
} }
/** /**
* 功能:将批量文件内容使用DEFLATE压缩算法压缩,Base64编码生成字符串并返回<br> * 功能:将批量文件内容使用DEFLATE压缩算法压缩,Base64编码生成字符串并返回<br>
* 适用到的交易:批量代付,批量代收,批量退货<br> * 适用到的交易:批量代付,批量代收,批量退货<br>
...@@ -388,7 +395,7 @@ public class AcpService { ...@@ -388,7 +395,7 @@ public class AcpService {
*/ */
public static String enCodeFileContent(String filePath, String encoding){ public static String enCodeFileContent(String filePath, String encoding){
String baseFileContent = ""; String baseFileContent = "";
File file = new File(filePath); File file = new File(filePath);
if (!file.exists()) { if (!file.exists()) {
try { try {
...@@ -420,13 +427,13 @@ public class AcpService { ...@@ -420,13 +427,13 @@ public class AcpService {
} }
return baseFileContent; return baseFileContent;
} }
/** /**
* 功能:解析交易返回的fileContent字符串并落地 ( 解base64,解DEFLATE压缩并落地)<br> * 功能:解析交易返回的fileContent字符串并落地 ( 解base64,解DEFLATE压缩并落地)<br>
* 适用到的交易:对账文件下载,批量交易状态查询<br> * 适用到的交易:对账文件下载,批量交易状态查询<br>
* @param data 返回报文map<br> * @param data 返回报文map<br>
* @param fileDirectory 落地的文件目录(绝对路径) * @param fileDirectory 落地的文件目录(绝对路径)
* @param encoding 上送请求报文域encoding字段的值<br> * @param encoding 上送请求报文域encoding字段的值<br>
*/ */
public static String deCodeFileContent(Map<String, String> data,String fileDirectory,String encoding) { public static String deCodeFileContent(Map<String, String> data,String fileDirectory,String encoding) {
// 解析返回文件 // 解析返回文件
...@@ -483,8 +490,8 @@ public class AcpService { ...@@ -483,8 +490,8 @@ public class AcpService {
} }
return fc; return fc;
} }
/** /**
* 功能:持卡人信息域customerInfo构造<br> * 功能:持卡人信息域customerInfo构造<br>
* 说明:不勾选对敏感信息加密权限使用旧的构造customerInfo域方式,不对敏感信息进行加密(对 phoneNo,cvn2, expired不加密),但如果送pin的话则加密<br> * 说明:不勾选对敏感信息加密权限使用旧的构造customerInfo域方式,不对敏感信息进行加密(对 phoneNo,cvn2, expired不加密),但如果送pin的话则加密<br>
...@@ -498,11 +505,11 @@ public class AcpService { ...@@ -498,11 +505,11 @@ public class AcpService {
customerInfoMap.put("cvn2", "123"); //卡背面的cvn2三位数字(不加密)<br> customerInfoMap.put("cvn2", "123"); //卡背面的cvn2三位数字(不加密)<br>
customerInfoMap.put("expired", "2311"); //有效期 年在前月在后(不加密)<br> customerInfoMap.put("expired", "2311"); //有效期 年在前月在后(不加密)<br>
* @param accNo customerInfoMap送了密码那么卡号必送,如果customerInfoMap未送密码pin,此字段可以不送<br> * @param accNo customerInfoMap送了密码那么卡号必送,如果customerInfoMap未送密码pin,此字段可以不送<br>
* @param encoding 上送请求报文域encoding字段的值<br> * @param encoding 上送请求报文域encoding字段的值<br>
* @return base64后的持卡人信息域字段<br> * @return base64后的持卡人信息域字段<br>
*/ */
public static String getCustomerInfo(Map<String,String> customerInfoMap,String accNo,String encoding) { public String getCustomerInfo(Map<String,String> customerInfoMap,String accNo,String encoding) {
if(customerInfoMap.isEmpty()) if(customerInfoMap.isEmpty())
return "{}"; return "{}";
StringBuffer sf = new StringBuffer("{"); StringBuffer sf = new StringBuffer("{");
...@@ -530,7 +537,7 @@ public class AcpService { ...@@ -530,7 +537,7 @@ public class AcpService {
} }
return customerInfo; return customerInfo;
} }
/** /**
* 功能:持卡人信息域customerInfo构造,勾选对敏感信息加密权限 适用新加密规范,对pin和phoneNo,cvn2,expired加密 <br> * 功能:持卡人信息域customerInfo构造,勾选对敏感信息加密权限 适用新加密规范,对pin和phoneNo,cvn2,expired加密 <br>
* 适用到的交易: <br> * 适用到的交易: <br>
...@@ -547,13 +554,13 @@ public class AcpService { ...@@ -547,13 +554,13 @@ public class AcpService {
* @param encoding 上送请求报文域encoding字段的值 * @param encoding 上送请求报文域encoding字段的值
* @return base64后的持卡人信息域字段 <br> * @return base64后的持卡人信息域字段 <br>
*/ */
public static String getCustomerInfoWithEncrypt(Map<String,String> customerInfoMap,String accNo,String encoding) { public String getCustomerInfoWithEncrypt(Map<String,String> customerInfoMap,String accNo,String encoding) {
if(customerInfoMap.isEmpty()) if(customerInfoMap.isEmpty())
return "{}"; return "{}";
StringBuffer sf = new StringBuffer("{"); StringBuffer sf = new StringBuffer("{");
//敏感信息加密域 //敏感信息加密域
StringBuffer encryptedInfoSb = new StringBuffer(""); StringBuffer encryptedInfoSb = new StringBuffer("");
for(Iterator<String> it = customerInfoMap.keySet().iterator(); it.hasNext();){ for(Iterator<String> it = customerInfoMap.keySet().iterator(); it.hasNext();){
String key = it.next(); String key = it.next();
String value = customerInfoMap.get(key); String value = customerInfoMap.get(key);
...@@ -571,7 +578,7 @@ public class AcpService { ...@@ -571,7 +578,7 @@ public class AcpService {
sf.append(key).append(SDKConstants.EQUAL).append(value).append(SDKConstants.AMPERSAND); sf.append(key).append(SDKConstants.EQUAL).append(value).append(SDKConstants.AMPERSAND);
} }
} }
if(!encryptedInfoSb.toString().equals("")){ if(!encryptedInfoSb.toString().equals("")){
encryptedInfoSb.setLength(encryptedInfoSb.length()-1);//去掉最后一个&符号 encryptedInfoSb.setLength(encryptedInfoSb.length()-1);//去掉最后一个&符号
log.info("组装的customerInfo encryptedInfo明文:"+ encryptedInfoSb.toString()); log.info("组装的customerInfo encryptedInfo明文:"+ encryptedInfoSb.toString());
...@@ -579,7 +586,7 @@ public class AcpService { ...@@ -579,7 +586,7 @@ public class AcpService {
}else{ }else{
sf.setLength(sf.length()-1); sf.setLength(sf.length()-1);
} }
String customerInfo = sf.append("}").toString(); String customerInfo = sf.append("}").toString();
log.info("组装的customerInfo明文:"+customerInfo); log.info("组装的customerInfo明文:"+customerInfo);
try { try {
...@@ -589,7 +596,7 @@ public class AcpService { ...@@ -589,7 +596,7 @@ public class AcpService {
} }
return customerInfo; return customerInfo;
} }
/** /**
* 解析返回报文(后台通知)中的customerInfo域:<br> * 解析返回报文(后台通知)中的customerInfo域:<br>
* 解base64,如果带敏感信息加密 encryptedInfo 则将其解密并将 encryptedInfo中的域放到customerInfoMap返回<br> * 解base64,如果带敏感信息加密 encryptedInfo 则将其解密并将 encryptedInfo中的域放到customerInfoMap返回<br>
...@@ -597,7 +604,7 @@ public class AcpService { ...@@ -597,7 +604,7 @@ public class AcpService {
* @param encoding<br> * @param encoding<br>
* @return * @return
*/ */
public static Map<String, String> parseCustomerInfo(String customerInfo, String encoding) { public Map<String, String> parseCustomerInfo(String customerInfo, String encoding) {
Map<String, String> customerInfoMap = null; Map<String, String> customerInfoMap = null;
try { try {
byte[] b = Base64.decodeBase64(customerInfo); byte[] b = Base64.decodeBase64(customerInfo);
...@@ -626,7 +633,7 @@ public class AcpService { ...@@ -626,7 +633,7 @@ public class AcpService {
* @param encoding<br> * @param encoding<br>
* @return * @return
*/ */
public static Map<String,String> parseCustomerInfo(String customerInfo, String certPath, public Map<String,String> parseCustomerInfo(String customerInfo, String certPath,
String certPwd, String encoding){ String certPwd, String encoding){
Map<String,String> customerInfoMap = null; Map<String,String> customerInfoMap = null;
try { try {
...@@ -656,36 +663,36 @@ public class AcpService { ...@@ -656,36 +663,36 @@ public class AcpService {
* @param encoding<br> * @param encoding<br>
* @return 加密的内容<br> * @return 加密的内容<br>
*/ */
public static String encryptPin(String accNo, String pin, String encoding) { public String encryptPin(String accNo, String pin, String encoding) {
byte[] pinblock = com.liquidnet.service.dragon.channel.unionpay.sdk.SecureUtil.pinblock(accNo, pin); byte[] pinblock = com.liquidnet.service.dragon.channel.unionpay.sdk.SecureUtil.pinblock(accNo, pin);
return Base64.encodeBase64String(com.liquidnet.service.dragon.channel.unionpay.sdk.SecureUtil.encrypt(com.liquidnet.service.dragon.channel.unionpay.sdk.CertUtil.getEncryptCert().pubKey, pinblock)); return Base64.encodeBase64String(com.liquidnet.service.dragon.channel.unionpay.sdk.SecureUtil.encrypt(certUtil.getEncryptCert().pubKey, pinblock));
} }
/** /**
* 敏感信息加密并做base64(卡号,手机号,cvn2,有效期)<br> * 敏感信息加密并做base64(卡号,手机号,cvn2,有效期)<br>
* @param data 送 phoneNo,cvn2,有效期<br> * @param data 送 phoneNo,cvn2,有效期<br>
* @param encoding<br> * @param encoding<br>
* @return 加密的密文<br> * @return 加密的密文<br>
*/ */
public static String encryptData(String data, String encoding) { public String encryptData(String data, String encoding) {
try { try {
return Base64.encodeBase64String(com.liquidnet.service.dragon.channel.unionpay.sdk.SecureUtil.encrypt(com.liquidnet.service.dragon.channel.unionpay.sdk.CertUtil.getEncryptCert().pubKey, data.getBytes(encoding))); return Base64.encodeBase64String(com.liquidnet.service.dragon.channel.unionpay.sdk.SecureUtil.encrypt(certUtil.getEncryptCert().pubKey, data.getBytes(encoding)));
} catch (Exception e) { } catch (Exception e) {
log.error(e.getMessage(), e); log.error(e.getMessage(), e);
return null; return null;
} }
} }
/** /**
* 敏感信息解密,使用配置文件acp_sdk.properties解密<br> * 敏感信息解密,使用配置文件acp_sdk.properties解密<br>
* @param base64EncryptedInfo 加密信息<br> * @param base64EncryptedInfo 加密信息<br>
* @param encoding<br> * @param encoding<br>
* @return 解密后的明文<br> * @return 解密后的明文<br>
*/ */
public static String decryptData(String base64EncryptedInfo, String encoding) { public String decryptData(String base64EncryptedInfo, String encoding) {
return new String(com.liquidnet.service.dragon.channel.unionpay.sdk.SecureUtil.decrypt(com.liquidnet.service.dragon.channel.unionpay.sdk.CertUtil.getSignCertPrivateKey(), Base64.decodeBase64(base64EncryptedInfo)), Charset.forName(encoding)); return new String(com.liquidnet.service.dragon.channel.unionpay.sdk.SecureUtil.decrypt(certUtil.getSignCertPrivateKey(), Base64.decodeBase64(base64EncryptedInfo)), Charset.forName(encoding));
} }
/** /**
* 敏感信息解密,通过传入的私钥解密<br> * 敏感信息解密,通过传入的私钥解密<br>
* @param base64EncryptedInfo 加密信息<br> * @param base64EncryptedInfo 加密信息<br>
...@@ -694,9 +701,9 @@ public class AcpService { ...@@ -694,9 +701,9 @@ public class AcpService {
* @param encoding<br> * @param encoding<br>
* @return * @return
*/ */
public static String decryptData(String base64EncryptedInfo, String certPath, public String decryptData(String base64EncryptedInfo, String certPath,
String certPwd, String encoding) { String certPwd, String encoding) {
return new String(com.liquidnet.service.dragon.channel.unionpay.sdk.SecureUtil.decrypt(com.liquidnet.service.dragon.channel.unionpay.sdk.CertUtil.getSignCertPrivateKeyByStoreMap(certPath, certPwd), return new String(com.liquidnet.service.dragon.channel.unionpay.sdk.SecureUtil.decrypt(certUtil.getSignCertPrivateKeyByStoreMap(certPath, certPwd),
Base64.decodeBase64(base64EncryptedInfo)), Charset.forName(encoding)); Base64.decodeBase64(base64EncryptedInfo)), Charset.forName(encoding));
} }
...@@ -707,41 +714,41 @@ public class AcpService { ...@@ -707,41 +714,41 @@ public class AcpService {
* @return 加密的密文<br> * @return 加密的密文<br>
* @deprecated * @deprecated
*/ */
public static String encryptTrack(String trackData, String encoding) { public String encryptTrack(String trackData, String encoding) {
try { try {
return Base64.encodeBase64String(com.liquidnet.service.dragon.channel.unionpay.sdk.SecureUtil.encrypt(com.liquidnet.service.dragon.channel.unionpay.sdk.CertUtil.getEncryptTrackPublicKey(), trackData.getBytes(encoding))); return Base64.encodeBase64String(com.liquidnet.service.dragon.channel.unionpay.sdk.SecureUtil.encrypt(certUtil.getEncryptTrackPublicKey(), trackData.getBytes(encoding)));
} catch (Exception e) { } catch (Exception e) {
log.error(e.getMessage(), e); log.error(e.getMessage(), e);
return null; return null;
} }
} }
/** /**
* 获取敏感信息加密证书的物理序列号<br> * 获取敏感信息加密证书的物理序列号<br>
* @return * @return
*/ */
public static String getEncryptCertId(){ public String getEncryptCertId(){
return com.liquidnet.service.dragon.channel.unionpay.sdk.CertUtil.getEncryptCert().certId; return certUtil.getEncryptCert().certId;
} }
/** /**
* *
* 有卡交易信息域(cardTransData)构造<br> * 有卡交易信息域(cardTransData)构造<br>
* 所有子域需用“{}”包含,子域间以“&”符号链接。格式如下:{子域名1=值&子域名2=值&子域名3=值}<br> * 所有子域需用“{}”包含,子域间以“&”符号链接。格式如下:{子域名1=值&子域名2=值&子域名3=值}<br>
* 说明:本示例仅供参考,开发时请根据接口文档中的报文要素组装<br> * 说明:本示例仅供参考,开发时请根据接口文档中的报文要素组装<br>
* *
* @param cardTransDataMap cardTransData的数据<br> * @param cardTransDataMap cardTransData的数据<br>
* @param requestData 必须包含merId、orderId、txnTime、txnAmt,磁道加密时需要使用<br> * @param requestData 必须包含merId、orderId、txnTime、txnAmt,磁道加密时需要使用<br>
* @param encoding 编码<br> * @param encoding 编码<br>
* @return * @return
*/ */
public static String getCardTransData(Map<String, String> cardTransDataMap, public String getCardTransData(Map<String, String> cardTransDataMap,
Map<String, String> requestData, Map<String, String> requestData,
String encoding) { { String encoding) { {
StringBuffer cardTransDataBuffer = new StringBuffer(); StringBuffer cardTransDataBuffer = new StringBuffer();
if(cardTransDataMap.containsKey("track2Data")){ if(cardTransDataMap.containsKey("track2Data")){
StringBuffer track2Buffer = new StringBuffer(); StringBuffer track2Buffer = new StringBuffer();
track2Buffer.append(requestData.get("merId")) track2Buffer.append(requestData.get("merId"))
...@@ -749,10 +756,10 @@ public class AcpService { ...@@ -749,10 +756,10 @@ public class AcpService {
.append(SDKConstants.COLON).append(requestData.get("txnTime")) .append(SDKConstants.COLON).append(requestData.get("txnTime"))
.append(SDKConstants.COLON).append(requestData.get("txnAmt")==null?0:requestData.get("txnAmt")) .append(SDKConstants.COLON).append(requestData.get("txnAmt")==null?0:requestData.get("txnAmt"))
.append(SDKConstants.COLON).append(cardTransDataMap.get("track2Data")); .append(SDKConstants.COLON).append(cardTransDataMap.get("track2Data"));
cardTransDataMap.put("track2Data", cardTransDataMap.put("track2Data",
AcpService.encryptData(track2Buffer.toString(), encoding)); this.encryptData(track2Buffer.toString(), encoding));
} }
if(cardTransDataMap.containsKey("track3Data")){ if(cardTransDataMap.containsKey("track3Data")){
StringBuffer track3Buffer = new StringBuffer(); StringBuffer track3Buffer = new StringBuffer();
track3Buffer.append(requestData.get("merId")) track3Buffer.append(requestData.get("merId"))
...@@ -760,17 +767,17 @@ public class AcpService { ...@@ -760,17 +767,17 @@ public class AcpService {
.append(SDKConstants.COLON).append(requestData.get("txnTime")) .append(SDKConstants.COLON).append(requestData.get("txnTime"))
.append(SDKConstants.COLON).append(requestData.get("txnAmt")==null?0:requestData.get("txnAmt")) .append(SDKConstants.COLON).append(requestData.get("txnAmt")==null?0:requestData.get("txnAmt"))
.append(SDKConstants.COLON).append(cardTransDataMap.get("track3Data")); .append(SDKConstants.COLON).append(cardTransDataMap.get("track3Data"));
cardTransDataMap.put("track3Data", cardTransDataMap.put("track3Data",
AcpService.encryptData(track3Buffer.toString(), encoding)); this.encryptData(track3Buffer.toString(), encoding));
} }
return cardTransDataBuffer.append(SDKConstants.LEFT_BRACE) return cardTransDataBuffer.append(SDKConstants.LEFT_BRACE)
.append(SDKUtil.createLinkString(cardTransDataMap, false, false, encoding)) .append(SDKUtil.createLinkString(cardTransDataMap, false, false, encoding))
.append(SDKConstants.RIGHT_BRACE).toString(); .append(SDKConstants.RIGHT_BRACE).toString();
} }
} }
/** /**
* 获取应答报文中的加密公钥证书,并存储到本地,备份原始证书,并自动替换证书<br> * 获取应答报文中的加密公钥证书,并存储到本地,备份原始证书,并自动替换证书<br>
* 更新成功则返回1,无更新返回0,失败异常返回-1<br> * 更新成功则返回1,无更新返回0,失败异常返回-1<br>
...@@ -809,7 +816,7 @@ public class AcpService { ...@@ -809,7 +816,7 @@ public class AcpService {
throw new RuntimeException("不认识这个编码?" + encoding, e); throw new RuntimeException("不认识这个编码?" + encoding, e);
} }
} }
/** /**
* 组成{a=b&c=d}字符串 * 组成{a=b&c=d}字符串
* @param map * @param map
......
/** /**
* *
* Licensed Property to China UnionPay Co., Ltd. * Licensed Property to China UnionPay Co., Ltd.
* *
* (C) Copyright of China UnionPay Co., Ltd. 2010 * (C) Copyright of China UnionPay Co., Ltd. 2010
* All Rights Reserved. * All Rights Reserved.
* *
* *
* Modification History: * Modification History:
* ============================================================================= * =============================================================================
* Author Date Description * Author Date Description
...@@ -18,7 +18,10 @@ package com.liquidnet.service.dragon.channel.unionpay.sdk; ...@@ -18,7 +18,10 @@ package com.liquidnet.service.dragon.channel.unionpay.sdk;
import lombok.extern.slf4j.Slf4j; import lombok.extern.slf4j.Slf4j;
import org.apache.commons.io.FileUtils; import org.apache.commons.io.FileUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.annotation.Configuration;
import javax.annotation.PostConstruct;
import java.io.*; import java.io.*;
import java.math.BigInteger; import java.math.BigInteger;
import java.security.*; import java.security.*;
...@@ -33,10 +36,13 @@ import static com.liquidnet.service.dragon.channel.unionpay.sdk.SDKUtil.isEmpty; ...@@ -33,10 +36,13 @@ import static com.liquidnet.service.dragon.channel.unionpay.sdk.SDKUtil.isEmpty;
/** /**
* @ClassName: CertUtil * @ClassName: CertUtil
* @Description: acpsdk证书工具类,主要用于对证书的加载和使用 * @Description: acpsdk证书工具类,主要用于对证书的加载和使用
* @date 2016-7-22 下午2:46:20 * @date 2021-11-09 下午2:46:20
*/ */
@Slf4j @Slf4j
@Configuration
public class CertUtil { public class CertUtil {
@Autowired
private SDKConfig sdkConfig;
/** 验签中级证书 */ /** 验签中级证书 */
private static X509Certificate middleCert = null; private static X509Certificate middleCert = null;
...@@ -61,16 +67,13 @@ public class CertUtil { ...@@ -61,16 +67,13 @@ public class CertUtil {
protected PrivateKey priKey; protected PrivateKey priKey;
} }
static {
addProvider();//向系统添加BC provider
init();
}
/** /**
* 初始化所有证书. * 初始化所有证书.
*/ */
public static void init() { @PostConstruct
public void init() {
try { try {
addProvider();//向系统添加BC provider
initSignCert();//初始化签名私钥证书 initSignCert();//初始化签名私钥证书
initMiddleCert();//初始化验签证书的中级证书 initMiddleCert();//初始化验签证书的中级证书
initRootCert();//初始化验签证书的根证书 initRootCert();//初始化验签证书的根证书
...@@ -82,11 +85,11 @@ public class CertUtil { ...@@ -82,11 +85,11 @@ public class CertUtil {
log.error("init失败。", e); log.error("init失败。", e);
} }
} }
/** /**
* 添加签名,验签,加密算法提供者 * 添加签名,验签,加密算法提供者
*/ */
private static void addProvider(){ private void addProvider(){
if (Security.getProvider("BC") == null) { if (Security.getProvider("BC") == null) {
log.debug("add BC provider"); log.debug("add BC provider");
Security.addProvider(new org.bouncycastle.jce.provider.BouncyCastleProvider()); Security.addProvider(new org.bouncycastle.jce.provider.BouncyCastleProvider());
...@@ -104,7 +107,7 @@ public class CertUtil { ...@@ -104,7 +107,7 @@ public class CertUtil {
* @param pwd * @param pwd
* @return * @return
*/ */
private static Cert addSignCert(String path, String pwd) { private Cert addSignCert(String path, String pwd) {
if (isEmpty(path) || isEmpty(pwd)) { if (isEmpty(path) || isEmpty(pwd)) {
log.warn("签名证书路径或证书密码为空。 停止加载签名私钥证书。"); log.warn("签名证书路径或证书密码为空。 停止加载签名私钥证书。");
...@@ -158,7 +161,7 @@ public class CertUtil { ...@@ -158,7 +161,7 @@ public class CertUtil {
* @param path * @param path
* @return * @return
*/ */
public static X509Certificate readX509Cert(String path) { public X509Certificate readX509Cert(String path) {
X509Certificate cert = null; X509Certificate cert = null;
CertificateFactory cf = null; CertificateFactory cf = null;
FileInputStream in = null; FileInputStream in = null;
...@@ -183,10 +186,10 @@ public class CertUtil { ...@@ -183,10 +186,10 @@ public class CertUtil {
/** /**
* 用配置文件acp_sdk.properties中配置的私钥路径和密码 加载签名证书,会清空重新加载,一般仅第一次加载时调用即可 * 用配置文件acp_sdk.properties中配置的私钥路径和密码 加载签名证书,会清空重新加载,一般仅第一次加载时调用即可
*/ */
private static void initSignCert() { private void initSignCert() {
signCerts.clear(); signCerts.clear();
String path = SDKConfig.getConfig().getSignCertPath(); String path = sdkConfig.getSignCertPath();
String pwd = SDKConfig.getConfig().getSignCertPwd(); String pwd = sdkConfig.getSignCertPwd();
if(isEmpty(path) || isEmpty(pwd)) { if(isEmpty(path) || isEmpty(pwd)) {
log.warn(SDKConfig.SDK_SIGNCERT_PATH + " or " + SDKConfig.SDK_SIGNCERT_PWD + " is empty"); log.warn(SDKConfig.SDK_SIGNCERT_PATH + " or " + SDKConfig.SDK_SIGNCERT_PWD + " is empty");
return; return;
...@@ -198,8 +201,8 @@ public class CertUtil { ...@@ -198,8 +201,8 @@ public class CertUtil {
/** /**
* 用配置文件acp_sdk.properties配置路径 加载5.1验签证书中级证书 * 用配置文件acp_sdk.properties配置路径 加载5.1验签证书中级证书
*/ */
private static void initMiddleCert() { private void initMiddleCert() {
String path = SDKConfig.getConfig().getMiddleCertPath(); String path = sdkConfig.getMiddleCertPath();
if(isEmpty(path)){ if(isEmpty(path)){
log.warn(SDKConfig.SDK_MIDDLECERT_PATH + " is empty"); log.warn(SDKConfig.SDK_MIDDLECERT_PATH + " is empty");
return; return;
...@@ -211,8 +214,8 @@ public class CertUtil { ...@@ -211,8 +214,8 @@ public class CertUtil {
/** /**
* 用配置文件acp_sdk.properties配置路径 加载5.1验签证书根证书 * 用配置文件acp_sdk.properties配置路径 加载5.1验签证书根证书
*/ */
private static void initRootCert() { private void initRootCert() {
String path = SDKConfig.getConfig().getRootCertPath(); String path = sdkConfig.getRootCertPath();
if(isEmpty(path)){ if(isEmpty(path)){
log.warn(SDKConfig.SDK_ROOTCERT_PATH + " is empty"); log.warn(SDKConfig.SDK_ROOTCERT_PATH + " is empty");
return; return;
...@@ -220,14 +223,14 @@ public class CertUtil { ...@@ -220,14 +223,14 @@ public class CertUtil {
rootCert = readX509Cert(path); rootCert = readX509Cert(path);
log.info("加载根证书==>" + path + (rootCert != null ?"成功":"失败")); log.info("加载根证书==>" + path + (rootCert != null ?"成功":"失败"));
} }
/** /**
* 用配置文件acp_sdk.properties配置路径 加载磁道公钥 * 用配置文件acp_sdk.properties配置路径 加载磁道公钥
*/ */
private static void initTrackKey() { private void initTrackKey() {
String modulus = SDKConfig.getConfig().getEncryptTrackKeyModulus(); String modulus = sdkConfig.getEncryptTrackKeyModulus();
String exponent = SDKConfig.getConfig().getEncryptTrackKeyExponent(); String exponent = sdkConfig.getEncryptTrackKeyExponent();
if(isEmpty(modulus) || isEmpty(exponent)){ if(isEmpty(modulus) || isEmpty(exponent)){
log.warn(SDKConfig.SDK_ENCRYPTTRACKKEY_MODULUS + " or " + SDKConfig.SDK_ENCRYPTTRACKKEY_EXPONENT + " is empty"); log.warn(SDKConfig.SDK_ENCRYPTTRACKKEY_MODULUS + " or " + SDKConfig.SDK_ENCRYPTTRACKKEY_EXPONENT + " is empty");
return; return;
...@@ -239,11 +242,11 @@ public class CertUtil { ...@@ -239,11 +242,11 @@ public class CertUtil {
/** /**
* 用配置文件acp_sdk.properties配置路径 加载验签证书 * 用配置文件acp_sdk.properties配置路径 加载验签证书
*/ */
private static void initValidateCertFromDir() { private void initValidateCertFromDir() {
verifyCerts.clear(); verifyCerts.clear();
String dir = SDKConfig.getConfig().getValidateCertDir(); String dir = sdkConfig.getValidateCertDir();
if (isEmpty(dir)) { if (isEmpty(dir)) {
log.error("WARN: acpsdk.validateCert.dir is empty"); log.error("WARN: acpsdk.validateCert.dir is empty");
return; return;
...@@ -272,8 +275,8 @@ public class CertUtil { ...@@ -272,8 +275,8 @@ public class CertUtil {
/** /**
* 用配置文件acp_sdk.properties配置路径 加载敏感信息加密证书 * 用配置文件acp_sdk.properties配置路径 加载敏感信息加密证书
*/ */
private static void initEncryptCert() { private void initEncryptCert() {
String path = SDKConfig.getConfig().getEncryptCertPath(); String path = sdkConfig.getEncryptCertPath();
if(isEmpty(path)){ if(isEmpty(path)){
log.warn(SDKConfig.SDK_ENCRYPTCERT_PATH + " is empty"); log.warn(SDKConfig.SDK_ENCRYPTCERT_PATH + " is empty");
return; return;
...@@ -291,8 +294,8 @@ public class CertUtil { ...@@ -291,8 +294,8 @@ public class CertUtil {
/** /**
* 用配置文件acp_sdk.properties配置路径 加载6.0统一支付产品pin加密证书 * 用配置文件acp_sdk.properties配置路径 加载6.0统一支付产品pin加密证书
*/ */
private static void initPinEncryptCert() { private void initPinEncryptCert() {
String path = SDKConfig.getConfig().getPinEncryptCertPath(); String path = sdkConfig.getPinEncryptCertPath();
if(isEmpty(path)){ if(isEmpty(path)){
log.warn(SDKConfig.SDK_PINENCRYPTCERT_PATH + " is empty"); log.warn(SDKConfig.SDK_PINENCRYPTCERT_PATH + " is empty");
return; return;
...@@ -306,13 +309,13 @@ public class CertUtil { ...@@ -306,13 +309,13 @@ public class CertUtil {
CertUtil.pinEncryptCert = c; CertUtil.pinEncryptCert = c;
} }
} }
/** /**
* *
*/ */
private static Cert getSignCert() { private Cert getSignCert() {
String path = SDKConfig.getConfig().getSignCertPath(); String path = sdkConfig.getSignCertPath();
String pwd = SDKConfig.getConfig().getSignCertPwd(); String pwd = sdkConfig.getSignCertPwd();
if(isEmpty(path) || isEmpty(pwd)) { if(isEmpty(path) || isEmpty(pwd)) {
log.error("未配置默认签名证书时无法调用此方法。"); log.error("未配置默认签名证书时无法调用此方法。");
return null; return null;
...@@ -326,7 +329,7 @@ public class CertUtil { ...@@ -326,7 +329,7 @@ public class CertUtil {
* @param pwd * @param pwd
* @return * @return
*/ */
private static Cert getSignCert(String path, String pwd) { private Cert getSignCert(String path, String pwd) {
if(isEmpty(path) || isEmpty(pwd)) { if(isEmpty(path) || isEmpty(pwd)) {
log.error("传入的签名路径或密码为空。"); log.error("传入的签名路径或密码为空。");
return null; return null;
...@@ -344,10 +347,10 @@ public class CertUtil { ...@@ -344,10 +347,10 @@ public class CertUtil {
/** /**
* 获取敏感信息加密证书PublicKey * 获取敏感信息加密证书PublicKey
* *
* @return * @return
*/ */
protected static Cert getEncryptCert() { protected Cert getEncryptCert() {
if(CertUtil.encryptCert == null) { if(CertUtil.encryptCert == null) {
initEncryptCert(); initEncryptCert();
} }
...@@ -356,10 +359,10 @@ public class CertUtil { ...@@ -356,10 +359,10 @@ public class CertUtil {
/** /**
* 获取敏感信息加密证书PublicKey * 获取敏感信息加密证书PublicKey
* *
* @return * @return
*/ */
protected static Cert getPinEncryptCert() { protected Cert getPinEncryptCert() {
if(CertUtil.pinEncryptCert == null) { if(CertUtil.pinEncryptCert == null) {
initPinEncryptCert(); initPinEncryptCert();
} }
...@@ -369,21 +372,21 @@ public class CertUtil { ...@@ -369,21 +372,21 @@ public class CertUtil {
/** /**
* 重置敏感信息加密证书公钥。 * 重置敏感信息加密证书公钥。
*/ */
public static int resetEncryptCertPublicKey(String strCert) { public int resetEncryptCertPublicKey(String strCert) {
if (isEmpty(strCert)) { if (isEmpty(strCert)) {
log.error("传入证书信息为空。"); log.error("传入证书信息为空。");
return -1; return -1;
} }
X509Certificate x509Cert = CertUtil.genCertificateByStr(strCert); X509Certificate x509Cert = this.genCertificateByStr(strCert);
// 没换,不需要更新 // 没换,不需要更新
if (CertUtil.getEncryptCert().certId.equals( if (this.getEncryptCert().certId.equals(
x509Cert.getSerialNumber().toString(10))) { x509Cert.getSerialNumber().toString(10))) {
log.info("返回证书和原证书一样,不用更新。"); log.info("返回证书和原证书一样,不用更新。");
return 0; return 0;
} }
final String localCertPath = SDKConfig.getConfig().getEncryptCertPath(); final String localCertPath = sdkConfig.getEncryptCertPath();
if(isEmpty(localCertPath)){ if(isEmpty(localCertPath)){
log.error("未配置加密证书路径,无法执行此方法。"); log.error("未配置加密证书路径,无法执行此方法。");
return -1; return -1;
...@@ -420,21 +423,21 @@ public class CertUtil { ...@@ -420,21 +423,21 @@ public class CertUtil {
/** /**
* 重置pin敏感信息加密证书公钥。 * 重置pin敏感信息加密证书公钥。
*/ */
public static int resetPinEncryptCertPublicKey(String strCert) { public int resetPinEncryptCertPublicKey(String strCert) {
if (isEmpty(strCert)) { if (isEmpty(strCert)) {
log.error("传入证书信息为空。"); log.error("传入证书信息为空。");
return -1; return -1;
} }
X509Certificate x509Cert = CertUtil.genCertificateByStr(strCert); X509Certificate x509Cert = this.genCertificateByStr(strCert);
// 没换,不需要更新 // 没换,不需要更新
if (CertUtil.getPinEncryptCert().certId.equals( if (this.getPinEncryptCert().certId.equals(
x509Cert.getSerialNumber().toString(10))) { x509Cert.getSerialNumber().toString(10))) {
log.info("返回证书和原证书一样,不用更新。"); log.info("返回证书和原证书一样,不用更新。");
return 0; return 0;
} }
final String localCertPath = SDKConfig.getConfig().getPinEncryptCertPath(); final String localCertPath = sdkConfig.getPinEncryptCertPath();
if(isEmpty(localCertPath)){ if(isEmpty(localCertPath)){
log.error("未配置加密证书路径,无法执行此方法。"); log.error("未配置加密证书路径,无法执行此方法。");
return -1; return -1;
...@@ -467,26 +470,26 @@ public class CertUtil { ...@@ -467,26 +470,26 @@ public class CertUtil {
return -1; return -1;
} }
} }
/** /**
* 获取磁道加密证书PublicKey * 获取磁道加密证书PublicKey
* *
* @return * @return
*/ */
public static PublicKey getEncryptTrackPublicKey() { public PublicKey getEncryptTrackPublicKey() {
if (null == encryptTrackKey) { if (null == encryptTrackKey) {
initTrackKey(); initTrackKey();
} }
return encryptTrackKey; return encryptTrackKey;
} }
/** /**
* 通过certId获取验签证书Map中对应证书PublicKey * 通过certId获取验签证书Map中对应证书PublicKey
* *
* @param certId 证书物理序号 * @param certId 证书物理序号
* @return 通过证书编号获取到的公钥 * @return 通过证书编号获取到的公钥
*/ */
public static PublicKey getValidatePublicKey(String certId) { public PublicKey getValidatePublicKey(String certId) {
if(certId == null) { if(certId == null) {
log.error("没有传入certId."); log.error("没有传入certId.");
return null; return null;
...@@ -501,13 +504,13 @@ public class CertUtil { ...@@ -501,13 +504,13 @@ public class CertUtil {
} }
return result; return result;
} }
/** /**
* 获取配置文件acp_sdk.properties中配置的签名私钥证书certId * 获取配置文件acp_sdk.properties中配置的签名私钥证书certId
* *
* @return 证书的物理编号 * @return 证书的物理编号
*/ */
public static String getSignCertId() { public String getSignCertId() {
Cert c = getSignCert(); Cert c = getSignCert();
if(c == null) return null; if(c == null) return null;
return c.certId; return c.certId;
...@@ -518,7 +521,7 @@ public class CertUtil { ...@@ -518,7 +521,7 @@ public class CertUtil {
* *
* @return 证书的物理编号 * @return 证书的物理编号
*/ */
public static PrivateKey getSignCertPrivateKey() { public PrivateKey getSignCertPrivateKey() {
Cert c = getSignCert(); Cert c = getSignCert();
if(c == null) return null; if(c == null) return null;
return c.priKey; return c.priKey;
...@@ -530,7 +533,7 @@ public class CertUtil { ...@@ -530,7 +533,7 @@ public class CertUtil {
* @param pwd * @param pwd
* @return * @return
*/ */
public static String getCertIdByKeyStoreMap(String path, String pwd) { public String getCertIdByKeyStoreMap(String path, String pwd) {
Cert c = getSignCert(path, pwd); Cert c = getSignCert(path, pwd);
if(c == null) return null; if(c == null) return null;
return c.certId; return c.certId;
...@@ -541,7 +544,7 @@ public class CertUtil { ...@@ -541,7 +544,7 @@ public class CertUtil {
* @param pwd * @param pwd
* @return * @return
*/ */
public static PrivateKey getSignCertPrivateKeyByStoreMap(String path, String pwd) { public PrivateKey getSignCertPrivateKeyByStoreMap(String path, String pwd) {
Cert c = getSignCert(path, pwd); Cert c = getSignCert(path, pwd);
if(c == null) return null; if(c == null) return null;
return c.priKey; return c.priKey;
...@@ -552,14 +555,14 @@ public class CertUtil { ...@@ -552,14 +555,14 @@ public class CertUtil {
// * // *
// * @return // * @return
// */ // */
// public static String getEncryptCertId() { // public String getEncryptCertId() {
// Cert c = getEncryptCert(); // Cert c = getEncryptCert();
// if(c == null) return null; // if(c == null) return null;
// return c.certId; // return c.certId;
// } // }
// //
// //
// public static PublicKey getEncryptCertPublicKey(){ // public PublicKey getEncryptCertPublicKey(){
// Cert c = getEncryptCert(); // Cert c = getEncryptCert();
// if(c == null) return null; // if(c == null) return null;
// return c.pubKey; // return c.pubKey;
...@@ -570,22 +573,22 @@ public class CertUtil { ...@@ -570,22 +573,22 @@ public class CertUtil {
// * // *
// * @return // * @return
// */ // */
// public static String getPinEncryptCertId() { // public String getPinEncryptCertId() {
// Cert c = getPinEncryptCert(); // Cert c = getPinEncryptCert();
// if(c == null) return null; // if(c == null) return null;
// return c.certId; // return c.certId;
// } // }
// //
// //
// public static PublicKey getPinEncryptCertPublicKey(){ // public PublicKey getPinEncryptCertPublicKey(){
// Cert c = getEncryptCert(); // Cert c = getEncryptCert();
// if(c == null) return null; // if(c == null) return null;
// return c.pubKey; // return c.pubKey;
// } // }
/** /**
* 使用模和指数生成RSA公钥 注意:此代码用了默认补位方式,为RSA/None/PKCS1Padding,不同JDK默认的补位方式可能不同 * 使用模和指数生成RSA公钥 注意:此代码用了默认补位方式,为RSA/None/PKCS1Padding,不同JDK默认的补位方式可能不同
* *
* @param modulus * @param modulus
* 模 * 模
* @param exponent * @param exponent
...@@ -604,32 +607,32 @@ public class CertUtil { ...@@ -604,32 +607,32 @@ public class CertUtil {
return null; return null;
} }
} }
/** /**
* 将字符串转换为X509Certificate对象. * 将字符串转换为X509Certificate对象.
* *
* @param x509CertString * @param x509CertString
* @return * @return
*/ */
public static X509Certificate genCertificateByStr(String x509CertString) { public X509Certificate genCertificateByStr(String x509CertString) {
X509Certificate x509Cert = null; X509Certificate x509Cert = null;
try { try {
CertificateFactory cf = CertificateFactory.getInstance("X.509", "BC"); CertificateFactory cf = CertificateFactory.getInstance("X.509", "BC");
InputStream tIn = new ByteArrayInputStream( InputStream tIn = new ByteArrayInputStream(
x509CertString.getBytes("ISO-8859-1")); x509CertString.getBytes("ISO-8859-1"));
x509Cert = (X509Certificate) cf.generateCertificate(tIn); x509Cert = (X509Certificate) cf.generateCertificate(tIn);
} catch (Exception e) { } catch (Exception e) {
log.error("gen certificate error", e); log.error("gen certificate error", e);
} }
return x509Cert; return x509Cert;
} }
/** /**
* 从配置文件acp_sdk.properties中获取验签公钥使用的中级证书 * 从配置文件acp_sdk.properties中获取验签公钥使用的中级证书
* @return * @return
*/ */
private static X509Certificate getMiddleCert() { private X509Certificate getMiddleCert() {
String path = SDKConfig.getConfig().getMiddleCertPath(); String path = sdkConfig.getMiddleCertPath();
if (isEmpty(path)) { if (isEmpty(path)) {
log.error("未配置中级证书时无法调用此方法。"); log.error("未配置中级证书时无法调用此方法。");
return null; return null;
...@@ -644,8 +647,8 @@ public class CertUtil { ...@@ -644,8 +647,8 @@ public class CertUtil {
* 从配置文件acp_sdk.properties中获取验签公钥使用的根证书 * 从配置文件acp_sdk.properties中获取验签公钥使用的根证书
* @return * @return
*/ */
private static X509Certificate getRootCert() { private X509Certificate getRootCert() {
String path = SDKConfig.getConfig().getRootCertPath(); String path = sdkConfig.getRootCertPath();
if (isEmpty(path)) { if (isEmpty(path)) {
log.error("未配置根证书时无法调用此方法。"); log.error("未配置根证书时无法调用此方法。");
return null; return null;
...@@ -661,8 +664,8 @@ public class CertUtil { ...@@ -661,8 +664,8 @@ public class CertUtil {
* @param aCert * @param aCert
* @return * @return
*/ */
public static String getIdentitiesFromCertficate(X509Certificate aCert) { public String getIdentitiesFromCertficate(X509Certificate aCert) {
String tDN = aCert.getSubjectDN().toString(); String tDN = aCert.getSubjectDN().toString();
String tPart = ""; String tPart = "";
if ((tDN != null)) { if ((tDN != null)) {
String tSplitStr[] = tDN.substring(tDN.indexOf("CN=")).split("@"); String tSplitStr[] = tDN.substring(tDN.indexOf("CN=")).split("@");
...@@ -672,19 +675,19 @@ public class CertUtil { ...@@ -672,19 +675,19 @@ public class CertUtil {
} }
return tPart; return tPart;
} }
/** /**
* 验证书链。 * 验证书链。
* @param cert * @param cert
* @return * @return
*/ */
public static boolean verifyCertificateChain(X509Certificate cert, X509Certificate middleCert, X509Certificate rootCert){ public boolean verifyCertificateChain(X509Certificate cert, X509Certificate middleCert, X509Certificate rootCert){
if (null == cert) { if (null == cert) {
log.error("cert must Not null"); log.error("cert must Not null");
return false; return false;
} }
if (null == middleCert) { if (null == middleCert) {
log.error("middleCert must Not null"); log.error("middleCert must Not null");
return false; return false;
...@@ -694,30 +697,30 @@ public class CertUtil { ...@@ -694,30 +697,30 @@ public class CertUtil {
log.error("rootCert or cert must Not null"); log.error("rootCert or cert must Not null");
return false; return false;
} }
try { try {
X509CertSelector selector = new X509CertSelector(); X509CertSelector selector = new X509CertSelector();
selector.setCertificate(cert); selector.setCertificate(cert);
Set<TrustAnchor> trustAnchors = new HashSet<TrustAnchor>(); Set<TrustAnchor> trustAnchors = new HashSet<TrustAnchor>();
trustAnchors.add(new TrustAnchor(rootCert, null)); trustAnchors.add(new TrustAnchor(rootCert, null));
PKIXBuilderParameters pkixParams = new PKIXBuilderParameters( PKIXBuilderParameters pkixParams = new PKIXBuilderParameters(
trustAnchors, selector); trustAnchors, selector);
Set<X509Certificate> intermediateCerts = new HashSet<X509Certificate>(); Set<X509Certificate> intermediateCerts = new HashSet<X509Certificate>();
intermediateCerts.add(rootCert); intermediateCerts.add(rootCert);
intermediateCerts.add(middleCert); intermediateCerts.add(middleCert);
intermediateCerts.add(cert); intermediateCerts.add(cert);
pkixParams.setRevocationEnabled(false); pkixParams.setRevocationEnabled(false);
CertStore intermediateCertStore = CertStore.getInstance("Collection", CertStore intermediateCertStore = CertStore.getInstance("Collection",
new CollectionCertStoreParameters(intermediateCerts), "BC"); new CollectionCertStoreParameters(intermediateCerts), "BC");
pkixParams.addCertStore(intermediateCertStore); pkixParams.addCertStore(intermediateCertStore);
CertPathBuilder builder = CertPathBuilder.getInstance("PKIX", "BC"); CertPathBuilder builder = CertPathBuilder.getInstance("PKIX", "BC");
@SuppressWarnings("unused") @SuppressWarnings("unused")
PKIXCertPathBuilderResult result = (PKIXCertPathBuilderResult) builder PKIXCertPathBuilderResult result = (PKIXCertPathBuilderResult) builder
.build(pkixParams); .build(pkixParams);
...@@ -731,7 +734,7 @@ public class CertUtil { ...@@ -731,7 +734,7 @@ public class CertUtil {
return false; return false;
} }
public static PublicKey verifyAndGetVerifyPubKey(String x509CertString){ public PublicKey verifyAndGetVerifyPubKey(String x509CertString){
if(isEmpty(x509CertString)) { if(isEmpty(x509CertString)) {
log.error("验签公钥证书传了空。"); log.error("验签公钥证书传了空。");
...@@ -741,13 +744,13 @@ public class CertUtil { ...@@ -741,13 +744,13 @@ public class CertUtil {
return verifyCerts510.get(x509CertString); return verifyCerts510.get(x509CertString);
log.debug("验签公钥证书:["+x509CertString+"]"); log.debug("验签公钥证书:["+x509CertString+"]");
X509Certificate x509Cert = CertUtil.genCertificateByStr(x509CertString); X509Certificate x509Cert = this.genCertificateByStr(x509CertString);
if (x509Cert == null) { if (x509Cert == null) {
log.error("convert signPubKeyCert failed"); log.error("convert signPubKeyCert failed");
return null; return null;
} }
// 验证证书链 // 验证证书链
if (!CertUtil.verifyCertificate(x509Cert)) { if (!this.verifyCertificate(x509Cert)) {
log.error("验证公钥证书失败,证书信息:[" + x509CertString + "]"); log.error("验证公钥证书失败,证书信息:[" + x509CertString + "]");
return null; return null;
} }
...@@ -762,37 +765,37 @@ public class CertUtil { ...@@ -762,37 +765,37 @@ public class CertUtil {
* @param cert * @param cert
* @return * @return
*/ */
private static boolean verifyCertificate(X509Certificate cert) { private boolean verifyCertificate(X509Certificate cert) {
if ( null == cert) { if ( null == cert) {
log.error("cert must Not null"); log.error("cert must Not null");
return false; return false;
} }
try { try {
cert.checkValidity();//验证有效期 cert.checkValidity();//验证有效期
if(!verifyCertificateChain(cert, CertUtil.getMiddleCert(), CertUtil.getRootCert())){ if(!verifyCertificateChain(cert, this.getMiddleCert(), this.getRootCert())){
return false; return false;
} }
} catch (Exception e) { } catch (Exception e) {
log.error("verifyCertificate fail", e); log.error("verifyCertificate fail", e);
return false; return false;
} }
if(SDKConfig.getConfig().isIfValidateCNName()){ if(sdkConfig.isIfValidateCNName()){
// 验证公钥是否属于银联 // 验证公钥是否属于银联
if(!UNIONPAY_CNNAME.equals(CertUtil.getIdentitiesFromCertficate(cert))) { if(!UNIONPAY_CNNAME.equals(this.getIdentitiesFromCertficate(cert))) {
log.error("cer owner is not CUP:" + CertUtil.getIdentitiesFromCertficate(cert)); log.error("cer owner is not CUP:" + this.getIdentitiesFromCertficate(cert));
return false; return false;
} }
} else { } else {
// 验证公钥是否属于银联 // 验证公钥是否属于银联
if(!UNIONPAY_CNNAME.equals(CertUtil.getIdentitiesFromCertficate(cert)) if(!UNIONPAY_CNNAME.equals(this.getIdentitiesFromCertficate(cert))
&& !"00040000:SIGN".equals(CertUtil.getIdentitiesFromCertficate(cert))) { && !"00040000:SIGN".equals(this.getIdentitiesFromCertficate(cert))) {
log.error("cer owner is not CUP:" + CertUtil.getIdentitiesFromCertficate(cert)); log.error("cer owner is not CUP:" + this.getIdentitiesFromCertficate(cert));
return false; return false;
} }
} }
return true; return true;
} }
/** /**
...@@ -818,7 +821,7 @@ public class CertUtil { ...@@ -818,7 +821,7 @@ public class CertUtil {
printProviders(); printProviders();
log.info("================= SYS INFO end====================="); log.info("================= SYS INFO end=====================");
} }
/** /**
* 打jre中印算法提供者列表 * 打jre中印算法提供者列表
*/ */
...@@ -832,7 +835,7 @@ public class CertUtil { ...@@ -832,7 +835,7 @@ public class CertUtil {
/** /**
* 证书文件过滤器 * 证书文件过滤器
* *
*/ */
static class CerFilter implements FilenameFilter { static class CerFilter implements FilenameFilter {
public boolean isCer(String name) { public boolean isCer(String name) {
...@@ -843,7 +846,7 @@ public class CertUtil { ...@@ -843,7 +846,7 @@ public class CertUtil {
} }
} }
public static Collection<PublicKey> getVerifySignPubKeys(){ public Collection<PublicKey> getVerifySignPubKeys(){
return verifyCerts.values(); return verifyCerts.values();
} }
} }
...@@ -2,6 +2,8 @@ package com.liquidnet.service.dragon.channel.unionpay.sdk; ...@@ -2,6 +2,8 @@ package com.liquidnet.service.dragon.channel.unionpay.sdk;
import lombok.extern.slf4j.Slf4j; import lombok.extern.slf4j.Slf4j;
import org.apache.commons.codec.binary.Base64; import org.apache.commons.codec.binary.Base64;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;
import java.io.IOException; import java.io.IOException;
import java.nio.charset.Charset; import java.nio.charset.Charset;
...@@ -16,8 +18,13 @@ import static com.liquidnet.service.dragon.channel.unionpay.sdk.SDKConstants.*; ...@@ -16,8 +18,13 @@ import static com.liquidnet.service.dragon.channel.unionpay.sdk.SDKConstants.*;
* @date 2018-12-10 下午2:44:37 * @date 2018-12-10 下午2:44:37
*/ */
@Slf4j @Slf4j
@Component
public class QrcService { public class QrcService {
@Autowired
private SDKConfig sdkConfig;
@Autowired
private CertUtil certUtil;
/** /**
* 请求报文签名(使用配置文件中配置的私钥证书或者对称密钥签名)<br> * 请求报文签名(使用配置文件中配置的私钥证书或者对称密钥签名)<br>
* 功能:对请求报文进行签名,并计算赋值certid,signature字段并返回<br> * 功能:对请求报文进行签名,并计算赋值certid,signature字段并返回<br>
...@@ -25,10 +32,10 @@ public class QrcService { ...@@ -25,10 +32,10 @@ public class QrcService {
* @param encoding 上送请求报文域encoding字段的值<br> * @param encoding 上送请求报文域encoding字段的值<br>
* @return 签名后的map对象<br> * @return 签名后的map对象<br>
*/ */
public static Map<String, String> sign(Map<String, String> reqData,String encoding) { public Map<String, String> sign(Map<String, String> reqData,String encoding) {
return signByCertInfo(reqData, SDKConfig.getConfig().getSignCertPath(), SDKConfig.getConfig().getSignCertPwd(), encoding); return signByCertInfo(reqData, sdkConfig.getSignCertPath(), sdkConfig.getSignCertPwd(), encoding);
} }
/** /**
* 多证书签名(通过传入私钥证书路径和密码签名)<br> * 多证书签名(通过传入私钥证书路径和密码签名)<br>
* 功能:如果有多个商户号接入银联,每个商户号对应不同的证书可以使用此方法:传入私钥证书和密码(并且在acp_sdk.properties中 配置 acpsdk.singleMode=false)<br> * 功能:如果有多个商户号接入银联,每个商户号对应不同的证书可以使用此方法:传入私钥证书和密码(并且在acp_sdk.properties中 配置 acpsdk.singleMode=false)<br>
...@@ -38,7 +45,7 @@ public class QrcService { ...@@ -38,7 +45,7 @@ public class QrcService {
* @param encoding 上送请求报文域encoding字段的值<br> * @param encoding 上送请求报文域encoding字段的值<br>
* @return 签名后的map对象<br> * @return 签名后的map对象<br>
*/ */
public static Map<String, String> signByCertInfo(Map<String, String> reqData, String certPath, public Map<String, String> signByCertInfo(Map<String, String> reqData, String certPath,
String certPwd, String encoding) { String certPwd, String encoding) {
Map<String, String> data = SDKUtil.filterBlank(reqData); Map<String, String> data = SDKUtil.filterBlank(reqData);
...@@ -62,14 +69,14 @@ public class QrcService { ...@@ -62,14 +69,14 @@ public class QrcService {
try { try {
if (VERSION_1_0_0.equals(version)) { if (VERSION_1_0_0.equals(version)) {
//被扫脱机码两个接口无视配置固定按sha256withrsa处理。下面两个ifelse别改变顺序。 //被扫脱机码两个接口无视配置固定按sha256withrsa处理。下面两个ifelse别改变顺序。
if (QRC_SIGNTYPE_SHA256WITHRSA.equals(signType) if (QRC_SIGNTYPE_SHA256WITHRSA.equals(signType)
|| "0420000903".equals(reqType) || "0420000903".equals(reqType)
|| "0410000903".equals(reqType)) { || "0410000903".equals(reqType)) {
data.put(SDKConstants.param_certId, CertUtil.getCertIdByKeyStoreMap(certPath, certPwd)); data.put(SDKConstants.param_certId, certUtil.getCertIdByKeyStoreMap(certPath, certPwd));
data.put(SDKConstants.param_signature, SDKUtil.signRsa2(data, certPath, certPwd, encoding)); data.put(SDKConstants.param_signature, SDKUtil.signRsa2(data, certPath, certPwd, encoding));
return data; return data;
} else if (QRC_SIGNTYPE_SHA1WITHRSA.equals(signType)) { } else if (QRC_SIGNTYPE_SHA1WITHRSA.equals(signType)) {
data.put(SDKConstants.param_certId, CertUtil.getCertIdByKeyStoreMap(certPath, certPwd)); data.put(SDKConstants.param_certId, certUtil.getCertIdByKeyStoreMap(certPath, certPwd));
data.put(SDKConstants.param_signature, SDKUtil.signRsa(data, certPath, certPwd, encoding)); data.put(SDKConstants.param_signature, SDKUtil.signRsa(data, certPath, certPwd, encoding));
return data; return data;
} else if (QRC_SIGNTYPE_SM3WITHSM2.equals(signType)) { } else if (QRC_SIGNTYPE_SM3WITHSM2.equals(signType)) {
...@@ -91,14 +98,14 @@ public class QrcService { ...@@ -91,14 +98,14 @@ public class QrcService {
* @param encoding 上送请求报文域encoding字段的值<br> * @param encoding 上送请求报文域encoding字段的值<br>
* @return true 通过 false 未通过<br> * @return true 通过 false 未通过<br>
*/ */
public static boolean validate(Map<String, String> resData, String encoding) { public boolean validate(Map<String, String> resData, String encoding) {
log.info("验签处理开始"); log.info("验签处理开始");
if (SDKUtil.isEmpty(encoding)) { if (SDKUtil.isEmpty(encoding)) {
encoding = "UTF-8"; encoding = "UTF-8";
} }
String certId = resData.get(SDKConstants.param_certId); String certId = resData.get(SDKConstants.param_certId);
log.info("对返回报文串验签使用的验签公钥序列号:[" + certId + "]"); log.info("对返回报文串验签使用的验签公钥序列号:[" + certId + "]");
PublicKey verifyKey = CertUtil.getValidatePublicKey(certId); PublicKey verifyKey = certUtil.getValidatePublicKey(certId);
if(verifyKey == null) { if(verifyKey == null) {
log.error("未找到此序列号证书。"); log.error("未找到此序列号证书。");
return false; return false;
...@@ -110,13 +117,13 @@ public class QrcService { ...@@ -110,13 +117,13 @@ public class QrcService {
if (SDKUtil.isEmpty(signType)) { if (SDKUtil.isEmpty(signType)) {
signType = QRC_SIGNTYPE_SHA1WITHRSA; signType = QRC_SIGNTYPE_SHA1WITHRSA;
} }
try { try {
if (VERSION_1_0_0.equals(version)) { if (VERSION_1_0_0.equals(version)) {
//被扫脱机码两个接口无视配置固定按sha256withrsa处理。下面两个ifelse别改变顺序。 //被扫脱机码两个接口无视配置固定按sha256withrsa处理。下面两个ifelse别改变顺序。
if (QRC_SIGNTYPE_SHA256WITHRSA.equals(signType) if (QRC_SIGNTYPE_SHA256WITHRSA.equals(signType)
|| "0420000903".equals(reqType) || "0420000903".equals(reqType)
|| "0410000903".equals(reqType)) { || "0410000903".equals(reqType)) {
boolean result = SDKUtil.verifyRsa2(resData, verifyKey, encoding); boolean result = SDKUtil.verifyRsa2(resData, verifyKey, encoding);
log.info("验签" + (result? "成功":"失败") + "。"); log.info("验签" + (result? "成功":"失败") + "。");
return result; return result;
...@@ -147,7 +154,7 @@ public class QrcService { ...@@ -147,7 +154,7 @@ public class QrcService {
public static String encryptPin(String accNo, String pin, String encoding) { public static String encryptPin(String accNo, String pin, String encoding) {
return AcpService.encryptPin(accNo, pin, encoding); return AcpService.encryptPin(accNo, pin, encoding);
} }
/** /**
* 敏感信息加密并做base64(卡号,手机号,cvn2,有效期)<br> * 敏感信息加密并做base64(卡号,手机号,cvn2,有效期)<br>
* @param data 送 phoneNo,cvn2,有效期<br> * @param data 送 phoneNo,cvn2,有效期<br>
...@@ -157,7 +164,7 @@ public class QrcService { ...@@ -157,7 +164,7 @@ public class QrcService {
public static String encryptData(String data, String encoding) { public static String encryptData(String data, String encoding) {
return AcpService.encryptData(data, encoding); return AcpService.encryptData(data, encoding);
} }
/** /**
* 敏感信息解密,使用配置文件acp_sdk.properties解密<br> * 敏感信息解密,使用配置文件acp_sdk.properties解密<br>
* @param base64EncryptedInfo 加密信息<br> * @param base64EncryptedInfo 加密信息<br>
...@@ -176,19 +183,19 @@ public class QrcService { ...@@ -176,19 +183,19 @@ public class QrcService {
* @param encoding<br> * @param encoding<br>
* @return * @return
*/ */
public static String decryptData(String base64EncryptedInfo, String certPath, public static String decryptData(String base64EncryptedInfo, String certPath,
String certPwd, String encoding) { String certPwd, String encoding) {
return AcpService.decryptData(base64EncryptedInfo, certPath, certPwd, encoding); return AcpService.decryptData(base64EncryptedInfo, certPath, certPwd, encoding);
} }
/** /**
* 获取敏感信息加密证书的物理序列号<br> * 获取敏感信息加密证书的物理序列号<br>
* @return * @return
*/ */
public static String getEncryptCertId(){ public String getEncryptCertId(){
return CertUtil.getEncryptCert().certId; return certUtil.getEncryptCert().certId;
} }
/** /**
* 功能:后台交易提交请求报文并接收同步应答报文<br> * 功能:后台交易提交请求报文并接收同步应答报文<br>
* @param reqData 请求报文<br> * @param reqData 请求报文<br>
...@@ -199,7 +206,7 @@ public class QrcService { ...@@ -199,7 +206,7 @@ public class QrcService {
public static Map<String,String> post(Map<String, String> reqData, String reqUrl,String encoding) { public static Map<String,String> post(Map<String, String> reqData, String reqUrl,String encoding) {
return AcpService.post(reqData, reqUrl, encoding); return AcpService.post(reqData, reqUrl, encoding);
} }
/** /**
* base64({a=b&c=d}) * base64({a=b&c=d})
* @param map * @param map
...@@ -213,7 +220,7 @@ public class QrcService { ...@@ -213,7 +220,7 @@ public class QrcService {
.append(SDKConstants.RIGHT_BRACE).toString(); .append(SDKConstants.RIGHT_BRACE).toString();
return Base64.encodeBase64String(info.getBytes(Charset.forName(encoding))); return Base64.encodeBase64String(info.getBytes(Charset.forName(encoding)));
} }
/** /**
* base64(rsa({a=b&c=d})) * base64(rsa({a=b&c=d}))
* @param map * @param map
...@@ -240,7 +247,7 @@ public class QrcService { ...@@ -240,7 +247,7 @@ public class QrcService {
data = data.substring(1, data.length() - 1); data = data.substring(1, data.length() - 1);
return SDKUtil.parseRespString(data); return SDKUtil.parseRespString(data);
} }
/** /**
* base64(rsa({a=b&c=d})) * base64(rsa({a=b&c=d}))
* 解析返回报文的payerInfo域,敏感信息加密时使用:<br> * 解析返回报文的payerInfo域,敏感信息加密时使用:<br>
...@@ -253,7 +260,7 @@ public class QrcService { ...@@ -253,7 +260,7 @@ public class QrcService {
data = data.substring(1, data.length() - 1); data = data.substring(1, data.length() - 1);
return SDKUtil.parseRespString(data); return SDKUtil.parseRespString(data);
} }
/** /**
* base64(rsa({a=b&c=d})) * base64(rsa({a=b&c=d}))
* 解析返回报文中的payerInfo域,敏感信息加密时使用,多证书方式。<br> * 解析返回报文中的payerInfo域,敏感信息加密时使用,多证书方式。<br>
...@@ -261,7 +268,7 @@ public class QrcService { ...@@ -261,7 +268,7 @@ public class QrcService {
* @param encoding<br> * @param encoding<br>
* @return * @return
*/ */
public static Map<String, String> parseKVEncBase64Field(String base64data, String certPath, public static Map<String, String> parseKVEncBase64Field(String base64data, String certPath,
String certPwd, String encoding){ String certPwd, String encoding){
String data = QrcService.decryptData(base64data, certPath, certPwd, encoding); String data = QrcService.decryptData(base64data, certPath, certPwd, encoding);
data = data.substring(1, data.length() - 1); data = data.substring(1, data.length() - 1);
...@@ -290,10 +297,10 @@ public class QrcService { ...@@ -290,10 +297,10 @@ public class QrcService {
public static String base64Decode(String base64Str, String encoding){ public static String base64Decode(String base64Str, String encoding){
return AcpService.base64Decode(base64Str, encoding); return AcpService.base64Decode(base64Str, encoding);
} }
/** /**
* luhn算法 * luhn算法
* *
* @param number * @param number
* @return * @return
*/ */
......
...@@ -15,7 +15,11 @@ ...@@ -15,7 +15,11 @@
*/ */
package com.liquidnet.service.dragon.channel.unionpay.sdk; package com.liquidnet.service.dragon.channel.unionpay.sdk;
import lombok.Data;
import lombok.extern.slf4j.Slf4j; import lombok.extern.slf4j.Slf4j;
import org.springframework.boot.autoconfigure.AutoConfigureOrder;
import org.springframework.boot.context.properties.ConfigurationProperties;
import org.springframework.stereotype.Component;
import java.io.*; import java.io.*;
import java.util.Properties; import java.util.Properties;
...@@ -27,13 +31,14 @@ import java.util.Properties; ...@@ -27,13 +31,14 @@ import java.util.Properties;
* @date 2016-7-22 下午4:04:55 * @date 2016-7-22 下午4:04:55
*/ */
@Slf4j @Slf4j
@Component
@ConfigurationProperties(prefix = "acpsdk")
@Data
public class SDKConfig { public class SDKConfig {
public static final String FILE_NAME = "acp_sdk.properties";
/** 前台请求URL. */ /** 前台请求URL. */
private String frontRequestUrl; private String frontTransUrl;
/** 后台请求URL. */ /** 后台请求URL. */
private String backRequestUrl; private String backTransUrl;
/** 二维码统一下单请求URL. */ /** 二维码统一下单请求URL. */
private String orderRequestUrl; private String orderRequestUrl;
/** 单笔查询 */ /** 单笔查询 */
...@@ -219,536 +224,4 @@ public class SDKConfig { ...@@ -219,536 +224,4 @@ public class SDKConfig {
public static final String SDK_FRONTURL = "acpsdk.frontUrl"; public static final String SDK_FRONTURL = "acpsdk.frontUrl";
/** 前台失败通知地址 */ /** 前台失败通知地址 */
public static final String SDK_FRONT_FAIL_URL = "acpsdk.frontFailUrl"; public static final String SDK_FRONT_FAIL_URL = "acpsdk.frontFailUrl";
/** 操作对象. */
private static SDKConfig config = null;
/** 属性文件对象. */
protected Properties properties;
protected SDKConfig() {
super();
}
/**
* 获取config对象.
* @return
*/
public static SDKConfig getConfig() {
if(config == null) {
log.warn("未主动调用loadPropertiesFromSrc或loadPropertiesFromPath方法,默认调loadPropertiesFromSrc初始化");
SDKConfig.loadPropertiesFromSrc();
}
if(config == null) {
log.error("初始化失败");
config = new SDKConfig();
}
return config;
}
/**
* 从properties文件加载
*
* @param rootPath
* 不包含文件名的目录.
*/
public static void loadPropertiesFromPath(String rootPath) {
Properties properties = getPropertiesFromPath(rootPath);
loadProperties(properties);
}
protected static Properties getPropertiesFromSrc() {
InputStream in = null;
try {
log.info("从classpath: " +SDKConfig.class.getClassLoader().getResource("").getPath()+" 获取属性文件"+FILE_NAME);
in = SDKConfig.class.getClassLoader().getResourceAsStream(FILE_NAME);
if (in == null) {
log.error(FILE_NAME + "属性文件未能在classpath指定的目录下 "+SDKConfig.class.getClassLoader().getResource("").getPath()+" 找到!");
return null;
}
Properties properties = new Properties();
properties.load(in);
return properties;
} catch (IOException e) {
log.error(e.getMessage(), e);
} finally {
if (in != null) {
try {
in.close();
} catch (IOException e) {
}
}
}
return null;
}
protected static Properties getPropertiesFromPath(String rootPath) {
if (rootPath == null || "".equals(rootPath.trim())) {
log.error("rootPath为空");
return null;
}
String path = rootPath + File.separator + FILE_NAME;
log.info("从路径读取配置文件: " + path);
File file = new File(path);
InputStream in = null;
if (!file.exists()) {
log.error(rootPath + "不存在" + FILE_NAME);
return null;
}
try {
in = new FileInputStream(file);
Properties properties = new Properties();
properties.load(in);
return properties;
} catch (FileNotFoundException e) {
log.error(e.getMessage(), e);
} catch (IOException e) {
log.error(e.getMessage(), e);
} finally {
if (in != null) {
try {
in.close();
} catch (IOException e) {
}
}
}
return null;
}
/**
* 从classpath路径下加载配置参数
*/
public static void loadPropertiesFromSrc() {
Properties properties = getPropertiesFromSrc();
loadProperties(properties);
}
/**
* 根据传入的 {@link Properties}对象设置配置参数
*
* @param pro
*/
public static void loadProperties(Properties pro) {
config = new SDKConfig();
config.loadProperties1(pro);
}
/**
* 根据传入的 {@link Properties}对象设置配置参数
*
* @param pro
*/
protected void loadProperties1(Properties pro) {
if(pro == null) {
log.error("loadProperties input is null");
return;
}
if(this.properties == null) {
this.properties = pro;
}
log.info("开始从属性文件中加载配置项");
String value = null;
value = pro.getProperty(SDK_SIGNCERT_PATH);
if (!SDKUtil.isEmpty(value)) {
this.signCertPath = value.trim();
log.info("配置项:私钥签名证书路径==>"+SDK_SIGNCERT_PATH +"==>"+ value+" 已加载");
}
value = pro.getProperty(SDK_SIGNCERT_PWD);
if (!SDKUtil.isEmpty(value)) {
this.signCertPwd = value.trim();
log.info("配置项:私钥签名证书密码==>"+SDK_SIGNCERT_PWD +" 已加载");
}
value = pro.getProperty(SDK_SIGNCERT_TYPE);
if (!SDKUtil.isEmpty(value)) {
this.signCertType = value.trim();
log.info("配置项:私钥签名证书类型==>"+SDK_SIGNCERT_TYPE +"==>"+ value+" 已加载");
}
value = pro.getProperty(SDK_ENCRYPTCERT_PATH);
if (!SDKUtil.isEmpty(value)) {
this.encryptCertPath = value.trim();
log.info("配置项:敏感信息加密证书==>"+SDK_ENCRYPTCERT_PATH +"==>"+ value+" 已加载");
}
value = pro.getProperty(SDK_VALIDATECERT_DIR);
if (!SDKUtil.isEmpty(value)) {
this.validateCertDir = value.trim();
log.info("配置项:验证签名证书路径(这里配置的是目录,不要指定到公钥文件)==>"+SDK_VALIDATECERT_DIR +"==>"+ value+" 已加载");
}
value = pro.getProperty(SDK_PINENCRYPTCERT_PATH);
if (!SDKUtil.isEmpty(value)) {
this.pinEncryptCertPath = value.trim();
log.info("配置项:6.0.0统一支付产品加密pin证书路径(这里配置的是目录,不要指定到公钥文件)==>"+SDK_PINENCRYPTCERT_PATH +"==>"+ value+" 已加载");
}
value = pro.getProperty(SDK_FRONT_URL);
if (!SDKUtil.isEmpty(value)) {
this.frontRequestUrl = value.trim();
}
value = pro.getProperty(SDK_BACK_URL);
if (!SDKUtil.isEmpty(value)) {
this.backRequestUrl = value.trim();
}
value = pro.getProperty(SDK_ORDER_URL);
if (!SDKUtil.isEmpty(value)) {
this.orderRequestUrl = value.trim();
}
value = pro.getProperty(SDK_BATQ_URL);
if (!SDKUtil.isEmpty(value)) {
this.batchQueryUrl = value.trim();
}
value = pro.getProperty(SDK_BATTRANS_URL);
if (!SDKUtil.isEmpty(value)) {
this.batchTransUrl = value.trim();
}
value = pro.getProperty(SDK_FILETRANS_URL);
if (!SDKUtil.isEmpty(value)) {
this.fileTransUrl = value.trim();
}
value = pro.getProperty(SDK_SIGNQ_URL);
if (!SDKUtil.isEmpty(value)) {
this.singleQueryUrl = value.trim();
}
value = pro.getProperty(SDK_CARD_URL);
if (!SDKUtil.isEmpty(value)) {
this.cardRequestUrl = value.trim();
}
value = pro.getProperty(SDK_APP_URL);
if (!SDKUtil.isEmpty(value)) {
this.appRequestUrl = value.trim();
}
// value = pro.getProperty(SDK_ENCRYPTTRACKCERT_PATH);
// if (!SDKUtil.isEmpty(value)) {
// this.encryptTrackCertPath = value.trim();
// }
value = pro.getProperty(SDK_SECURITYKEY);
if (!SDKUtil.isEmpty(value)) {
this.secureKey = value.trim();
}
value = pro.getProperty(SDK_ROOTCERT_PATH);
if (!SDKUtil.isEmpty(value)) {
this.rootCertPath = value.trim();
}
value = pro.getProperty(SDK_MIDDLECERT_PATH);
if (!SDKUtil.isEmpty(value)) {
this.middleCertPath = value.trim();
}
/**缴费部分**/
value = pro.getProperty(JF_SDK_FRONT_TRANS_URL);
if (!SDKUtil.isEmpty(value)) {
this.jfFrontRequestUrl = value.trim();
}
value = pro.getProperty(JF_SDK_BACK_TRANS_URL);
if (!SDKUtil.isEmpty(value)) {
this.jfBackRequestUrl = value.trim();
}
value = pro.getProperty(JF_SDK_SINGLE_QUERY_URL);
if (!SDKUtil.isEmpty(value)) {
this.jfSingleQueryUrl = value.trim();
}
value = pro.getProperty(JF_SDK_CARD_TRANS_URL);
if (!SDKUtil.isEmpty(value)) {
this.jfCardRequestUrl = value.trim();
}
value = pro.getProperty(JF_SDK_APP_TRANS_URL);
if (!SDKUtil.isEmpty(value)) {
this.jfAppRequestUrl = value.trim();
}
value = pro.getProperty(QRC_BACK_TRANS_URL);
if (!SDKUtil.isEmpty(value)) {
this.qrcBackTransUrl = value.trim();
}
value = pro.getProperty(QRC_B2C_ISS_BACK_TRANS_URL);
if (!SDKUtil.isEmpty(value)) {
this.qrcB2cIssBackTransUrl = value.trim();
}
value = pro.getProperty(QRC_B2C_MER_BACK_TRANS_URL);
if (!SDKUtil.isEmpty(value)) {
this.qrcB2cMerBackTransUrl = value.trim();
}
value = pro.getProperty(QRC_B2C_MER_BACK_SYN_TRANS_URL);
if (!SDKUtil.isEmpty(value)) {
this.qrcB2cMerBackSynTransUrl = value.trim();
}
/**综合认证**/
value = pro.getProperty(ZHRZ_SDK_FRONT_TRANS_URL);
if (!SDKUtil.isEmpty(value)) {
this.zhrzFrontRequestUrl = value.trim();
}
value = pro.getProperty(ZHRZ_SDK_BACK_TRANS_URL);
if (!SDKUtil.isEmpty(value)) {
this.zhrzBackRequestUrl = value.trim();
}
value = pro.getProperty(ZHRZ_SDK_SINGLE_QUERY_URL);
if (!SDKUtil.isEmpty(value)) {
this.zhrzSingleQueryUrl = value.trim();
}
value = pro.getProperty(ZHRZ_SDK_CARD_TRANS_URL);
if (!SDKUtil.isEmpty(value)) {
this.zhrzCardRequestUrl = value.trim();
}
value = pro.getProperty(ZHRZ_SDK_APP_TRANS_URL);
if (!SDKUtil.isEmpty(value)) {
this.zhrzAppRequestUrl = value.trim();
}
value = pro.getProperty(ZHRZ_SDK_FACE_TRANS_URL);
if (!SDKUtil.isEmpty(value)) {
this.zhrzFaceRequestUrl = value.trim();
}
value = pro.getProperty(TRANS_URL);
if (!SDKUtil.isEmpty(value)) {
this.transUrl = value.trim();
}
value = pro.getProperty(SDK_ENCRYPTTRACKKEY_EXPONENT);
if (!SDKUtil.isEmpty(value)) {
this.encryptTrackKeyExponent = value.trim();
}
value = pro.getProperty(SDK_ENCRYPTTRACKKEY_MODULUS);
if (!SDKUtil.isEmpty(value)) {
this.encryptTrackKeyModulus = value.trim();
}
value = pro.getProperty(SDK_IF_VALIDATE_CN_NAME);
if (!SDKUtil.isEmpty(value)) {
if( SDKConstants.FALSE_STRING.equals(value.trim()))
this.ifValidateCNName = false;
}
value = pro.getProperty(SDK_IF_VALIDATE_REMOTE_CERT);
if (!SDKUtil.isEmpty(value)) {
if( SDKConstants.TRUE_STRING.equals(value.trim()))
this.ifValidateRemoteCert = true;
}
value = pro.getProperty(SDK_SIGN_METHOD);
if (!SDKUtil.isEmpty(value)) {
this.signMethod = value.trim();
}
value = pro.getProperty(SDK_SIGN_METHOD);
if (!SDKUtil.isEmpty(value)) {
this.signMethod = value.trim();
}
value = pro.getProperty(SDK_VERSION);
if (!SDKUtil.isEmpty(value)) {
this.version = value.trim();
}
value = pro.getProperty(SDK_FRONTURL);
if (!SDKUtil.isEmpty(value)) {
this.frontUrl = value.trim();
}
value = pro.getProperty(SDK_BACKURL);
if (!SDKUtil.isEmpty(value)) {
this.backUrl = value.trim();
}
value = pro.getProperty(SDK_FRONT_FAIL_URL);
if (!SDKUtil.isEmpty(value)) {
this.frontFailUrl = value.trim();
}
}
public String getFrontRequestUrl() {
return frontRequestUrl;
}
public String getBackRequestUrl() {
return backRequestUrl;
}
public String getOrderRequestUrl() {
return orderRequestUrl;
}
public String getSignCertPath() {
return signCertPath;
}
public String getSignCertPwd() {
return signCertPwd;
}
public String getSignCertType() {
return signCertType;
}
public String getEncryptCertPath() {
return encryptCertPath;
}
public String getValidateCertDir() {
return validateCertDir;
}
public String getSingleQueryUrl() {
return singleQueryUrl;
}
public String getBatchQueryUrl() {
return batchQueryUrl;
}
public String getBatchTransUrl() {
return batchTransUrl;
}
public String getFileTransUrl() {
return fileTransUrl;
}
public String getSignCertDir() {
return signCertDir;
}
public Properties getProperties() {
return properties;
}
public String getCardRequestUrl() {
return cardRequestUrl;
}
public String getAppRequestUrl() {
return appRequestUrl;
}
// public String getEncryptTrackCertPath() {
// return encryptTrackCertPath;
// }
public String getPinEncryptCertPath() {
return pinEncryptCertPath;
}
public String getJfFrontRequestUrl() {
return jfFrontRequestUrl;
}
public String getJfBackRequestUrl() {
return jfBackRequestUrl;
}
public String getJfSingleQueryUrl() {
return jfSingleQueryUrl;
}
public String getJfCardRequestUrl() {
return jfCardRequestUrl;
}
public String getJfAppRequestUrl() {
return jfAppRequestUrl;
}
public String getSingleMode() {
return singleMode;
}
public String getEncryptTrackKeyExponent() {
return encryptTrackKeyExponent;
}
public String getEncryptTrackKeyModulus() {
return encryptTrackKeyModulus;
}
public String getSecureKey() {
return secureKey;
}
public String getMiddleCertPath() {
return middleCertPath;
}
public boolean isIfValidateCNName() {
return ifValidateCNName;
}
public boolean isIfValidateRemoteCert() {
return ifValidateRemoteCert;
}
public String getSignMethod() {
return signMethod;
}
public String getQrcBackTransUrl() {
return qrcBackTransUrl;
}
public String getQrcB2cIssBackTransUrl() {
return qrcB2cIssBackTransUrl;
}
public String getQrcB2cMerBackTransUrl() {
return qrcB2cMerBackTransUrl;
}
public String getQrcB2cMerBackSynTransUrl() {
return qrcB2cMerBackSynTransUrl;
}
public String getZhrzFrontRequestUrl() {
return zhrzFrontRequestUrl;
}
public String getZhrzBackRequestUrl() {
return zhrzBackRequestUrl;
}
public String getZhrzSingleQueryUrl() {
return zhrzSingleQueryUrl;
}
public String getZhrzCardRequestUrl() {
return zhrzCardRequestUrl;
}
public String getZhrzAppRequestUrl() {
return zhrzAppRequestUrl;
}
public String getZhrzFaceRequestUrl() {
return zhrzFaceRequestUrl;
}
public String getVersion() {
return version;
}
public String getFrontUrl() {
return frontUrl;
}
public String getBackUrl() {
return backUrl;
}
public String getFrontFailUrl() {
return frontFailUrl;
}
public String getRootCertPath() {
return rootCertPath;
}
public String getTransUrl() {
return transUrl;
}
} }
/** /**
* *
* Licensed Property to China UnionPay Co., Ltd. * Licensed Property to China UnionPay Co., Ltd.
* *
* (C) Copyright of China UnionPay Co., Ltd. 2010 * (C) Copyright of China UnionPay Co., Ltd. 2010
* All Rights Reserved. * All Rights Reserved.
* *
* *
* Modification History: * Modification History:
* ============================================================================= * =============================================================================
* Author Date Description * Author Date Description
...@@ -19,6 +19,8 @@ import lombok.extern.slf4j.Slf4j; ...@@ -19,6 +19,8 @@ import lombok.extern.slf4j.Slf4j;
import org.apache.commons.codec.DecoderException; import org.apache.commons.codec.DecoderException;
import org.apache.commons.codec.binary.Base64; import org.apache.commons.codec.binary.Base64;
import org.apache.commons.codec.binary.Hex; import org.apache.commons.codec.binary.Hex;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;
import java.io.ByteArrayOutputStream; import java.io.ByteArrayOutputStream;
import java.io.IOException; import java.io.IOException;
...@@ -33,14 +35,16 @@ import java.util.zip.Inflater; ...@@ -33,14 +35,16 @@ import java.util.zip.Inflater;
import static com.liquidnet.service.dragon.channel.unionpay.sdk.SDKConstants.*; import static com.liquidnet.service.dragon.channel.unionpay.sdk.SDKConstants.*;
/** /**
* *
* @ClassName SDKUtil * @ClassName SDKUtil
* @Description acpsdk工具类 * @Description acpsdk工具类
* @date 2016-7-22 下午4:06:18 * @date 2016-7-22 下午4:06:18
*/ */
@Slf4j @Slf4j
@Component
public class SDKUtil { public class SDKUtil {
@Autowired
private CertUtil certUtil;
/** /**
* 全渠道5.0、二维码signType=01用。 * 全渠道5.0、二维码signType=01用。
* 1. 按ascii排序。【注意不是字母顺序】 * 1. 按ascii排序。【注意不是字母顺序】
...@@ -55,14 +59,14 @@ public class SDKUtil { ...@@ -55,14 +59,14 @@ public class SDKUtil {
* @param encoding * @param encoding
* @return * @return
*/ */
public static String signRsa(Map<String, String> data, String certPath, String certPwd, String encoding) { public String signRsa(Map<String, String> data, String certPath, String certPwd, String encoding) {
try{ try{
String stringData = createLinkString(data, true, false, encoding); String stringData = createLinkString(data, true, false, encoding);
log.info("打印排序后待签名请求报文串(交易返回11验证签名失败时可以用来同正确的进行比对):[" + stringData + "]"); log.info("打印排序后待签名请求报文串(交易返回11验证签名失败时可以用来同正确的进行比对):[" + stringData + "]");
byte[] sha1 = SecureUtil.sha1(stringData.getBytes(encoding)); byte[] sha1 = SecureUtil.sha1(stringData.getBytes(encoding));
String sha1Hex = byteArrayToHexString(sha1).toLowerCase(); String sha1Hex = byteArrayToHexString(sha1).toLowerCase();
log.info("sha1结果(交易返回11验证签名失败可以用来同正确的进行比对):[" + sha1Hex + "]"); log.info("sha1结果(交易返回11验证签名失败可以用来同正确的进行比对):[" + sha1Hex + "]");
return Base64.encodeBase64String(SecureUtil.getSignature(CertUtil.getSignCertPrivateKeyByStoreMap(certPath, certPwd), sha1Hex.getBytes())); return Base64.encodeBase64String(SecureUtil.getSignature(certUtil.getSignCertPrivateKeyByStoreMap(certPath, certPwd), sha1Hex.getBytes()));
} catch (Exception e) { } catch (Exception e) {
log.error("calcSignRsa Error", e); log.error("calcSignRsa Error", e);
return null; return null;
...@@ -83,14 +87,14 @@ public class SDKUtil { ...@@ -83,14 +87,14 @@ public class SDKUtil {
* @param encoding * @param encoding
* @return * @return
*/ */
public static String signRsa2(Map<String, String> data, String certPath, String certPwd, String encoding) { public String signRsa2(Map<String, String> data, String certPath, String certPwd, String encoding) {
try { try {
String stringData = createLinkString(data, true, false, encoding); String stringData = createLinkString(data, true, false, encoding);
log.info("打印排序后待签名请求报文串(交易返回11验证签名失败时可以用来同正确的进行比对):[" + stringData + "]"); log.info("打印排序后待签名请求报文串(交易返回11验证签名失败时可以用来同正确的进行比对):[" + stringData + "]");
byte[] sha256 = SecureUtil.sha256(stringData.getBytes(encoding)); byte[] sha256 = SecureUtil.sha256(stringData.getBytes(encoding));
String sha256Hex = byteArrayToHexString(sha256).toLowerCase(); String sha256Hex = byteArrayToHexString(sha256).toLowerCase();
log.info("sha256(交易返回11验证签名失败可以用来同正确的进行比对):[" + sha256Hex + "]"); log.info("sha256(交易返回11验证签名失败可以用来同正确的进行比对):[" + sha256Hex + "]");
return Base64.encodeBase64String(SecureUtil.getSignatureSHA256(CertUtil.getSignCertPrivateKeyByStoreMap(certPath, certPwd), sha256Hex.getBytes())); return Base64.encodeBase64String(SecureUtil.getSignatureSHA256(certUtil.getSignCertPrivateKeyByStoreMap(certPath, certPwd), sha256Hex.getBytes()));
} catch (Exception e) { } catch (Exception e) {
log.error("calcSignRsa2 Error", e); log.error("calcSignRsa2 Error", e);
return null; return null;
...@@ -426,15 +430,15 @@ public class SDKUtil { ...@@ -426,15 +430,15 @@ public class SDKUtil {
* @param certType * @param certType
* @return * @return
*/ */
public static int updateEncryptCert(String strCert, String certType ) { public int updateEncryptCert(String strCert, String certType ) {
if (isEmpty(strCert) || isEmpty(certType)) if (isEmpty(strCert) || isEmpty(certType))
return -1; return -1;
if (CERTTYPE_01.equals(certType)) { if (CERTTYPE_01.equals(certType)) {
// 更新敏感信息加密公钥 // 更新敏感信息加密公钥
return CertUtil.resetEncryptCertPublicKey(strCert); return certUtil.resetEncryptCertPublicKey(strCert);
} else if (CERTTYPE_02.equals(certType)) { } else if (CERTTYPE_02.equals(certType)) {
// 更新pin敏感信息加密公钥 // 更新pin敏感信息加密公钥
return CertUtil.resetPinEncryptCertPublicKey(strCert); return certUtil.resetPinEncryptCertPublicKey(strCert);
} else { } else {
log.info("unknown cerType:"+certType); log.info("unknown cerType:"+certType);
return -1; return -1;
...@@ -449,7 +453,7 @@ public class SDKUtil { ...@@ -449,7 +453,7 @@ public class SDKUtil {
public static Map<String, String> filterBlank(Map<String, String> contentData){ public static Map<String, String> filterBlank(Map<String, String> contentData){
Map<String, String> submitFromData = new HashMap<String, String>(); Map<String, String> submitFromData = new HashMap<String, String>();
Set<String> keyset = contentData.keySet(); Set<String> keyset = contentData.keySet();
for(String key : keyset){ for(String key : keyset){
String value = contentData.get(key); String value = contentData.get(key);
if (!isEmpty(value)) { if (!isEmpty(value)) {
...@@ -458,10 +462,10 @@ public class SDKUtil { ...@@ -458,10 +462,10 @@ public class SDKUtil {
} }
return submitFromData; return submitFromData;
} }
/** /**
* 解压缩. * 解压缩.
* *
* @param inputByte * @param inputByte
* byte[]数组类型的数据 * byte[]数组类型的数据
* @return 解压缩后的数据 * @return 解压缩后的数据
...@@ -492,7 +496,7 @@ public class SDKUtil { ...@@ -492,7 +496,7 @@ public class SDKUtil {
/** /**
* 压缩. * 压缩.
* *
* @param inputByte * @param inputByte
* 需要解压缩的byte[]数组 * 需要解压缩的byte[]数组
* @return 压缩后的数据 * @return 压缩后的数据
...@@ -516,10 +520,10 @@ public class SDKUtil { ...@@ -516,10 +520,10 @@ public class SDKUtil {
compresser.end(); compresser.end();
return o.toByteArray(); return o.toByteArray();
} }
/** /**
* 判断字符串是否为NULL或空 * 判断字符串是否为NULL或空
* *
* @param s * @param s
* 待判断的字符串数据 * 待判断的字符串数据
* @return 判断结果 true-是 false-否 * @return 判断结果 true-是 false-否
......
/** /**
* *
* Licensed Property to China UnionPay Co., Ltd. * Licensed Property to China UnionPay Co., Ltd.
* *
* (C) Copyright of China UnionPay Co., Ltd. 2010 * (C) Copyright of China UnionPay Co., Ltd. 2010
* All Rights Reserved. * All Rights Reserved.
* *
* *
* Modification History: * Modification History:
* ============================================================================= * =============================================================================
* Author Date Description * Author Date Description
...@@ -210,7 +210,7 @@ public class SecureUtil { ...@@ -210,7 +210,7 @@ public class SecureUtil {
return null; return null;
} }
} }
// /** // /**
// * ANSI X9.8格式(不带主账号信息)pinblock // * ANSI X9.8格式(不带主账号信息)pinblock
// * @param pin // * @param pin
...@@ -238,29 +238,29 @@ public class SecureUtil { ...@@ -238,29 +238,29 @@ public class SecureUtil {
// return null; // return null;
// } // }
// } // }
public static byte[] tripleDesEncryptECBPKCS5Padding(byte[] key, byte[] data) { public static byte[] tripleDesEncryptECBPKCS5Padding(byte[] key, byte[] data) {
try { try {
if(data == null || data.length % 8 != 0) if(data == null || data.length % 8 != 0)
throw new IllegalArgumentException("data is null or error data length."); throw new IllegalArgumentException("data is null or error data length.");
SecretKey sk = getTripleDesKey(key); SecretKey sk = getTripleDesKey(key);
Cipher cipher = Cipher.getInstance("DESede/ECB/PKCS5Padding"); Cipher cipher = Cipher.getInstance("DESede/ECB/PKCS5Padding");
cipher.init(Cipher.ENCRYPT_MODE, sk); cipher.init(Cipher.ENCRYPT_MODE, sk);
return cipher.doFinal(data); return cipher.doFinal(data);
} catch (Exception e) { } catch (Exception e) {
log.error("加密失败", e); log.error("加密失败", e);
return null; return null;
} }
} }
/** /**
* 后补0到位数为unitLength的整数倍 * 后补0到位数为unitLength的整数倍
* @param value * @param value
* @return * @return
*/ */
public static byte[] rightPadZero(byte[] value, final int unitLength){ public static byte[] rightPadZero(byte[] value, final int unitLength){
if (value.length % unitLength == 0) if (value.length % unitLength == 0)
...@@ -268,7 +268,7 @@ public class SecureUtil { ...@@ -268,7 +268,7 @@ public class SecureUtil {
int len = (value.length/unitLength + 1) * unitLength; int len = (value.length/unitLength + 1) * unitLength;
return Arrays.copyOf(value, len); return Arrays.copyOf(value, len);
} }
/** /**
* 通过byte数组得到SecretKey类型的密钥 * 通过byte数组得到SecretKey类型的密钥
* @param key * @param key
...@@ -276,12 +276,12 @@ public class SecureUtil { ...@@ -276,12 +276,12 @@ public class SecureUtil {
* @throws IllegalArgumentException * @throws IllegalArgumentException
*/ */
private static SecretKey getTripleDesKey(byte[] key) { private static SecretKey getTripleDesKey(byte[] key) {
if (key == null || !(key.length== 8||key.length== 16||key.length== 24)) if (key == null || !(key.length== 8||key.length== 16||key.length== 24))
throw new IllegalArgumentException("key is null or error key length."); throw new IllegalArgumentException("key is null or error key length.");
byte[] specKey = new byte[24]; byte[] specKey = new byte[24];
try { try {
switch (key.length) { switch (key.length) {
case 16: case 16:
......
package com.liquidnet.service;
import com.liquidnet.service.dragon.channel.unionpay.sdk.SDKConfig;
import lombok.extern.slf4j.Slf4j;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.test.context.SpringBootTest;
import org.springframework.test.context.junit4.SpringJUnit4ClassRunner;
/**
* @author AnJiabin <anjiabin@zhengzai.tv>
* @version V1.0
* @Description: TODO
* @class: TestSdkConfig
* @Package com.liquidnet.service
* @Copyright: LightNet @ Copyright (c) 2021
* @date 2021/11/9 10:57
*/
@Slf4j
@RunWith(SpringJUnit4ClassRunner.class)
@SpringBootTest
public class TestSdkConfig {
@Autowired
private SDKConfig sdkConfig;
@Test
public void pringSdkConfigInfo(){
System.out.println(sdkConfig.getFileTransUrl());
System.out.println(sdkConfig.getSignCertPath());
System.out.println(sdkConfig.getSignCertPwd());
System.out.println(sdkConfig.getSignCertType());
System.out.println(sdkConfig.getEncryptCertPath());
System.out.println(sdkConfig.getMiddleCertPath());
System.out.println(sdkConfig.getRootCertPath());
}
}
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment