Uniapp小程序微信登录实践举例

524 阅读2分钟

思路:

  • uniapp通过appid获取jscodo
  • 调用后端接口,利用jscode、appid、secret获得openId
  • 后端鉴别用户openId是否已注册,是登录成功,否则需要注册或绑定手机号

操作列子

  1. Uniapp登录按钮
<button @click="wxLogin" class="login-btn cu-btn block bg-blue lg round" type="primary">微信登录</button>
  1. 登录获得jscode
// 微信登录,这里获得 jscode 传给后端去获取openID
async wxLogin() {
        this.$modal.loading("登录中,请耐心等待...")
        var that=this;
        uni.login({
                provider: "weixin",
                success: function(res) {
                        console.log(res.code)
                        that.$store.dispatch('WXLogin', res.code).then(() => {
                                that.$modal.closeLoading()
                                that.loginSuccess()
                        }).catch(() => {

                        })
                },
        });
},
  1. uniapp的Store Action中访问后端接口,获得token
// 微信登录 
WXLogin({commit}, jscode) {
        console.warn(jscode)
        //后端接口去验证 jscode 获得的OpenID是否存在,存在则说明该用户登录成功,返回token
        //在后端获取OpenID是安全的操作
        return new Promise((resolve, reject) => {
          wxLogin(jscode).then(res => {
            setToken(res.data.access_token)
            commit('SET_TOKEN', res.data.access_token)
            resolve()
          }).catch(error => {
            reject(error)
          })
        })
},

4.Java后端接口,利用appid、jscode、secret获得openId,然后刷新token


public LoginUser wxLogin(String jsCode) {

    if (StringUtils.isAnyBlank(jsCode)) {
        recordLogService.recordLogininfor(jsCode, Constants.LOGIN_FAIL, "微信登录的JsCode为空");
        throw new ServiceException("微信登录的JsCode为空");
    }
    try {
        // 这里应该优化,需要数据库建立一个表单,记录小程序的appid,传上来后,后端这里通过appid获取secret,这样可以适配多个小程序
        String url = String.format("https://api.weixin.qq.com/sns/jscode2session?appid=(你的AppId)&secret=(你的Secret)&grant_type=authorization_code&js_code=%s", jsCode);
        //获取微信OpenID
        OkHttpClient client = new OkHttpClient().newBuilder()
                .build();
        MediaType mediaType = MediaType.parse("text/plain");
        //RequestBody body = RequestBody.create(mediaType, "");
        Request request = new Request.Builder()
                .url(url)
                .get()
                .build();

        Response response = client.newCall(request).execute();

        String openid="";
        if(response.isSuccessful()){
            String res = response.body().string();
            System.out.printf(res);
            // 对应获取对象
            JSONObject object= JSONObject.parseObject(res);
            //  如果所含对象的值 是null  返回的值 并不是对象 null  只是一个字符串 null
            openid=object.getString("openid");

        }

        // 查询用户信息
        R<LoginUser> userResult = remoteUserService.getUserInfoByOpenId(openid, SecurityConstants.INNER);

        if (StringUtils.isNull(userResult) || StringUtils.isNull(userResult.getData())) {
            recordLogService.recordLogininfor(jsCode, Constants.LOGIN_FAIL, "jsCode对应的OpenID用户不存在");
            throw new ServiceException("jsCode:" + jsCode + " 对应的OpenID用户不存在");
        }

        if (R.FAIL == userResult.getCode()) {
            throw new ServiceException(userResult.getMsg());
        }

        LoginUser userInfo = userResult.getData();
        SysUser user = userResult.getData().getSysUser();
        if (UserStatus.DELETED.getCode().equals(user.getDelFlag())) {
            recordLogService.recordLogininfor(jsCode, Constants.LOGIN_FAIL, "对不起,您的账号已被删除");
            throw new ServiceException("对不起,您的账号:" + jsCode + " 已被删除");
        }
        if (UserStatus.DISABLE.getCode().equals(user.getStatus())) {
            recordLogService.recordLogininfor(jsCode, Constants.LOGIN_FAIL, "用户已停用,请联系管理员");
            throw new ServiceException("对不起,您的账号:" + jsCode + " 已停用");
        }

        recordLogService.recordLogininfor(userInfo.getUsername(), Constants.LOGIN_SUCCESS, "微信JsCode登录成功");
        return userInfo;
    } catch (IOException e) {
        throw new RuntimeException(e);
    }
}

  1. 当然这里我个人觉得需要优化的地方是,前端把appid,jscode一起传参。后端多租户即可实现按照不同的appid来处理用户的token