前沿:
错误都逻辑:
用户授权(bindgetuserinfo)–>wx.login()[获取sessionKey]–>授权手机号码(bindgetphonenumber)
正确都逻辑:
wx.login()[获取sessionKey]–>用户授权(bindgetuserinfo)–>授权手机号码(bindgetphonenumber)
问题:小程序在解密手机号、用户信息都出现第一次调用解密失败,第二次成功,
原因: 通过open-type=“getUserInfo” 先获取iv和encryptedData,再获取code, 这时的sessionKey 和vi 是不匹配的.
解决方案: 先获取code 再获取iv和encryptedData
如果不按照上面顺序你将会在解析的时候报错
javax.crypto.BadPaddingException: Given final block not properly padded
1.需要获取微信中的 appid & secretid & wxcode(这个是前端调用的code)
2.访问小程序的url:
"https://api.weixin.qq.com/sns/jscode2session?appid=%s&secret=%s&js_code=%s&grant_type=authorization_code"
3.该小程序会返回 sessionKey & openid (这个解密手机号需要用key)
4.这时候获取的sessionKey 前端调用手机号码接口 返回的数据是
private String encryptedData;
private String iv;
5.手机号码内容解密
import cfca.sadk.org.bouncycastle.util.encoders.Base64;
import javax.crypto.Cipher;
import javax.crypto.spec.IvParameterSpec;
import javax.crypto.spec.SecretKeySpec;
import java.security.spec.AlgorithmParameterSpec;
import cn.hutool.json.JSONObject;
import cn.hutool.json.JSONUtil;
private String getPhoneNumberForWx(String encryptedData, String iv,String sessionKey){
try {
byte[] encData = Base64.decode(encryptedData);
byte[] iv = Base64.decode(iv);
byte[] key = Base64.decode(sessionKey);
AlgorithmParameterSpec ivSpec = new IvParameterSpec(iv);
Cipher cipher = Cipher.getInstance("AES/CBC/PKCS5Padding");
SecretKeySpec keySpec = new SecretKeySpec(key, "AES");
cipher.init(Cipher.DECRYPT_MODE, keySpec, ivSpec);
String wxInformation = new String(cipher.doFinal(encData), "UTF-8");
JSONObject jsonObject = JSONUtil.parseObj(wxInformation);
String phoneNumber = jsonObject.getStr("phoneNumber");
if(StringUtils.isBlank(phoneNumber)){
throw new RuntimeException("微信接口没有返回手机号");
}
return phoneNumber;
}catch (Exception e) {
e.printStackTrace();
}
return null;
}
这里是微信返回的对象内容
{
"phoneNumber": "15825059525",
"purePhoneNumber": "15825059525",
"countryCode": "86",
"watermark": {
"timestamp": 1690248376,
"appid": "wx123913fb153xda3C9e"
}
}