1、前端向微信获取code给个后端,后端根据code换取openid和sessionKey
2、前端用户点击授权调用微信getPhoneNumber方法获取加密的用户数据,即加密encryptedData和iv,传给后端
3后端解密encryptedData和iv拿到用户手机号执行登陆注册的逻辑
注:getPhoneNumber方法必须绑定在button组件里。详情官网:微信小程序获取手机号
public String wxRegistry(String encryptedData, String iv, String code) {
//第一步:通过code获取openid sessionKey
JSONObject sessionKeyOrOpenId = getSessionKeyOrOpenId(code);
String openid = sessionKeyOrOpenId.getStr("openid");
String sessionKey = sessionKeyOrOpenId.getStr("session_key");
//第二步:从encryptedData iv 解密 用户信息 拿到手机号
JSONObject userInfo = getUserInfo(encryptedData, iv, sessionKey);
String phone = userInfo.getStr("phoneNumber");
System.err.println("--------------------------------------------");
System.err.println("执行手机号注册登录逻辑");
System.err.println("--------------------------------------------");
return null;
}
@Value("${wechat.sessionHost}")
private String requestUrl;
@Value("${wechat.appId}")
private String appId;
@Value("${wechat.secret}")
private String secret;
public JSONObject getSessionKeyOrOpenId(String code) throws CustomizeException {
Map requestUrlParam = new HashMap<>();
requestUrlParam.put("appid", appId);//小程序appId
requestUrlParam.put("secret", secret);//小程序 appSecret
requestUrlParam.put("js_code", code);//小程序端返回的code
requestUrlParam.put("grant_type", "authorization_code");//默认参数
//发送post请求读取调用微信接口获取openid用户唯一标识
//我用的hutool工具包的HttpUtil、JSONUtil,各位按需导入
JSONObject SessionKeyOpenId = null;
try {
String result = HttpUtil.get(requestUrl, requestUrlParam);
SessionKeyOpenId = JSONUtil.parseObj(result);
} catch (Exception e) {
e.printStackTrace();
}
return SessionKeyOpenId;
}
public static JSONObject getUserInfo(String encryptedData, String iv, String sessionKey) {
// 被加密的数据
byte[] dataByte = cn.hutool.core.codec.Base64.decode(encryptedData);
// 加密秘钥
byte[] keyByte = cn.hutool.core.codec.Base64.decode(sessionKey);
// 偏移量
byte[] ivByte = cn.hutool.core.codec.Base64.decode(iv);
try {
// 如果密钥不足16位,那么就补足.
int base = 16;
keyByte = completToBase(keyByte, base);
ivByte = completToBase(ivByte, base);
// 初始化
Security.addProvider(new BouncyCastleProvider());
Cipher cipher = Cipher.getInstance("AES/CBC/PKCS7Padding", "BC");
SecretKeySpec spec = new SecretKeySpec(keyByte, "AES");
AlgorithmParameters parameters = AlgorithmParameters.getInstance("AES");
parameters.init(new IvParameterSpec(ivByte));
cipher.init(Cipher.DECRYPT_MODE, spec, parameters);// 初始化
byte[] resultByte = cipher.doFinal(dataByte);
if (null != resultByte && resultByte.length > 0) {
String result = new String(resultByte, "UTF-8");
System.out.println(result);
return JSONUtil.parseObj(result);
}
} catch (NoSuchAlgorithmException e) {
log.error(e.getMessage(), e);
} catch (NoSuchPaddingException e) {
log.error(e.getMessage(), e);
} catch (InvalidParameterSpecException e) {
log.error(e.getMessage(), e);
} catch (IllegalBlockSizeException e) {
log.error(e.getMessage(), e);
} catch (BadPaddingException e) {
log.error(e.getMessage(), e);
} catch (UnsupportedEncodingException e) {
log.error(e.getMessage(), e);
} catch (InvalidKeyException e) {
log.error(e.getMessage(), e);
} catch (InvalidAlgorithmParameterException e) {
log.error(e.getMessage(), e);
} catch (NoSuchProviderException e) {
log.error(e.getMessage(), e);
}
return null;
}
//补全数组位数
public static byte[] completToBase(byte[] bytes, int base) {
byte[] temp = new byte[]{};
if (bytes.length % base != 0) {
int groups = bytes.length / base + (bytes.length % base != 0 ? 1 : 0);
temp = new byte[groups * base];
Arrays.fill(temp, (byte) 0);
System.arraycopy(bytes, 0, temp, 0, bytes.length);
return temp;
} else {
return bytes;
}
}
至此授权手机号登录完成!so easy。