微信扫码登录实现

需求

使用微信扫码登录的授权方式登录系统

实现

此扫码登陆过程中使用了,微信开放平台(需支付300开通开发者认证)的网站应用实现的。

官方文档:https://developers.weixin.qq.com/doc/oplatform/Website_App/WeChat_Login/Wechat_Login.html

流程:

image-20220205204119502

大概就是:前端调接口获取后端生成的state(可以用验证登录授权的有效性)——>用户扫码后确认授权——>前端开始调用微信开放平台的接口之后回调服务端接口——>回调时传入了两个参数,code和state——>根据code,appid和appSecret调用接口获取access_token——根据access_token获取微信用户的个人信息

代码:

前端vue:
安装一个插件:
npm install vue-wxlogin --save-dev
引入组件:
<wxlogin
         appid="xxxxxx"
         :scope="'snsapi_login'"
         theme="black"
         redirect_uri="redirectUrl"
         :state="xxxxxx"
         :self_redirect="'true'"
         rel="external nofollow"
         />

注:重定向地址需要使用urlEncode对链接进行处理

后端SpringBoot:
后端生成state接口
@ApiOperation(value = "企业端:获取扫码登录的state", notes = " \n author:ZhuGuangLiang")
@AnonymousGetMapping("/wx/qrcode")
public Result<Object> getQrCode() throws IOException {
    //生成票据
    String state= IdUtil.simpleUUID();
    //可以将state参数作为存放在redis中的授权用户信息key键
    redisUtils.set(state, JSON.toJSON(new CompanyWxDTO()), 5 * 60);
    return Result.success(state);
}
回调接口,并携带state和code参数

注:回调接口,尽量不要抛出异常,异常可以在登录接口抛出

@ApiOperation(value = "企业端:微信用户授权后,回调地址", notes = " \n author:ZhuGuangLiang")
@AnonymousGetMapping("/wx/callback")
public void callback(String code, String state) {
    companyAuthService.callback(code, state);
}
//方法中所有第三方接口都可在官方文档中找到
@Override
public void callback(String code, String state) {
    //authurl获取access_token的接口,可以看官方文档中的第二步
    JSONObject resultAuthUrl = JSONObject.parseObject(HttpUtil.get(String.format(authUrl, appid, secret, code)));
    boolean isSuccess = true;
    if (resultAuthUrl.containsKey("errcode")) {
        log.error("授权失败");
        isSuccess = false;
        //			throw new BadRequestException(ResultEnum.USER_NO_AUTH);
    }
    String openid = resultAuthUrl.getString("openid");
    String accessToken = resultAuthUrl.getString("access_token");
    String refreshToken = resultAuthUrl.getString("refresh_token");
    //根据code获取access_toke
    LambdaQueryWrapper<SpiritCompanyUser> queryWrapper = new LambdaQueryWrapper<>();
    queryWrapper.eq(SpiritCompanyUser::getOpenid, openid);
    CompanyWxDTO companyWxDTO = loginUtils.noExceptinCheckCompanyUser(queryWrapper);
    int type = companyWxDTO.getType();
    if (!isSuccess) {
        //登录失败,此时我使用type类型去记录每一种异常
        companyWxDTO.setType(7);
    }
    if (type == 1 && isSuccess) {
        //校验授权凭证
        JSONObject resultCheckToken = JSONObject.parseObject(HttpUtil.get(String.format(checkTokenUrl, accessToken, openid)));
        if (resultCheckToken.getInteger("errcode") == 40003) {
            //刷新token,防止出现token失效
            JSONObject resultRefreshToken = JSONObject.parseObject(HttpUtil.get(String.format(refreshTokenUrl, appid, refreshToken)));
            accessToken = resultRefreshToken.getString("access_token");
        }
        //获取用户信息
        JSONObject resultUserInfoUrl = JSONObject.parseObject(HttpUtil.get(String.format(userInfoUrl, accessToken, openid)));
        log.info("resultUserInfoUrl:" + resultUserInfoUrl.toString());
        if (resultUserInfoUrl.containsKey("errcode")) {
            log.error("获取用户信息失败");
            //同上
            companyWxDTO.setType(8);
        }
        companyWxDTO.setAvatarUrl(resultUserInfoUrl.getString("headimgurl"));
        companyWxDTO.setNickName(resultUserInfoUrl.getString("nickname"));
        companyWxDTO.setOpenid(openid);
        companyWxDTO.setUnionid(resultUserInfoUrl.getString("unionid"));
        log.info("微信用户授权成功");
    }
    companyWxDTO.setTicket(state);
    redisUtils.set(state, JSON.toJSON(companyWxDTO), 5 * 60);
}
  • 8
    点赞
  • 44
    收藏
    觉得还不错? 一键收藏
  • 2
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值