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<String> 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
  }
}

微信扫一扫体验一把:

03-05 21:53