支付寶官方解密文檔: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; }
雖然是參考代碼,但我的感受太隨意了。作了一些簡單的修改,編譯和邏輯都沒有問題了。json
/** * 敏感信息解密 */ @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" }