农行直连支付

原创 宇宙     发表于  2022-04-27 16:03       2
原文链接:

如何进行加签验签

  1. 加签
    加签采用SHA1withRSA非对称签名算法,使用商户私钥完成对请求报文的加签,然后对签名串进行Base64转码。

1.1 加签代码

   /***
    * 加签方法
    *
    * @param merchantPrivateKey         商户私钥
    * @param merchantPrivateKeyPassword 商户私钥密码
    * @param message                    请求报文原始数据
    * @return 加签后的请求报文
    */
public static String signRequest(byte[] merchantPrivateKey, String merchantPrivateKeyPassword, String message) throws Exception {
        Signature tSignature = Signature.getInstance(SHA1withRSA);
        KeyStore tKeyStore = KeyStore.getInstance("PKCS12", new com.sun.net.ssl.internal.ssl.Provider().getName());
        tKeyStore.load(new ByteArrayInputStream(merchantPrivateKey), merchantPrivateKeyPassword.toCharArray());
        Enumeration e = tKeyStore.aliases();
        String tAliases = null;
        while (e.hasMoreElements()) {
            tAliases = (String) e.nextElement();
            break;
        }
        PrivateKey iMerchantKey = (PrivateKey) tKeyStore.getKey(tAliases, merchantPrivateKeyPassword.toCharArray());
        tSignature.initSign(iMerchantKey);
        tSignature.update(message.toString().getBytes("UTF-8"));
        String signatureInBase64 = new String(Base64.encodeBase64(tSignature.sign()), "UTF-8");
        String signedRequest = "{\"Message\":" + message + "," +
                "\"Signature-Algorithm\":" + "\"" + SIGNATURE_ALGORITHM + "\"" + "," +
                "\"Signature\":" + "\"" + signatureInBase64 + "\"}";
        return signedRequest;
    }

1.2 加签示例
a. 设定请求报文原始数据

String message = "{\"Version\":\"V3.0.0\",\"Format\":\"JSON\",\"Merchant\":{\"ECMerchantType\":\"EBUS\",\"MerchantID\":\"103882200000958\"},\"TrxRequest\":{\"TrxType\":\"PayReq\",\"Order\":{\"PayTypeID\":\"ImmediatePay\",\"OrderDate\":\"2021/02/04\",\"OrderTime\":\"16:36:18\",\"orderTimeoutDate\":\"20211231000000\",\"OrderNo\":\"ON2021456440301001\",\"CurrencyCode\":\"156\",\"OrderAmount\":\"1.00\",\"SubsidyAmount\":\"1.00\",\"Fee\":\"\",\"AccountNo\":\"\",\"OrderDesc\":\"\",\"OrderURL\":\"\",\"ReceiverAddress\":\"北京\",\"InstallmentMark\":\"0\",\"CommodityType\":\"0101\",\"BuyIP\":\"127.0.0.1\",\"ExpiredDate\":\"30\",\"SplitAccInfoItems\":\"\",\"OrderItems\":{\"SubMerName\":\"\",\"SubMerId\":\"\",\"SubMerMCC\":\"\",\"SubMerchantRemarks\":\"\",\"ProductID\":\"\",\"ProductName\":\"中国移动IP卡\",\"UnitPrice\":\"\",\"Qty\":\"\",\"ProductRemarks\":\"\",\"ProductType\":\"\",\"ProductDiscount\":\"\",\"ProductExpiredDate\":\"\"}},\"PaymentType\":\"A\",\"PaymentLinkType\":\"1\",\"ReceiveAccount\":\"\",\"ReceiveAccName\":\"\",\"NotifyType\":\"0\",\"ResultNotifyURL\":\"http://yourwebsite/appname/MerchantResult.jsp\",\"MerchantRemarks\":\"\",\"IsBreakAccount\":\"0\",\"SplitAccTemplate\":\"\"}}";

b. 设定商户私钥

byte[] merchantPrivateKey = readFile("D:/IdeaProjects/EBUS_CLIENT/out/artifacts/WebRoot/cert/test/103882200000958.pfx");

c. 设定商户私钥密码

String merchantPrivateKeyPassword = "11112222";

d. 进行加签

String signedRequest = EBusPayUtil.signRequest(merchantPrivateKey, merchantPrivateKeyPassword, message);

e. 组装加签后请求报文

{"Message":{"Version":"V3.0.0","Format":"JSON","Merchant":{"ECMerchantType":"EBUS","MerchantID":"103882200000958"},"TrxRequest":{"TrxType":"PayReq","Order":{"PayTypeID":"ImmediatePay","OrderDate":"2021/02/04","OrderTime":"16:36:18","orderTimeoutDate":"20211231000000","OrderNo":"ON2021456440301001","CurrencyCode":"156","OrderAmount":"1.00","SubsidyAmount":"1.00","Fee":"","AccountNo":"","OrderDesc":"","OrderURL":"","ReceiverAddress":"北京","InstallmentMark":"0","CommodityType":"0101","BuyIP":"127.0.0.1","ExpiredDate":"30","SplitAccInfoItems":"","OrderItems":{"SubMerName":"","SubMerId":"","SubMerMCC":"","SubMerchantRemarks":"","ProductID":"","ProductName":"中国移动IP卡","UnitPrice":"","Qty":"","ProductRemarks":"","ProductType":"","ProductDiscount":"","ProductExpiredDate":""}},"PaymentType":"A","PaymentLinkType":"1","ReceiveAccount":"","ReceiveAccName":"","NotifyType":"0","ResultNotifyURL":"http://yourwebsite/appname/MerchantResult.jsp","MerchantRemarks":"","IsBreakAccount":"0","SplitAccTemplate":""}},"Signature-Algorithm":"SHA1withRSA","Signature":"FsWwYCwn/vRUt66j5FmvSBlTC2rfagNOlzom60ISEy9TSJus0+lJL/PxsxEiEvQV8jcbM1NDciwk4ffIQl3nnmqVcvHpF2JNXQWev19ELARfukJLsUCmVZuAVW8Na4K0yCvfEZDdc5w/ju+EnZulhgjwYVb/a5JHayzkidINBTM="}

加签后的请求报文由三部分组成:Message字段及对应的值:请求报文原始数据,Signature-Algorithm字段及对应的值:加密算法即SHA1withRSA,Signature字段及对应的值:签名串

  1. 验签
    验签采用SHA1withRSA非对称签名算法,首先对签名串进行Base64转码,然后结合网上支付平台证书与返回报文中的签名串、报文信息、签名算法进行验签。

2.1 验签代码

/***
 * 验签方法
 *
 * @param signatureAlgorithm 返回报文中的Signature-Algorithm字段对应的值
 * @param signature          返回报文中的Signature字段对应的值
 * @param message            返回报文中的Message字段对应的值
 * @param trustPayCert       网上支付平台证书
 * @return true:验签成功,false:验签失败
 */
public static boolean verifyResponse(String signatureAlgorithm, String signature, String message, byte[] trustPayCert) throws Exception {
    java.security.Security.addProvider(new com.sun.net.ssl.internal.ssl.Provider());
    CertificateFactory tCertificateFactory = CertificateFactory.getInstance("X.509");
    ByteArrayInputStream trustPayCertInByteArray = new ByteArrayInputStream(trustPayCert);
    Certificate certificate = null;
    while (trustPayCertInByteArray.available() > 0) {
        certificate = tCertificateFactory.generateCertificate(trustPayCertInByteArray);
        break;
    }
    byte[] signatureInBytes = Base64.decodeBase64(signature.getBytes("GBK"));
    Signature signatureInstance = Signature.getInstance(SHA1withRSA);
    signatureInstance.initVerify(certificate);
    signatureInstance.update(message.getBytes("GBK"));
    return signatureInstance.verify(signatureInBytes);
}

2.2 验签示例
a. 获取返回报文中的Signature-Algorithm字段对应的签名算法

String signatureAlgorithm="SHA1withRSA";

b. 获取返回报文中的Signature字段对应的签名信息

String signature = "J1vXDnsTgbgmnpS/yLzu2m94A82mmva+P+2oGX52gqoV7CS2QWdLBqXf7uz/5P6Obq4ow0H7rraT1YA3xNd1FQbuOZCrwEx61yaEJbMludbKjhtm/B8dXcmPqnW+DzOzcuGr2yU8vCMt8DEH0rouei6q3AugOatV6NCf2bTTMyM=";

c. 获取返回报文中的Message字段对应的加签内容

String message = "{\"Version\":\"V3.0.0\",\"Format\":\"JSON\",\"Merchant\":{\"ECMerchantType\":\"EBUS\",\"MerchantID\":\"103882200000958\"},\"ReturnCode\":\"0000\",\"ErrorMessage\":\"交易成功\",\"TrxType\":\"PayReq\",\"OrderNo\":\"ON2021456440301001\",\"PaymentURL\":\"https://pay.test.abchina.com/perbankold/PaymentModeNewAct.ebf?TOKEN=16124277721648016933\",\"OrderAmount\":\"1.00\",\"OneQRForAll\":\"http://mpay.test.abchina.com/mpay/mobileBank/zh_CN/EBusinessModule/BarcodeH5Act.aspx?token=16124277721648016933\"}";     

d. 读取网上支付平台公钥文件

byte[] trustPayCert = readFile("D:/IdeaProjects/EBUS_CLIENT/out/artifacts/WebRoot/cert/test/TrustPayTest.cer");

e. 进行验签

boolean result = EBusPayUtil.verifyResponse(signatureAlgorithm, signature, message, trustPayCert)

相关文章

公众号
QQ讨论群