企业微信 + 第三方应用(Vue H5):第一阶段 - 授权登录及前端实现
企业微信接入第三方应用
- 企业微信接入第三方应用(以服务商身份)
- 一.确认我们是第三方应用开发还是企业内部开发选项(对后面有很大区别)
- 二.需要的准备:注册两个企业,一个作为应用的服务商,一个作为应用的使用者,使用服务商的企业登陆到服务商的管理平台。此处需要注意的是,企业微信有两个管理平台,一个是企业微信管理后台另一个是服务商管理平台,不要登陆错了。
- 这里开始前端部分了
企业微信接入第三方应用(以服务商身份)
一.确认我们是第三方应用开发还是企业内部开发选项(对后面有很大区别)
首先,要明确两个概念,就是微信和企业微信不是一个东西(虽然有些信息互通)、企业微信应用和服务商的第三方应用也不是一个东西(虽然也有些接口可以调用),企业内部开发指的是开发某个企业自己用的应用,而第三方应用开发指的就是开发者作为服务商开发第三方应用,让其他企业(使用企业微信的人)安装你(服务商)开发的应用。这次主要记录作为服务商第三方应用的开发过程
二.需要的准备:注册两个企业,一个作为应用的服务商,一个作为应用的使用者,使用服务商的企业登陆到服务商的管理平台。此处需要注意的是,企业微信有两个管理平台,一个是企业微信管理后台另一个是服务商管理平台,不要登陆错了。
企业微信管理后台:
https://work.weixin.qq.com/wework_admin
企业微信服务商管理后台:
https://open.work.weixin.qq.com/wwopen/developer
图一:企业微信管理后
图二:企业微信服务商管理后台
- 第一步,在服务商平台创建一个应用,将需要填写的信息填入。基础信息可以根据实际情况填写,开发信息可能刚接触的时候并不清楚如何填写,这里可以暂时先写随便写一个,后面可以修改并且需要认证,下文会将用到的一一进行介绍。
- 第二步,结束,因为我们已经有第三方应用了,哈哈
- 第三步,开发文档,将以上信息了解了之后,还需要看下官方文档。因为笔者是作为java开发的角度来进行开发的,所以主要需要了解的是快速入门和服务端开发API。注意,此处文档区分第三方应用开发和企业内部开发,服务商开发第三方应用一定是第三方应用的那一篇文档,千万不要看错了!
- 文档链接:
https://work.weixin.qq.com/api/doc
-
快速开发,注意此处的三个场景:企业的、应用的和服务商的。在开发过程中一定要分清这三者的区别,这是重中之重,“企业的”是指登录者所属的企业;“应用的”是指开发者的第三方应用;“服务商的”是指应用所属的企业,这和登录的企业不一样,一定要区分清楚!(此处不分清楚,后面会有很多坑)
-
服务端API,这里就是主要获取需要的信息api都有,但此处要区分清楚应用的、企业的、服务商的、个人的信息,它们不可通用(如下面介绍的user_ticket和suite_ticket不是一个东西)
第四步: 指令回调流程的建立,在第二步中说到指令回调Url,需要在这里进行配置,企业微信官方会每10分钟调用一次,或者手动点击“刷新Ticket”,或者在编辑完成确认的时候会进行回调。
-
指令回调的需要先参考这篇文档(其中有好几个需要注意的点)
-
注意点1:解密此处有demo,直接使用官方的即可
-
-
注意点2:验证回调和实际数据传输方式不同:验证是GET请求,解密后需要将明文的echostr返回回去,实际数据传输是POST请求,入参是xml格式传入(但是在链接上也会有解密需要的参数msg_signature、timestamp、nonce因此都要接收),需要返回success
注意点3:此处数据类型可能有很多种,具体可以参考文档的这边,此处只是接收了suite_ticket(应用ticket)类型进行处理
以下是网上写的demo的代码(此处用dom4j解析xml字符串):
需要后端处理
@ResponseBody
@RequestMapping(value = "/directCallback")
public void directCallback(HttpServletRequest request, HttpServletResponse response) throws Exception {
System.out.println("----------------------------");
System.out.println("this is directCallback");
response.setCharacterEncoding("UTF-8");
try {
String corpid = request.getParameter("corpid");
// 企业微信加密签名
String msgSignature = request.getParameter("msg_signature");
// 时间戳 与nonce结合使用,用于防止请求重放攻击
String timestamp = request.getParameter("timestamp");
// 校验时字符串
String echostr = request.getParameter("echostr");
// 随机数 与timestamp结合使用,用于防止请求重放攻击
String nonce = request.getParameter("nonce");
System.out.println("msgSignature: "+ msgSignature);
System.out.println("timestamp: "+ timestamp);
System.out.println("echostr: "+ echostr);
System.out.println("nonce: "+ nonce);
if("GET".equals(request.getMethod())) { // get请求表示是验证
System.out.println("corpid:" + corpid);
String echostrDecrypt = null;
// 校验服务商公司id
WXBizMsgCrypt wxcpt = new WXBizMsgCrypt(sToken, sEncodingAESKey, corpid);
echostrDecrypt = wxcpt.VerifyURL(msgSignature, timestamp, nonce, echostr);
System.out.println("verifyurl echostr: " + echostrDecrypt);
response.setCharacterEncoding("UTF-8");
response.getWriter().write(echostrDecrypt);
}else { // post请求表示是真实数据
// 获取传过来的xml信息(密文)
InputStream ins = request.getInputStream();
BufferedReader bufferedReader = new BufferedReader(new InputStreamReader(ins));
StringBuilder postData = new StringBuilder();
String line = null;
while((line=bufferedReader.readLine()) != null) {
postData.append(line);
}
System.out.println("postData:"+ postData);
WXBizMsgCrypt wxcpt = new WXBizMsgCrypt(sToken, sEncodingAESKey, suiteid);
String info = wxcpt.DecryptMsg(msgSignature, timestamp, nonce, postData.toString());
System.out.println("解析的明文是:" + info); // 此处明文是xml信息
// 解析xml,若InfoType是suite_ticket的话,说明是发送ticket的响应方式
Document doc = DocumentHelper.parseText(info);
Element root = doc.getRootElement();
String infoType = root.elementTextTrim("InfoType");
if("suite_ticket".equals(infoType)) { // 此处只是进行suite_ticket的处理,若是需要其他的处理需要在这里添加类型
String suiteTicket = root.elementTextTrim("SuiteTicket");
System.out.println("拿到的ticket是: " + suiteTicket);
}
response.getWriter().write("success");
}
System.out.println("----------------------------");
} catch (Exception e) {
//验证URL失败,错误原因请查看异常
e.printStackTrace();
}
}
第五步:建立应用授权流程(注意主体是应用),此处不是登陆者登录之后授权才能用那个流程,而是在安装应用时候的授权流程。此时是为了获取应用的access_token(第三方应用凭证)和permanent_code(永久授权码),有了access_token和permanent_code,加上之前的suite_ticket(应用ticket),很多其他的信息就可以获取到了
1.在服务商网站配置ip访问白名单,这一点不可忽略,否则无法访问
2.获取企业的access_token(第三方应用凭证),此处ticket就是企业微信官方每10分钟推送的suite_ticket(应用ticket),还需要应用的id和应用的secret
-
安装应用获取auth_code(临时授权码),此处只是进行安装测试,若需要正式上线需要走上线流程
-
使用另一个企业进行此处的安装测试之后,之前实现的回调接口会接收到临时授权码的信息
-
获取到permanent_code永久授权码有了access_token、permanent_code和suite_ticket之后,很多的信息都可以获取到了
第六步:用户登录时的用户授权流程,在用户登录的时候,需要用户授权应用,获取去到用户信息,将用户与第三方应用中的用户关联起来。此处,企业微信官方采用的是oauth2授权方式,oauth2授权流程可以参考文档此处--------此处请注意下后面的更新,有神坑!!!!!
这里开始前端部分了
- 1.构造oauth2授权链接,此处若是后面需要获取到用户的手机号、邮箱等敏感信息,
必须要使用手动授权方式(即scope=snsapi_privateinfo)
,服务商管理后台中创建的应用,必须支持获取用户的敏感信息,这两个条件只要有一个不满足就无法获取到用户的手机号等敏感信息。
H5登录页
- 2.构建一个空白页面放我们的重定向链接 比如
wechatLogin.vue
点击企微授权登录跳转到这个空白页
-
-
3.跳转成功后,我们当前这个url地址里面会有一个code码
我们需要通过正则或者js方法去拿到这个code,很多方法
展示一部分 -
2.获取第三方应用凭证token,调用那个接口去请求拿token
-
3.获取访问用户身份
-
4.获取用户敏感信息
-
5.登录验证用户
-
6.小插曲:判断是否为企微环境
-
end 把登录的token给存下来就Ok了