1、前往微信开放平台注册账号,然后关联小程序
2、小程序获取相关参数,提交给自己服务器后台
以下操作需要用户授权后进行:
wx.login({
success (res) {
if (res.code) {
//获取到code(用户登录凭证)
wx.getUserInfo({
success: function(resp) {
//获取到encryptedData(加密数据)和iv(偏移量)
//发起网络请求,将code、encryptedData和iv都提交到自己服务器后台
wx.request({
url: 'https://test.com/onLogin',
data: {
code: res.code,
encryptedData: resp.encryptedData,
iv: resp.iv
}
})
}
})
} else {
console.log('登录失败!' + res.errMsg)
}
}
})
3、通过code获取SessionKey(在自己服务器端做)
取小程序提供的参数code,请求以下链接获取access_token:
https://api.weixin.qq.com/sns...
参数说明
参数 | 是否必须 | 说明 |
---|---|---|
appid | 是 | 应用唯一标识,在微信开放平台提交应用审核通过后获得 |
secret | 是 | 应用密钥AppSecret,在微信开放平台提交应用审核通过后获得 |
code | 是 | 填写第一步获取的code参数 |
grant_type | 是 | 填authorization_code |
@Override
public String getSessionKey(String appid, String appSecret, String code) {
try {
String pattern = "https://api.weixin.qq.com/sns/jscode2session?appid=%s&secret=%s&grant_type=authorization_code&js_code=%s";
String url = String.format(Locale.ENGLISH, pattern, appid, appSecret, code);
ConvertedResponse response = EasyHttp.executeGet(url, new StringResponseConverter());
if (response.convertedResponse != null) {
log.debug(response.convertedResponse);
JSONObject jsonObject = JSON.parseObject(response.convertedResponse);
return jsonObject.getString("session_key");
}
} catch (Exception e) {
e.printStackTrace();
}
return null;
}
正确返回:
{
"session_key":"SESSION_KEY",
"openid":"OPEN_ID"
}
4、解密用户信息
现在根据上一步的SessionKey以及小程序提供的encryptedData和iv来解密,获取用户信息,如果正确解密,则整个第三方登录完成,解密失败则登录失败。
@Override
public String decryptUserInfo(String encryptedData, String iv, String sessionKey) {
try {
byte[] data = Base64.decodeBase64(encryptedData);
byte[] aseKey = Base64.decodeBase64(sessionKey);
byte[] ivData = Base64.decodeBase64(iv);
// 如果密钥不足16位,那么就补足
int base = 16;
if (aseKey.length % base != 0) {
int groups = aseKey.length / base + 1;
byte[] temp = new byte[groups * base];
Arrays.fill(temp, (byte) 0);
System.arraycopy(aseKey, 0, temp, 0, aseKey.length);
aseKey = temp;
}
Security.addProvider(new BouncyCastleProvider());
Cipher cipher = Cipher.getInstance("AES/CBC/PKCS7Padding");
SecretKeySpec spec = new SecretKeySpec(aseKey, "AES");
AlgorithmParameters params = AlgorithmParameters.getInstance("AES");
params.init(new IvParameterSpec(ivData));
cipher.init(Cipher.DECRYPT_MODE, spec, params);
byte[] result = cipher.doFinal(data);
String info = new String(result, StandardCharsets.UTF_8);
log.debug(info);
return info;
} catch (Exception e) {
log.error(e.getLocalizedMessage(), e);
return null;
}
}
正确的解密结果:
{
"openId": "OPENID",
"nickName": "NICKNAME",
"gender": GENDER,
"city": "CITY",
"province": "PROVINCE",
"country": "COUNTRY",
"avatarUrl": "AVATARURL",
"unionId": "UNIONID",
"watermark": {
"appid":"APPID",
"timestamp":TIMESTAMP
}
}