微信官方文档 https://developers.weixin.qq.com/miniprogram/dev/framework/open-ability/getPhoneNumber.html
全部放在一个Controller里了,方便看。代码中有些是自定义封装的工具类,关键部分就是try代码块中解密的用法。
@RequestMapping(rootUrl + "decodeWxAppPhone")
@ResponseBody
public Object decodeWxAppPhone(HttpServletRequest request,
HttpServletResponse response) {
response.setHeader("Access-Control-Allow-Origin", "*");
ResResult verResult = CommonSignUtils.verifyParamAndPermission(request,
"encrypted,iv,code");
if (ObjectHelper.isNotEmpty(verResult.getResObject())) {// 验证未通过
return verResult.getResObject();
}
String encrypted = verResult.getParams().get("encrypted");
String iv = verResult.getParams().get("iv");
String code = verResult.getParams().get("code");
Map params = new HashMap<>();
params.put("appid", appId);
params.put("secret", secret);
params.put("js_code", code);
params.put("grant_type", "authorization_code");
try {
// 向微信服务器发送post请求获取加密了的内容
String jsonStr= HTTPSocketFactory
.postHttp2("https://api.weixin.qq.com/sns/jscode2session",
params)
.getObject();
JSONObject jsonObject = JSON.parseObject(jsonStr);
String sessionkey = jsonObject.getString("session_key");
// 解密
byte[] encrypData = Base64Utils.decodeFromString(encrypted);
byte[] ivData = Base64Utils.decodeFromString(iv);
byte[] sessionKey1 = Base64Utils.decodeFromString(sessionkey);
AlgorithmParameterSpec ivSpec = new IvParameterSpec(ivData);
//java中自带的是PKCS5Padding填充,通过添加BouncyCastle组件来支持PKCS7Padding填充。
Security.addProvider(new org.bouncycastle.jce.provider.BouncyCastleProvider());
Cipher cipher = Cipher.getInstance("AES/CBC/PKCS7Padding");
SecretKeySpec keySpec = new SecretKeySpec(sessionKey1, "AES");
cipher.init(Cipher.DECRYPT_MODE, keySpec, ivSpec);
String resultString = new String(cipher.doFinal(encrypData), "UTF-8");
JSONObject object = JSONObject.parseObject(resultString);
// 拿到手机号码
String phone = object.getString("phoneNumber");
JSONObject returnObject = new JSONObject();
returnObject.put("phone", phone);
return Result.newSuccess(returnObject);
} catch (Exception e) {
e.printStackTrace();
return Result.newFailure(-1, "获取手机号异常失败");
}
}
遇到的错误:
javax.crypto.BadPaddingException: Given final block not properly pad
java.security.NoSuchAlgorithmException: Cannot find any provider supporting AES/CBC/PKCS7Padding
java.security.InvalidAlgorithmParameterException: ECB mode cannot use IV
java.lang.IllegalArgumentException: Last unit does not have enough valid bits
javax.crypto.BadPaddingException: pad block corrupted
偶尔报:javax.crypto.BadPaddingException: pad block corrupted
并且运行到这一句报的错:Cipher cipher = Cipher.getInstance("AES/CBC/PKCS7Padding","BC");
https://blog.csdn.net/zhanglf02/article/details/100124091
参考博客:
[1] https://blog.csdn.net/yuanhangLVli/article/details/82152178
[2] https://www.jianshu.com/p/2853b21fb42e
[3] https://blog.csdn.net/dywailly/article/details/46861777
[4] https://www.jianshu.com/p/f8cd7391d641