admin
2020-11-19 648d17212584aaed758035bcb3b591a025289b3a
支付宝工具优化
13个文件已添加
2个文件已修改
1987 ■■■■■ 已修改文件
utils/pom.xml 8 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
utils/src/main/java/org/yeshi/utils/alipay/AlipayUtil.java 166 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
utils/src/main/java/org/yeshi/utils/alipay/AlipayXcxUtil.java 80 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
utils/src/main/java/org/yeshi/utils/alipay/CertAlipayClient.java 79 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
utils/src/main/java/org/yeshi/utils/alipay/MyAbstractAlipayClient.java 1178 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
utils/src/main/java/org/yeshi/utils/alipay/MyCertAlipayRequest.java 35 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
utils/src/main/java/org/yeshi/utils/entity/alipay/AlipayAppInfo.java 46 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
utils/src/main/java/org/yeshi/utils/entity/alipay/AlipayCertInfo.java 39 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
utils/src/main/java/org/yeshi/utils/entity/alipay/AlipayTransferAccount.java 42 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
utils/src/main/java/org/yeshi/utils/entity/alipay/AlipayTransferInfo.java 134 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
utils/src/main/java/org/yeshi/utils/exception/AlipayCommonException.java 12 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
utils/src/main/java/org/yeshi/utils/exception/AlipayTransferException.java 39 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
utils/src/main/java/org/yeshi/utils/exception/AlipayXcxException.java 12 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
utils/src/test/java/com/yeshi/utils/AlipayTest.java 101 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
utils/src/test/java/com/yeshi/utils/Test.java 16 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
utils/pom.xml
@@ -37,6 +37,14 @@
      <version>build210</version>
    </dependency>
    <!-- https://mvnrepository.com/artifact/com.alipay.sdk/alipay-easysdk -->
    <dependency>
      <groupId>com.alipay.sdk</groupId>
      <artifactId>alipay-easysdk</artifactId>
      <version>2.1.0</version>
    </dependency>
  </dependencies>
</project>
utils/src/main/java/org/yeshi/utils/alipay/AlipayUtil.java
New file
@@ -0,0 +1,166 @@
package org.yeshi.utils.alipay;
import com.alibaba.fastjson.JSON;
import com.alipay.api.AlipayApiException;
import com.alipay.api.AlipayClient;
import com.alipay.api.CertAlipayRequest;
import com.alipay.api.DefaultAlipayClient;
import com.alipay.api.request.AlipayFundAccountQueryRequest;
import com.alipay.api.request.AlipayFundTransCommonQueryRequest;
import com.alipay.api.request.AlipayFundTransUniTransferRequest;
import com.alipay.api.response.AlipayFundAccountQueryResponse;
import com.alipay.api.response.AlipayFundTransCommonQueryResponse;
import com.alipay.api.response.AlipayFundTransUniTransferResponse;
import net.sf.json.JSONObject;
import org.yeshi.utils.StringUtil;
import org.yeshi.utils.entity.alipay.AlipayAppInfo;
import org.yeshi.utils.entity.alipay.AlipayCertInfo;
import org.yeshi.utils.entity.alipay.AlipayTransferInfo;
import org.yeshi.utils.exception.AlipayCommonException;
import org.yeshi.utils.exception.AlipayTransferException;
import java.math.BigDecimal;
public class AlipayUtil {
    public static AlipayClient getAlipayClient(AlipayAppInfo app) {
        AlipayClient alipayClient = new DefaultAlipayClient("https://openapi.alipay.com/gateway.do", app.getAppId(), app.getPrivateKey(), "json", "GBK", app.getAlipayPublicKey(), "RSA2");
        return alipayClient;
    }
    private static AlipayClient getAlipayClient(AlipayAppInfo app, AlipayCertInfo info) throws AlipayApiException {
        String privateKey = app.getPrivateKey();
        MyCertAlipayRequest certAlipayRequest = new MyCertAlipayRequest();
        certAlipayRequest.setServerUrl("https://openapi.alipay.com/gateway.do");
        certAlipayRequest.setAppId(app.getAppId());
        certAlipayRequest.setPrivateKey(privateKey);
        certAlipayRequest.setFormat("json");
        certAlipayRequest.setCharset("GBK");
        certAlipayRequest.setSignType("RSA2");
        certAlipayRequest.setCertStream(
                info.getAppCertPublicKeyStream());
        certAlipayRequest.setAlipayPublicCertStream(
                info.getAlipayPublicCertStream());
        certAlipayRequest.setRootCertStream(
                info.getAlipayRootCertStream());
        return new CertAlipayClient(certAlipayRequest);
    }
    /**
     * 统一转账(包含红包与转账)
     *
     * @param app
     * @param info
     * @param certInfo
     * @return
     * @throws AlipayApiException
     * @throws NumberFormatException
     * @throws AlipayTransferException
     */
    public static AlipayFundTransUniTransferResponse alipayFundTransUniTransfer(AlipayAppInfo app, AlipayTransferInfo info, AlipayCertInfo certInfo)
            throws AlipayApiException, NumberFormatException, AlipayTransferException {
        AlipayFundTransUniTransferRequest request = new AlipayFundTransUniTransferRequest();
        com.alibaba.fastjson.JSONObject json = new com.alibaba.fastjson.JSONObject();
        json.put("out_biz_no", info.getOutBizNo());
        json.put("trans_amount", info.getMoney().toString());
        json.put("product_code", info.getProductCode().name());
        json.put("order_title", info.getOrderTitle());
        JSONObject payee_info = new JSONObject();
        if (!StringUtil.isNullOrEmpty(info.getAccount().getUserId())) {
            payee_info.put("identity_type", "ALIPAY_USER_ID");
            payee_info.put("identity", info.getAccount().getUserId());
        } else {
            payee_info.put("identity", info.getAccount().getAccount());
            payee_info.put("identity_type", "ALIPAY_LOGON_ID");
            payee_info.put("name", info.getAccount().getName());
        }
        json.put("payee_info", payee_info);
        json.put("remark", info.getMark());
        json.put("biz_scene", info.getBizScene().name());
        com.alibaba.fastjson.JSONObject params = new com.alibaba.fastjson.JSONObject();
        if (AlipayTransferInfo.AlipayProductCodeEnum.STD_RED_PACKET == info.getProductCode()) {
            params.put("sub_biz_scene", "REDPACKET");
        }
        if (!StringUtil.isNullOrEmpty(info.getPayerName())) {
            params.put("payer_show_name", info.getPayerName());
        }
        json.put("business_params", params.toJSONString());
        request.setBizContent(json.toString());
        AlipayFundTransUniTransferResponse response = null;
        response = getAlipayClient(app, certInfo).certificateExecute(request);
        // 成功转账
        if (response != null && response.isSuccess() && "10000".equals(response.getCode())) {
            return response;
        } else// 转账失败
        {
            throw new AlipayTransferException(Integer.parseInt(response.getCode()), response.getSubCode(),
                    response.getBody());
        }
    }
    /**
     * 获取订单详情
     * API接口地址为:https://opendocs.alipay.com/apis/api_28/alipay.fund.trans.common.query/
     *
     * @param app
     * @param productCode
     * @param bizScene
     * @param outBizNo
     * @return
     * @throws AlipayApiException
     */
    public static AlipayFundTransCommonQueryResponse getOrderDetail(AlipayAppInfo app, AlipayCertInfo certInfo, AlipayTransferInfo.AlipayProductCodeEnum productCode, AlipayTransferInfo.AlipayBizSceneEnum bizScene, String outBizNo) throws AlipayApiException, AlipayCommonException {
        AlipayClient alipayClient = getAlipayClient(app, certInfo);
        AlipayFundTransCommonQueryRequest request = new AlipayFundTransCommonQueryRequest();
        com.alibaba.fastjson.JSONObject content = new com.alibaba.fastjson.JSONObject();
        if (productCode != null)
            content.put("product_code", productCode.name());
        if (bizScene != null)
            content.put("biz_scene", bizScene.name());
        content.put("out_biz_no", outBizNo);
        request.setBizContent(content.toString());
        AlipayFundTransCommonQueryResponse response = alipayClient.certificateExecute(request);
        if (response.isSuccess())
            return response;
        else
            throw new AlipayCommonException(response.getCode(), response.getSubMsg(), response.getBody());
    }
    /**
     * 获取账户余额
     * API接口地址:https://opendocs.alipay.com/apis/api_28/alipay.fund.account.query
     *
     * @param app
     * @param userId
     * @return
     * @throws AlipayApiException
     * @throws AlipayCommonException
     */
    public static BigDecimal getAccountBalance(AlipayAppInfo app, AlipayCertInfo certInfo, String userId) throws AlipayApiException, AlipayCommonException {
        AlipayClient alipayClient = getAlipayClient(app, certInfo);
        AlipayFundAccountQueryRequest request = new AlipayFundAccountQueryRequest();
        com.alibaba.fastjson.JSONObject content = new com.alibaba.fastjson.JSONObject();
        content.put("alipay_user_id", userId);
        content.put("account_type", "ACCTRANS_ACCOUNT");
        request.setBizContent(content.toString());
        AlipayFundAccountQueryResponse response = alipayClient.certificateExecute(request);
        if (response.isSuccess()) {
            return new BigDecimal(response.getAvailableAmount());
        } else {
            throw new AlipayCommonException(response.getCode(), response.getSubMsg(), response.getBody());
        }
    }
}
utils/src/main/java/org/yeshi/utils/alipay/AlipayXcxUtil.java
New file
@@ -0,0 +1,80 @@
package org.yeshi.utils.alipay;
import com.alibaba.fastjson.JSONObject;
import com.alipay.api.AlipayApiException;
import com.alipay.api.AlipayClient;
import com.alipay.api.DefaultAlipayClient;
import com.alipay.api.request.AlipayOpenAppMiniTemplatemessageSendRequest;
import com.alipay.api.request.AlipaySystemOauthTokenRequest;
import com.alipay.api.response.AlipayOpenAppMiniTemplatemessageSendResponse;
import com.alipay.api.response.AlipaySystemOauthTokenResponse;
import org.yeshi.utils.entity.alipay.AlipayAppInfo;
import org.yeshi.utils.exception.AlipayXcxException;
/**
 * 支付宝小程序帮助类
 */
public class AlipayXcxUtil {
    /**
     * 获取支付宝的用户ID
     *
     * @param app
     * @param code
     * @return
     * @throws AlipayApiException
     */
    public static String getUserId(AlipayAppInfo app, String code) throws AlipayApiException, AlipayXcxException {
        AlipayClient alipayClient = AlipayUtil.getAlipayClient(app);
        AlipaySystemOauthTokenRequest request = new AlipaySystemOauthTokenRequest();
        request.setGrantType("authorization_code");
        request.setCode(code);
        AlipaySystemOauthTokenResponse response = alipayClient.execute(request);
        if (!response.isSuccess()) {
            throw new AlipayXcxException(response.getCode(), response.getSubMsg(), response.getBody());
        }
        return response.getUserId();
    }
    /**
     * 发送模板消息
     *
     * @param app        应用信息
     * @param templateId 模板ID
     * @param page       小程序页面路径
     * @param userId     用户ID
     * @param formId     表单ID
     * @param params
     * @return
     * @throws AlipayApiException
     */
    public static void sendTemplateMsg(AlipayAppInfo app, String templateId, String page, String userId, String formId, String... params) throws AlipayApiException, AlipayXcxException {
        AlipayClient alipayClient = AlipayUtil.getAlipayClient(app);
        AlipayOpenAppMiniTemplatemessageSendRequest request = new AlipayOpenAppMiniTemplatemessageSendRequest();
        JSONObject content = new JSONObject();
        content.put("to_user_id", userId);
        content.put("form_id", formId);
        content.put("user_template_id", templateId);
        content.put("page", page);
        if (params != null && params.length > 0) {
            JSONObject data = new JSONObject();
            for (int i = 0; i < params.length; i++) {
                JSONObject item = new JSONObject();
                item.put("value", params[i]);
                data.put("keyword" + (i + 1), item);
            }
            content.put("data", data.toJSONString());
        }
        System.out.println(content.toString());
        request.setBizContent(content.toString());
        AlipayOpenAppMiniTemplatemessageSendResponse response = alipayClient.execute(request);
        if (!response.isSuccess()) {
            throw new AlipayXcxException(response.getCode(), response.getSubMsg(), response.getBody());
        }
    }
}
utils/src/main/java/org/yeshi/utils/alipay/CertAlipayClient.java
New file
@@ -0,0 +1,79 @@
package org.yeshi.utils.alipay;
import com.alipay.api.*;
import java.security.cert.X509Certificate;
import java.util.concurrent.ConcurrentHashMap;
public class CertAlipayClient extends MyAbstractAlipayClient {
    private String privateKey;
    private String encryptKey;
    private String alipayPublicKey;
    private Signer signer;
    private SignChecker signChecker;
    private Encryptor encryptor;
    private Decryptor decryptor;
    private X509Certificate cert;
    private ConcurrentHashMap<String, X509Certificate> alipayPublicCertMap;
    public CertAlipayClient(MyCertAlipayRequest certAlipayRequest) throws AlipayApiException {
        super(certAlipayRequest.getServerUrl(), certAlipayRequest.getAppId(), certAlipayRequest.getFormat(),
                certAlipayRequest.getCharset(), certAlipayRequest.getSignType(), certAlipayRequest.getCertStream(),
                certAlipayRequest.getAlipayPublicCertStream(), certAlipayRequest.getRootCertStream(),
                certAlipayRequest.getProxyHost(), certAlipayRequest.getProxyPort(), certAlipayRequest.getEncryptType());
        this.privateKey = certAlipayRequest.getPrivateKey();
        this.signer = new DefaultSigner(certAlipayRequest.getPrivateKey());
        this.encryptor = new DefaultEncryptor(certAlipayRequest.getEncryptor());
        this.decryptor = new DefaultDecryptor(certAlipayRequest.getEncryptor());
    }
    public Signer getSigner() {
        return signer;
    }
    public SignChecker getSignChecker() {
        return signChecker;
    }
    public Encryptor getEncryptor() {
        return encryptor;
    }
    public Decryptor getDecryptor() {
        return decryptor;
    }
    public X509Certificate getCert() {
        return cert;
    }
    public ConcurrentHashMap<String, X509Certificate> getAlipayPublicCertMap() {
        return alipayPublicCertMap;
    }
    public void setPrivateKey(String privateKey) {
        this.privateKey = privateKey;
        if (this.signer == null) {
            this.signer = new DefaultSigner(privateKey);
        }
    }
    public void setEncryptKey(String encryptKey) {
        this.encryptKey = encryptKey;
        if (this.encryptor == null) {
            this.encryptor = new DefaultEncryptor(encryptKey);
        }
        if (this.decryptor == null) {
            this.decryptor = new DefaultDecryptor(encryptKey);
        }
    }
    public void setAlipayPublicKey(String alipayPublicKey) {
        this.alipayPublicKey = alipayPublicKey;
        if (this.signChecker == null) {
            this.signChecker = new DefaultSignChecker(alipayPublicKey);
        }
    }
}
utils/src/main/java/org/yeshi/utils/alipay/MyAbstractAlipayClient.java
New file
@@ -0,0 +1,1178 @@
package org.yeshi.utils.alipay;
import com.alipay.api.*;
import com.alipay.api.Signer;
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.Charsets;
import com.alipay.api.internal.util.file.FileUtils;
import com.alipay.api.internal.util.file.IOUtils;
import com.alipay.api.internal.util.json.JSONWriter;
import org.bouncycastle.jce.provider.BouncyCastleProvider;
import javax.net.ssl.SSLException;
import java.io.*;
import java.math.BigInteger;
import java.nio.charset.Charset;
import java.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.*;
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 MyAbstractAlipayClient implements AlipayClient {
    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<String, X509Certificate> alipayPublicCertMap;
    private ConcurrentHashMap<String, String> alipayPublicKeyMap;
    protected boolean loadTest = false;
    static {
        //清除安全设置
        Security.setProperty("jdk.certpath.disabledAlgorithms", "");
    }
    /**
     * 批量API默认分隔符
     **/
    private static final String BATCH_API_DEFAULT_SPLIT = "#S#";
    public MyAbstractAlipayClient(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 MyAbstractAlipayClient(String serverUrl, String appId, String format,
                                  String charset, String signType, InputStream certInput,
                                  InputStream alipayPublicCertInput, InputStream rootCertInput, 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;
        //读取根证书(用来校验本地支付宝公钥证书失效后自动从网关下载的新支付宝公钥证书是否有效)
        this.rootCertContent = readStreamToString(rootCertInput);
        //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("AlipayRootCert Is Invalid");
            }
        }
        //获取应用证书
        this.cert = getCert(certInput);
        //获取支付宝公钥证书
        X509Certificate alipayPublicCert = getCert(alipayPublicCertInput);
        //appCertSN为最终发送给网关的应用证书序列号
        this.appCertSN = getCertSN(cert);
        if (StringUtils.isEmpty(this.appCertSN)) {
            throw new AlipayApiException("AppCert Is Invalid");
        }
        //alipayCertSN为支付宝公钥证书序列号
        this.alipayCertSN = getCertSN(alipayPublicCert);
        //将公钥证书以序列号为key存入map
        ConcurrentHashMap<String, X509Certificate> alipayPublicCertMap = new ConcurrentHashMap<String, X509Certificate>();
        alipayPublicCertMap.put(alipayCertSN, alipayPublicCert);
        this.alipayPublicCertMap = alipayPublicCertMap;
        //获取支付宝公钥以序列号为key存入map
        PublicKey publicKey = alipayPublicCert.getPublicKey();
        ConcurrentHashMap<String, String> alipayPublicKeyMap = new ConcurrentHashMap<String, String>();
        alipayPublicKeyMap.put(alipayCertSN, Base64.encodeBase64String(publicKey.getEncoded()));
        this.alipayPublicKeyMap = alipayPublicKeyMap;
    }
    /**
     * @param inputStream 证书路径
     * @return
     * @throws AlipayApiException
     */
    private X509Certificate getCert(InputStream inputStream) throws AlipayApiException {
        try {
            Security.addProvider(new BouncyCastleProvider());
            CertificateFactory cf = CertificateFactory.getInstance("X.509", "BC");
            X509Certificate cert = (X509Certificate) cf.generateCertificate(inputStream);
            return cert;
        } 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);
            }
        }
    }
    private String getCertSN(X509Certificate cf) throws AlipayApiException {
        try {
            MessageDigest md = MessageDigest.getInstance("MD5");
            md.update((cf.getIssuerX500Principal().getName() + cf.getSerialNumber()).getBytes());
            String certSN = new BigInteger(1, md.digest()).toString(16);
            //BigInteger会把0省略掉,需补全至32位
            certSN = fillMD5(certSN);
            return certSN;
        } catch (NoSuchAlgorithmException e) {
            throw new AlipayApiException(e);
        }
    }
    private static String fillMD5(String md5) {
        return md5.length() == 32 ? md5 : fillMD5("0" + md5);
    }
    private String readFileToString(String rootCertPath) throws AlipayApiException {
        try {
            File file = new File(rootCertPath);
            String client = FileUtils.readFileToString(file);
            return client;
        } catch (IOException e) {
            throw new AlipayApiException(e);
        }
    }
    private String readStreamToString(InputStream inputStream) throws AlipayApiException {
        try {
            return IOUtils.toString(inputStream, Charsets.toCharset(Charset.defaultCharset()));
        } catch (IOException e) {
            throw new AlipayApiException(e);
        }
    }
    //校验证书有效期以及是否支付宝颁发
    private boolean verifyCert(String cert) {
        return AntCertificationUtil.isTrusted(cert, this.rootCertContent);
    }
    public <T extends AlipayResponse> T certificateExecute(AlipayRequest<T> request) throws AlipayApiException {
        return certificateExecute(request, null);
    }
    public <T extends AlipayResponse> T certificateExecute(AlipayRequest<T> request, String accessToken) throws AlipayApiException {
        return certificateExecute(request, accessToken, null);
    }
    public <T extends AlipayResponse> T certificateExecute(AlipayRequest<T> request, String accessToken,
                                                           String appAuthToken) throws AlipayApiException {
        return _certificateExecute(request, accessToken, appAuthToken, null);
    }
    public <T extends AlipayResponse> T certificateExecute(AlipayRequest<T> request, String accessToken,
                                                           String appAuthToken, String targetAppId) throws AlipayApiException {
        return _certificateExecute(request, accessToken, appAuthToken, targetAppId);
    }
    public <T extends AlipayResponse> T _certificateExecute(AlipayRequest<T> request, String accessToken,
                                                            String appAuthToken, String targetAppId) throws AlipayApiException {
        T tRsp = null;
        try {
            long beginTime = System.currentTimeMillis();
            Map<String, Object> rt = doPost(request, accessToken, appAuthToken, this.appCertSN, targetAppId);
            Map<String, Long> costTimeMap = new HashMap<String, Long>();
            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<T> parser = null;
            if (AlipayConstants.FORMAT_XML.equals(this.format)) {
                parser = new ObjectXmlParser<T>(request.getResponseClass());
            } else {
                parser = new ObjectJsonParser<T>(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 <T extends AlipayResponse> void checkResponseCertSign(AlipayRequest<T> request,
                                                                  AlipayParser<T> parser,
                                                                  String responseBody,
                                                                  boolean responseIsSuccess) throws AlipayApiException {
        CertItem certItem = parser.getCertItem(request, responseBody);
        if (certItem == null) {
            throw new AlipayApiException("cert check fail: Body is Empty!");
        }
        if (certItem.getCert() == null && responseIsSuccess
                && !request.getApiMethodName().equals(AlipayOpenAppAlipaycertDownloadRequest.ALIPAYCERT_DOWNLOAD)) {
            throw new AlipayApiException("cert check fail: ALIPAY_CERT_SN is Empty!");
        }
        String alipayPublicKey = null;
        if (certItem.getCert() != null) {
            if (!alipayPublicCertMap.containsKey(certItem.getCert())) {
                //如果返回的支付宝公钥证书序列号与本地支付宝公钥证书序列号不匹配,通过返回的支付宝公钥证书序列号去网关拉取新的支付宝公钥证书
                AlipayOpenAppAlipaycertDownloadRequest alipayRequest = new AlipayOpenAppAlipaycertDownloadRequest();
                alipayRequest.setBizContent("{" +
                        "\"alipay_cert_sn\":\"" + certItem.getCert() + "\"" +
                        "  }");
                Map<String, Object> rt = doPost(alipayRequest, null, null, this.appCertSN, null);
                // 解析实际串
                String respContent = rt.get("rsp").toString();
                AlipayParser<AlipayOpenAppAlipaycertDownloadResponse> parserCert = null;
                parserCert = new ObjectJsonParser<AlipayOpenAppAlipaycertDownloadResponse>(alipayRequest.getResponseClass());
                AlipayOpenAppAlipaycertDownloadResponse alipayResponse = parserCert.parse(respContent);
                if (!alipayResponse.isSuccess()) {
                    throw new AlipayApiException("支付宝公钥证书校验失败,请确认是否为支付宝签发的有效公钥证书");
                }
                String alipayCertContent = alipayResponse.getAlipayCertContent();
                InputStream inputStream = null;
                try {
                    byte[] alipayCert = Base64.decodeBase64String(alipayCertContent);
                    String alipayPublicCertStr = new String(alipayCert);
                    if (!verifyCert(alipayPublicCertStr)) {
                        throw new AlipayApiException("支付宝公钥证书校验失败,请确认是否为支付宝签发的有效公钥证书");
                    }
                    inputStream = new ByteArrayInputStream(alipayCert);
                    CertificateFactory cf = CertificateFactory.getInstance("X.509", "BC");
                    X509Certificate alipayPublicCertNew = (X509Certificate) cf.generateCertificate(inputStream);
                    //获取新证书和公钥添加到map中
                    String alipayCertSNNew = 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(
                                        "cert check fail: check Cert and Data Fail!JSON also!");
                            }
                        } else {
                            throw new AlipayApiException("cert check fail: check Cert and Data Fail!");
                        }
                    }
                }
            } else {
                throw new AlipayApiException("cert check fail: check Cert and Data Fail! CertSN non-existent");
            }
        }
    }
    public <T extends AlipayResponse> T execute(AlipayRequest<T> request) throws AlipayApiException {
        return execute(request, null);
    }
    public <T extends AlipayResponse> T execute(AlipayRequest<T> request,
                                                String accessToken) throws AlipayApiException {
        return execute(request, accessToken, null);
    }
    public <T extends AlipayResponse> T execute(AlipayRequest<T> request, String accessToken,
                                                String appAuthToken) throws AlipayApiException {
        return execute(request, accessToken, appAuthToken, null);
    }
    public <T extends AlipayResponse> T execute(AlipayRequest<T> request, String accessToken,
                                                String appAuthToken, String targetAppId) throws AlipayApiException {
        //如果根证书序列号非空,抛异常提示开发者使用certificateExecute
        if (!StringUtils.isEmpty(this.alipayRootCertSN)) {
            throw new AlipayApiException("检测到证书相关参数已初始化,证书模式下请改为调用certificateExecute");
        }
        AlipayParser<T> parser = null;
        if (AlipayConstants.FORMAT_XML.equals(this.format)) {
            parser = new ObjectXmlParser<T>(request.getResponseClass());
        } else {
            parser = new ObjectJsonParser<T>(request.getResponseClass());
        }
        return _execute(request, parser, accessToken, appAuthToken, targetAppId);
    }
    public BatchAlipayResponse execute(BatchAlipayRequest request) throws AlipayApiException {
        long beginTime = System.currentTimeMillis();
        //发送请求
        Map<String, Object> rt = doPost(request);
        if (rt == null) {
            return null;
        }
        Map<String, Long> costTimeMap = new HashMap<String, Long>();
        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<BatchAlipayResponse> parser = null;
        if (AlipayConstants.FORMAT_XML.equals(this.format)) {
            parser = new ObjectXmlParser<BatchAlipayResponse>(request.getResponseClass());
        } else {
            parser = new ObjectJsonParser<BatchAlipayResponse>(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<AlipayParser<?>> parserList = new ArrayList<AlipayParser<?>>();
            List<AlipayRequestWrapper> 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);
            throw e;
        } catch (AlipayApiException e) {
            AlipayLogger.logBizError((String) rt.get("rsp"), costTimeMap);
            throw new AlipayApiException(e);
        }
    }
    /**
     * @param request
     * @return
     * @throws AlipayApiException
     */
    private Map<String, Object> doPost(BatchAlipayRequest request) throws AlipayApiException {
        Map<String, Object> result = new HashMap<String, Object>();
        RequestParametersHolder requestHolder = getRequestHolderWithSign(request);
        String url = getRequestUrl(requestHolder);
        // 打印完整请求报文
        if (AlipayLogger.isBizDebugEnabled()) {
            AlipayLogger.logBizDebug(getRedirectUrl(requestHolder));
        }
        result.put("prepareTime", System.currentTimeMillis());
        String rsp = null;
        try {
            rsp = WebUtils.doPost(url, requestHolder.getApplicationParams(), charset,
                    connectTimeout, readTimeout, proxyHost, proxyPort);
        } 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 <T extends AlipayResponse> RequestParametersHolder getRequestHolderWithSign(BatchAlipayRequest request)
            throws AlipayApiException {
        List<AlipayRequestWrapper> 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<String, Object> 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("当前API不支持加密请求");
            }
            // 需要加密必须设置密钥和加密算法
            if (StringUtils.isEmpty(this.encryptType) || getEncryptor() == null) {
                throw new AlipayApiException("API请求要求加密,则必须设置密钥类型和加密器");
            }
            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 extends AlipayResponse> T pageExecute(AlipayRequest<T> request) throws AlipayApiException {
        return pageExecute(request, "POST");
    }
    public <T extends AlipayResponse> T pageExecute(AlipayRequest<T> 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<T> 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 extends AlipayResponse> T sdkExecute(AlipayRequest<T> request) throws AlipayApiException {
        RequestParametersHolder requestHolder = getRequestHolderWithSign(request, null, null,
                this.appCertSN, null);
        // 打印完整请求报文
        if (AlipayLogger.isBizDebugEnabled()) {
            AlipayLogger.logBizDebug(getSdkParams(requestHolder));
        }
        T rsp = null;
        try {
            Class<T> 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 extends AlipayResponse, T extends AlipayRequest<TR>> TR parseAppSyncResult(Map<String, String> result,
                                                                                          Class<T> requsetClazz) throws AlipayApiException {
        TR tRsp = null;
        String rsp = result.get("result");
        try {
            T request = requsetClazz.newInstance();
            Class<TR> 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<TR> parser = null;
                if (AlipayConstants.FORMAT_XML.equals(this.format)) {
                    parser = new ObjectXmlParser<TR>(responseClazz);
                } else {
                    parser = new ObjectJsonParser<TR>(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 <T extends AlipayResponse> 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("当前API不支持加密请求");
            }
            // 需要加密必须设置密钥和加密算法
            if (StringUtils.isEmpty(this.encryptType) || getEncryptor() == null) {
                throw new AlipayApiException("API请求要求加密,则必须设置密钥类型和加密器");
            }
            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<String, String> 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<String, String> 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 extends AlipayResponse> T _execute(AlipayRequest<T> request, AlipayParser<T> parser,
                                                  String authToken, String appAuthToken,
                                                  String targetAppId) throws AlipayApiException {
        long beginTime = System.currentTimeMillis();
        //适配新增证书序列号的请求
        Map<String, Object> rt = doPost(request, authToken, appAuthToken, null, targetAppId);
        if (rt == null) {
            return null;
        }
        Map<String, Long> costTimeMap = new HashMap<String, Long>();
        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);
            throw e;
        } catch (AlipayApiException e) {
            AlipayLogger.logBizError((String) rt.get("rsp"), costTimeMap);
            throw new AlipayApiException(e);
        }
        tRsp.setParams((AlipayHashMap) rt.get("textParams"));
        if (!tRsp.isSuccess()) {
            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 <T extends AlipayResponse> Map<String, Object> doPost(AlipayRequest<T> request,
                                                                  String accessToken, String appAuthToken,
                                                                  String appCertSN, String targetAppId) throws AlipayApiException {
        Map<String, Object> result = new HashMap<String, Object>();
        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;
        try {
            if (request instanceof AlipayUploadRequest) {
                AlipayUploadRequest<T> uRequest = (AlipayUploadRequest<T>) request;
                Map<String, FileItem> fileParams = AlipayUtils.cleanupMap(uRequest.getFileParams());
                rsp = WebUtils.doPost(url, requestHolder.getApplicationParams(), fileParams,
                        charset, connectTimeout, readTimeout, proxyHost, proxyPort);
            } else {
                rsp = WebUtils.doPost(url, requestHolder.getApplicationParams(), charset,
                        connectTimeout, readTimeout, proxyHost, proxyPort);
            }
        } 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);
        return result;
    }
    /**
     * 检查响应签名
     *
     * @param request
     * @param parser
     * @param responseBody
     * @param responseIsSucess
     * @throws AlipayApiException
     */
    private <T extends AlipayResponse> void checkResponseSign(AlipayRequest<T> request,
                                                              AlipayParser<T> parser,
                                                              String responseBody,
                                                              boolean responseIsSucess) throws AlipayApiException {
        // 针对成功结果且有支付宝公钥的进行验签
        if (getSignChecker() != null) {
            SignItem signItem = parser.getSignItem(request, responseBody);
            if (signItem == null) {
                throw new AlipayApiException("sign check fail: Body is Empty!");
            }
            if (responseIsSucess
                    || (!responseIsSucess && !StringUtils.isEmpty(signItem.getSign()))) {
                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(
                                    "sign check fail: check Sign and Data Fail!JSON also!");
                        }
                    } else {
                        throw new AlipayApiException("sign check fail: check Sign and Data Fail!");
                    }
                }
            }
        }
    }
    /**
     * 解密响应
     *
     * @param request
     * @param rt
     * @param parser
     * @return
     * @throws AlipayApiException
     */
    private <T extends AlipayResponse> ResponseEncryptItem decryptResponse(AlipayRequest<T> request,
                                                                           Map<String, Object> rt,
                                                                           AlipayParser<T> parser) throws AlipayApiException {
        String responseBody = (String) rt.get("rsp");
        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);
    }
    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;
    }
    void setProxyHost(String proxyHost) {
        this.proxyHost = proxyHost;
    }
    void setProxyPort(int proxyPort) {
        this.proxyPort = proxyPort;
    }
    void setCert(X509Certificate cert) {
        this.cert = cert;
    }
    void setAlipayPublicCertMap(ConcurrentHashMap<String, X509Certificate> alipayPublicCertMap) {
        this.alipayPublicCertMap = alipayPublicCertMap;
    }
    public abstract Signer getSigner();
    public abstract SignChecker getSignChecker();
    public abstract Encryptor getEncryptor();
    public abstract Decryptor getDecryptor();
}
utils/src/main/java/org/yeshi/utils/alipay/MyCertAlipayRequest.java
New file
@@ -0,0 +1,35 @@
package org.yeshi.utils.alipay;
import com.alipay.api.CertAlipayRequest;
import java.io.InputStream;
public class MyCertAlipayRequest extends CertAlipayRequest {
    private InputStream certStream;
    private InputStream alipayPublicCertStream;
    private InputStream rootCertStream;
    public InputStream getCertStream() {
        return certStream;
    }
    public void setCertStream(InputStream certStream) {
        this.certStream = certStream;
    }
    public InputStream getAlipayPublicCertStream() {
        return alipayPublicCertStream;
    }
    public void setAlipayPublicCertStream(InputStream alipayPublicCertStream) {
        this.alipayPublicCertStream = alipayPublicCertStream;
    }
    public InputStream getRootCertStream() {
        return rootCertStream;
    }
    public void setRootCertStream(InputStream rootCertStream) {
        this.rootCertStream = rootCertStream;
    }
}
utils/src/main/java/org/yeshi/utils/entity/alipay/AlipayAppInfo.java
New file
@@ -0,0 +1,46 @@
package org.yeshi.utils.entity.alipay;
/**
 * 支付宝应用信息
 */
public class AlipayAppInfo {
    private String appId;
    private String privateKey;
    private String alipayPublicKey;
    public AlipayAppInfo(String appId, String privateKey) {
        this.appId = appId;
        this.privateKey = privateKey;
    }
    public AlipayAppInfo(String appId, String privateKey, String alipayPublicKey) {
        this.appId = appId;
        this.privateKey = privateKey;
        this.alipayPublicKey = alipayPublicKey;
    }
    public String getAppId() {
        return appId;
    }
    public void setAppId(String appId) {
        this.appId = appId;
    }
    public String getPrivateKey() {
        return privateKey;
    }
    public void setPrivateKey(String privateKey) {
        this.privateKey = privateKey;
    }
    public String getAlipayPublicKey() {
        return alipayPublicKey;
    }
    public void setAlipayPublicKey(String alipayPublicKey) {
        this.alipayPublicKey = alipayPublicKey;
    }
}
utils/src/main/java/org/yeshi/utils/entity/alipay/AlipayCertInfo.java
New file
@@ -0,0 +1,39 @@
package org.yeshi.utils.entity.alipay;
import java.io.InputStream;
public class AlipayCertInfo {
    private InputStream appCertPublicKeyStream;//应用公钥证书
    private InputStream alipayPublicCertStream;//支付宝公钥证书
    private InputStream alipayRootCertStream;//支付宝根证书
    public AlipayCertInfo(InputStream appCertPublicKeyStream, InputStream alipayPublicCertStream, InputStream alipayRootCertStream) {
        this.appCertPublicKeyStream = appCertPublicKeyStream;
        this.alipayPublicCertStream = alipayPublicCertStream;
        this.alipayRootCertStream = alipayRootCertStream;
    }
    public InputStream getAppCertPublicKeyStream() {
        return appCertPublicKeyStream;
    }
    public void setAppCertPublicKeyStream(InputStream appCertPublicKeyStream) {
        this.appCertPublicKeyStream = appCertPublicKeyStream;
    }
    public InputStream getAlipayRootCertStream() {
        return alipayRootCertStream;
    }
    public void setAlipayRootCertStream(InputStream alipayRootCertStream) {
        this.alipayRootCertStream = alipayRootCertStream;
    }
    public InputStream getAlipayPublicCertStream() {
        return alipayPublicCertStream;
    }
    public void setAlipayPublicCertStream(InputStream alipayPublicCertStream) {
        this.alipayPublicCertStream = alipayPublicCertStream;
    }
}
utils/src/main/java/org/yeshi/utils/entity/alipay/AlipayTransferAccount.java
New file
@@ -0,0 +1,42 @@
package org.yeshi.utils.entity.alipay;
public class AlipayTransferAccount {
    private String account;
    private String name;
    private String userId;
    public AlipayTransferAccount(String userId) {
        this.userId = userId;
    }
    public AlipayTransferAccount(String name, String account) {
        this.name = name;
        this.account = account;
    }
    public String getAccount() {
        return account;
    }
    public void setAccount(String account) {
        this.account = account;
    }
    public String getName() {
        return name;
    }
    public void setName(String name) {
        this.name = name;
    }
    public String getUserId() {
        return userId;
    }
    public void setUserId(String userId) {
        this.userId = userId;
    }
}
utils/src/main/java/org/yeshi/utils/entity/alipay/AlipayTransferInfo.java
New file
@@ -0,0 +1,134 @@
package org.yeshi.utils.entity.alipay;
import java.math.BigDecimal;
public class AlipayTransferInfo {
    public final static String TYPE_TRANSFER_ACCOUNT = "TRANS_ACCOUNT_NO_PWD";//单笔无密转账到支付宝账户
    public final static String TYPE_REDPACKET = "STD_RED_PACKET";//现金红包
    public final static String TYPE_REDPACKET_BANDCARD = "TRANS_BANKCARD_NO_PWD";//单笔无密转账到银行卡
    public enum AlipayProductCodeEnum {
        STD_RED_PACKET("现金红包"), TRANS_ACCOUNT_NO_PWD("单笔无密转账到支付宝账户"), TRANS_BANKCARD_NO_PWD("单笔无密转账到银行卡");
        private String name;
        private AlipayProductCodeEnum(String name) {
            this.name = name;
        }
    }
    public enum AlipayBizSceneEnum {
        PERSONAL_PAY("C2C现金红包-发红包"), PERSONAL_COLLECTION("C2C现金红包-领红包"), REFUND("C2C现金红包-红包退回"), DIRECT_TRANSFER("B2C现金红包、单笔无密转账");
        private String name;
        private AlipayBizSceneEnum(String name) {
            this.name = name;
        }
    }
    private String outBizNo;
    private BigDecimal money;//转账限额0.1,红包限额0.01
    private String orderTitle;
    private String mark;
    private AlipayTransferAccount account;
    private AlipayProductCodeEnum productCode;
    private AlipayBizSceneEnum bizScene;
    private String payerName;
    public String getOutBizNo() {
        return outBizNo;
    }
    public void setOutBizNo(String outBizNo) {
        this.outBizNo = outBizNo;
    }
    public BigDecimal getMoney() {
        return money;
    }
    public void setMoney(BigDecimal money) {
        this.money = money;
    }
    public String getOrderTitle() {
        return orderTitle;
    }
    public void setOrderTitle(String orderTitle) {
        this.orderTitle = orderTitle;
    }
    public String getMark() {
        return mark;
    }
    public void setMark(String mark) {
        this.mark = mark;
    }
    public AlipayTransferAccount getAccount() {
        return account;
    }
    public void setAccount(AlipayTransferAccount account) {
        this.account = account;
    }
    public AlipayProductCodeEnum getProductCode() {
        return productCode;
    }
    public void setProductCode(AlipayProductCodeEnum productCode) {
        this.productCode = productCode;
    }
    public AlipayBizSceneEnum getBizScene() {
        return bizScene;
    }
    public void setBizScene(AlipayBizSceneEnum bizScene) {
        this.bizScene = bizScene;
    }
    public String getPayerName() {
        return payerName;
    }
    public void setPayerName(String payerName) {
        this.payerName = payerName;
    }
    public static class AlipayTransferInfoFactory {
        public static AlipayTransferInfo createRedPack(String outBizNo, BigDecimal money, String orderTitle, String mark, AlipayTransferAccount account, String payerName) {
            AlipayTransferInfo info = new AlipayTransferInfo();
            info.setBizScene(AlipayBizSceneEnum.DIRECT_TRANSFER);
            info.setProductCode(AlipayProductCodeEnum.STD_RED_PACKET);
            info.setOutBizNo(outBizNo);
            info.setPayerName(payerName);
            info.setOrderTitle(orderTitle);
            info.setMoney(money);
            info.setMark(mark);
            info.setAccount(account);
            return info;
        }
        public static AlipayTransferInfo createAccountTransfer(String outBizNo, BigDecimal money, String orderTitle, String mark, AlipayTransferAccount account, String payerName) {
            AlipayTransferInfo info = new AlipayTransferInfo();
            info.setBizScene(AlipayBizSceneEnum.DIRECT_TRANSFER);
            info.setProductCode(AlipayProductCodeEnum.TRANS_ACCOUNT_NO_PWD);
            info.setOutBizNo(outBizNo);
            info.setPayerName(payerName);
            info.setOrderTitle(orderTitle);
            info.setMoney(money);
            info.setMark(mark);
            info.setAccount(account);
            return info;
        }
    }
}
utils/src/main/java/org/yeshi/utils/exception/AlipayCommonException.java
New file
@@ -0,0 +1,12 @@
package org.yeshi.utils.exception;
public class AlipayCommonException extends Exception {
    private String code;
    private String subMsg;
    private String body;
    public AlipayCommonException(String code, String subMsg, String body) {
        super(body);
    }
}
utils/src/main/java/org/yeshi/utils/exception/AlipayTransferException.java
New file
@@ -0,0 +1,39 @@
package org.yeshi.utils.exception;
public class AlipayTransferException extends Exception {
    public AlipayTransferException() {
    }
    /**
     * 支付宝转账异常
     */
    private static final long serialVersionUID = 1L;
    private int code;
    private String subCode;
    private String msg;
    public int getCode() {
        return code;
    }
    public String getMsg() {
        return msg;
    }
    public String getSubCode() {
        return subCode;
    }
    public AlipayTransferException(int code, String subCode, String msg) {
        this.code = code;
        this.msg = msg;
        this.subCode = subCode;
    }
    @Override
    public String getMessage() {
        return this.msg;
    }
}
utils/src/main/java/org/yeshi/utils/exception/AlipayXcxException.java
New file
@@ -0,0 +1,12 @@
package org.yeshi.utils.exception;
public class AlipayXcxException extends Exception {
    private String code;
    private String subMsg;
    private String body;
    public AlipayXcxException(String code, String subMsg, String body) {
        super(body);
    }
}
utils/src/test/java/com/yeshi/utils/AlipayTest.java
New file
@@ -0,0 +1,101 @@
package com.yeshi.utils;
import com.alipay.api.AlipayApiException;
import org.yeshi.utils.alipay.AlipayUtil;
import org.yeshi.utils.entity.alipay.AlipayAppInfo;
import org.yeshi.utils.alipay.AlipayXcxUtil;
import org.yeshi.utils.entity.alipay.AlipayCertInfo;
import org.yeshi.utils.entity.alipay.AlipayTransferAccount;
import org.yeshi.utils.entity.alipay.AlipayTransferInfo;
import org.yeshi.utils.exception.AlipayCommonException;
import org.yeshi.utils.exception.AlipayTransferException;
import java.io.FileInputStream;
import java.io.FileNotFoundException;
import java.math.BigDecimal;
public class AlipayTest {
    private static AlipayCertInfo getCertInfo() throws FileNotFoundException {
        String rootPath = "D:\\项目\\支付宝小程序\\密匙\\天天免费抽奖\\证书\\";
        return new AlipayCertInfo(new FileInputStream(rootPath + "应用公钥证书_appCertPublicKey_2021002111652055.crt"), new FileInputStream(rootPath + "支付宝公钥证书_alipayCertPublicKey_RSA2.crt"), new FileInputStream(rootPath + "支付宝根证书_alipayRootCert.crt"));
    }
    private static AlipayAppInfo getAppInfo() {
        String privateKey = "MIIEvwIBADANBgkqhkiG9w0BAQEFAASCBKkwggSlAgEAAoIBAQCYoo2UGR2VYGOIhNg2jvDGYuilR1aHH6kz6HbYVuFbpCwfnONkvcY5TMw0oDrzKceHGZOt04gPcQdTacIZs9cMQwUapy/735xW6Ix7QihvWlqjCxBa5o0LN2cXbsaF06a4TUxuNrXZwk32k3uuwHZdZ+EsI1C5J9wN1B2ltDIwniSk7RTEFNEWpgKtdAd25KLkElUFXAYK2aWZbQ/ogPAPc2wSpj0fmLvUB5OZLvW/PMFIsAA+63lrlcAe+SksCTJkFsKg7uWzAnpPVrrVkbCKVGsMd1Xi29OSWWJfFch3TJ+mmkOIsKA4f1Zf99rsGdODXMqHqeba+pG6vaZ/zzbbAgMBAAECggEAYGUAftBhw43NLlGfbs1VOCUNAhyMg+e150dfjv9HcaW8C/b8EQpc3qEmsfGjaSAwl5zKjFP0MLRUSRSYdb0DCgZledCuWCZ/SM+ysME2YiSw6xk4qf/CgZvqqnzWOXxSZUDEDTLWJAE3VYsM6G86EYFiToq7F0QaEE2ur5Cexd6Owif9A/ruvOAmbtMfMeKTvsfmNQHT2N5eUYNf1HvvqogKjYuhyz7D3LH51rCXpmKPxo3ohKFL4eBNO42VhvC+78jAfICsWm5l2x706iWGRv6wofifR/rIpnEsIa7RyTENihR2yI77as5vWqJy7J+BZHNtGnBec4FMqQpbdUkWqQKBgQDdbPKm4AA0IN7kSqtVBhxLhK8U5xXlQi3qpWZq0w9jAo1iZJCiy2j0G8dEnLxT40zZlj6tAe5n0p4lUP4q0zpQTfHQcJHoqCX9h09BujOds4Q4AKJSAv61IxrNreZ8A0LktrvpqmjiTDpfo0ASA6hTBsBR3lbzsEb0rx/Kc7AYhwKBgQCwd9YEDLe81Wxymp1QVKD+RCGzGIo/LHljPDWYQBRoJxUZwglo4Pibeu6Ud3zXinB7fftKzFtb9hpjw2R5y2AQOAEOyBeCwpBVT25TrF767halKM7qOhGNox74h1Rmn3P7R+8FY/NQVaRFVqgmuyo3mB/K3rfU2pRwXhDD9UhIDQKBgQDSUslOX1lyKoLtoEuMMIix5u+TUElJAgqxZriY4bAs4ODBRDrql4Iy1Sv7bVGp8S8vQvp3xWzaK4JSedNjhE5QtyjpT/QYZZfocR2ElkSvGDSQKXIFqpicICM2mWdkBokEzNpDgr2rrrKH435ZXiYF71TArwwy3w8XHj15RVhQgwKBgQCqU4BmeEAAK595HnMozgZ2ZRyB2PXW8/5WIg843ODVhqN/MSIT8NEEgSs2cf41rJHVIEwkbgrgQDJIiJe6VuppvSSIN+k5dMILFZfPe1hRquyAjVrqCRJYO1HxX+2+/7jamRvDgC2hJIhhxLqYZ57f+hz1mvKkqDUOIDzeZylVIQKBgQCP6gZtZ8eCM3jx5Z6gpgHFdvAIcwJVdRep4dr2f1aHZ/f1sy45UxOoFIgWJt2IWo5jPRBWDPeImN9w8gLSkJSSIS1yFWkoXCoDXSF0aO+61I9S1vJf383HawBgLBrVMG7dOUA+8PTFJCt4o6NQ7weMPH9xzgMkFB6g+MQYRYIelA==";
        String alipayPublicKey = "MIIDrDCCApSgAwIBAgIQICARGS8npSJhwLjG7UhKEDANBgkqhkiG9w0BAQsFADCBgjELMAkGA1UEBhMCQ04xFjAUBgNVBAoMDUFudCBGaW5hbmNpYWwxIDAeBgNVBAsMF0NlcnRpZmljYXRpb24gQXV0aG9yaXR5MTkwNwYDVQQDDDBBbnQgRmluYW5jaWFsIENlcnRpZmljYXRpb24gQXV0aG9yaXR5IENsYXNzIDIgUjEwHhcNMjAxMTE5MDM0NzEwWhcNMjIxMTE5MDM0NzEwWjCBjDELMAkGA1UEBhMCQ04xJzAlBgNVBAoMHumHjeW6huW/q+ecgeenkeaKgOaciemZkOWFrOWPuDEPMA0GA1UECwwGQWxpcGF5MUMwQQYDVQQDDDrmlK/ku5jlrp0o5Lit5Zu9Kee9kee7nOaKgOacr+aciemZkOWFrOWPuC0yMDg4NDMxMjExNDgzNDg1MIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEAok8S9kzeLpZGvPX/g4tcYuYZU3Kcot4vx3seU0lS52DgtsIi/4TvBVOj55vNRSJkmJV7GtUeMpgpJSmf3kyNlN9X1POyWxotSN495wAgxOIe8848F/BJekkm/L50v1QScsVxRr10R7Fj3GvsX9bwdmKMfPjYcLJiPsH/rMynAP9BdqN6xTDeoE9bLvZeIVhA4rEQOVZcwoi0fPtyWuUwviSGG/DVcMewF5GYNM0XFxUghUDkjRdFrd5Ew42rCXbVZF2BuESdilN+xZb39N9hxwo1GPpo1p76Ut+yUUl5ZlKqJn1tQ4sjVDtmBFuyNjLjad4ocdSU4sc2NPoMgUsfEQIDAQABoxIwEDAOBgNVHQ8BAf8EBAMCA/gwDQYJKoZIhvcNAQELBQADggEBAFijTHijQKuai1jGckt2V7TuOIJ9UE0iHkMSETE35XZoEm19JeBnOtNSLr8a1ngmDxcDQ+szrMsw/Z7BmxxGzxJRmADrpkVaQ/2+4gp9+CBRzI4YBPkxgogUsmON6DFnwZPFe35imszPvV0y3kPf7tKJSDXVeV8HLcOOJa0rd1kyjXYXmNG5XrXR2MdYf+py6sOvNGttb3HTq2P+3FmcUrxNp8yK1KH2vnewAp5BBg2OfSkW9R2fKNlzqsUI3OVLWfOgnGHBkR/PL0VKyP479BJtiWmkN4Ccc7P9rx1R5ro+bkqfPdfDMpchW5A5TlQOKuzzt6glqQuVrJqBjjzvj3M=";
        return new AlipayAppInfo("2021002111652055", privateKey, alipayPublicKey);
    }
    private static void getUserId() {
        try {
            String userId = AlipayXcxUtil.getUserId(getAppInfo(), "edac277c44954270a9bcfd210fc8YX77");
            System.out.println(userId);
        } catch (Exception e) {
            e.printStackTrace();
        }
    }
    private static void sendMsg() {
        String userId = "2088812685461771";
        String formId = "MjA4ODgxMjY4NTQ2MTc3MV8xNjA1Njg3OTQ0NjE2XzE2Ng==1";
        try {
            AlipayXcxUtil.sendTemplateMsg(getAppInfo(), "677118be3b914b98be8cc58d4addc0db", "page/component/form/form", userId, formId, new String[]{"开奖结果测试", "开奖期数1"});
        } catch (Exception e) {
            e.printStackTrace();
        }
    }
    private static void transfer() {
        AlipayTransferInfo info = new AlipayTransferInfo();
        new AlipayTransferAccount("2088812685461771");
        info.setAccount(new AlipayTransferAccount("贺小辉", "18581318252"));
        info.setMark("备注");
        info.setMoney(new BigDecimal("0.01"));
        info.setOrderTitle("标题");
        info.setOutBizNo("TEST-6");
        info.setPayerName("*");
        info.setBizScene(AlipayTransferInfo.AlipayBizSceneEnum.DIRECT_TRANSFER);
        info.setProductCode(AlipayTransferInfo.AlipayProductCodeEnum.STD_RED_PACKET);
        try {
            AlipayUtil.alipayFundTransUniTransfer(getAppInfo(), info, getCertInfo());
        } catch (FileNotFoundException e) {
            e.printStackTrace();
        } catch (AlipayApiException e) {
            e.printStackTrace();
        } catch (AlipayTransferException e) {
            e.printStackTrace();
        }
    }
    private static void getBalance() {
        try {
            BigDecimal balance = AlipayUtil.getAccountBalance(getAppInfo(), getCertInfo(), "2088431211483485");
            System.out.println(balance);
        } catch (FileNotFoundException e) {
        } catch (AlipayApiException e) {
            e.printStackTrace();
        } catch (AlipayCommonException e) {
            e.printStackTrace();
        }
    }
    private static void getOrderDetail() {
        try {
            AlipayUtil.getOrderDetail(getAppInfo(), getCertInfo(), AlipayTransferInfo.AlipayProductCodeEnum.STD_RED_PACKET, AlipayTransferInfo.AlipayBizSceneEnum.DIRECT_TRANSFER, "TEST-5");
        } catch (Exception e) {
            e.printStackTrace();
        }
    }
    public static void main(String[] args) {
        getOrderDetail();
    }
}
utils/src/test/java/com/yeshi/utils/Test.java
@@ -1,18 +1,14 @@
package com.yeshi.utils;
import org.yeshi.utils.LinuxRemoteCommandUtil;
public class Test {
    public static void main(String[] args) {
        String solrIP = "203.195.196.115";
        String serverAccount = "root";
        String serverPwd = "Yeshi2016@";
        try {
            LinuxRemoteCommandUtil.execute(solrIP, serverAccount, serverPwd, "/solr/solr-7.5.0/solr_restart.sh");
        } catch (Exception e) {
            e.printStackTrace();
        }
    }
    private static void getUserId(){
    }