企业微信接入系列-扫码绑定/登录

本文涉及的产品
云数据库 Redis 版,社区版 2GB
推荐场景:
搭建游戏排行榜
简介: 讲述在企业后台管理平台账号绑定企业微信以及企业微信扫码登录企业管理平台

文档介绍

企业微信扫码授权登录官方文档地址:https://developer.work.weixin.qq.com/document/path/91025,在进行企业微信扫码授权绑定/登录之前需要先自建应用,同时需要开启网页授权登录,具体自建应用的相关操作可以参考博文:https://developer.aliyun.com/article/1136114

管理平台接入

完成了上面企业微信管理后台的相关配置之后,我们就可以按照文档步骤开始操作了

构造二维码

关于构造企业微信扫码绑定/登录二维码一共有两种方式:构造独立窗口登录二维码、构造内嵌登录二维码,下面简单说一下构造独立窗口登录二维码

构造独立窗口登录二维码

构造独立窗口登录二维码,可以在页面放置一个button按钮,添加点击事件,在触发点击事件时访问连接https://open.work.weixin.qq.com/wwopen/sso/qrConnect?appid=CORPID&agentid=AGENTID&redirect_uri=REDIRECT_URI&state=STATE,效果如图

image.png连接参数说明:

image.png

下面我们主要说一下构造内嵌登录二维码

构造内嵌登录二维码

构造内嵌登录二维码,就是在页面中引入js同时在页面做处理,

1.在页面中引入js

<script src="http://wwcdn.weixin.qq.com/node/wework/wwopen/js/wwLogin-1.2.7.js"></script>

2.页面引入div元素

<div id="login_container_wechat" style="padding-left: 50px;"></div>

3.实例化js对象

    //点击企业微信
    function bind_wechat() {
        var redirectUrl = projectUrl+'system/user/profile/bindWeChat';
        //console.log(redirectUrl);
        var wwLogin = new WwLogin({
            "id": "login_container_wechat",
            "appid": wechatAppId,
            "agentid": agentId,
            "redirect_uri": redirectUrl,
            "state": "STATE",
            "href": "",
            "lang": "zh",
        });
        wwLogin.destroyed() // 注意wwLogin为实例对象
    }

参数说明

参数 必须 说明
id 企业页面显示二维码的DOM id
appid 企业微信的CorpID,在企业微信管理端查看
agentid 授权方的网页应用ID,在具体的网页应用中查看
redirect_uri 重定向地址,需要进行UrlEncode
state 用于保持请求和回调的状态,授权请求后原样带回给企业。该参数可用于防止csrf攻击(跨站请求伪造攻击),建议企业带上该参数,可设置为简单的随机数加session进行校验
href 自定义样式链接,企业可根据实际需求覆盖默认样式。详见文档底部FAQ
lang 自定义语言,支持zh、en;lang为空则从Headers读取Accept-Language
self_redirect true:手机点击确认登录后可以在 iframe 内跳转到 redirect_uri,false:手机点击确认登录后可以在 top window 跳转到 redirect_uri。默认为 false。

页面效果

构造内嵌登录二维码后页面展示效果

image.png

Java代码

Java代码部分主要分为绑定企业微信和企业微信扫码登录,首先说一下企业后台管理平台账号绑定企业微信的操作

绑定企业微信

绑定企业微信java代码

    @RequestMapping("/bindWeChat")
    public String bingWeChat(HttpServletRequest request) {
    //获取当前登录用户信息
        User sysUser = ShiroUtils.getSysUser();
        Long userId = sysUser.getUserId();
        String msg = "";
        //校验是否登录
        if (userId != null) {
            String code = request.getParameter("code");
            //获取用户信息userid
            String userid = weChatService.getUserid(code);
            if (StringUtils.isNotEmpty(userid)) {
                //判定当前用户是否已经绑定
                List<UserWechat> wechats = userWechatService.selectUserWechatByUserId(userId);
                //List<UserWechat> wechats = userWechatService.selectUserWechatByWechatUserid(userid);
                if (CollectionUtils.isEmpty(wechats)) {
                    UserWechat wechat = new UserWechat();
                    wechat.setWechatUserid(userid);
                    wechat.setUserId(userId);
                    wechat.setCreateBy(String.valueOf(userId));
                    wechat.setCreateTime(new Date());
                    wechat.setUpdateTime(wechat.getCreateTime());
                    // 获取用户信息
                    WeChatGetUserInfoByUseridResponse userInfo = weChatService.getUserInfoByInnerApp(userid);
                    if ( Objects.equals(userInfo.getErrcode(), 0L) ) {
                        wechat.setName(userInfo.getName());
                        wechat.setMobile(userInfo.getMobile());
                        wechat.setDepartment(Arrays.stream(userInfo.getDepartment()).map(String::valueOf).collect(Collectors.joining(",")));
                        wechat.setSort(Arrays.stream(userInfo.getOrder()).map(String::valueOf).collect(Collectors.joining(",")));
                        wechat.setPosition(userInfo.getPosition());
                        wechat.setGender(userInfo.getGender());
                        wechat.setEmail(userInfo.getEmail());
                        wechat.setBizMail(userInfo.getBizMail());
                        wechat.setIsLeaderInDept(Arrays.stream(userInfo.getIsLeaderInDept()).map(String::valueOf).collect(Collectors.joining(",")));
                        wechat.setDirectLeader(Arrays.stream(userInfo.getDirectLeader()).map(String::valueOf).collect(Collectors.joining(",")));
                        wechat.setAvatar(userInfo.getAvatar());
                        wechat.setThumbAvatar(userInfo.getThumbAvatar());
                        wechat.setTelephone(userInfo.getTelephone());
                        wechat.setAlias(userInfo.getAlias());
                        wechat.setExtattr(Optional.ofNullable(userInfo.getExtattr()).map(item->item.toJSONString()).orElse(null));
                        wechat.setStatus(Optional.ofNullable(userInfo.getStatus()).map(Long::intValue).orElse(null));
                        wechat.setQrCode(userInfo.getQrCode());
                        wechat.setExternalProfile(Optional.ofNullable(userInfo.getExternalProfile()).map(item->item.toJSONString()).orElse(null));
                        wechat.setExternalPosition(userInfo.getExternalPosition());
                        wechat.setAddress(userInfo.getAddress());
                        wechat.setOpenUserid(userInfo.getOpenUserid());
                        wechat.setMainDepartment(userInfo.getMainDepartment());
                    }
                    int i = userWechatService.insertUserWechat(wechat);
                    //绑定成功
                    msg = "three-three";
                }else {
                    //已绑定过了
                    msg = "two-two";
                }
            }else {
                //绑定失败
                msg = "four-four";
            }
        }else {
            //未登录
            msg = "one-one";
        }
        return redirect("/system/user/profile?msg="+msg);
    }

代码说明:

UserWechat对象:主要是本地数据库保存企业微信用户信息的数据库表对应的对象,大家可以根据业务需要确定需要保存的UserWechat字段;

调用企业微信接口方法

    /**
     * 获取accesstocken--自建应用
     * https://developer.work.weixin.qq.com/document/path/91039
     * @return
     */
    private String getAccessToken () {
        //首先判断redis中是否已经有accessToken,有的话直接取出返回,减少调用次数,提高响应效率
        String accessToken = redisService.get("accessToken");
        if ( StringUtils.isNotEmpty(accessToken) ) {
            return accessToken;
        }
        String url = "https://qyapi.weixin.qq.com/cgi-bin/gettoken?corpid="+ ConstantConfig.wechatAppId+"&corpsecret="+ ConstantConfig.wechatSecret;
        ResponseEntity<String> get = RestUtils.get(url, String.class);
        if (Objects.nonNull(get)) {
            String body = get.getBody();
            WeChatGettokenResponse res = JSON.parseObject(body, WeChatGettokenResponse.class);
            if (res.getErrcode() == 0) {
                redisService.setWithExpire("accessToken",res.getAccessToken(),3600L, TimeUnit.SECONDS);
                accessToken = res.getAccessToken();
            }
        }
        return accessToken;
    }
    /**
     * 扫码获取用户userid--自建应用
     * https://developer.work.weixin.qq.com/document/path/91437
     * @param code
     * @return
     */
    @Override
    public String getUserid(String code) {
        String accessToken = getAccessToken();
        if (StringUtils.isNotEmpty(accessToken)) {
            String url = "https://qyapi.weixin.qq.com/cgi-bin/auth/getuserinfo?access_token="+accessToken+ "&code="+code;
            ResponseEntity<String> get = RestUtils.get(url, String.class);
            if (Objects.nonNull(get)) {
                String body = get.getBody();
                WeChatGetUseridByCodeResponse res = JSON.parseObject(body, WeChatGetUseridByCodeResponse.class);
                String userid = res.getUserid();
                return userid;
            }
        }
        return null;
    }
    /**
     * 获取用户信息
     *
     * @param userid
     * @return
     */
    @Override
    public WeChatGetUserInfoByUseridResponse getUserInfoByInnerApp(String userid) throws WechatWorkApiException {
    //首先判断redis中是否已经有当前用户,有的话则无需调用企业微信接口,当然此段代码也可以去掉
        Object object = redisService.get(userid);
        if (Objects.nonNull(object)) {
            return (WeChatGetUserInfoByUseridResponse) object;
        }
        String accessToken = getAccessToken();
        if ( StringUtils.isEmpty(accessToken) ) {
            throw new WechatWorkApiException("企业微信-自建应用accessToken找不到");
        }
        String url = "https://qyapi.weixin.qq.com/cgi-bin/user/get?access_token={accessToken}&userid={userId}";
        Map<String, Object> params = new HashMap<>(4);
        params.put("accessToken", accessToken);
        params.put("userId", userid);
        try {
            ResponseEntity<String> result = RestUtils.get(url, String.class, params);
            WeChatGetUserInfoByUseridResponse res = JSON.parseObject(result.getBody(), WeChatGetUserInfoByUseridResponse.class);
            if (res.getErrcode() == 0) {
                redisService.setWithExpire(userid,res,600L, TimeUnit.SECONDS);
            }
            return res;
        } catch (Exception e) {
            throw new WechatWorkApiException("调用企业微信-获取用户信息接口异常:", e);
        }
    }

企业微信接口返回值实体类

WeChatGettokenResponse.java

public class WeChatGettokenResponse extends WeChatResponse {
    private static final long serialVersionUID = 9059923845826321694L;
    @ApiField("access_token")
    private String accessToken;
    @ApiField("expires_in")
    private Long expiresIn;
    public String getAccessToken() {
        return accessToken;
    }
    public void setAccessToken(String accessToken) {
        this.accessToken = accessToken;
    }
    public Long getExpiresIn() {
        return expiresIn;
    }
    public void setExpiresIn(Long expiresIn) {
        this.expiresIn = expiresIn;
    }
}

WeChatGetUseridByCodeResponse.java

public class WeChatGetUseridByCodeResponse extends WeChatResponse {
    private static final long serialVersionUID = 1952405193554901932L;
    @ApiField("userid")
    private String userid;
    public String getUserid() {
        return userid;
    }
    public void setUserid(String userid) {
        this.userid = userid;
    }
}

WeChatGetUserInfoByUseridResponse.java

public class WeChatGetUserInfoByUseridResponse extends WeChatResponse {
    private static final long serialVersionUID = -5645000854038589898L;
    @ApiField("userid")
    private String userid;
    @ApiField("name")
    private String name;
    @ApiField("department")
    private Long[] department;
    @ApiField("order")
    private Long[] order;
    @ApiField("position")
    private String position;
    @ApiField("mobile")
    private String mobile;
    @ApiField("gender")
    private String gender;
    @ApiField("email")
    private String email;
    @ApiField("biz_mail")
    private String bizMail;
    @ApiField("is_leader_in_dept")
    private Long[] isLeaderInDept;
    @ApiField("direct_leader")
    private String[] directLeader;
    @ApiField("avatar")
    private String avatar;
    @ApiField("thumb_avatar")
    private String thumbAvatar;
    @ApiField("telephone")
    private String telephone;
    @ApiField("alias")
    private String alias;
    @ApiField("address")
    private String address;
    @ApiField("open_userid")
    private String openUserid;
    @ApiField("main_department")
    private Long mainDepartment;
    @ApiField("extattr")
    private JSONObject extattr;
    @ApiField("status")
    private Long status;
    @ApiField("qr_code")
    private String qrCode;
    @ApiField("external_position")
    private String externalPosition;
    @ApiField("external_profile")
    private JSONObject externalProfile;
    public String getUserid() {
        return userid;
    }
    public void setUserid(String userid) {
        this.userid = userid;
    }
    public String getName() {
        return name;
    }
    public void setName(String name) {
        this.name = name;
    }
    public Long[] getDepartment() {
        return department;
    }
    public void setDepartment(Long[] department) {
        this.department = department;
    }
    public Long[] getOrder() {
        return order;
    }
    public void setOrder(Long[] order) {
        this.order = order;
    }
    public String getPosition() {
        return position;
    }
    public void setPosition(String position) {
        this.position = position;
    }
    public String getMobile() {
        return mobile;
    }
    public void setMobile(String mobile) {
        this.mobile = mobile;
    }
    public String getGender() {
        return gender;
    }
    public void setGender(String gender) {
        this.gender = gender;
    }
    public String getEmail() {
        return email;
    }
    public void setEmail(String email) {
        this.email = email;
    }
    public String getBizMail() {
        return bizMail;
    }
    public void setBizMail(String bizMail) {
        this.bizMail = bizMail;
    }
    public Long[] getIsLeaderInDept() {
        return isLeaderInDept;
    }
    public void setIsLeaderInDept(Long[] isLeaderInDept) {
        this.isLeaderInDept = isLeaderInDept;
    }
    public String[] getDirectLeader() {
        return directLeader;
    }
    public void setDirectLeader(String[] directLeader) {
        this.directLeader = directLeader;
    }
    public String getAvatar() {
        return avatar;
    }
    public void setAvatar(String avatar) {
        this.avatar = avatar;
    }
    public String getThumbAvatar() {
        return thumbAvatar;
    }
    public void setThumbAvatar(String thumbAvatar) {
        this.thumbAvatar = thumbAvatar;
    }
    public String getTelephone() {
        return telephone;
    }
    public void setTelephone(String telephone) {
        this.telephone = telephone;
    }
    public String getAlias() {
        return alias;
    }
    public void setAlias(String alias) {
        this.alias = alias;
    }
    public String getAddress() {
        return address;
    }
    public void setAddress(String address) {
        this.address = address;
    }
    public String getOpenUserid() {
        return openUserid;
    }
    public void setOpenUserid(String openUserid) {
        this.openUserid = openUserid;
    }
    public Long getMainDepartment() {
        return mainDepartment;
    }
    public void setMainDepartment(Long mainDepartment) {
        this.mainDepartment = mainDepartment;
    }
    public JSONObject getExtattr() {
        return extattr;
    }
    public void setExtattr(JSONObject extattr) {
        this.extattr = extattr;
    }
    public Long getStatus() {
        return status;
    }
    public void setStatus(Long status) {
        this.status = status;
    }
    public String getQrCode() {
        return qrCode;
    }
    public void setQrCode(String qrCode) {
        this.qrCode = qrCode;
    }
    public String getExternalPosition() {
        return externalPosition;
    }
    public void setExternalPosition(String externalPosition) {
        this.externalPosition = externalPosition;
    }
    public JSONObject getExternalProfile() {
        return externalProfile;
    }
    public void setExternalProfile(JSONObject externalProfile) {
        this.externalProfile = externalProfile;
    }
}

WeChatResponse.java

public class WeChatResponse implements Serializable {
    private static final long serialVersionUID = 2109769518803249524L;
    @ApiField("errcode")
    private Long errcode;
    @ApiField("errmsg")
    private String errmsg;
    public Long getErrcode() {
        return errcode;
    }
    public void setErrcode(Long errcode) {
        this.errcode = errcode;
    }
    public String getErrmsg() {
        return errmsg;
    }
    public void setErrmsg(String errmsg) {
        this.errmsg = errmsg;
    }
}

这样整套扫码授权绑定企业微信的操作就算完成了,其实企业微信扫码登录的操作和绑定基本步骤相同,这里不细说代码,讲一下代码主要结构

企业微信扫码登录

企业微信扫码登录页面二维码构造参考【构造内嵌登录二维码】操作步骤,后台java代码结构

    /**
     * 扫码登录并跳转到index
     * @param request
     * @return
     */
    @RequestMapping("/loginScan")
    public String loginSys(HttpServletRequest request)
    {
        String code = request.getParameter("code");
        String msg = "";
        //扫码登录
        try {
            //1.获取企业微信用户信息userid
            String userid = weChatService.getUserid(code);
            //2.根据 企业微信 userid 获取企业微信用户绑定信息
            //3.根据绑定信息中企业管理平台userId获取管理平台对应的账户User对象
      //4.执行登录逻辑
            return doLoginSystem(use);
        } catch (Exception e) {
            e.printStackTrace();
        }
    //失败则重定向到登录页面
        return redirect("/login");
    }

最后

以上就是企业微信绑定企业管理平台账号同时支持企业微信扫码登录的主要代码,欢迎有问题的小伙伴一起讨论。

相关实践学习
基于Redis实现在线游戏积分排行榜
本场景将介绍如何基于Redis数据库实现在线游戏中的游戏玩家积分排行榜功能。
云数据库 Redis 版使用教程
云数据库Redis版是兼容Redis协议标准的、提供持久化的内存数据库服务,基于高可靠双机热备架构及可无缝扩展的集群架构,满足高读写性能场景及容量需弹性变配的业务需求。 产品详情:https://www.aliyun.com/product/kvstore &nbsp; &nbsp; ------------------------------------------------------------------------- 阿里云数据库体验:数据库上云实战 开发者云会免费提供一台带自建MySQL的源数据库&nbsp;ECS 实例和一台目标数据库&nbsp;RDS实例。跟着指引,您可以一步步实现将ECS自建数据库迁移到目标数据库RDS。 点击下方链接,领取免费ECS&amp;RDS资源,30分钟完成数据库上云实战!https://developer.aliyun.com/adc/scenario/51eefbd1894e42f6bb9acacadd3f9121?spm=a2c6h.13788135.J_3257954370.9.4ba85f24utseFl
相关文章
|
4月前
|
存储 JavaScript 开发工具
uniapp-实现微信授权登录
uniapp-实现微信授权登录
756 0
|
4月前
|
存储 JSON JavaScript
前后端分离项目知识汇总(微信扫码登录,手机验证码登录,JWT)-1
前后端分离项目知识汇总(微信扫码登录,手机验证码登录,JWT)
67 0
|
4月前
|
小程序
内网环境中ruoyi若依实现微信小程序授权登录解决办法
内网环境中ruoyi若依实现微信小程序授权登录解决办法
181 0
|
5月前
|
小程序 前端开发 JavaScript
微信小程序(二十一)小程序登录获取openid和unionid
在微信小程序中,因为各种各样的原因我们会需要获取到用户的openid或者unionid下面就简单来讲一下在小程序中如何获取openid和unionid。 步骤一:微信登录获取登录凭证
208 0
|
5月前
|
小程序 API 开发者
微信小程序授权登录流程以及应用到的API
微信小程序授权登录流程以及应用到的API
204 0
|
6月前
|
JSON 前端开发 安全
前后端分离项目知识汇总(微信扫码登录,手机验证码登录,JWT)-2
前后端分离项目知识汇总(微信扫码登录,手机验证码登录,JWT)
41 0
|
3月前
|
小程序 JavaScript
微信小程序授权登录?
微信小程序授权登录?
|
4月前
|
JSON 前端开发 安全
前后端分离项目知识汇总(微信扫码登录,手机验证码登录,JWT)-2
前后端分离项目知识汇总(微信扫码登录,手机验证码登录,JWT)
58 0
|
4月前
|
小程序 数据安全/隐私保护
微信小程序实现一个简单的登录功能
微信小程序实现一个简单的登录功能
|
4月前
|
小程序
uniapp 微信小程序登录 新手专用 引入即可
uniapp 微信小程序登录 新手专用 引入即可
32 0

热门文章

最新文章