企业微信自建应用-聊天工具栏获取用户信息

2,910 阅读6分钟

打开企微聊天工具栏(侧边栏),需要提前配置侧边栏应用页面,添加员工,给员工添加到对应的部门,员工再添加外部联系人(客户)。然后可以在和客户的聊天窗口看到联调工具栏的入口按钮,点击打开侧边栏。 1.png 聊天工具栏获取用户信息分两部分:一个是获取当前内部用户的userId,一个是获取外部联系人(客户)的externalUserId。

1.获取当前用户的userId

// router/index.js

import Vue from 'vue'
import Router from 'vue-router'
import { routes } from './routes'
import { getWxConfig, getUserInfo } from '@/apis/apis';
Vue.use(Router);
function Authorize(to) {
    // 先获取企微配置信息
    getWxConfig().then((res) => {
        let { code, data, message } = res || {};
        if (code === 200) {
            let corpid = data.corpid;
            let originUrl = location.href; originUrl;
            let redirectUrl = originUrl.split('?')[0];
            let returnUrl = `https://open.weixin.qq.com/connect/oauth2/authorize?appid=${corpid}&redirect_uri=${encodeURIComponent(redirectUrl)}&response_type=code&scope=snsapi_base&state=STATE#wechat_redirect`
            window.location.href = returnUrl;
        } else {
            console.log(message);
        }
        console.log('error', error)
    })
}
// 通过oAuth2授权获取当前用户userId
function getWxUserInfo(to, from, next, authCode) {
    getUserInfo(authCode).then((res) => {
        let { code, data, message } = res || {};
        if (code === 200) {
            let { userId } = data || {};
            if (userId) {
                localStorage.setItem('userId', userId);
                next();
            } else {
                Authorize(to)
            }
        } else {
            console.log(message);
            // PC端侧边栏tab页面切换后再切回来, 页面地址还是上次重定向后的带code的,此时code已经消费过一次,再调接口获取用户信息会失败, 所以加上重新授权的逻辑
            Authorize(to)
        }
    }).catch(() => {
        Authorize(to)
    })
}
const router = new Router({
    mode: 'history',
    scrollBehavior(to, from, savedPosition) {
        if (savedPosition) { // 如果savedPosition存在,滚动条自动跳到记录的值的地方
            return savedPosition
        return { x: 0, y: 0 } // savedPosition也是一个记录x轴和y轴位置的对象
    },
    routes: routes
})
router.beforeEach((to, from, next) => {
    // 判断是否是微信浏览器打开
    let ua = navigator.userAgent.toLowerCase();
    let isWeixin = ua.indexOf('micromessenger') != -1;
    if (!isWeixin) {
        next()
        return
    }
    // 不需要授权的页面
    if (to.name === 'xxx') {
        next()
        return
    }
    // 企微环境获取当前用户userId和外部客户externalUserId
    let code = to.query.code || '';
    if (code) {
        // 有code说明是授权过的,重定向地址, 调接口获取当前用户信息
        getWxUserInfo(to, from, next, code);
    } else {
        // 获取授权
        Authorize(to);
    }
})
export default router

这里遇到一个坑:在企微刷新当前页面获取userId的接口报400029错误,一开始以为是接口的问题,后面发现第一次接口是调成功的,第二次失败了,因为刷新的时候链接还是第一次授权后带code的链接,这个code已经被消费了,所以需要重新授权获取。
改完又发现另一个问题, 获取userId的接口是调通了, 但是返回了external_userId字段, userId为null, 神马情况, 难道调错接口了。后面各种排查发现,原来我用的这个账号同时被其他人添加为外部客户了,userId为null是因为没有扫码关注企业,啊~ 2.png

2.获取外部联系人的userId(即下externalUserId)

// index.html
<script src="https://res.wx.qq.com/open/js/jweixin-1.2.0.js"></script>
<script src="https://open.work.weixin.qq.com/wwopen/js/jwxwork-1.0.0.js"></script>

在侧边栏配置的多个tab页面都需要获取外部联系人externalUserId, 为了方便复用封装了下面的externalUserId.js, 在需要用到外部联系人externalUserId的页面引入。获取外部联系人externalUserId需要后台提供两个签名接口,一个用来获取企业签名信息,一个用来获取应用签名信息,接口入参url是不带#号的url, 接口调用顺序需要是先企业后应用。获取完企业签名信息后,需要添加js-sdk企业验证配置wx.config,使用到的js接口列表都需要添加到jsApiList。验证配置完成会执行 wx.ready,然后获取应用签名并验证应用配置信息,验证完成调用wx.invoke('getCurExternalContact', {}, function (res) {})接口, 即可获取外部联系人externalUserId。

// mixins/externalUserId.js
// 签名获取外部用户externalUserId逻辑

import { getSign, getAgentSign } from '@/apis/apis';
export default {
    data() {
        return {
            externalUserId: ''
        };
    },
    created() {

    },
    mounted() {
        // 获取企业签名信息
        localStorage.removeItem('externalUserId');
        this.getCompanySign();
    },
    methods: {
        //获取企业签名信息
        getCompanySign() {
            // let url = "获取config或agentConfig配置的参数接口";
            //该paramUrl 为你使用微信sdk-js相关接口的页面地址 该地址需要配置到应用后台的可信域名下
            let url = window.location.href.split("#")[0];
            let params = { url };
            getSign(params).then(res => {
                this.companyConfigInit(res.data);
            }).catch(err => {
                console.log(err);
            });
        },

        //企业验证配置
        companyConfigInit(data) {
            let that = this;
            // noncestr: "ww09b472814e7d260f"
            // signature: "442fde92aa1a440e5e9636364378186e6463306c"
            // timestamp: "1647912587432
            let { timestamp, noncestr, signature } = data || {};
            let wxConfig = localStorage.getItem('wxConfig') ? JSON.parse(localStorage.getItem('wxConfig')) : {};
            let { corpid } = wxConfig;
            // eslint-disable-next-line
            wx.config({
                beta: true, // 必须这么写,否则wx.invoke调用形式的jsapi会有问题
                debug: false, // 开启调试模式,调用的所有api的返回值会在客户端alert出来,若要查看传入的参数,可以在pc端打开,参数信息会通过log打出,仅在pc端时才会打印。
                appId: corpid, // 必填,企业微信的corpID
                timestamp: timestamp, // 必填,生成签名的时间戳
                nonceStr: noncestr, // 必填,生成签名的随机串
                signature: signature, // 必填,签名,见 附录-JS-SDK使用权限签名算法
                jsApiList: ["getContext", "getCurExternalContact", "invoke"] //你要调用的sdk接口必填,需要使用的JS接口列表,凡是要调用的接口都需要传进来
            });
            // eslint-disable-next-line
            wx.ready(function () {
                that.appAgentConfig();
            });
            // eslint-disable-next-line
            wx.error(function (res) {
                console.log('config失败了', res)
            });
        },

        //获取应用签名信息
        appAgentConfig() {
            let url = window.location.href.split("#")[0];
            let params = { url };
            getAgentSign(params).then((res) => {
                let { code, data, message } = res || {};
                if (code === 200) {
                    this.appConfigInit(data);
                } else {
                    console.log(message);
                }
            })
        },

        //应用验证配置
        appConfigInit(data) {
            let that = this;
            let { timestamp, noncestr, signature } = data || {};
            let wxConfig = localStorage.getItem('wxConfig') ? JSON.parse(localStorage.getItem('wxConfig')) : {};
            let { corpid, agentid } = wxConfig;
            // eslint-disable-next-line
            wx.agentConfig({
                corpid,
                agentid,
                timestamp: timestamp,
                nonceStr: noncestr,
                signature: signature,
                jsApiList: ["getContext", "getCurExternalContact", "invoke"],
                success: function () {
                    // eslint-disable-next-line
                    wx.invoke('getCurExternalContact', {
                    }, function (res) {
                        // alert('invoke成功了')
                        // alert(JSON.stringify(res),'invokeData数据')
                        console.log('invoke成功了', res)
                        if (res.err_msg == "getCurExternalContact:ok") {
                            localStorage.setItem('externalUserId', res.userId);
                            // this.$store.dispatch("common/setExternalUserId", res.userId);
                            that.externalUserId = res.userId; //返回当前外部联系人userId
                            // alert(that.externalUserId);
                        } else {
                            //错误处理
                        }
                        //查看相关接口是否可以调用
                        // that.checkJsApi();
                    });
                },
                fail: function (res) {
                    console.log('invoke失败了', res)
                    // alert('invoke失败了', res)
                    if (res.errMsg.indexOf("function not exist") > -1) {
                        alert("版本过低请升级");
                    }
                }
            });
        },
    }
}

这里有个坑:原本我是将mounted里面的内容放在created里面,但是切换客户会出现externalUserId还是上个客户的问题(偶发性)。后来调试发现企业微信侧边栏多个tab页面之间互相切换,pc端会将页面缓存(移动端目前没有发现这个问题),第一次访问A页面会走A页面的生命周期create方法,切换到B页面不会执行A页面的distory生命周期。从B页面切回A页面时,不会执行A页面的生命周期create方法,直接执行生命周期mounted方法,所以就把初始化相关操作放在了mounted里面。

页面中引入mixin,可以通过this.externalUserId调接口获取外部用户的信息。

// xxx.vue
<script>
    import externalUserInfoMixin from "@/mixins/externalUserInfo.js";
    export default {
        mixins: [externalUserInfoMixin]
    }
</script>

3.另:企微调试工具

参考:https://blog.csdn.net/Cris_are/article/details/111031601

4.添加外部联系人

e954ecbabe50911d3585d5eb8101656d.jpg e7fc0d6644b96c0b8dd89d0b336fb152.jpg

按照如图如操作,添加的外部联系人会有@微信绿色标记。

end~ 刚开始做企微,有点懵,写的不好的地方,欢迎评论指出 ~