1.网管支付测试通过

This commit is contained in:
Actinia-517
2017-12-15 22:43:12 +08:00
parent c9296100fa
commit 76f36d07c2
11 changed files with 287 additions and 60 deletions

View File

@@ -1,17 +1,9 @@
package com.egzosn.pay.common.http;
import com.alibaba.fastjson.JSON;
import org.apache.http.Consts;
import org.apache.http.entity.ContentType;
import org.apache.http.entity.StringEntity;
import java.io.UnsupportedEncodingException;
import java.net.URLEncoder;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.regex.Matcher;
import java.util.regex.Pattern;
/**
* URL表达式处理器
@@ -115,7 +107,7 @@ public class UriVariables {
continue;
}
builder.append(key).append("=").append(URLEncoder.encode((String) pe.get(key), "utf-8")).append("&");
builder.append(key).append("=").append(URLEncoder.encode( pe.get(key).toString(), "utf-8")).append("&");
} catch (UnsupportedEncodingException e) {
e.printStackTrace();
}

View File

@@ -37,9 +37,10 @@ public class CertDescriptor {
/** 证书容器,存储对商户请求报文签名私钥证书. */
private KeyStore keyStore = null;
/** 验签中级证书 */
/** 验签公钥/中级证书 */
private X509Certificate publicKeyCert = null;
/** 验签根证书 */
private X509Certificate rootKeyCert = null;
@@ -53,7 +54,7 @@ public class CertDescriptor {
CertificateFactory cf = null;
FileInputStream in = null;
try {
cf = CertificateFactory.getInstance("X.509", "BC");
cf = CertificateFactory.getInstance("X.509");
in = new FileInputStream(path);
encryptCertTemp = (X509Certificate) cf.generateCertificate(in);
// 打印证书加载信息,供测试阶段调试
@@ -63,9 +64,7 @@ public class CertDescriptor {
log.error("InitCert Error", e);
} catch (FileNotFoundException e) {
log.error("InitCert Error File Not Found", e);
} catch (NoSuchProviderException e) {
log.error("LoadVerifyCert Error No BC Provider", e);
} finally {
}finally {
if (null != in) {
try {
in.close();
@@ -82,7 +81,7 @@ public class CertDescriptor {
*
* @return
*/
public PrivateKey getSignCertPrivateKey() {
public PrivateKey getSignCertPrivateKey(String pwd) {
try {
Enumeration<String> aliasenum = keyStore.aliases();
String keyAlias = null;
@@ -90,7 +89,7 @@ public class CertDescriptor {
keyAlias = aliasenum.nextElement();
}
PrivateKey privateKey = (PrivateKey) keyStore.getKey(keyAlias,
"SDKConfig.getConfig().getSignCertPwd()".toCharArray());
pwd.toCharArray());
return privateKey;
} catch (KeyStoreException e) {
log.error("getSignCertPrivateKey Error", e);
@@ -171,11 +170,10 @@ public class CertDescriptor {
private KeyStore getKeyInfo(String pfxkeyfile, String keypwd,
String type) throws IOException {
log.warn("加载签名证书==>" + pfxkeyfile);
FileInputStream fis = null;
try {
KeyStore ks = KeyStore.getInstance(type, "BC");
try(FileInputStream fis = new FileInputStream(pfxkeyfile);) {
KeyStore ks = KeyStore.getInstance(type);
log.warn("Load RSA CertPath=[" + pfxkeyfile + "],Pwd=["+ keypwd + "],type=["+type+"]");
fis = new FileInputStream(pfxkeyfile);
char[] nPassword = null;
nPassword = null == keypwd || "".equals(keypwd.trim()) ? null: keypwd.toCharArray();
if (null != ks) {
@@ -185,9 +183,6 @@ public class CertDescriptor {
} catch (Exception e) {
log.error("getKeyInfo Error", e);
return null;
} finally {
if(null!=fis)
fis.close();
}
}
@@ -255,23 +250,43 @@ public class CertDescriptor {
}
/**
* 用配置文件acp_sdk.properties配置路径 加载敏感信息加密证书
* 加载中级证书
*/
public void initPublicCert(String certPath) {
if (!StringUtils.isEmpty(certPath)) {
publicKeyCert = initCert(certPath);
log.info("Load MiddleCert Successful");
log.info("Load PublicKeyCert Successful");
} else {
log.info("WARN: acpsdk.middle.path is empty");
log.info("PublicKeyCert is empty");
}
}
/**
* 从配置文件acp_sdk.properties中获取验签公钥使用的中级证书
* 加载根证书
*/
public void initRootCert(String certPath) {
if (!StringUtils.isEmpty(certPath)) {
rootKeyCert = initCert(certPath);
log.info("Load RootCert Successful");
} else {
log.info("RootCert is empty");
}
}
/**
* 获取公钥/中级证书
* @return
*/
public X509Certificate getPublicCert() {
return publicKeyCert;
}
/**
* 获取中级证书
* @return
*/
public X509Certificate getRootCert() {
return rootKeyCert;
}
/**

View File

@@ -25,7 +25,7 @@ public class SHA256 {
public static String sign(String text, String key, String input_charset) {
//拼接key
text = text + key;
return DigestUtils.sha512Hex( StringUtils.getContentBytes(text, input_charset));
return DigestUtils.sha256Hex( StringUtils.getContentBytes(text, input_charset));
}

View File

@@ -2,6 +2,7 @@
package com.egzosn.pay.demo.controller;
import com.alibaba.fastjson.JSONObject;
import com.egzosn.pay.ali.bean.AliTransactionType;
import com.egzosn.pay.common.api.Callback;
import com.egzosn.pay.common.api.PayConfigStorage;
@@ -82,7 +83,7 @@ public class PayController {
//获取对应的支付账户操作工具可根据账户id
PayResponse payResponse = service.getPayResponse(payId);
PayOrder order = new PayOrder("订单title", "摘要", null == price ? new BigDecimal(0.01) : price, UUID.randomUUID().toString().replace("-", ""), PayType.valueOf(payResponse.getStorage().getPayType()).getTransactionType(transactionType));
PayOrder order = new PayOrder("订单title", "摘要", null == price ? new BigDecimal(0.01) : price, "22222222233", PayType.valueOf(payResponse.getStorage().getPayType()).getTransactionType(transactionType));
// ------ 微信H5使用----
order.setSpbillCreateIp(request.getHeader("X-Real-IP"));
StringBuffer requestURL = request.getRequestURL();
@@ -309,7 +310,9 @@ public class PayController {
PayResponse payResponse = service.getPayResponse(payId);
PayConfigStorage storage = payResponse.getStorage();
//获取支付方返回的对应参数
Map<String, Object> params = payResponse.getService().getParameter2Map(request.getParameterMap(), request.getInputStream());
// Map<String, Object> params = payResponse.getService().getParameter2Map(request.getParameterMap(), request.getInputStream());
Map<String, Object> params = JSONObject.parseObject("{\"bizType\":\"000201\",\"signPubKeyCert\":\"-----BEGIN CERTIFICATE-----\\r\\nMIIEQzCCAyugAwIBAgIFEBJJZVgwDQYJKoZIhvcNAQEFBQAwWDELMAkGA1UEBhMC\\r\\nQ04xMDAuBgNVBAoTJ0NoaW5hIEZpbmFuY2lhbCBDZXJ0aWZpY2F0aW9uIEF1dGhv\\r\\ncml0eTEXMBUGA1UEAxMOQ0ZDQSBURVNUIE9DQTEwHhcNMTcxMTAxMDcyNDA4WhcN\\r\\nMjAxMTAxMDcyNDA4WjB3MQswCQYDVQQGEwJjbjESMBAGA1UEChMJQ0ZDQSBPQ0Ex\\r\\nMQ4wDAYDVQQLEwVDVVBSQTEUMBIGA1UECxMLRW50ZXJwcmlzZXMxLjAsBgNVBAMU\\r\\nJTA0MUBaMjAxNy0xMS0xQDAwMDQwMDAwOlNJR05AMDAwMDAwMDEwggEiMA0GCSqG\\r\\nSIb3DQEBAQUAA4IBDwAwggEKAoIBAQDDIWO6AESrg+34HgbU9mSpgef0sl6avr1d\\r\\nbD/IjjZYM63SoQi3CZHZUyoyzBKodRzowJrwXmd+hCmdcIfavdvfwi6x+ptJNp9d\\r\\nEtpfEAnJk+4quriQFj1dNiv6uP8ARgn07UMhgdYB7D8aA1j77Yk1ROx7+LFeo7rZ\\r\\nDdde2U1opPxjIqOPqiPno78JMXpFn7LiGPXu75bwY2rYIGEEImnypgiYuW1vo9UO\\r\\nG47NMWTnsIdy68FquPSw5FKp5foL825GNX3oJSZui8d2UDkMLBasf06Jz0JKz5AV\\r\\nblaI+s24/iCfo8r+6WaCs8e6BDkaijJkR/bvRCQeQpbX3V8WoTLVAgMBAAGjgfQw\\r\\ngfEwHwYDVR0jBBgwFoAUz3CdYeudfC6498sCQPcJnf4zdIAwSAYDVR0gBEEwPzA9\\r\\nBghggRyG7yoBATAxMC8GCCsGAQUFBwIBFiNodHRwOi8vd3d3LmNmY2EuY29tLmNu\\r\\nL3VzL3VzLTE0Lmh0bTA5BgNVHR8EMjAwMC6gLKAqhihodHRwOi8vdWNybC5jZmNh\\r\\nLmNvbS5jbi9SU0EvY3JsMjQ4NzIuY3JsMAsGA1UdDwQEAwID6DAdBgNVHQ4EFgQU\\r\\nmQQLyuqYjES7qKO+zOkzEbvdFwgwHQYDVR0lBBYwFAYIKwYBBQUHAwIGCCsGAQUF\\r\\nBwMEMA0GCSqGSIb3DQEBBQUAA4IBAQAujhBuOcuxA+VzoUH84uoFt5aaBM3vGlpW\\r\\nKVMz6BUsLbIpp1ho5h+LaMnxMs6jdXXDh/du8X5SKMaIddiLw7ujZy1LibKy2jYi\\r\\nYYfs3tbZ0ffCKQtv78vCgC+IxUUurALY4w58fRLLdu8u8p9jyRFHsQEwSq+W5+bP\\r\\nMTh2w7cDd9h+6KoCN6AMI1Ly7MxRIhCbNBL9bzaxF9B5GK86ARY7ixkuDCEl4XCF\\r\\nJGxeoye9R46NqZ6AA/k97mJun//gmUjStmb9PUXA59fR5suAB5o/5lBySZ8UXkrI\\r\\npp/iLT8vIl1hNgLh0Ghs7DBSx99I+S3VuUzjHNxL6fGRhlix7Rb8\\r\\n-----END CERTIFICATE-----\",\"orderId\":\"20171213224128\",\"signature\":\"l8xBYSoMNzt01DDa9/JYcrQKWxN5tasUgSxf6NNsQK5t+DqMr2G9qhHXnDg5bEzeRyTFP4bM3htX9RTRhXYDy7EEsL46ZD4ib5I6mp2wXx+26zscUcLdJUiddkY5eFvQK4tPC8blw7Y6p858yiVJpHgbOK3cONhS7vwPJtK2jMbkY+GATu3aZ4iygkQc75cG+EW8nJQVwLNh7q9A6A6II18EFxR7XubdlIHXv/InVaS6ux8Wh2nmQlhRRnLtHq1ri7v1QPlu2FzM+kaf7/fn61iGr8zEPj62NzWDXue62LUfb4kTRgdkcJnfJBJl8vjZ/w93UtsnK3zjzJC/Nu+wCw==\",\"txnSubType\":\"01\",\"traceNo\":\"492156\",\"accNo\":\"6221********0000\",\"settleAmt\":\"1000\",\"settleCurrencyCode\":\"156\",\"settleDate\":\"1213\",\"txnType\":\"01\",\"encoding\":\"UTF-8\",\"version\":\"5.1.0\",\"queryId\":\"511712132241284921568\",\"accessType\":\"0\",\"exchangeRate\":\"0\",\"respMsg\":\"success\",\"traceTime\":\"1213224128\",\"txnTime\":\"20171213224128\",\"merId\":\"777290058154626\",\"currencyCode\":\"156\",\"respCode\":\"00\",\"signMethod\":\"01\",\"txnAmt\":\"1000\"}");
if (null == params) {
return payResponse.getService().getPayOutMessage("fail", "失败").toMessage();
}

View File

@@ -83,19 +83,20 @@ public class ApyAccountRepository {
ApyAccount apyAccount4 = new ApyAccount();
apyAccount4.setPayId(4);
apyAccount4.setPartner("777290058110097");
apyAccount4.setPartner("777290058154626");
// apyAccount4.setAppid("777290058110097");
apyAccount4.setPublicKey("");
apyAccount4.setPrivateKey("000000");
apyAccount4.setNotifyUrl("http://sailinmu.iok.la:19088/backRcvResponse");
apyAccount4.setPublicKey("D:\\certs\\acp_test_middle.cer;D:\\certs\\acp_test_root.cer");
apyAccount4.setPrivateKey("D:\\certs\\acp_test_sign.pfx;000000");
apyAccount4.setNotifyUrl("http://b1234780541.eicp.net/payBack4.json");
// 无需同步回调可不填 app填这个就可以
apyAccount4.setReturnUrl("http://sailinmu.iok.la:19088/backRcvResponse");
apyAccount4.setReturnUrl("http://b1234780541.eicp.net/payBack4.json");
apyAccount4.setSeller("");
apyAccount4.setInputCharset("UTF-8");
apyAccount4.setSignType(SignUtils.RSA.name());
apyAccount4.setSignType(SignUtils.RSA2.name());
apyAccount4.setPayType(PayType.unionPay);
apyAccount4.setMsgType(MsgType.json);
apyAccounts.put(apyAccount4.getPayId(), apyAccount3);
apyAccount4.setTest(true);
apyAccounts.put(apyAccount4.getPayId(), apyAccount4);
}
//_____________________________________________________________

View File

@@ -150,6 +150,8 @@ public enum PayType implements BasePayType {
@Override
public PayService getPayService(ApyAccount apyAccount) {
UnionPayConfigStorage unionPayConfigStorage = new UnionPayConfigStorage();
unionPayConfigStorage.setMerId(apyAccount.getPartner());
unionPayConfigStorage.setCertSign(true);
unionPayConfigStorage.setKeyPublic(apyAccount.getPublicKey());
unionPayConfigStorage.setKeyPrivate(apyAccount.getPrivateKey());
unionPayConfigStorage.setNotifyUrl(apyAccount.getNotifyUrl());

View File

@@ -44,7 +44,7 @@ public class ApyAccountService {
*/
public PayResponse getPayResponse(Integer id) {
PayResponse payResponse = payResponses.get(id);
PayResponse payResponse = null;
if (payResponse == null) {
ApyAccount apyAccount = dao.findByPayId(id);
if (apyAccount == null) {

View File

@@ -0,0 +1,83 @@
<input type="hidden" name="bizType" id="bizType" value="000201"/>
<input type="hidden" name="txnSubType" id="txnSubType" value="01"/>
<input type="hidden" name="orderId" id="orderId" value="20171212232030"/>
<input type="hidden" name="backUrl" id="backUrl" value="http://222.222.222.222:8080/ACPSample_B2C/backRcvResponse"/>
<input type="hidden" name="signature" id="signature" value="FKkJ04TFKLLaZOqfLpRED6zUifJy5csUGLxt966+td9yz8F9HUpS2F763nB5WgiS5Unt8740tIpQtomad19njYH+MdtxNn5dphxcxWMBKxqZenQRV/4fDa4kxsOE63vvyTqtoKH7MPYvZ3ZQ43ZF4PNdVQ0Ksnnv1wMvEuneu8c="/>
<input type="hidden" name="txnType" id="txnType" value="01"/>
<input type="hidden" name="channelType" id="channelType" value="07"/>
<input type="hidden" name="frontUrl" id="frontUrl" value="http://localhost:8080/ACPSample_B2C/frontRcvResponse"/>
<input type="hidden" name="certId" id="certId" value="40220995861346480087409489142384722381"/>
<input type="hidden" name="encoding" id="encoding" value="UTF-8"/>
<input type="hidden" name="version" id="version" value="5.1.0"/>
<input type="hidden" name="accessType" id="accessType" value="0"/>
<input type="hidden" name="txnTime" id="txnTime" value="20171212232030"/>
<input type="hidden" name="merId" id="merId" value="700000000000001"/>
<input type="hidden" name="payTimeout" id="payTimeout" value="20171212233540"/>
<input type="hidden" name="currencyCode" id="currencyCode" value="156"/>
<input type="hidden" name="signMethod" id="signMethod" value="01"/>
<input type="hidden" name="txnAmt" id="txnAmt" value="1000"/>
<input type="hidden" name="bizType" id="bizType" value="000201"/>
<input type="hidden" name="orderId" id="orderId" value="20171212232030"/>
<input type="hidden" name="txnSubType" id="txnSubType" value="01"/>
<input type="hidden" name="backUrl" id="backUrl" value="http://222.222.222.222:8080/ACPSample_B2C/backRcvResponse"/>
<input type="hidden" name="signature" id="signature" value="G7TyB1z07jZYr8QuX9EV5c1m7Ub5aR1fECePE5MQ2GT4iuCHtrJJxFiypYGvMevqOBFl0cG11iEctPJJ8Lbi7JVMUpxENIrZVWcINFrk5uv9n1PIsKTqefEdTARpaJzUD3eb32fr3axBU5qDVk1rRTrmjagzD67q8AP4vgtjih4="/>
<input type="hidden" name="txnType" id="txnType" value="01"/>
<input type="hidden" name="channelType" id="channelType" value="07"/>
<input type="hidden" name="frontUrl" id="frontUrl" value="http://localhost:8080/ACPSample_B2C/frontRcvResponse"/>
<input type="hidden" name="certId" id="certId" value="40220995861346480087409489142384722381"/>
<input type="hidden" name="encoding" id="encoding" value="UTF-8"/>
<input type="hidden" name="version" id="version" value="5.1.0"/>
<input type="hidden" name="accessType" id="accessType" value="0"/>
<input type="hidden" name="merId" id="merId" value="700000000000001"/>
<input type="hidden" name="txnTime" id="txnTime" value="20171212232030"/>
<input type="hidden" name="payTimeout" id="payTimeout" value="20171212233540"/>
<input type="hidden" name="currencyCode" id="currencyCode" value="156"/>
<input type="hidden" name="signMethod" id="signMethod" value="01"/>
<input type="hidden" name="txnAmt" id="txnAmt" value="100000"/>
</form></body><script type="text/javascript">document.all.pay_form.submit();</script></html>
<input type="hidden" name="accessType" id="accessType" value="0"/>
<input type="hidden" name="backUrl" id="backUrl" value="http://222.222.222.222:8080/ACPSample_B2C/backRcvResponse"/>
<input type="hidden" name="bizType" id="bizType" value="000201"/>
<input type="hidden" name="certId" id="certId" value="40220995861346480087409489142384722381"/>
<input type="hidden" name="channelType" id="channelType" value="07"/>
<input type="hidden" name="currencyCode" id="currencyCode" value="156"/>
<input type="hidden" name="encoding" id="encoding" value="UTF-8"/>
<input type="hidden" name="frontUrl" id="frontUrl" value="http://localhost:8080/ACPSample_B2C/frontRcvResponse"/>
<input type="hidden" name="merId" id="merId" value="700000000000001"/>
<input type="hidden" name="orderId" id="orderId" value="20171212232030"/>
<input type="hidden" name="payTimeout" id="payTimeout" value="20171212233540"/>
<input type="hidden" name="signMethod" id="signMethod" value="01"/>
<input type="hidden" name="signature" id="signature" value="WDBPtNuGF9Te4dFG7Yu29LSusvNLHqEYmvCaW69iAxbMlqjnKf0yZ+GXm1MgJ2W7am89UnrCbFYKurE40fw404DqGy/Dx4ML4/xc0V+kP68nwbS9JUMLv0YD2NzgrlZwByRHsfmxyU907mwIcGmQ/lYPiy+wDFrUOU7MdJZIstg="/>
<input type="hidden" name="txnAmt" id="txnAmt" value="1000"/>
<input type="hidden" name="txnSubType" id="txnSubType" value="01"/>
<input type="hidden" name="txnTime" id="txnTime" value="20171212232030"/>
<input type="hidden" name="txnType" id="txnType" value="01"/>
<input type="hidden" name="version" id="version" value="5.1.0"/></form></body><script type="text/javascript">document.all.pay_form.submit();</script></html>
<!--<input type="hidden" name="accessType" id="accessType" value="0"/>
<input type="hidden" name="backUrl" id="backUrl" value="http://222.222.222.222:8080/ACPSample_B2C/backRcvResponse"/>
<input type="hidden" name="bizType" id="bizType" value="000201"/>
<input type="hidden" name="certId" id="certId" value="40220995861346480087409489142384722381"/>
<input type="hidden" name="channelType" id="channelType" value="07"/>
<input type="hidden" name="currencyCode" id="currencyCode" value="156"/>
<input type="hidden" name="encoding" id="encoding" value="UTF-8"/>
<input type="hidden" name="frontUrl" id="frontUrl" value="http://localhost:8080/ACPSample_B2C/frontRcvResponse"/>
<input type="hidden" name="merId" id="merId" value="700000000000001"/>
<input type="hidden" name="orderDesc" id="orderDesc" value="订单title"/>
<input type="hidden" name="orderId" id="orderId" value="31bf4774c7654b689e0280e6db83a8be"/>
<input type="hidden" name="payTimeout" id="payTimeout" value="20171212233540"/>
<input type="hidden" name="signMethod" id="signMethod" value="01"/>
<input type="hidden" name="signature" id="signature" value="GXlNRjti/PTZXrFEgcxWZacYwUjmrRJQacpRnvYfXexofXTBrTdIF4d5uKedG9u4Sms0JB3QwcJcqnBlPbVpbkyykAIXbjhi2iEexE5mU8xiuLMNVx65ZECwMWygLc2ULffXNC9pLRZW5cV5g5zUVcsvEt+FIgFJjXX3LOC1duk="/>
<input type="hidden" name="txnAmt" id="txnAmt" value="100000"/>
<input type="hidden" name="txnSubType" id="txnSubType" value="01"/>
<input type="hidden" name="txnTime" id="txnTime" value="20171212232030"/>
<input type="hidden" name="txnType" id="txnType" value="01"/>
<input type="hidden" name="version" id="version" value="5.1.0"/>-->

View File

@@ -0,0 +1,2 @@
<html><head><meta http-equiv="Content-Type" content="text/html; charset=UTF-8"/></head><body><form id = "pay_form" action="https://gateway.test.95516.com/gateway/api/frontTransReq.do" method="post"></form></body><script type="text/javascript">document.all.pay_form.submit();</script></html>
<html><head><meta http-equiv="Content-Type" content="text/html; charset=UTF-8"/></head><body><form id = "pay_form" action="https://gateway.test.95516.com/gateway/api/frontTransReq.do" method="post"></form></body><script type="text/javascript">document.all.pay_form.submit();</script></html>

View File

@@ -18,10 +18,7 @@ public class UnionPayConfigStorage extends BasePayConfigStorage {
*/
private volatile String merId;
/**
* 应用私钥rsa_private pkcs8格式 生成签名时使用
*/
private volatile String keyPrivatePwd;
/**
* 商户收款账号
@@ -42,9 +39,9 @@ public class UnionPayConfigStorage extends BasePayConfigStorage {
super.setKeyPrivate(keyPrivate);
if (isCertSign() && keyPrivate.length() < 1024 && keyPrivate.contains(";")){
String[] split = keyPrivate.split(";");
keyPrivatePwd = split[1];
setKeyPrivateCertPwd( split[1]);
super.setKeyPrivate(split[0]);
getCertDescriptor().initPrivateSignCert(getKeyPrivate(), keyPrivatePwd, "PKCS12");
getCertDescriptor().initPrivateSignCert(getKeyPrivate(), getKeyPrivateCertPwd(), "PKCS12");
}
}
@@ -53,7 +50,9 @@ public class UnionPayConfigStorage extends BasePayConfigStorage {
public void setKeyPublic(String keyPublic) {
super.setKeyPublic(keyPublic);
if (isCertSign() && keyPublic.length() < 1024 ){
getCertDescriptor().initPublicCert(keyPublic);
String[] split = keyPublic.split(";");
getCertDescriptor().initPublicCert(split[0]);
getCertDescriptor().initRootCert(split[1]);
}
}

View File

@@ -10,17 +10,21 @@ import com.egzosn.pay.common.exception.PayErrorException;
import com.egzosn.pay.common.http.HttpConfigStorage;
import com.egzosn.pay.common.util.MatrixToImageWriter;
import com.egzosn.pay.common.util.sign.SignUtils;
import com.egzosn.pay.common.util.sign.encrypt.*;
import com.egzosn.pay.common.util.sign.encrypt.RSA;
import com.egzosn.pay.common.util.sign.encrypt.RSA2;
import com.egzosn.pay.common.util.str.StringUtils;
import com.egzosn.pay.union.sdk.SDKConstants;
import com.egzosn.pay.union.enums.UnionTransactionType;
import com.egzosn.pay.union.request.UnionQueryOrder;
import com.egzosn.pay.union.sdk.SDKConstants;
import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
import java.awt.image.BufferedImage;
import java.io.ByteArrayInputStream;
import java.io.InputStream;
import java.io.UnsupportedEncodingException;
import java.math.BigDecimal;
import java.security.cert.*;
import java.text.DateFormat;
import java.text.SimpleDateFormat;
import java.util.*;
@@ -32,7 +36,7 @@ import java.util.*;
*/
public class UnionPayService extends BasePayService {
//日志
protected static final Log LOG = LogFactory.getLog(UnionPayService.class);
protected static final Log log = LogFactory.getLog(UnionPayService.class);
/**
* 测试域名
*/
@@ -66,6 +70,7 @@ public class UnionPayService extends BasePayService {
public UnionPayService (PayConfigStorage payConfigStorage, HttpConfigStorage configStorage) {
super(payConfigStorage, configStorage);
}
@@ -83,7 +88,7 @@ public class UnionPayService extends BasePayService {
//商户代码
params.put(SDKConstants.param_merId, payConfigStorage.getPid());
DateFormat df = new SimpleDateFormat("YYYYMMDDhhmmss");
DateFormat df = new SimpleDateFormat("yyyyMMddHHmmss");
//订单发送时间
params.put(SDKConstants.param_txnTime, df.format(System.currentTimeMillis()));
// 订单超时时间。
@@ -126,7 +131,6 @@ public class UnionPayService extends BasePayService {
// 校验失败
}
}else{
}
return false;
}
@@ -214,13 +218,13 @@ public class UnionPayService extends BasePayService {
parameters.put(SDKConstants.param_signMethod, SDKConstants.SIGNMETHOD_RSA);
parameters.put(SDKConstants.param_certId, payConfigStorage.getCertDescriptor().getSignCertId());
signStr = SignUtils.SHA1.createSign( SignUtils.parameterText(parameters, "&", "signature"),"", payConfigStorage.getInputCharset());
parameters.put(SDKConstants.param_signature, RSA.sign(signStr, payConfigStorage.getCertDescriptor().getSignCertPrivateKey(), payConfigStorage.getInputCharset()));
parameters.put(SDKConstants.param_signature, RSA.sign(signStr, payConfigStorage.getCertDescriptor().getSignCertPrivateKey(payConfigStorage.getKeyPrivateCertPwd()), payConfigStorage.getInputCharset()));
break;
case RSA2:
parameters.put(SDKConstants.param_signMethod, SDKConstants.SIGNMETHOD_RSA);
parameters.put(SDKConstants.param_certId, payConfigStorage.getCertDescriptor().getSignCertId());
signStr = SignUtils.SHA256.createSign( SignUtils.parameterText(parameters, "&", "signature"),"", payConfigStorage.getInputCharset());
parameters.put(SDKConstants.param_signature, RSA2.sign(signStr, payConfigStorage.getCertDescriptor().getSignCertPrivateKey(), payConfigStorage.getInputCharset()));
parameters.put(SDKConstants.param_signature, RSA2.sign(signStr, payConfigStorage.getCertDescriptor().getSignCertPrivateKey(payConfigStorage.getKeyPrivateCertPwd()), payConfigStorage.getInputCharset()));
break;
case SHA1:
case SHA256:
@@ -254,7 +258,11 @@ public class UnionPayService extends BasePayService {
return RSA.verify(data, stringSign, payConfigStorage.getCertDescriptor().getPublicCert().getPublicKey(), payConfigStorage.getInputCharset());
case RSA2:
data = SignUtils.SHA256.createSign(data,"", payConfigStorage.getInputCharset());
return RSA2.verify(data, stringSign, payConfigStorage.getCertDescriptor().getPublicCert().getPublicKey(), payConfigStorage.getInputCharset());
X509Certificate cert = genCertificateByStr(resData.get(SDKConstants.param_signPubKeyCert).toString());
/*验证证书链*/
verifyCertificate(cert);
return RSA2.verify(data, stringSign,cert.getPublicKey(), payConfigStorage.getInputCharset());
// return RSA2.verify(data, stringSign, payConfigStorage.getCertDescriptor().getPublicCert().getPublicKey(), payConfigStorage.getInputCharset());
case SHA1:
case SHA256:
case SM3:
@@ -265,6 +273,50 @@ public class UnionPayService extends BasePayService {
}
}
/**
* 验证证书链
* @param cert
*/
private void verifyCertificate (X509Certificate cert) {
try {
cert.checkValidity();//验证有效期
X509Certificate middleCert = payConfigStorage.getCertDescriptor().getPublicCert();
X509Certificate rootCert = payConfigStorage.getCertDescriptor().getRootCert();
X509CertSelector selector = new X509CertSelector();
selector.setCertificate(cert);
Set<TrustAnchor> trustAnchors = new HashSet<TrustAnchor>();
trustAnchors.add(new TrustAnchor(rootCert, null));
PKIXBuilderParameters pkixParams = new PKIXBuilderParameters(
trustAnchors, selector);
Set<X509Certificate> intermediateCerts = new HashSet<X509Certificate>();
intermediateCerts.add(rootCert);
intermediateCerts.add(middleCert);
intermediateCerts.add(cert);
pkixParams.setRevocationEnabled(false);
CertStore intermediateCertStore = CertStore.getInstance("Collection",
new CollectionCertStoreParameters(intermediateCerts));
pkixParams.addCertStore(intermediateCertStore);
CertPathBuilder builder = CertPathBuilder.getInstance("PKIX");
@SuppressWarnings("unused")
PKIXCertPathBuilderResult result = (PKIXCertPathBuilderResult) builder
.build(pkixParams);
} catch (java.security.cert.CertPathBuilderException e) {
log.error("verify certificate chain fail.", e);
} catch (CertificateExpiredException e) {
log.error(e);
} catch (CertificateNotYetValidException e) {
log.error(e);
} catch (Exception e) {
log.error(e);
}
}
/**
* 获取输出二维码,用户返回给支付端,
*
@@ -368,6 +420,24 @@ public class UnionPayService extends BasePayService {
throw new PayErrorException(new PayException("1000", "验证签名失败", response.toJSONString()));
}
}
/**
* 将字符串转换为X509Certificate对象.
*
* @param x509CertString
* @return
*/
public static X509Certificate genCertificateByStr(String x509CertString) {
X509Certificate x509Cert = null;
try {
CertificateFactory cf = CertificateFactory.getInstance("X.509");
InputStream tIn = new ByteArrayInputStream(
x509CertString.getBytes("ISO-8859-1"));
x509Cert = (X509Certificate) cf.generateCertificate(tIn);
} catch (Exception e) {
log.error("gen certificate error", e);
}
return x509Cert;
}
/**
* 将请求参数或者请求流转化为 Map
@@ -378,7 +448,30 @@ public class UnionPayService extends BasePayService {
*/
@Override
public Map<String, Object> getParameter2Map (Map<String, String[]> parameterMap, InputStream is) {
return null;
Map<String, Object> params = new TreeMap<String,Object>();
for (Iterator iter = parameterMap.keySet().iterator(); iter.hasNext();) {
String name = (String) iter.next();
String[] values = parameterMap.get(name);
String valueStr = "";
for (int i = 0,len = values.length; i < len; i++) {
valueStr += (i == len - 1) ? values[i]
: values[i] + ",";
}
//乱码解决这段代码在出现乱码时使用。如果mysign和sign不相等也可以使用这段代码转化
//valueStr = new String(valueStr.getBytes("ISO-8859-1"), "gbk");
if (!valueStr.matches("\\w+")){
try {
if(valueStr.equals(new String(valueStr.getBytes("iso8859-1"), "iso8859-1"))){
valueStr=new String(valueStr.getBytes("iso8859-1"), payConfigStorage.getInputCharset());
}
} catch (UnsupportedEncodingException e) {
e.printStackTrace();
}
}
params.put(name, valueStr);
}
return params;
}
/**
@@ -415,7 +508,28 @@ public class UnionPayService extends BasePayService {
*/
@Override
public String buildRequest (Map<String, Object> orderInfo, MethodType method) {
return null;
StringBuffer sf = new StringBuffer();
sf.append("<html><head><meta http-equiv=\"Content-Type\" content=\"text/html; charset="+payConfigStorage.getInputCharset()+"\"/></head><body>");
sf.append("<form id = \"pay_form\" action=\"" + getFrontTransUrl()
+ "\" method=\"post\">");
if (null != orderInfo && 0 != orderInfo.size()) {
Set<Map.Entry<String, Object>> set = orderInfo.entrySet();
Iterator<Map.Entry<String, Object>> it = set.iterator();
while (it.hasNext()) {
Map.Entry<String, Object> ey = it.next();
String key = ey.getKey();
Object value = ey.getValue();
sf.append("<input type=\"hidden\" name=\"" + key + "\" id=\""
+ key + "\" value=\"" + value + "\"/>");
}
}
sf.append("</form>");
sf.append("</body>");
sf.append("<script type=\"text/javascript\">");
sf.append("document.all.pay_form.submit();");
sf.append("</script>");
sf.append("</html>");
return sf.toString();
}
@@ -542,6 +656,22 @@ public class UnionPayService extends BasePayService {
}
}
/**
* 将parameterMap对应的key存放至params
* @param parameterMap 请求参数
* @param params 转化的对象
* @param key 需要取值的key
* @return params
*/
public Map<String, Object> conversion(Map<String, String[]> parameterMap, Map<String, Object> params ,String key){
String[] values = parameterMap.get(key);
String valueStr = "";
for (int i = 0,len = values.length; i < len; i++) {
valueStr += (i == len - 1) ? values[i] : values[i] + ",";
}
params.put(key, valueStr);
return params;
}
/**
* 下载对账单
*
@@ -569,10 +699,10 @@ 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 getFrontTransUrl () {
return String.format(FRONT_TRANS_URL,payConfigStorage.isTest() ? TEST_BASE_DOMAIN : RELEASE_BASE_DOMAIN);
}
public String getBackTransUrl () {
return String.format(BACK_TRANS_URL, payConfigStorage.isTest() ? TEST_BASE_DOMAIN : RELEASE_BASE_DOMAIN);
}