Java实现微信小程序登录

 java实现微信小程序登录的流程如图所示,首先微信小程序端调用wx.login()获取临时登录凭证code,然后将code发送给我们的后端服务,后端服务使用code、appId、appSecret调用微信服务端的接口获取openId和sessionKey。到这一步,就已经实现了在微信侧的登录了,接下来就是结合自身的业务逻辑生成登录凭证(token)返回给小程序端进行后续的接口调用了。

我们这里对登录流程做了进一步的细化,要求使用用户的手机号进行登录。

因此第一步是通过临时登录凭证(code)获取到openId和sessionKey以后,将openId返回给小程序端,并将openId和sessionKey存入redis

public String getOpenId(String code) {
    //构建请求url
    String url = buildWeChatOpenIdUrl(code);
    //发送请求
    JSONObject response = requestWeChatApi(url);

    //将openid -> session key存入redis
    String redisKey = RedisKey.WX_OPENID + response.getString("openid");
    stringRedisTemplate.opsForValue().set(redisKey,
                       response.getString("session_key"), 10, TimeUnit.MINUTES);
    return response.getString("openid");
}
/**
 * 构建获取微信openId的url
 */
private String buildWeChatOpenIdUrl(String code) {
    return UriComponentsBuilder.fromHttpUrl(wxConfig.getOpenIdApiUrl())
            .queryParam("appid", wxConfig.getAppId())
            .queryParam("secret", wxConfig.getAppSecret())
            .queryParam("js_code", code)
            .queryParam("grant_type", "authorization_code")
            .toUriString();
}

第二步,小程序端通过用户授权可获取用户手机号,但此时的手机号是加密状态,因此小程序端将获取到的加密信息(encryptedData)以及openId和iv发送至后端服务,后端服务可使用sessionKey和iv对加密信息(encryptedData)进行解密从而获取用户的详细信息。

public void login(LoginDTO request) {
    //根据openid获取session key
    String sessionKey = stringRedisTemplate.opsForValue().get(RedisKey.WX_OPENID + request.getOpenId());
    if (StringUtils.isBlank(sessionKey)) {
        throw new BizException("session key失效");
    }
    //解密用户手机号
    String userPhoneNumber = getUserPhoneNumber(sessionKey, request.getIv(), request.getEncryptedData());
    if (StringUtils.isBlank(userPhoneNumber)) {
        throw new BizException("账号异常");
    }
    //todo 业务登录流程...
}

/**
 * 获取用户手机号
 */
private String getUserPhoneNumber(String sessionKey, String iv, String encryptedData) {
    try {
        Security.addProvider(new BouncyCastleProvider());
        Cipher cipher = Cipher.getInstance("AES/CBC/PKCS7Padding");
        SecretKeySpec keySpec = new SecretKeySpec(Base64.getDecoder().decode(sessionKey), "AES");
        AlgorithmParameters parameters = AlgorithmParameters.getInstance("AES");
        parameters.init(new IvParameterSpec(Base64.getDecoder().decode(iv)));
        cipher.init(Cipher.DECRYPT_MODE, keySpec, parameters);

        byte[] result = cipher.doFinal(Base64.getDecoder().decode(encryptedData));
        String phoneNumberJsonStr = new String(result, StandardCharsets.UTF_8);
        JSONObject phoneNumberJson = JSONObject.parseObject(phoneNumberJsonStr);
        return phoneNumberJson.getString("purePhoneNumber");
    } catch (Exception e) {
        log.error("微信用户手机号解密异常,sessionKey:{}, encryptedData:{}, iv:{}, 错误信息:{}", sessionKey, encryptedData, iv, e.getMessage());
        return null;
    }
}

获取到用户手机号以后,就可以进行我们自己业务的登录流程啦~

  • 3
    点赞
  • 4
    收藏
    觉得还不错? 一键收藏
  • 1
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值