文档介绍
企业微信扫码授权登录官方文档地址: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,效果如图
连接参数说明:
下面我们主要说一下构造内嵌登录二维码
构造内嵌登录二维码
构造内嵌登录二维码,就是在页面中引入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。 |
页面效果
构造内嵌登录二维码后页面展示效果
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"); }
最后
以上就是企业微信绑定企业管理平台账号同时支持企业微信扫码登录的主要代码,欢迎有问题的小伙伴一起讨论。