diff --git a/pay-java-union/src/main/java/com/egzosn/pay/union/SDK/CertUtil.java b/pay-java-union/src/main/java/com/egzosn/pay/union/SDK/CertUtil.java index 4d8bcaa..58b1e83 100644 --- a/pay-java-union/src/main/java/com/egzosn/pay/union/SDK/CertUtil.java +++ b/pay-java-union/src/main/java/com/egzosn/pay/union/SDK/CertUtil.java @@ -61,40 +61,6 @@ public class CertUtil { - /** - * 请求报文签名(使用配置文件中配置的私钥证书或者对称密钥签名)
- * 功能:对请求报文进行签名,并计算赋值certid,signature字段并返回
- * @param reqData 请求报文map
- * @param encoding 上送请求报文域encoding字段的值
- * @return 签名后的map对象
- */ - public static Map sign(Map reqData,String encoding) { - reqData = filterBlank(reqData); - SDKUtils.signParams(reqData, encoding); - return reqData; - } - /** - * 过滤请求报文中的空字符串或者空字符串 - * @param contentData - * @return - */ - public static Map filterBlank(Map contentData){ - Map submitFromData = new HashMap(); - Set keyset = contentData.keySet(); - for(String key:keyset){ - String value = contentData.get(key); - if (StringUtils.isNotBlank(value)) { - // 对value值进行去除前后空处理 - submitFromData.put(key, value.trim()); - } - } - return submitFromData; - } - - - - - static { init(); } diff --git a/pay-java-union/src/main/java/com/egzosn/pay/union/SDK/SDKUtils.java b/pay-java-union/src/main/java/com/egzosn/pay/union/SDK/SDKUtils.java deleted file mode 100644 index 9cab50c..0000000 --- a/pay-java-union/src/main/java/com/egzosn/pay/union/SDK/SDKUtils.java +++ /dev/null @@ -1,204 +0,0 @@ -package com.egzosn.pay.union.SDK;/** - * Description: - * author: Fuzx - * date: 2017/11/27 0027 - */ - -import com.egzosn.pay.common.util.sign.SecureUtil; -import com.egzosn.pay.common.util.sign.SignUtils; -import com.egzosn.pay.common.util.sign.encrypt.Base64; -import com.egzosn.pay.common.util.sign.encrypt.RSA; -import com.egzosn.pay.common.util.sign.encrypt.SHA256; -import com.egzosn.pay.common.util.str.StringUtils; -import org.apache.commons.logging.Log; -import org.apache.commons.logging.LogFactory; - -import java.io.*; -import java.security.cert.X509Certificate; -import java.util.ArrayList; -import java.util.List; -import java.util.Map; -import java.util.zip.Inflater; -import java.util.zip.ZipEntry; -import java.util.zip.ZipInputStream; - -import static com.egzosn.pay.union.SDK.SDKConstants.*; - -/** - * @author Actinia - * @email hayesfu@qq.com - * @create 2017 2017/11/27 0027 - */ -public class SDKUtils { - //日志 - protected static final Log log = LogFactory.getLog(SDKUtils.class); - - /** - * 验证签名 - * - * @param resData - * 返回报文数据 - * @param encoding - * 编码格式 - * @return - */ - public static boolean validate(Map resData, String encoding) { - log.info("验签处理开始"); - if (StringUtils.isEmpty(encoding)) { - encoding = "UTF-8"; - } - String signMethod = resData.get(SDKConstants.param_signMethod).toString(); - String version = resData.get(SDKConstants.param_version).toString(); - if (SIGNMETHOD_RSA.equals(signMethod) || VERSION_1_0_0.equals(version) || VERSION_5_0_1.equals(version)) { - // 获取返回报文的版本号 - if (VERSION_5_0_0.equals(version) || VERSION_1_0_0.equals(version) || VERSION_5_0_1.equals(version)) { - String stringSign = resData.get(SDKConstants.param_signature).toString(); - log.info("签名原文:["+stringSign+"]"); - // 从返回报文中获取certId ,然后去证书静态Map中查询对应验签证书对象 - String certId = resData.get(SDKConstants.param_certId).toString(); - log.info("对返回报文串验签使用的验签公钥序列号:["+certId+"]"); - // 将Map信息转换成key1=value1&key2=value2的形式 - String stringData = SignUtils.parameterText(resData); - log.info("待验签返回报文串:["+stringData+"]"); - try { - // 验证签名需要用银联发给商户的公钥证书. - return SecureUtil.validateSignBySoft(CertUtil.getValidatePublicKey(certId), Base64.decode(stringSign), - SecureUtil.sha1X16(stringData, encoding)); - } catch (UnsupportedEncodingException e) { - log.error(e.getMessage(), e); - } catch (Exception e) { - log.error(e.getMessage(), e); - } - } else if (VERSION_5_1_0.equals(version)) { - // 1.从返回报文中获取公钥信息转换成公钥对象 - String strCert = resData.get(SDKConstants.param_signPubKeyCert).toString(); - log.info("验签公钥证书:["+strCert+"]"); - X509Certificate x509Cert = CertUtil.genCertificateByStr(strCert); - if(x509Cert == null) { - log.error("convert signPubKeyCert failed"); - return false; - } - // 2.验证证书链 - if (!CertUtil.verifyCertificate(x509Cert)) { - log.error("验证公钥证书失败,证书信息:["+strCert+"]"); - return false; - } - - // 3.验签 - String stringSign = resData.get(SDKConstants.param_signature).toString(); - log.info("签名原文:["+stringSign+"]"); - // 将Map信息转换成key1=value1&key2=value2的形式 - String stringData = SignUtils.parameterText(resData); - log.info("待验签返回报文串:["+stringData+"]"); - try { - // 验证签名需要用银联发给商户的公钥证书. - boolean result = SecureUtil.validateSignBySoft256(x509Cert - .getPublicKey(), Base64.decode(stringSign - ), SHA256.sign( - stringData, "", encoding).getBytes()); - log.info("验证签名" + (result? "成功":"失败")); - return result; - } catch (UnsupportedEncodingException e) { - log.error(e.getMessage(), e); - } catch (Exception e) { - log.error(e.getMessage(), e); - } - } - - } else if (SIGNMETHOD_SHA256.equals(signMethod)) { - // 1.进行SHA256验证 - String stringSign = resData.get(SDKConstants.param_signature).toString(); - log.info("签名原文:["+stringSign+"]"); - // 将Map信息转换成key1=value1&key2=value2的形式 - String stringData = SignUtils.parameterText(resData); - log.info("待验签返回报文串:["+stringData+"]"); - String strBeforeSha256 = stringData - + SDKConstants.AMPERSAND - + SecureUtil.sha256X16Str(SDKConfig.getConfig() - .getSecureKey(), encoding); - String strAfterSha256 = SecureUtil.sha256X16Str(strBeforeSha256, - encoding); - boolean result = stringSign.equals(strAfterSha256); - log.info("验证签名" + (result? "成功":"失败")); - return result; - } else if (SIGNMETHOD_SM3.equals(signMethod)) { - // 1.进行SM3验证 - String stringSign = resData.get(SDKConstants.param_signature).toString(); - log.info("签名原文:["+stringSign+"]"); - // 将Map信息转换成key1=value1&key2=value2的形式 - String stringData = SignUtils.parameterText(resData); - log.info("待验签返回报文串:["+stringData+"]"); - String strBeforeSM3 = stringData - + SDKConstants.AMPERSAND - + SecureUtil.sm3X16Str(SDKConfig.getConfig() - .getSecureKey(), encoding); - String strAfterSM3 = SecureUtil - .sm3X16Str(strBeforeSM3, encoding); - boolean result = stringSign.equals(strAfterSM3); - log.info("验证签名" + (result? "成功":"失败")); - return result; - } - return false; - } - - /** - * 对参数加密 - * @param data - * @param encoding - * @return - */ - public static boolean signParams(Map data,String encoding){ - if (StringUtils.isBlank(encoding)) { - encoding = "UTF-8"; - } - String signMethod = data.get(SDKConstants.param_signMethod); - String version = data.get(SDKConstants.param_version); - if(StringUtils.isBlank(signMethod)){ - log.info("银联签名方式不能为空"); - return false; - } - if(StringUtils.isBlank(version)){ - log.info("版本号不能为空"); - return false; - } - if (SIGNMETHOD_RSA.equals(signMethod)|| VERSION_1_0_0.equals(version) || SDKConstants.VERSION_5_0_1.equals(version)) { - if (SDKConstants.VERSION_5_0_0.equals(version) || VERSION_1_0_0.equals(version) || SDKConstants.VERSION_5_0_1.equals(version)) { - data.put(SDKConstants.param_certId, CertUtil.getSignCertId()); - String stringData = SignUtils.parameterText(data); - String stringSign = null; - try { - // 通过SHA1进行摘要并转16进制 - byte[] signDigest = SecureUtil - .sha1X16(stringData, encoding); - stringSign = RSA.sign(signDigest, CertUtil.getSignCertPrivateKey()); - // 设置签名域值 - data.put(SDKConstants.param_signature, stringSign); - return true; - } catch (Exception e) { - e.printStackTrace(); - return false; - } - } - }else if (SDKConstants.SIGNMETHOD_SHA256.equals(signMethod)) { - String stringData = SignUtils.parameterText(data); - String strBeforeSha256 = stringData - + SDKConstants.AMPERSAND - + SecureUtil.sha256X16Str(SDKConfig.getConfig().getSecureKey(), encoding); - String strAfterSha256 = SecureUtil.sha256X16Str(strBeforeSha256, - encoding); - data.put(SDKConstants.param_signature, strAfterSha256); - } else if (SDKConstants.SIGNMETHOD_SM3.equals(signMethod)) { - String stringData = SignUtils.parameterText(data); - String strBeforeSM3 = stringData - + SDKConstants.AMPERSAND - + SecureUtil.sm3X16Str(SDKConfig.getConfig().getSecureKey(), encoding); - String strAfterSM3 = SecureUtil.sm3X16Str(strBeforeSM3, encoding); - // 设置签名域值 - data.put(SDKConstants.param_signature, strAfterSM3); - } - - return false; - } - - -} diff --git a/pay-java-union/src/main/java/com/egzosn/pay/union/api/UnionPayService.java b/pay-java-union/src/main/java/com/egzosn/pay/union/api/UnionPayService.java index 9fe21e7..e0db012 100644 --- a/pay-java-union/src/main/java/com/egzosn/pay/union/api/UnionPayService.java +++ b/pay-java-union/src/main/java/com/egzosn/pay/union/api/UnionPayService.java @@ -14,7 +14,6 @@ import com.egzosn.pay.common.util.str.StringUtils; import com.egzosn.pay.union.SDK.CertUtil; import com.egzosn.pay.union.SDK.SDKConfig; import com.egzosn.pay.union.SDK.SDKConstants; -import com.egzosn.pay.union.SDK.SDKUtils; import com.egzosn.pay.union.enums.UnionTransactionType; import com.egzosn.pay.union.request.UnionQueryOrder; import org.apache.commons.logging.Log; @@ -37,7 +36,32 @@ import java.util.Map; public class UnionPayService extends BasePayService { //日志 protected static final Log log = LogFactory.getLog(UnionPayService.class); - + /** + * 测试域名 + */ + private static final String TEST_BASE_DOMAIN = "test.95516.com"; + /** + * 正式域名 + */ + private static final String RELEASE_BASE_DOMAIN = "95516.com"; + /** + * 交易请求地址 + */ + private static final String FRONT_TRANS_URL= "https://gateway.%s/gateway/api/frontTransReq.do"; + private static final String BACK_TRANS_URL= "https://gateway.%s/gateway/api/backTransReq.do"; + private static final String SINGLE_QUERY_URL= "https://gateway.%s/gateway/api/queryTrans.do"; + private static final String BATCH_TRANS_URL= "https://gateway.%s/gateway/api/batchTrans.do"; + private static final String FILE_TRANS_URL= "https://filedownload.%s/"; + private static final String APP_TRANS_URL= "https://gateway.%s/gateway/api/appTransReq.do"; + private static final String CARD_TRANS_URL= "https://gateway.%s/gateway/api/cardTransReq.do"; + /** + * 以下缴费产品使用,其余产品用不到 + */ +// private static final String JF_FRONT_TRANS_URL= "https://gateway.%s/jiaofei/api/frontTransReq.do"; +// private static final String JF_BACK_TRANS_URL= "https://gateway.%s/jiaofei/api/backTransReq.do"; +// private static final String JF_SINGLE_QUERY_URL= "https://gateway.%s/jiaofei/api/queryTrans.do"; +// private static final String JF_APP_TRANS_URL= "https://gateway.%s/jiaofei/api/appTransReq.do"; +// private static final String JF_CARD_TRANS_URL= "https://gateway.%s/jiaofei/api/cardTransReq.do"; public UnionPayService (PayConfigStorage payConfigStorage) { super(payConfigStorage); @@ -77,7 +101,7 @@ public class UnionPayService extends BasePayService { @Override public boolean verify (Map result) { if(result != null){ - if(SDKUtils.validate(result, payConfigStorage.getInputCharset())){ + if(this.vailSign(result)){ String respCode = result.get("respCode").toString(); if(("00").equals(respCode)){ @@ -195,16 +219,59 @@ public class UnionPayService extends BasePayService { * @param parameters 请求参数 * @return 请求参数 */ - private Map setSign(Map parameters){ + private Map setSign(Map parameters){ SignUtils signUtils = SignUtils.valueOf(payConfigStorage.getSignType()); + String data = SignUtils.parameterText(parameters); parameters.put(SDKConstants.param_signMethod, getSignMethod(signUtils)); - - String sign = createSign( SignUtils.parameterText(parameters, "&"), payConfigStorage.getInputCharset()); - - parameters.put("sign", sign); + String stringSign = ""; + switch (signUtils){ + case RSA: + parameters.put(SDKConstants.param_certId, CertUtil.getSignCertId()); + stringSign = SignUtils.SHA1.createSign(data,"",payConfigStorage.getInputCharset()); + stringSign = signUtils.createSign(stringSign,payConfigStorage.getKeyPrivate(),payConfigStorage.getInputCharset()); + break; + case SHA256: + String before = SignUtils.SHA256.createSign(SDKConfig.getConfig().getSecureKey(),"",payConfigStorage.getInputCharset()); + stringSign = SignUtils.SHA256.createSign(data,"&"+before,payConfigStorage.getInputCharset()); + break; + case SM3: + stringSign = SignUtils.SM3.createSign(data,SDKConfig.getConfig().getSecureKey(),payConfigStorage.getInputCharset()); + break; + default: + parameters.put(SDKConstants.param_certId, CertUtil.getSignCertId()); + stringSign = SignUtils.SHA1.createSign(data,"",payConfigStorage.getInputCharset()); + stringSign = signUtils.createSign(stringSign,payConfigStorage.getKeyPrivate(),payConfigStorage.getInputCharset()); + } + parameters.put(SDKConstants.param_signature, stringSign); return parameters; } + /** + * 验证数据合法性 + * @param resData 请求参数 + * @return 请求参数 + */ + private boolean vailSign(Map resData){ + SignUtils signUtils = SignUtils.valueOf(payConfigStorage.getSignType()); + //签名原文 + String stringSign = resData.get(SDKConstants.param_signature).toString(); + String data = SignUtils.parameterText(resData); + switch (signUtils){ + case RSA: + //todo 不确定这样可靠 + return SignUtils.RSA.verify(resData,stringSign,payConfigStorage.getKeyPublic(),payConfigStorage.getInputCharset()); + case SHA256: + String before = SignUtils.SHA256.createSign(SDKConfig.getConfig().getSecureKey(),"",payConfigStorage.getInputCharset()); + String nowSign = SignUtils.SHA256.createSign(data,"&"+before,payConfigStorage.getInputCharset()); + return stringSign.equals(nowSign); + case SM3: + nowSign = SignUtils.SM3.createSign(data,SDKConfig.getConfig().getSecureKey(),payConfigStorage.getInputCharset()); + return stringSign.equals(nowSign); + default: + return false; + } + } + /** * 获取输出二维码,用户返回给支付端, * @@ -214,12 +281,9 @@ public class UnionPayService extends BasePayService { @Override public BufferedImage genQrPay (PayOrder order) { Map params = orderInfo(order); - - - - CertUtil.sign(params,payConfigStorage.getInputCharset().toUpperCase()); - JSONObject response = getHttpRequestTemplate().postForObject(SDKConfig.getConfig().getBackRequestUrl(),params,JSONObject.class); - if(SDKUtils.validate(response,payConfigStorage.getInputCharset().toUpperCase())){ + this.setSign(params); + JSONObject response = getHttpRequestTemplate().postForObject(this.getBackTransUrl(),params,JSONObject.class); + if(this.vailSign(response)){ if("00".equals(response.getString(SDKConstants.param_respCode))){ //成功,获取tn号 return MatrixToImageWriter.writeInfoToJpgBuff( response.getString(SDKConstants.param_respCode)); @@ -240,8 +304,8 @@ public class UnionPayService extends BasePayService { @Override public Map microPay (PayOrder order) { Map params = orderInfo(order); - CertUtil.sign(params,payConfigStorage.getInputCharset().toUpperCase()); - return getHttpRequestTemplate().postForObject(SDKConfig.getConfig().getBackRequestUrl(),params,JSONObject.class); + this.setSign(params); + return getHttpRequestTemplate().postForObject(this.getBackTransUrl(),params,JSONObject.class); } @@ -257,9 +321,9 @@ public class UnionPayService extends BasePayService { Map params = this.getCommonParam(); UnionTransactionType.QUERY.convertMap(params); params.put(SDKConstants.param_orderId,outTradeNo); - CertUtil.sign(params,payConfigStorage.getInputCharset().toUpperCase()); - JSONObject response = getHttpRequestTemplate().postForObject(SDKConfig.getConfig().getBackRequestUrl(),params,JSONObject.class); - if(SDKUtils.validate(response,payConfigStorage.getInputCharset().toUpperCase())){ + this.setSign(params); + JSONObject response = getHttpRequestTemplate().postForObject(this.getSingleQueryUrl(),params,JSONObject.class); + if(this.vailSign(response)){ if("00".equals(response.getString(SDKConstants.param_respCode))){ String origRespCode = response.getString(SDKConstants.param_origRespCode); if(("00").equals(origRespCode)){ @@ -296,9 +360,9 @@ public class UnionPayService extends BasePayService { if(StringUtils.isNotBlank(queryOrder.getOrigTxnTime())) { params.put(SDKConstants.param_origTxnTime, queryOrder.getOrigOrderId()); } - CertUtil.sign(params,payConfigStorage.getInputCharset().toUpperCase()); - JSONObject response = getHttpRequestTemplate().postForObject(SDKConfig.getConfig().getBackRequestUrl(),params,JSONObject.class); - if(SDKUtils.validate(response,payConfigStorage.getInputCharset().toUpperCase())){ + this.setSign(params); + JSONObject response = getHttpRequestTemplate().postForObject(this.getBackTransUrl(),params,JSONObject.class); + if(this.vailSign(response)){ if("00".equals(response.getString(SDKConstants.param_respCode))){ String origRespCode = response.getString(SDKConstants.param_origRespCode); //交易成功,更新商户订单状态 @@ -471,9 +535,9 @@ public class UnionPayService extends BasePayService { DateFormat df = new SimpleDateFormat("MMDD"); params.put(SDKConstants.param_settleDate,df.format(new Date())); params.put(SDKConstants.param_fileType,billType); - CertUtil.sign(params,payConfigStorage.getInputCharset().toUpperCase()); - Map response = getHttpRequestTemplate().postForObject(SDKConfig.getConfig().getBackRequestUrl(),params,Map.class); - if(SDKUtils.validate(response,payConfigStorage.getInputCharset().toUpperCase())){ + this.setSign(params); + Map response = getHttpRequestTemplate().postForObject(this.getFileTransUrl(),params,Map.class); + if(this.vailSign(response)){ if("00".equals(response.get(SDKConstants.param_respCode))){ return response.get(SDKConstants.param_fileContent).toString(); @@ -513,7 +577,51 @@ public class UnionPayService extends BasePayService { return null; } +// public String getFrontTransUrl () { +// return payConfigStorage.isTest() ? String.format(FRONT_TRANS_URL,TEST_BASE_DOMAIN):String.format(FRONT_TRANS_URL,RELEASE_BASE_DOMAIN); +// } +// + public String getBackTransUrl () { + return payConfigStorage.isTest() ? String.format(BACK_TRANS_URL,TEST_BASE_DOMAIN):String.format(BACK_TRANS_URL,RELEASE_BASE_DOMAIN); + } + public String getSingleQueryUrl () { + return payConfigStorage.isTest() ? String.format(SINGLE_QUERY_URL,TEST_BASE_DOMAIN):String.format(SINGLE_QUERY_URL,RELEASE_BASE_DOMAIN); + } +// +// public String getBatchTransUrl () { +// return payConfigStorage.isTest() ? String.format(BATCH_TRANS_URL,TEST_BASE_DOMAIN):String.format(BATCH_TRANS_URL,RELEASE_BASE_DOMAIN); +// } + public String getFileTransUrl () { + return payConfigStorage.isTest() ? String.format(FILE_TRANS_URL,TEST_BASE_DOMAIN):String.format(FILE_TRANS_URL,RELEASE_BASE_DOMAIN); + } +// public String getAppTransUrl () { +// return payConfigStorage.isTest() ? String.format(APP_TRANS_URL,TEST_BASE_DOMAIN):String.format(APP_TRANS_URL,RELEASE_BASE_DOMAIN); +// } +// +// public String getCardTransUrl () { +// return payConfigStorage.isTest() ? String.format(CARD_TRANS_URL,TEST_BASE_DOMAIN):String.format(CARD_TRANS_URL,RELEASE_BASE_DOMAIN); +// } +// +// public String getJfFrontTransUrl () { +// return payConfigStorage.isTest() ? String.format(JF_FRONT_TRANS_URL,TEST_BASE_DOMAIN):String.format(JF_FRONT_TRANS_URL,RELEASE_BASE_DOMAIN); +// } +// +// public String getJfBackTransUrl () { +// return payConfigStorage.isTest() ? String.format(JF_BACK_TRANS_URL,TEST_BASE_DOMAIN):String.format(JF_BACK_TRANS_URL,RELEASE_BASE_DOMAIN); +// } +// +// public String getJfSingleQueryUrl () { +// return payConfigStorage.isTest() ? String.format(JF_SINGLE_QUERY_URL,TEST_BASE_DOMAIN):String.format(JF_SINGLE_QUERY_URL,RELEASE_BASE_DOMAIN); +// } +// +// public String getJfAppTransUrl () { +// return payConfigStorage.isTest() ? String.format(JF_APP_TRANS_URL,TEST_BASE_DOMAIN):String.format(JF_APP_TRANS_URL,RELEASE_BASE_DOMAIN); +// } +// +// public String getJfCardTransUrl () { +// return payConfigStorage.isTest() ? String.format(JF_CARD_TRANS_URL,TEST_BASE_DOMAIN):String.format(JF_CARD_TRANS_URL,RELEASE_BASE_DOMAIN); +// } }