支付寶敏感信息解密


  支付寶官方解密文檔:https://docs.alipay.com/mini/introduce/aes

String response = "小程序前端提交的";

//1. 獲取驗簽和解密所需要的參數
Map<String, String> openapiResult = JSON.parseObject(response,
            new TypeReference<Map<String, String>>() {
            }, Feature.OrderedField);
String signType = StringUtil.defaultIfBlank(openapiResult.get("signType"), "RSA2");
String charset = StringUtil.defaultIfBlank(openapiResult.get("charset"), "UTF-8");
String encryptType = StringUtil.defaultIfBlank(openapiResult.get("encryptType"), "AES");
String sign = openapiResult.get("sign");
//如果密文的
boolean isDataEncrypted = !content.startsWith("{");
boolean signCheckPass = false;

//2. 驗簽
String signContent = content;
String signVeriKey = "你的小程序對應的支付寶公鑰(為擴展考慮建議用appId+signType做密鑰存儲隔離)";
String encryptType = "你的小程序對應的加解密密鑰(為擴展考慮建議用appId+encryptType做密鑰存儲隔離)"
//如果是加密的報文則需要在密文的前后添加雙引號
if (isDataEncrypted) {
    signContent = "\"" + signContent + "\"";
}
try {
    signCheckPass = AlipaySignature.rsaCheck(signContent, sign, signVeriKey, charset, signType);
} catch (AlipayApiException e) {
    //驗簽異常, 日志
}
if(!signCheckPass) {
    //驗簽不通過(異常或者報文被篡改),終止流程(不需要做解密)
    throw new Exception("驗簽失敗");
}

//3. 解密
String plainData = null;
if (isDataEncrypted) {
    try {
        AlipayEncrypt.decryptContent(content, encryptType, decryptKey, charset);
    } catch (AlipayApiException e) {
        //加密異常, 日志
       throw new Exception("解密異常");
    }
} else {
    plainData = content;
}

  雖然是參考代碼,但個人感覺太隨意了。做了一些簡單的修改,編譯和邏輯都沒有問題了。

/**
 * 敏感信息解密
 */
@PostMapping(value = "/decryptor", produces = MediaType.APPLICATION_JSON_UTF8_VALUE)
public RestResponse decryptor(@RequestBody String encryptContent) {
    RestResponse restResponse = new RestResponse();

    try {
        Map<String, String> openapiResult = JSON.parseObject(encryptContent,
                new TypeReference<Map<String, String>>() {
                },
                Feature.OrderedField);
        String signType = StringUtils.defaultIfBlank(openapiResult.get("sign_type"), "RSA2");
        String charset = StringUtils.defaultIfBlank(openapiResult.get("charset"), "UTF-8");
        String encryptType = StringUtils.defaultIfBlank(openapiResult.get("encrypt_type"), "AES");
        String sign = openapiResult.get("sign");
        String content = openapiResult.get("response");

        LOGGER.info(String.format("准備驗簽和解密,sign=[%s], signType=[%s], encryptType=[%s], encryptContent=[%s]", sign, signType, encryptType, encryptContent));

        //如果密文的
        boolean isDataEncrypted = !content.startsWith("{");
        boolean signCheckPass;

        //2. 驗簽
        String signContent = content;
        //支付寶應用公鑰
        String signVeriKey = ALIPAY_APPLET_PUBLIC_SECRET;

        //如果是加密的報文則需要在密文的前后添加雙引號
        if (isDataEncrypted) {
            signContent = "\"" + signContent + "\"";
        }
        try {
            signCheckPass = AlipaySignature.rsaCheck(signContent, sign, signVeriKey, charset, signType);
        } catch (AlipayApiException e) {
            //驗簽異常, 日志
            LOGGER.error("驗簽異常,encryptContent=" + encryptContent, e);
            restResponse.setRestStatus(RestStatus.FAIL_100021);
            return restResponse;
        }
        if (!signCheckPass) {
            //驗簽不通過(異常或者報文被篡改),終止流程(不需要做解密)
            LOGGER.error("驗簽失敗,encryptContent=" + encryptContent);
            restResponse.setRestStatus(RestStatus.FAIL_100021);
            return restResponse;
        }

        //支付寶小程序AES秘鑰
        String encryptKey = ALIPAY_APPLET_AES_SECRET;

        //3. 解密
        String plainData;
        if (isDataEncrypted) {
            try {
                plainData = AlipayEncrypt.decryptContent(content, encryptType, encryptKey, charset);
            } catch (AlipayApiException e) {
                //解密異常, 日志
                LOGGER.error("解密異常,encryptContent=" + encryptContent, e);
                restResponse.setRestStatus(RestStatus.FAIL_100021);
                return restResponse;
            }
        } else {
            plainData = content;
        }
        restResponse.setData(plainData);
        restResponse.setRestStatus(RestStatus.SUCCESS);
    } catch (Exception e) {
        LOGGER.error("驗簽解密異常,encryptContent=" + encryptContent, e);
        restResponse.setRestStatus(RestStatus.FAIL_100021);
    }
    return restResponse;
}

  解密報文示例。

{"response":"+A9tOP5n2uUJaQRJOxLj6+rR0yooZWC/SQhcHDJ1BbLKkEA+hUr2ah3KOzL/+RwuyO4mH5ZSeFRpOrNPyTac/w==","sign":"V9OSmt5iTWr2tqpW/p6jjTcvpdiva8WxjnC7nvqyHg5eT181/61wcKysoTgLuNfFd2XbKvULHxi9mZDIh3OAR1PDIs0aOEhzimORbf9wBofoWfGKlq2iwWKeSSnxyS0W4maF0VrS0kNySsx5ta7eBGtSlGozOOR6R7oeygNdd43jOo33pZmUA0fo6DSHZH5lblrwqL4t0UcLSFLx1kqVNi28BsRQA5OxqkUp78PsxPGdps0CI9gQcAHfCKbKYk6F1bimw+R3k7ympm2esdEfl59Yym7lpz7gtOkGuNDjY3Y/urrYwGt7Kq/EX5BcIYA4DCS4nPkyb3wPRkH1VKBE+g=="}
或者

{ "response": "hvDOnibG0DPcOFPNubK3DEfLQGL4=", "sign": "OIwk7zfZMp5GX78Ow==", "sign_type": "RSA2", "encrypt_type": "AES", "charset": "UTF-8" }

 


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM