企业微信第三方应用接入
说明
与企业内部应用不同,第三方应用开发完毕是给客户安装使用的,我们目前场景是客服系统,客服新增企业渠道方式接入,则客服系统可以通过企业微信接收会话和工单
文档:https://developer.work.weixin.qq.com/document/path/90664
创建应用
后台后 企业后台 服务商后台 开发者后台,相关配置都在服务商后台哦
首先需要注册为第三方服务商 具体步骤看文档
配置回调
自定义丰富的服务行为。比如,用户向应用发消息时,识别消息关键词,回复不同的消息内容;用户点击应用菜单时,转化为指令,执行自动化任务。
可以及时获取到状态变化。比如,通讯录发生变化时,不需要定时去拉取通讯录对比,而是实时地获取到变化的通讯录结点,进行同步。
数据回调
应用的相关消息和事件
指令回调
注:指令回调是POST请求 之前限制了GET导致授权失败
文档:https://developer.work.weixin.qq.com/document/path/90613
在发生授权、通讯录变更、ticket变化等事件时,企业微信服务器会向应用的“指令回调URL”推送相应的事件消息。
验签解密
注意这里容易踩坑
配置回调验证是get请求,是解密密文返回明文,corpId取企业id 在企业微信我的企业里面查看
真实回调推送是post请求,返回succees corpid取取密文的ToUserName
<xml><ToUserName><![CDATA[wwfeadddc1e5f6d884]]></ToUserName><Encrypt><![CDATA[WoH/Lf+VjzvFZHszdZL7eMLnZV+U3afCdpa6Hfx/pRS7Q1ZuVSPAT2cMVFXW6E0ScW45qrvL7PtiPP4Dvbi48JmivHwzIKAeYuoHbethNGRMP3RoVpWHz+eHymfkjw1Gg89k+HRdoe/qlaEW9MIkB1oEjRkt7iUTII7UXEpOLoNbhpqnIdzSiq7w8tLnDF1B7d9YWTTVcar6Zgp796mTpII+hXgYMhm7zJkztCfRs30uVOfDxf3R9MINC/Zf90F0iculCdL0TKJ8Gw42dAt3uWn3ii7X68axB9g3fD0YONKXN9lUdgCZWg/MhcmV8HGvUfZz4vMEYnHiA/IjVEo4hY3g2AZbnwPAOMEg8CmaFfNLHX0r4FFGyVB0DjQcdita0H2YEAqX5MVAqot4Q2kxK7GP0+dJccTg1d2a2dPL5Bk=]]></Encrypt>
回调验签方式官方有提供demo https://developer.work.weixin.qq.com/document/path/90930
@ResponseBody @RequestMapping(value = {"/callback-data", "/callback-directive"}) public String callbackData(HttpServletRequest request, HttpServletResponse response) { // 打印日志 String requestBody = Mvcs.getRequestBody(request); log.info("#64 weixinQiyeGet, weixin_qiye_, requestBody={}", requestBody); String queryString = request.getQueryString(); log.info("#66 weixinQiyeGet, weixin_qiye_, queryString={}", queryString); Enumeration<?> enu = request.getHeaderNames(); ; while (enu.hasMoreElements()) { String headerName = (String) enu.nextElement(); log.info("#70 weixinQiyeGet, weixin_qiye_, 请求头name={},value={}", headerName, request.getHeader(headerName)); } String msg_signature = request.getParameter("msg_signature"); Asserts.noEmpty(msg_signature, "msg_signature 为空"); String timestamp = request.getParameter("timestamp"); Asserts.noEmpty(timestamp, "timestamp 为空"); String nonce = request.getParameter("nonce"); Asserts.noEmpty(nonce, "nonce 为空"); String echostr = request.getParameter("echostr"); Asserts.noEmpty(echostr, "echostr 为空"); //回调配置中的token String token = ""; //回调配置中的encodingAESKey String encodingAESKey = ""; //企业唯一标识,我的企业中查看 String corpId = ""; WXBizMsgCrypt wxcpt = null; String logInfo = " String msg_signature = \"%s\";\n" + " String timestamp = \"%s\";\n" + " String nonce = \"%s\";\n" + " String echostr = \"%s\";"; log.info("#94 Decrypt \n {}", String.format(logInfo, msg_signature, timestamp, nonce, echostr)); try { wxcpt = new WXBizMsgCrypt(token, encodingAESKey, corpId); String decryptedEchoStr = wxcpt.VerifyURL(msg_signature, timestamp, nonce, echostr); return decryptedEchoStr; } catch (AesException e) { log.error("weixinQiyeGet error, msg_signature=" + msg_signature + ", timestamp=" + timestamp + ", nonce=" + nonce + ", echostr=" + echostr, e); } return null; } /** * 临时测试本地调试 * * @param args */ public static void main(String[] args) { //回调配置中的token String token = ""; //回调配置中的encodingAESKey String encodingAESKey = ""; //企业唯一标识,我的企业中查看 String corpId = ""; WXBizMsgCrypt wxcpt = null; //企业微信回调:企业微信加密签名,msg_signature计算结合了企业填写的token、请求中的timestamp、nonce、加密的消息体 String msg_signature = ""; //企业微信回调 时间戳。与nonce结合使用,用于防止请求重放攻击。 String timestamp = ""; //企业微信回调 随机数。与timestamp结合使用,用于防止请求重放攻击 String nonce = ""; //加密的字符串。需要解密得到消息内容明文,解密后有random、msg_len、msg、receiveid四个字段,其中msg即为消息内容明文 String echostr = ""; try { //企业微信SDK DEMO的类 wxcpt = new WXBizMsgCrypt(token, encodingAESKey, corpId); String decryptedEchoStr = wxcpt.VerifyURL(msg_signature, timestamp, nonce, echostr); log.info("decryptedEchoStr={}", decryptedEchoStr); EweiMvcs.write(decryptedEchoStr); } catch (AesException e) { log.error("weixinQiyeGet error, msg_signature=" + msg_signature + ", timestamp=" + timestamp + ", nonce=" + nonce + ", echostr=" + echostr, e); } }
corpid获取
因为解密验证签名需要corpid 针对get推送又没推送 可以通过url配置获取
/callback-data?corpid=$CORPID$
调试
可以使用官方的调试工具:https://developer.work.weixin.qq.com/resource/devtool‘
白名单配置
调用相关api,需要配置白名单否则会抛错not allow to access from your ip
需要超级管用账号,再服务商后台->服务商信息tab页修改 需要admin权限
接口调用许可
文档https://developer.work.weixin.qq.com/document/path/95652
测试企业直接购买 只需支付0元
设置许可自动激活
服务商手动继承:服务商后台-应用管理-接口许可管理-账号继承
API帐号继承:https://developer.work.weixin.qq.com/document/path/95673
自动继承,成员退出应用可见范围的次日凌晨,该成员的接口许可账号会更新为待转移转移状态,新成员进入应用时便可自动继承该待转移账号进行使用
自动激活相关介绍:https://open.work.weixin.qq.com/wwopen/common/readDocument/39545
第三方应用安装
测试阶段将企业加入测试列表
从服务商网站发起方式
文档:https://developer.work.weixin.qq.com/document/path/90597
需要设置安装可信域名和回调域名一致 应用里面设置
https://open.work.weixin.qq.com/3rdapp/install?suite_id=wwfeadddc1e5f6d884&pre_auth_code=qvUmZ67FjJogA-Vw51g-73U1E2xV3kUU6EpS-jgYT6VtnlQ6rJG4Z8lCdeRuOjbD&redirect_uri=https%3A%2F%2Fadmin.itkeeping.com%2Fqy_wexin%2Fcallback-directive&state=STATE
打开这个链接就是一个二维码 安装企业管理员扫码就能走安装授权流程 如果出现无权限登录,首先需要管理员,还有就是当前浏览器是否已经保持了其他账号的登录状态
针对测试应用需要将授权配置改为测试
https://developer.work.weixin.qq.com/document/path/90602
注意每个pro_auth_code都需要调用一次测试授权 否则会报 redirect_uri 与配置的授权完成回调域名不一致
如何让员工看到应用
https://www.weixinsiwei.com/?id=8524
手机端
管理端
如何获取当前应用id
如果是h5应用则在首页url带上应用id,如果是菜单 则在生成菜单上带上应用id
常见为题
安装链接报redirect_uri不一致
https://developer.work.weixin.qq.com/community/question/detail?content_id=16407715261755602214

获取预授权吗 需要调用此设置authType 生产为0(默认) 测试为1
/** * https://developer.work.weixin.qq.com/document/10975#设置授权配置 * 如果redirect_uri 与配置的授权完成回调域名不一致 * * @param suite_access_token */ public static Map<String, Object> setSessionInfo(String suite_access_token, String preAuthCode, String[] appIds, Integer authType) { Request request = new Request(); request.setUrl("https://qyapi.weixin.qq.com/cgi-bin/service/set_session_info?suite_access_token=" + suite_access_token); request.setMethod(Request.POST); Map<String, Object> session_info = Maps.of("appid", appIds, "auth_type", authType); request.setRequestBody(JSON.toJSONString(Maps.of("pre_auth_code", preAuthCode, "session_info", session_info))); Response response = request.execute(); String result = response.getBody(); log.info("#98 setSessionInfo param={},result={}", JSON.toJSONString(session_info), result); Map<String, Object> map = JSON.parseObject(result); return map; }
应用上线提示未正常对接OAuth2登录
应用上线注意项
1.千万要注意,在应用首页就需要302走oauth2,我之前是做的先到一个中间页面 ajax拿oauth链接用户点击授权才跳(后面知道原因了。因为产品过期 续费支付都是企业微信控制,在进入应用判断过期就跳到企业微信的过期处理页面了)
2.安装即用,如果是saas安装后根据授权回调获取企业信息 动态创建服务商和用户信息并与安装人员open_id自动关联
3.桌面端和手机端需要适配 因为有个人工安装体验环节
4.上线需要开通商户号,商户号审核时间很长,提前处理 因为三方应用涉及到购买 必须配一个付费版
我遇到过的问题
1.机器审核应用首页没有对接oauth2 需要用户输入服务商地址才走,未审核通过
2.人工审核,需要应用可用,手机端和桌面端
3.需要开通商户号 审核 要等很久
关于多企业切换企业上一个企业的localstorage缓存还存在问题
关键:
ios切换企业后,cookie和localstorage会自动清空的
安卓,cookie自动清空的,但localstorage不会清空
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· 全程不用写代码,我用AI程序员写了一个飞机大战
· MongoDB 8.0这个新功能碉堡了,比商业数据库还牛
· 记一次.NET内存居高不下排查解决与启示
· DeepSeek 开源周回顾「GitHub 热点速览」
· 白话解读 Dapr 1.15:你的「微服务管家」又秀新绝活了
2018-12-20 Spring Cloud-Zuul(十)
2018-12-20 Spring Cloud-hystrix Feign(九)