企业微信第三方应用接入

说明

与企业内部应用不同,第三方应用开发完毕是给客户安装使用的,我们目前场景是客服系统,客服新增企业渠道方式接入,则客服系统可以通过企业微信接收会话和工单

文档: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不会清空

 

 

posted @ 2022-12-20 10:14  意犹未尽  阅读(1282)  评论(0编辑  收藏  举报