com.alipay.api.AbstractAlipayClient Maven / Gradle / Ivy
Go to download
Show more of this group Show more artifacts with this name
Show all versions of alipay-sdk-java Show documentation
Show all versions of alipay-sdk-java Show documentation
Alipay openapi SDK for Java
Copyright © 2018 杭州蚂蚁金服
All rights reserved.
版权所有 (C)杭州蚂蚁金服
http://open.alipay.com
/**
* Alipay.com Inc. Copyright (c) 2004-2012 All Rights Reserved.
*/
package com.alipay.api;
import com.alipay.api.internal.parser.json.ObjectJsonParser;
import com.alipay.api.internal.parser.xml.ObjectXmlParser;
import com.alipay.api.internal.util.*;
import com.alipay.api.internal.util.codec.Base64;
import com.alipay.api.internal.util.file.FileUtils;
import com.alipay.api.internal.util.json.JSONWriter;
import javax.net.ssl.SSLException;
import java.io.ByteArrayInputStream;
import java.io.File;
import java.io.IOException;
import java.io.InputStream;
import java.security.NoSuchProviderException;
import java.security.PublicKey;
import java.security.Security;
import java.security.cert.CertificateException;
import java.security.cert.CertificateFactory;
import java.security.cert.X509Certificate;
import java.text.DateFormat;
import java.text.SimpleDateFormat;
import java.util.ArrayList;
import java.util.Date;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.TimeZone;
import java.util.concurrent.ConcurrentHashMap;
/**
* @author liuqun.lq
* @version $Id: AbstractAlipayClient.java, v 0.1 2018-07-03 10:45:21 liuqun.lq Exp $
*/
public abstract class AbstractAlipayClient implements AlipayClient {
/**
* 批量API默认分隔符
**/
private static final String BATCH_API_DEFAULT_SPLIT = "#S#";
static {
//清除安全设置
Security.setProperty("jdk.certpath.disabledAlgorithms", "");
}
protected boolean loadTest = false;
private String serverUrl;
private String appId;
private String prodCode;
private String format = AlipayConstants.FORMAT_JSON;
private String signType = AlipayConstants.SIGN_TYPE_RSA;
private String encryptType = AlipayConstants.ENCRYPT_TYPE_AES;
private String charset;
private int connectTimeout = 3000;
private int readTimeout = 15000;
private String proxyHost;
private int proxyPort;
private SignChecker signChecker;
private String appCertSN;
private String alipayCertSN;
private String alipayRootCertSN;
private String alipayRootSm2CertSN;
private String rootCertContent;
private X509Certificate cert;
private ConcurrentHashMap alipayPublicCertMap;
private ConcurrentHashMap alipayPublicKeyMap;
private Map headers;
private int maxIdleConnections = 0;
private long keepAliveDuration = 10000L;
private AbstractHttpClient customizedHttpClient;
public AbstractAlipayClient(String serverUrl, String appId, String format,
String charset, String signType) {
this.serverUrl = serverUrl;
this.appId = appId;
if (!StringUtils.isEmpty(format)) {
this.format = format;
}
this.charset = charset;
if (!StringUtils.isEmpty(signType)) {
this.signType = signType;
}
}
public AbstractAlipayClient(String serverUrl, String appId, String format,
String charset, String signType, String proxyHost,
int proxyPort) {
this(serverUrl, appId, format, charset, signType);
this.proxyHost = proxyHost;
this.proxyPort = proxyPort;
}
public AbstractAlipayClient(String serverUrl, String appId, String format,
String charset, String signType, String encryptType) {
this(serverUrl, appId, format, charset, signType);
if (!StringUtils.isEmpty(encryptType)) {
this.encryptType = encryptType;
}
}
public AbstractAlipayClient(String serverUrl, String appId, String format,
String charset, String signType,
String certPath, String certContent,
String alipayPublicCertPath, String alipayPublicCertContent,
String rootCertPath, String rootCertContent,
String proxyHost, int proxyPort, String encryptType) throws AlipayApiException {
this(serverUrl, appId, format, charset, signType);
if (!StringUtils.isEmpty(encryptType)) {
this.encryptType = encryptType;
}
this.proxyHost = proxyHost;
this.proxyPort = proxyPort;
//公钥证书未设置,提前返回,跳过后续证书初始化内容
if (StringUtils.isEmpty(alipayPublicCertContent) && StringUtils.isEmpty(alipayPublicCertPath)) {
return;
}
//读取根证书(用来校验本地支付宝公钥证书失效后自动从网关下载的新支付宝公钥证书是否有效)
if (StringUtils.isEmpty(rootCertContent) && StringUtils.isEmpty(rootCertPath)) {
throw new AlipayApiException(AlipayApiErrorEnum.ROOT_CERT_EMPTY_ERROR);
}
this.rootCertContent = StringUtils.isEmpty(rootCertContent) ? readFileToString(rootCertPath) : rootCertContent;
//alipayRootCertSN根证书序列号
if (AlipayConstants.SIGN_TYPE_SM2.equals(signType)) {
this.alipayRootSm2CertSN = AntCertificationUtil.getRootCertSN(this.rootCertContent, "SM2");
} else {
this.alipayRootCertSN = AntCertificationUtil.getRootCertSN(this.rootCertContent);
if (StringUtils.isEmpty(this.alipayRootCertSN)) {
throw new AlipayApiException(AlipayApiErrorEnum.ROOT_CERT_ERROR);
}
}
//获取应用证书
if (StringUtils.isEmpty(certContent) && StringUtils.isEmpty(certPath)) {
throw new AlipayApiException(AlipayApiErrorEnum.APP_CERT_EMPTY_ERROR);
}
try {
this.cert = StringUtils.isEmpty(certContent) ? AntCertificationUtil.getCertFromPath(certPath)
: AntCertificationUtil.getCertFromContent(certContent);
//appCertSN为最终发送给网关的应用证书序列号
this.appCertSN = AntCertificationUtil.getCertSN(cert);
} catch (AlipayApiException e) {
AlipayLogger.logBizError("提取应用公钥证书失败");
}
if (StringUtils.isEmpty(this.appCertSN)) {
throw new AlipayApiException(AlipayApiErrorEnum.APP_CERT_ERROR);
}
//获取支付宝公钥证书
try {
X509Certificate alipayPublicCert = StringUtils.isEmpty(alipayPublicCertContent) ?
AntCertificationUtil.getCertFromPath(alipayPublicCertPath) :
AntCertificationUtil.getCertFromContent(alipayPublicCertContent);
//alipayCertSN为支付宝公钥证书序列号
this.alipayCertSN = AntCertificationUtil.getCertSN(alipayPublicCert);
//将公钥证书以序列号为key存入map
ConcurrentHashMap alipayPublicCertMap = new ConcurrentHashMap();
alipayPublicCertMap.put(alipayCertSN, alipayPublicCert);
this.alipayPublicCertMap = alipayPublicCertMap;
//获取支付宝公钥以序列号为key存入map
PublicKey publicKey = alipayPublicCert.getPublicKey();
ConcurrentHashMap alipayPublicKeyMap = new ConcurrentHashMap();
alipayPublicKeyMap.put(alipayCertSN, Base64.encodeBase64String(publicKey.getEncoded()));
this.alipayPublicKeyMap = alipayPublicKeyMap;
} catch (AlipayApiException e) {
throw new AlipayApiException(AlipayApiErrorEnum.ALIPAY_PUBLIC_CERT_ERROR, e);
}
}
private String readFileToString(String rootCertPath) throws AlipayApiException {
try {
return FileUtils.readFileToString(new File(rootCertPath));
} catch (IOException e) {
throw new AlipayApiException(e);
}
}
//校验证书有效期以及是否支付宝颁发
private boolean verifyCert(String cert) {
return AntCertificationUtil.isTrusted(cert, this.rootCertContent);
}
public T certificateExecute(AlipayRequest request) throws AlipayApiException {
return certificateExecute(request, null);
}
public T certificateExecute(AlipayRequest request, String accessToken) throws AlipayApiException {
return certificateExecute(request, accessToken, null);
}
public T certificateExecute(AlipayRequest request, String accessToken,
String appAuthToken) throws AlipayApiException {
return _certificateExecute(request, accessToken, appAuthToken, null);
}
public T certificateExecute(AlipayRequest request, String accessToken,
String appAuthToken, String targetAppId) throws AlipayApiException {
return _certificateExecute(request, accessToken, appAuthToken, targetAppId);
}
public T _certificateExecute(AlipayRequest request, String accessToken,
String appAuthToken, String targetAppId) throws AlipayApiException {
T tRsp = null;
try {
long beginTime = System.currentTimeMillis();
Map rt = doPost(request, accessToken, appAuthToken, this.appCertSN, targetAppId);
Map costTimeMap = new HashMap();
if (rt.containsKey("prepareTime")) {
costTimeMap.put("prepareCostTime", (Long) (rt.get("prepareTime")) - beginTime);
if (rt.containsKey("requestTime")) {
costTimeMap.put("requestCostTime", (Long) (rt.get("requestTime")) - (Long) (rt.get("prepareTime")));
}
}
AlipayParser parser = null;
if (AlipayConstants.FORMAT_XML.equals(this.format)) {
parser = new ObjectXmlParser(request.getResponseClass());
} else {
parser = new ObjectJsonParser(request.getResponseClass());
}
// 若需要解密则先解密
ResponseEncryptItem responseItem = decryptResponse(request, rt, parser);
// 解析实际串
tRsp = parser.parse(responseItem.getRealContent());
tRsp.setBody(responseItem.getRealContent());
checkResponseCertSign(request, parser, responseItem.getRespContent(), tRsp.isSuccess());
if (costTimeMap.containsKey("requestCostTime")) {
costTimeMap.put("postCostTime", System.currentTimeMillis() - (Long) (rt.get("requestTime")));
}
tRsp.setParams((AlipayHashMap) rt.get("textParams"));
if (!tRsp.isSuccess()) {
AlipayLogger.logErrorScene(rt, tRsp, "", costTimeMap);
} else {
AlipayLogger.logBizSummary(rt, tRsp, costTimeMap);
}
return tRsp;
} catch (RuntimeException e) {
AlipayLogger.logBizError(e);
throw new AlipayApiException(e);
} catch (AlipayApiException e) {
AlipayLogger.logBizError(e);
throw new AlipayApiException(e);
}
}
/**
* 检查响应签名
*
* @param request
* @param parser
* @param responseBody
* @param responseIsSuccess
* @throws AlipayApiException
*/
private void checkResponseCertSign(AlipayRequest request,
AlipayParser parser,
String responseBody,
boolean responseIsSuccess) throws AlipayApiException {
CertItem certItem = parser.getCertItem(request, responseBody);
if (certItem == null) {
throw new AlipayApiException(AlipayApiErrorEnum.CHECK_CERT_BODY_EMPTY_ERROR);
}
if (certItem.getCert() == null && responseIsSuccess
&& !request.getApiMethodName().equals(AlipayOpenAppAlipaycertDownloadRequest.ALIPAYCERT_DOWNLOAD)) {
throw new AlipayApiException(AlipayApiErrorEnum.CHECK_ALIPAY_CERT_SN_EMPTY_ERROR);
}
String alipayPublicKey = null;
if (certItem.getCert() != null) {
if (!alipayPublicCertMap.containsKey(certItem.getCert())) {
//如果返回的支付宝公钥证书序列号与本地支付宝公钥证书序列号不匹配,通过返回的支付宝公钥证书序列号去网关拉取新的支付宝公钥证书
AlipayOpenAppAlipaycertDownloadRequest alipayRequest = new AlipayOpenAppAlipaycertDownloadRequest();
alipayRequest.setBizContent("{" +
"\"alipay_cert_sn\":\"" + certItem.getCert() + "\"" +
" }");
Map rt = doPost(alipayRequest, null, null, this.appCertSN, null);
// 解析实际串
String respContent = rt.get("rsp").toString();
AlipayParser parserCert = null;
parserCert = new ObjectJsonParser(alipayRequest.getResponseClass());
AlipayOpenAppAlipaycertDownloadResponse alipayResponse = parserCert.parse(respContent);
if (!alipayResponse.isSuccess()) {
throw new AlipayApiException(AlipayApiErrorEnum.CHECK_ALIPAY_CERT_SN_ERROR);
}
String alipayCertContent = alipayResponse.getAlipayCertContent();
InputStream inputStream = null;
try {
byte[] alipayCert = Base64.decodeBase64String(alipayCertContent);
String alipayPublicCertStr = new String(alipayCert);
if (!verifyCert(alipayPublicCertStr)) {
throw new AlipayApiException(AlipayApiErrorEnum.CHECK_ALIPAY_CERT_SN_ERROR);
}
inputStream = new ByteArrayInputStream(alipayCert);
CertificateFactory cf = CertificateFactory.getInstance("X.509", "BC");
X509Certificate alipayPublicCertNew = (X509Certificate) cf.generateCertificate(inputStream);
//获取新证书和公钥添加到map中
String alipayCertSNNew = AntCertificationUtil.getCertSN(alipayPublicCertNew);
this.alipayPublicCertMap.put(alipayCertSNNew, alipayPublicCertNew);
PublicKey publicKey = alipayPublicCertNew.getPublicKey();
String alipayPublicKeyNew = Base64.encodeBase64String(publicKey.getEncoded());
this.alipayPublicKeyMap.put(alipayCertSNNew, alipayPublicKeyNew);
} catch (NoSuchProviderException e) {
throw new AlipayApiException(e);
} catch (CertificateException e) {
throw new AlipayApiException(e);
} finally {
try {
if (inputStream != null) {
inputStream.close();
}
} catch (IOException e) {
throw new AlipayApiException(e);
}
}
} else if (!alipayPublicKeyMap.containsKey(certItem.getCert())) {
PublicKey publicKey = alipayPublicCertMap.get(certItem.getCert()).getPublicKey();
this.alipayPublicKeyMap.put(certItem.getCert(), Base64.encodeBase64String(publicKey.getEncoded()));
}
// 针对成功结果且有支付宝公钥的进行验签
if (alipayPublicCertMap.containsKey(certItem.getCert())) {
alipayPublicKey = this.alipayPublicKeyMap.get(certItem.getCert());
if (responseIsSuccess
|| (!responseIsSuccess && !StringUtils.isEmpty(certItem.getSign()))) {
signChecker = new DefaultSignChecker(alipayPublicKey);
boolean rsaCheckContent = signChecker.checkCert(certItem.getSignSourceDate(),
certItem.getSign(), this.signType, this.charset, alipayPublicKey);
if (!rsaCheckContent) {
// 针对JSON \/问题,替换/后再尝试做一次验证
if (!StringUtils.isEmpty(certItem.getSignSourceDate())
&& certItem.getSignSourceDate().contains("\\/")) {
String srouceData = certItem.getSignSourceDate().replace("\\/", "/");
boolean jsonCheck = getSignChecker().check(srouceData, certItem.getSign(),
this.signType, this.charset);
if (!jsonCheck) {
throw new AlipayApiException(AlipayApiErrorEnum.CHECK_CERT_JSON_ERROR);
}
} else {
throw new AlipayApiException(AlipayApiErrorEnum.CHECK_CERT_ERROR);
}
}
}
} else {
throw new AlipayApiException(AlipayApiErrorEnum.CHECK_CERT_EXIST_ERROR);
}
}
}
public T execute(AlipayRequest request) throws AlipayApiException {
return execute(request, null);
}
public T execute(AlipayRequest request,
String accessToken) throws AlipayApiException {
return execute(request, accessToken, null);
}
public T execute(AlipayRequest request, String accessToken,
String appAuthToken) throws AlipayApiException {
return execute(request, accessToken, appAuthToken, null);
}
public T execute(AlipayRequest request, String accessToken,
String appAuthToken, String targetAppId) throws AlipayApiException {
//如果根证书序列号非空,抛异常提示开发者使用certificateExecute
if (!StringUtils.isEmpty(this.alipayRootCertSN)) {
throw new AlipayApiException(AlipayApiErrorEnum.CERT_EXECUTE_ERROR);
}
AlipayParser parser = null;
if (AlipayConstants.FORMAT_XML.equals(this.format)) {
parser = new ObjectXmlParser(request.getResponseClass());
} else {
parser = new ObjectJsonParser(request.getResponseClass());
}
return _execute(request, parser, accessToken, appAuthToken, targetAppId);
}
public BatchAlipayResponse execute(BatchAlipayRequest request) throws AlipayApiException {
long beginTime = System.currentTimeMillis();
//发送请求
Map rt = doPost(request);
if (rt == null) {
return null;
}
Map costTimeMap = new HashMap();
if (rt.containsKey("prepareTime")) {
costTimeMap.put("prepareCostTime", (Long) (rt.get("prepareTime")) - beginTime);
if (rt.containsKey("requestTime")) {
costTimeMap.put("requestCostTime", (Long) (rt.get("requestTime")) - (Long) (rt.get("prepareTime")));
}
}
AlipayParser parser = null;
if (AlipayConstants.FORMAT_XML.equals(this.format)) {
parser = new ObjectXmlParser(request.getResponseClass());
} else {
parser = new ObjectJsonParser(request.getResponseClass());
}
BatchAlipayResponse batchAlipayResponse = null;
try {
// 若需要解密则先解密
ResponseEncryptItem responseItem = decryptResponse(request, rt, parser);
// 解析实际串
batchAlipayResponse = parser.parse(responseItem.getRealContent());
batchAlipayResponse.setBody(responseItem.getRealContent());
// 验签是对请求返回原始串
checkResponseSign(request, parser, responseItem.getRespContent(), batchAlipayResponse.isSuccess());
if (costTimeMap.containsKey("requestCostTime")) {
costTimeMap.put("postCostTime", System.currentTimeMillis() - (Long) (rt.get("requestTime")));
}
// 构造响应解释器
List> parserList = new ArrayList>();
List requestList = request.getRequestList();
if (AlipayConstants.FORMAT_XML.equals(this.format)) {
for (AlipayRequestWrapper aRequestList : requestList) {
parserList.add(new ObjectXmlParser(aRequestList.getAlipayRequest().getResponseClass()));
}
} else {
for (AlipayRequestWrapper aRequestList : requestList) {
parserList.add(new ObjectJsonParser(aRequestList.getAlipayRequest().getResponseClass()));
}
}
//批量调用失败,直接返回
if (!batchAlipayResponse.isSuccess()) {
return batchAlipayResponse;
}
String[] responseArray = batchAlipayResponse.getResponseBody().split(BATCH_API_DEFAULT_SPLIT);
//循环解析业务API响应
for (int index = 0; index < responseArray.length; index++) {
AlipayResponse alipayResponse = parserList.get(index).parse(responseArray[index]);
alipayResponse.setBody(responseArray[index]);
batchAlipayResponse.addResponse(alipayResponse);
}
AlipayLogger.logBizDebug((String) rt.get("rsp"));
return batchAlipayResponse;
} catch (RuntimeException e) {
AlipayLogger.logBizError((String) rt.get("rsp"), costTimeMap, rt);
throw e;
} catch (AlipayApiException e) {
AlipayLogger.logBizError((String) rt.get("rsp"), costTimeMap, rt);
throw new AlipayApiException(e);
}
}
/**
* @param request
* @return
* @throws AlipayApiException
*/
private Map doPost(BatchAlipayRequest request) throws AlipayApiException {
Map result = new HashMap();
RequestParametersHolder requestHolder = getRequestHolderWithSign(request);
String url = getRequestUrl(requestHolder);
// 打印完整请求报文
if (AlipayLogger.isBizDebugEnabled()) {
AlipayLogger.logBizDebug(getRedirectUrl(requestHolder));
}
result.put("prepareTime", System.currentTimeMillis());
String rsp = null;
Map resHeaders = new HashMap();
try {
rsp = WebUtils.doPost(url, requestHolder.getApplicationParams(), charset,
connectTimeout, readTimeout, proxyHost, proxyPort, headers, resHeaders);
} catch (IOException e) {
throw new AlipayApiException(e);
}
result.put("requestTime", System.currentTimeMillis());
result.put("rsp", rsp);
result.put("textParams", requestHolder.getApplicationParams());
result.put("protocalMustParams", requestHolder.getProtocalMustParams());
result.put("protocalOptParams", requestHolder.getProtocalOptParams());
result.put("url", url);
return result;
}
/**
* 组装批量请求接口参数,处理加密、签名逻辑
*
* @param request
* @return
* @throws AlipayApiException
*/
private RequestParametersHolder getRequestHolderWithSign(BatchAlipayRequest request)
throws AlipayApiException {
List requestList = request.getRequestList();
//校验接口列表非空
if (requestList == null || requestList.isEmpty()) {
throw new AlipayApiException("40", "client-error:api request list is empty");
}
RequestParametersHolder requestHolder = new RequestParametersHolder();
//添加协议必须参数
AlipayHashMap protocalMustParams = new AlipayHashMap();
protocalMustParams.put(AlipayConstants.METHOD, request.getApiMethodName());
protocalMustParams.put(AlipayConstants.APP_ID, this.appId);
protocalMustParams.put(AlipayConstants.SIGN_TYPE, this.signType);
protocalMustParams.put(AlipayConstants.CHARSET, charset);
protocalMustParams.put(AlipayConstants.VERSION, request.getApiVersion());
if (request.isNeedEncrypt()) {
protocalMustParams.put(AlipayConstants.ENCRYPT_TYPE, this.encryptType);
}
//添加协议可选参数
AlipayHashMap protocalOptParams = new AlipayHashMap();
protocalOptParams.put(AlipayConstants.FORMAT, format);
protocalOptParams.put(AlipayConstants.ALIPAY_SDK, AlipayConstants.SDK_VERSION);
requestHolder.setProtocalOptParams(protocalOptParams);
Long timestamp = System.currentTimeMillis();
DateFormat df = new SimpleDateFormat(AlipayConstants.DATE_TIME_FORMAT);
df.setTimeZone(TimeZone.getTimeZone(AlipayConstants.DATE_TIMEZONE));
protocalMustParams.put(AlipayConstants.TIMESTAMP, df.format(new Date(timestamp)));
requestHolder.setProtocalMustParams(protocalMustParams);
//设置业务参数
AlipayHashMap appParams = new AlipayHashMap();
//构造请求主题
StringBuilder requestBody = new StringBuilder();
// 组装每个API的请求参数
for (int index = 0; index < requestList.size(); index++) {
AlipayRequestWrapper alipayRequestWrapper = requestList.get(index);
AlipayRequest alipayRequest = alipayRequestWrapper.getAlipayRequest();
Map apiParams = alipayRequest.getTextParams();
apiParams.put(AlipayConstants.METHOD, alipayRequest.getApiMethodName());
apiParams.put(AlipayConstants.APP_AUTH_TOKEN, alipayRequestWrapper.getAppAuthToken());
apiParams.put(AlipayConstants.ACCESS_TOKEN, alipayRequestWrapper.getAccessToken());
apiParams.put(AlipayConstants.TARGET_APP_ID, alipayRequestWrapper.getTargetAppId());
apiParams.put(AlipayConstants.PROD_CODE, alipayRequest.getProdCode());
apiParams.put(AlipayConstants.NOTIFY_URL, alipayRequest.getNotifyUrl());
apiParams.put(AlipayConstants.RETURN_URL, alipayRequest.getReturnUrl());
apiParams.put(AlipayConstants.TERMINAL_INFO, alipayRequest.getTerminalInfo());
apiParams.put(AlipayConstants.TERMINAL_TYPE, alipayRequest.getTerminalType());
apiParams.put(AlipayConstants.BATCH_REQUEST_ID, String.valueOf(index));
// 仅当API包含biz_content参数且值为空时,序列化bizModel填充bizContent
try {
if (alipayRequest.getClass().getMethod("getBizContent") != null
&& StringUtils.isEmpty(appParams.get(AlipayConstants.BIZ_CONTENT_KEY))
&& alipayRequest.getBizModel() != null) {
apiParams.put(AlipayConstants.BIZ_CONTENT_KEY,
new JSONWriter().write(alipayRequest.getBizModel(), true));
}
} catch (NoSuchMethodException e) {
// 找不到getBizContent则什么都不做
} catch (SecurityException e) {
AlipayLogger.logBizError(e);
}
requestBody.append(new JSONWriter().write(apiParams, false));
if (index != requestList.size() - 1) {
requestBody.append(BATCH_API_DEFAULT_SPLIT);
}
}
appParams.put(AlipayConstants.BIZ_CONTENT_KEY, requestBody.toString());
// 只有新接口和设置密钥才能支持加密
if (request.isNeedEncrypt()) {
if (StringUtils.isEmpty(appParams.get(AlipayConstants.BIZ_CONTENT_KEY))) {
throw new AlipayApiException(AlipayApiErrorEnum.ENCRYPT_IS_NEED_ERROR);
}
// 需要加密必须设置密钥和加密算法
if (StringUtils.isEmpty(this.encryptType) || getEncryptor() == null) {
throw new AlipayApiException(AlipayApiErrorEnum.ENCRYPT_EMPTY_ERROR);
}
String encryptContent = getEncryptor().encrypt(
appParams.get(AlipayConstants.BIZ_CONTENT_KEY), this.encryptType, this.charset);
appParams.put(AlipayConstants.BIZ_CONTENT_KEY, encryptContent);
}
requestHolder.setApplicationParams(appParams);
if (!StringUtils.isEmpty(this.signType)) {
String signContent = AlipaySignature.getSignatureContent(requestHolder);
protocalMustParams.put(AlipayConstants.SIGN,
getSigner().sign(signContent, this.signType, charset));
} else {
protocalMustParams.put(AlipayConstants.SIGN, "");
}
return requestHolder;
}
public T pageExecute(AlipayRequest request) throws AlipayApiException {
return pageExecute(request, "POST");
}
public T pageExecute(AlipayRequest request,
String httpMethod) throws AlipayApiException {
RequestParametersHolder requestHolder = getRequestHolderWithSign(request, null, null,
this.appCertSN, null);
// 打印完整请求报文
if (AlipayLogger.isBizDebugEnabled()) {
AlipayLogger.logBizDebug(getRedirectUrl(requestHolder));
}
T rsp = null;
try {
Class clazz = request.getResponseClass();
rsp = clazz.newInstance();
} catch (InstantiationException e) {
AlipayLogger.logBizError(e);
} catch (IllegalAccessException e) {
AlipayLogger.logBizError(e);
}
if ("GET".equalsIgnoreCase(httpMethod)) {
rsp.setBody(getRedirectUrl(requestHolder));
} else {
String baseUrl = getRequestUrl(requestHolder);
rsp.setBody(WebUtils.buildForm(baseUrl, requestHolder.getApplicationParams()));
}
return rsp;
}
public T sdkExecute(AlipayRequest request) throws AlipayApiException {
RequestParametersHolder requestHolder = getRequestHolderWithSign(request, null, null,
this.appCertSN, null);
// 打印完整请求报文
if (AlipayLogger.isBizDebugEnabled()) {
AlipayLogger.logBizDebug(getSdkParams(requestHolder));
}
T rsp = null;
try {
Class clazz = request.getResponseClass();
rsp = clazz.newInstance();
} catch (InstantiationException e) {
AlipayLogger.logBizError(e);
} catch (IllegalAccessException e) {
AlipayLogger.logBizError(e);
}
rsp.setBody(getSdkParams(requestHolder));
return rsp;
}
public > TR parseAppSyncResult(Map result,
Class requsetClazz) throws AlipayApiException {
TR tRsp = null;
String rsp = result.get("result");
try {
T request = requsetClazz.newInstance();
Class responseClazz = request.getResponseClass();
//result为空直接返回SYSTEM_ERROR
if (StringUtils.isEmpty(rsp)) {
tRsp = responseClazz.newInstance();
tRsp.setCode("20000");
tRsp.setSubCode("ACQ.SYSTEM_ERROR");
tRsp.setSubMsg(result.get("memo"));
} else {
AlipayParser parser = null;
if (AlipayConstants.FORMAT_XML.equals(this.format)) {
parser = new ObjectXmlParser (responseClazz);
} else {
parser = new ObjectJsonParser (responseClazz);
}
// 解析实际串
tRsp = parser.parse(rsp);
tRsp.setBody(rsp);
// 验签是对请求返回原始串
checkResponseSign(request, parser, rsp, tRsp.isSuccess());
if (!tRsp.isSuccess()) {
AlipayLogger.logBizError(rsp);
}
}
} catch (RuntimeException e) {
AlipayLogger.logBizError(rsp);
throw e;
} catch (AlipayApiException e) {
AlipayLogger.logBizError(rsp);
throw new AlipayApiException(e);
} catch (InstantiationException e) {
AlipayLogger.logBizError(rsp);
throw new AlipayApiException(e);
} catch (IllegalAccessException e) {
AlipayLogger.logBizError(rsp);
throw new AlipayApiException(e);
}
return tRsp;
}
/**
* 组装接口参数,处理加密、签名逻辑
*
* @param request
* @param accessToken
* @param appAuthToken
* @param appCertSN 应用证书序列号
* @return
* @throws AlipayApiException
*/
private RequestParametersHolder getRequestHolderWithSign(AlipayRequest> request,
String accessToken, String appAuthToken,
String appCertSN, String targetAppId)
throws AlipayApiException {
RequestParametersHolder requestHolder = new RequestParametersHolder();
AlipayHashMap appParams = new AlipayHashMap(request.getTextParams());
// 仅当API包含biz_content参数且值为空时,序列化bizModel填充bizContent
try {
if (request.getClass().getMethod("getBizContent") != null
&& StringUtils.isEmpty(appParams.get(AlipayConstants.BIZ_CONTENT_KEY))
&& request.getBizModel() != null) {
appParams.put(AlipayConstants.BIZ_CONTENT_KEY,
new JSONWriter().write(request.getBizModel(), true));
}
} catch (NoSuchMethodException e) {
// 找不到getBizContent则什么都不做
} catch (SecurityException e) {
AlipayLogger.logBizError(e);
}
// 只有新接口和设置密钥才能支持加密
if (request.isNeedEncrypt()) {
if (StringUtils.isEmpty(appParams.get(AlipayConstants.BIZ_CONTENT_KEY))) {
throw new AlipayApiException(AlipayApiErrorEnum.ENCRYPT_IS_NEED_ERROR);
}
// 需要加密必须设置密钥和加密算法
if (StringUtils.isEmpty(this.encryptType) || getEncryptor() == null) {
throw new AlipayApiException(AlipayApiErrorEnum.ENCRYPT_EMPTY_ERROR);
}
String encryptContent = getEncryptor().encrypt(
appParams.get(AlipayConstants.BIZ_CONTENT_KEY), this.encryptType, this.charset);
appParams.put(AlipayConstants.BIZ_CONTENT_KEY, encryptContent);
}
if (!StringUtils.isEmpty(appAuthToken)) {
appParams.put(AlipayConstants.APP_AUTH_TOKEN, appAuthToken);
}
requestHolder.setApplicationParams(appParams);
if (StringUtils.isEmpty(charset)) {
charset = AlipayConstants.CHARSET_UTF8;
}
AlipayHashMap protocalMustParams = new AlipayHashMap();
protocalMustParams.put(AlipayConstants.METHOD, request.getApiMethodName());
protocalMustParams.put(AlipayConstants.VERSION, request.getApiVersion());
protocalMustParams.put(AlipayConstants.APP_ID, this.appId);
protocalMustParams.put(AlipayConstants.SIGN_TYPE, this.signType);
protocalMustParams.put(AlipayConstants.TERMINAL_TYPE, request.getTerminalType());
protocalMustParams.put(AlipayConstants.TERMINAL_INFO, request.getTerminalInfo());
protocalMustParams.put(AlipayConstants.NOTIFY_URL, request.getNotifyUrl());
protocalMustParams.put(AlipayConstants.RETURN_URL, request.getReturnUrl());
protocalMustParams.put(AlipayConstants.CHARSET, charset);
if (!StringUtils.isEmpty(targetAppId)) {
protocalMustParams.put(AlipayConstants.TARGET_APP_ID, targetAppId);
}
if (request.isNeedEncrypt()) {
protocalMustParams.put(AlipayConstants.ENCRYPT_TYPE, this.encryptType);
}
//如果应用证书序列号非空,添加应用证书序列号
if (!StringUtils.isEmpty(appCertSN)) {
protocalMustParams.put(AlipayConstants.APP_CERT_SN, appCertSN);
}
//如果根证书序列号非空,添加根证书序列号
if (!StringUtils.isEmpty(this.alipayRootCertSN)) {
protocalMustParams.put(AlipayConstants.ALIPAY_ROOT_CERT_SN, this.alipayRootCertSN);
}
//如果SM2根证书序列号非空,添加SM2根证书序列号
if (!StringUtils.isEmpty(this.alipayRootSm2CertSN)) {
protocalMustParams.put(AlipayConstants.ALIPAY_ROOT_CERT_SN, this.alipayRootSm2CertSN);
}
Long timestamp = System.currentTimeMillis();
DateFormat df = new SimpleDateFormat(AlipayConstants.DATE_TIME_FORMAT);
df.setTimeZone(TimeZone.getTimeZone(AlipayConstants.DATE_TIMEZONE));
protocalMustParams.put(AlipayConstants.TIMESTAMP, df.format(new Date(timestamp)));
requestHolder.setProtocalMustParams(protocalMustParams);
AlipayHashMap protocalOptParams = new AlipayHashMap();
protocalOptParams.put(AlipayConstants.FORMAT, format);
protocalOptParams.put(AlipayConstants.ACCESS_TOKEN, accessToken);
protocalOptParams.put(AlipayConstants.ALIPAY_SDK, AlipayConstants.SDK_VERSION);
protocalOptParams.put(AlipayConstants.PROD_CODE, request.getProdCode());
requestHolder.setProtocalOptParams(protocalOptParams);
if (!StringUtils.isEmpty(this.signType)) {
String signContent = AlipaySignature.getSignatureContent(requestHolder);
protocalMustParams.put(AlipayConstants.SIGN,
getSigner().sign(signContent, this.signType, charset));
} else {
protocalMustParams.put(AlipayConstants.SIGN, "");
}
return requestHolder;
}
/**
* 获取POST请求的base url
*
* @param requestHolder
* @return
* @throws AlipayApiException
*/
private String getRequestUrl(RequestParametersHolder requestHolder) throws AlipayApiException {
StringBuilder urlSb = new StringBuilder(serverUrl);
try {
String sysMustQuery = WebUtils.buildQuery(loadTest ?
LoadTestUtil.getParamsWithLoadTestFlag(requestHolder.getProtocalMustParams())
: requestHolder.getProtocalMustParams(), charset);
String sysOptQuery = WebUtils.buildQuery(requestHolder.getProtocalOptParams(), charset);
urlSb.append("?");
urlSb.append(sysMustQuery);
if (sysOptQuery != null && sysOptQuery.length() > 0) {
urlSb.append("&");
urlSb.append(sysOptQuery);
}
} catch (IOException e) {
throw new AlipayApiException(e);
}
return urlSb.toString();
}
/**
* GET模式下获取跳转链接
*
* @param requestHolder
* @return
* @throws AlipayApiException
*/
private String getRedirectUrl(RequestParametersHolder requestHolder) throws AlipayApiException {
StringBuilder urlSb = new StringBuilder(serverUrl);
try {
Map sortedMap = AlipaySignature.getSortedMap(requestHolder);
String sortedQuery = WebUtils.buildQuery(loadTest ?
LoadTestUtil.getParamsWithLoadTestFlag(sortedMap) : sortedMap, charset);
urlSb.append("?");
urlSb.append(sortedQuery);
} catch (IOException e) {
throw new AlipayApiException(e);
}
return urlSb.toString();
}
/**
* 拼装sdk调用时所传参数
*
* @param requestHolder
* @return
* @throws AlipayApiException
*/
private String getSdkParams(RequestParametersHolder requestHolder) throws AlipayApiException {
StringBuilder urlSb = new StringBuilder();
try {
Map sortedMap = AlipaySignature.getSortedMap(requestHolder);
String sortedQuery = WebUtils.buildQuery(loadTest ?
LoadTestUtil.getParamsWithLoadTestFlag(sortedMap) : sortedMap, charset);
urlSb.append(sortedQuery);
} catch (IOException e) {
throw new AlipayApiException(e);
}
return urlSb.toString();
}
private T _execute(AlipayRequest request, AlipayParser parser,
String authToken, String appAuthToken,
String targetAppId) throws AlipayApiException {
long beginTime = System.currentTimeMillis();
//适配新增证书序列号的请求
Map rt = doPost(request, authToken, appAuthToken, null, targetAppId);
if (rt == null) {
return null;
}
Map costTimeMap = new HashMap();
if (rt.containsKey("prepareTime")) {
costTimeMap.put("prepareCostTime", (Long) (rt.get("prepareTime")) - beginTime);
if (rt.containsKey("requestTime")) {
costTimeMap.put("requestCostTime", (Long) (rt.get("requestTime")) - (Long) (rt.get("prepareTime")));
}
}
T tRsp = null;
try {
// 若需要解密则先解密
ResponseEncryptItem responseItem = decryptResponse(request, rt, parser);
// 解析实际串
tRsp = parser.parse(responseItem.getRealContent());
tRsp.setBody(responseItem.getRealContent());
// 验签是对请求返回原始串
checkResponseSign(request, parser, responseItem.getRespContent(), tRsp.isSuccess());
if (costTimeMap.containsKey("requestCostTime")) {
costTimeMap.put("postCostTime", System.currentTimeMillis() - (Long) (rt.get("requestTime")));
}
} catch (RuntimeException e) {
AlipayLogger.logBizError((String) rt.get("rsp"), costTimeMap, rt);
throw e;
} catch (AlipayApiException e) {
AlipayLogger.logBizError((String) rt.get("rsp"), costTimeMap, rt);
throw new AlipayApiException(e);
}
tRsp.setParams((AlipayHashMap) rt.get("textParams"));
if (!tRsp.isSuccess()) {
addTraceId(tRsp, rt);
AlipayLogger.logErrorScene(rt, tRsp, "", costTimeMap);
} else {
AlipayLogger.logBizSummary(rt, tRsp, costTimeMap);
}
return tRsp;
}
/**
* @param request
* @param accessToken
* @param appAuthToken
* @param appCertSN 应用证书序列号
* @return
* @throws AlipayApiException
*/
private Map doPost(AlipayRequest request,
String accessToken, String appAuthToken,
String appCertSN, String targetAppId) throws AlipayApiException {
Map result = new HashMap();
RequestParametersHolder requestHolder = getRequestHolderWithSign(request, accessToken,
appAuthToken, appCertSN, targetAppId);
String url = getRequestUrl(requestHolder);
// 打印完整请求报文
if (AlipayLogger.isBizDebugEnabled()) {
AlipayLogger.logBizDebug(getRedirectUrl(requestHolder));
}
result.put("prepareTime", System.currentTimeMillis());
String rsp = null;
Map resHeaders = new HashMap();
try {
if (request instanceof AlipayUploadRequest) {
AlipayUploadRequest uRequest = (AlipayUploadRequest) request;
Map fileParams = AlipayUtils.cleanupMap(uRequest.getFileParams());
rsp = customizedHttpClient == null ? WebUtils.doPost(url, requestHolder.getApplicationParams(), fileParams,
charset, connectTimeout, readTimeout, proxyHost, proxyPort, headers, resHeaders)
: customizedHttpClient.doPost(url, requestHolder.getApplicationParams(), fileParams, charset, resHeaders);
} else {
rsp = customizedHttpClient == null ? WebUtils.doPost(url, requestHolder.getApplicationParams(), charset,
connectTimeout, readTimeout, proxyHost, proxyPort, headers, resHeaders)
: customizedHttpClient.doPost(url, requestHolder.getApplicationParams(), charset, resHeaders);
}
} catch (SSLException e) {
if (e.getMessage().contains("the trustAnchors parameter must be non-empty")
|| e.getMessage().contains("PKIX path building failed")) {
throw new AlipayApiException("SDK已默认开启SSL服务端证书校验,"
+ "请确认本地JRE默认自带的CA证书库是否正确(JRE主目录下的lib/security/cacerts是否存在。" + e.getMessage(), e);
}
throw new AlipayApiException(e);
} catch (IOException e) {
throw new AlipayApiException(e);
}
result.put("requestTime", System.currentTimeMillis());
result.put("rsp", rsp);
result.put("textParams", requestHolder.getApplicationParams());
result.put("protocalMustParams", requestHolder.getProtocalMustParams());
result.put("protocalOptParams", requestHolder.getProtocalOptParams());
result.put("url", url);
if (resHeaders.containsKey("trace_id")) {
result.put("trace_id", resHeaders.get("trace_id"));
}
return result;
}
/**
* 检查响应签名
*
* @param request
* @param parser
* @param responseBody
* @param responseIsSucess
* @throws AlipayApiException
*/
private void checkResponseSign(AlipayRequest request,
AlipayParser parser,
String responseBody,
boolean responseIsSucess) throws AlipayApiException {
// 针对成功结果且有支付宝公钥的进行验签
if (getSignChecker() != null) {
SignItem signItem = parser.getSignItem(request, responseBody);
if (signItem == null) {
throw new AlipayApiException(AlipayApiErrorEnum.CHECK_SIGN_BODY_EMPTY_ERROR);
}
if (responseIsSucess
|| (!responseIsSucess && !StringUtils.isEmpty(signItem.getSign()))) {
// RSA或RSA2时检查当前公钥是不是应用公钥
if ((AlipayConstants.SIGN_TYPE_RSA.equals(this.signType) || AlipayConstants.SIGN_TYPE_RSA2.equals(this.signType))
&& checkAlipayPublicKey()) {
throw new AlipayApiException(AlipayApiErrorEnum.CHECK_ALIPAY_PUBLIC_KEY_ERROR);
}
boolean rsaCheckContent = getSignChecker().check(signItem.getSignSourceDate(),
signItem.getSign(), this.signType, this.charset);
if (!rsaCheckContent) {
// 针对JSON \/问题,替换/后再尝试做一次验证
if (!StringUtils.isEmpty(signItem.getSignSourceDate())
&& signItem.getSignSourceDate().contains("\\/")) {
String srouceData = signItem.getSignSourceDate().replace("\\/", "/");
boolean jsonCheck = getSignChecker().check(srouceData, signItem.getSign(),
this.signType, this.charset);
if (!jsonCheck) {
throw new AlipayApiException(AlipayApiErrorEnum.CHECK_SIGN_JSON_ERROR);
}
} else {
throw new AlipayApiException(AlipayApiErrorEnum.CHECK_SIGN_ERROR);
}
}
}
}
}
/**
* 判断alipayPublicKey是否是应用公钥
*
* @return
*/
public boolean checkAlipayPublicKey() {
String content = "checkAlipayPublicKey";
boolean rsaCheckContent = false;
try {
String signContent = getSigner().sign(content, this.signType, charset);
rsaCheckContent = getSignChecker().check(content, signContent, this.signType, this.charset);
} catch (Exception ignored) {
}
return rsaCheckContent;
}
/**
* 解密响应
*
* @param request
* @param rt
* @param parser
* @return
* @throws AlipayApiException
*/
private ResponseEncryptItem decryptResponse(AlipayRequest request,
Map rt,
AlipayParser parser) throws AlipayApiException {
String responseBody = (String) rt.get("rsp");
if (StringUtils.isEmpty(responseBody)) {
throw new AlipayApiException(AlipayApiErrorEnum.RESPONSE_BODY_EMPTY_ERROR);
}
String realBody = null;
// 解密
if (request.isNeedEncrypt()) {
// 解密原始串
realBody = parser.decryptSourceData(request, responseBody, this.format,
getDecryptor(), this.encryptType, this.charset);
} else {
// 解析原内容串
realBody = (String) rt.get("rsp");
}
return new ResponseEncryptItem(responseBody, realBody);
}
private void addTraceId(AlipayResponse response, Map rt) {
if (response == null) {
return;
}
Map params = response.getParams();
if (params == null) {
return;
}
if (rt == null) {
return;
}
if (!rt.containsKey("trace_id")) {
return;
}
String traceId = (String) rt.get("trace_id");
if (traceId == null || traceId.equals("")) {
return;
}
params.put("traceId", traceId);
}
void setServerUrl(String serverUrl) {
this.serverUrl = serverUrl;
}
void setAppId(String appId) {
this.appId = appId;
}
void setProdCode(String prodCode) {
this.prodCode = prodCode;
}
void setFormat(String format) {
this.format = format;
}
void setSignType(String signType) {
this.signType = signType;
}
void setEncryptType(String encryptType) {
this.encryptType = encryptType;
}
void setCharset(String charset) {
this.charset = charset;
}
public void setConnectTimeout(int connectTimeout) {
this.connectTimeout = connectTimeout;
}
public void setReadTimeout(int readTimeout) {
this.readTimeout = readTimeout;
}
/**
* 设置自定义http的header
*
* @param headers 自定义http的header
*/
void setHeaders(Map headers) {
this.headers = headers;
}
void setProxyHost(String proxyHost) {
this.proxyHost = proxyHost;
}
void setProxyPort(int proxyPort) {
this.proxyPort = proxyPort;
}
void setCert(X509Certificate cert) {
this.cert = cert;
}
void setAlipayPublicCertMap(ConcurrentHashMap alipayPublicCertMap) {
this.alipayPublicCertMap = alipayPublicCertMap;
}
public void setMaxIdleConnections(int maxIdleConnections) {
this.maxIdleConnections = maxIdleConnections;
}
public void setKeepAliveDuration(long keepAliveDuration) throws AlipayApiException {
if (keepAliveDuration > 60000) {
throw new AlipayApiException(AlipayApiErrorEnum.KEEPALIVE_DURATION_ERROR);
}
this.keepAliveDuration = keepAliveDuration;
}
public void setCustomizedHttpClient(AbstractHttpClient customizedHttpClient) {
this.customizedHttpClient = customizedHttpClient;
if (this.customizedHttpClient == null && maxIdleConnections > 0) {
this.customizedHttpClient = new HttpClientUtil();
}
//初始化变量
if (this.customizedHttpClient != null) {
this.customizedHttpClient.setConnectTimeout(connectTimeout);
this.customizedHttpClient.setReadTimeout(readTimeout);
this.customizedHttpClient.setCustomHeaders(headers);
this.customizedHttpClient.setProxyHost(proxyHost);
this.customizedHttpClient.setProxyPort(proxyPort);
this.customizedHttpClient.setMaxIdleConnections(maxIdleConnections);
this.customizedHttpClient.setKeepAliveDuration(keepAliveDuration);
}
}
public abstract Signer getSigner();
public abstract SignChecker getSignChecker();
public abstract Encryptor getEncryptor();
public abstract Decryptor getDecryptor();
}
© 2015 - 2024 Weber Informatics LLC | Privacy Policy