说明
与企业内部应用不同,第三方应用开发完毕是给客户安装使用的,我们目前场景是客服系统,客服新增企业渠道方式接入,则客服系统可以通过企业微信接收会话和工单
创建应用
后台后 企业后台 服务商后台 开发者后台,相关配置都在服务商后台哦
首先需要注册为第三方服务商 具体步骤看文档
配置回调
自定义丰富的服务行为。比如,用户向应用发消息时,识别消息关键词,回复不同的消息内容;用户点击应用菜单时,转化为指令,执行自动化任务。
可以及时获取到状态变化。比如,通讯录发生变化时,不需要定时去拉取通讯录对比,而是实时地获取到变化的通讯录结点,进行同步。
数据回调
应用的相关消息和事件
指令回调
注:指令回调是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
需要设置安装可信域名和回调域名一致 应用里面设置
打开这个链接就是一个二维码 安装企业管理员扫码就能走安装授权流程 如果出现无权限登录,首先需要管理员,还有就是当前浏览器是否已经保持了其他账号的登录状态
针对测试应用需要将授权配置改为测试
注意每个pro_auth_code都需要调用一次测试授权 否则会报 redirect_uri 与配置的授权完成回调域名不一致
如何让员工看到应用
手机端
管理端
如何获取当前应用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不会清空