uniapp项目上企业微信应用经历

前言

本文同样发于稀土掘金文章。我不知道同文章发2个平台是否允许,如果不允许的话可以私信或者留言告诉我否?谢谢

一、背景

uniapp项目,之前针对的app开发,真机调试安装都以app端为目标,做了很久,完成度较高,突然提需求要整上企业微信…我目前还是实习生,做之前完全没接触过这方面知识,踩了很多坑之后现在来记录下自己的经历,也想帮助后来者(做的时候查资料、debug太痛苦了)。

可能本文介绍的不是最优方案,作者目前还是实习生所以经验上可能有所欠缺,有更好的方案或哪里写的不好请指教:D。

二、项目结构

项目中nvue,vue页面混合使用,本篇文章所用到的项目结构展示

.
├── common  #公共基础文件
│   └── wxJSSDK.js  #企业微信sdk
├── pages  #页面
│   └── a.vue
├── App.vue
├── main.js
├── template.h5.html  #入口
.

前端要做的事

一、和后端交流建立测试应用

建议都先看看 企业微信开发文档

沟通后,先建一个企业(群),然后建一个应用,在工作台进入。因为企业微信调用特殊api需要可信且备案域名,需要前端搞一个域名或者内网穿透,我这里是用了nginx搭配内网穿透,买的花生壳的服务,nginx配置就简单带过吧,主要是转发访问到本地打包出来的文件,然后设置禁用缓存策略(不然很长一段时间打开都调的缓存);以及在某处塞一个带验证码的txt文件,后端访问一次后可以在企业微信加入可信域名白名单。

image.png

二、配置sdk

区分一下,项目里用的api分 通用api特殊api,通用api引入即可使用,默认通过wx.fn()调用,特殊api需要验证权限后才能允许调用,引入后通过 wx对象或者 jWeixin对象引用,这里看到有两个wx对象,冲突了,后面会说我的解决方案。

最难的一步

长话短说,在查阅大量博客和文档,甚至官方问答社区后,我目前得出的结论(2023-02-12)是:

  • 1.复制这个链接 http://open.work.weixin.qq.com/api/jsapidemo 到企业微信发送打开,随便一个群里都行,上面有的api,我称之为特殊api,需要注册后使用,具体注册流程看官方文档,简单来说就是每个页面用它的api都得先验证权限,等回调后再使用
  • 2.通过npm下载的jweixin-module缺失手势返回接口。似乎手动cv代码到本地也不起作用(同事报告),只能在线引入,参考官方文档 步骤一 目前是jWeixin1.2.0。
  • 3.安卓和ios,原本要用不同的对象调用注册后才能用的特殊api
  • 4.通用api,引入文件后使用wx对象调用

针对此,我做的事有:

  1. 在入口文件(template.h5.html 或者有些是 index.html)里加入以下代码,引入wx对象,目前我最常用到的通用api是在企业微信中更换标题。
<script>
    // 判断环境
    console.log('navigator.userAgent: ', navigator.userAgent);
    var ua = navigator.userAgent.toLowerCase();
    if(ua.match(/micromessenger/i) == 'micromessenger') {
        console.log('>>>微信环境<<<');
        var script = document.createElement('script');
	script.type = 'text/javascript';
	script.src = 'https://res.wx.qq.com/open/js/jweixin-1.2.0.js';
	document.head.appendChild(script);
    }
</script>
  1. 在common下新建js文件,我命名为wxJSSDK
  2. 在main.js中引入wxJSSDK.js,并挂载到全局对象()
// main.js
import Vue from 'vue'
import App from './App'
/* ... */
// ios调试工具,后面介绍
import VConsole from 'vconsole'
import jwx from '@/common/wxJSSDK'
var ua = navigator.userAgent.toLowerCase();
if(ua.match(/micromessenger/i) == 'micromessenger') {
    Vue.prototype.$jwx = jwx
    new VConsole()
}

为什么挂到全局对象,因为特殊api每次用都要先验证,为了不在每个页面文件都写同一遍代码,做成全局对象会很方便,要用的时候就 this.$jwx.fn() 即可。

  1. wxJSSDK.js代码

仅供参考。这部分就要处理上面说的几个痛点,封装后在页面就以this.$jwx.fn()使用了。

import store from 'xxx'

console.log('load SCRIPT');
const nuA = navigator.userAgent.toLowerCase();

// 本页面也要引入sdk
let script = document.createElement('script');
    script.type = 'text/javascript';
    script.src = 'https://res.wx.qq.com/open/js/jweixin-1.2.0.js';
    document.body.appendChild(script);

let commonWx = null;

if(!nuA.includes('micromessenger')) {
	console.log('非微信环境');
} else {
	// 安卓wx jWeixin都存在,ios下jWeixin不存在...所以会影响到后面
        // 需要处理成同一个对象
        // 可以先指定commonWx为jWeixin
	setTimeout(()=>{
		try{
                    commonWx = jWeixin;
		}catch(e) {}
		if(nuA.includes('iphone')) {
                    commonWx = wx;
		}
	}, 500);
}

export default {
    initJssdk: function(callback) {
        //获取当前url然后传递给后台获取授权和签名信息
	var cUrl = window.location.href.split('#')[0];
        uni.request({
            // 按企业微信官方文档要求,要传当前网页的URL, 不包含#及其后面部分 给后端处理
            url: '后端获取签名的接口地址',
            data:{
                url: cUrl // 例如 http://www.xxx.com/test/interface
            },
            method: 'xxx', // GET或者POST最常用
            header: {
                // 你的请求必带的头字段,一般是token什么的,登录时一般存store
                'xxx': store.xxx
            },
            success: (res) => {
                //注入config权限配置
                commonWx.config({
                    beta: true,
                    debug: false,
                    appId: res.xxx.appId,
                    timestamp: parseInt(res.xxx.timestamp),
                    nonceStr: res.xxx.nonceStr,
                    signature: res.xxx.signature,
                    // 这里是需要用到的特殊api名称
                    jsApiList: [
                        'onHistoryBack'// 控制返回
                    ]
                });
                if (callback) {
                    callback();
                }
            }
        })
    },
    
    // 封装微信JSSDK方法
    // return true放行,反之不执行
    onHistoryBack(fn) {
        this.initJssdk();
        commonWx.ready(() => {
            commonWx.onHistoryBack(() => {
                fn();
		return false;
            })
	});
	commonWx.error(res => {
            console.log("config fail:", res);
	});
    },
}

三、开发者工具

网址均复制到企业微信自建企业内粘贴发送打开。

官方特殊api demo http://open.work.weixin.qq.com/api/jsapidemo

(安卓下有效,点击→信息→TBS settings→打开vConsole调试功能) http://debugx5.qq.com

一是企业微信官方做的demo,可以看某api在移动端表现效果。

二是安卓端下点击可以勾选是否显示开发者工具(前端应该都知道这东西的重要性),当然苹果端就要借助库了,看上面main.js写法,通过npm安装(安卓同样有效)。

npm install vconsole

image.png

主要需求和开发建议

一、主要需求

1.手势返回

如不指定,默认下是返回前一个页面,即调用uni.navigateBack,当然最终也是调的wx.navigateBack,通用api不需要注册

那什么时候需要指定呢,我遇到的一个场景是 新增页,点击打开弹框组件选择人员,此时手势返回应该是关闭弹框而非关闭页面

还记得前文配的wxJSSDK.js么,因为在main.js中挂载到了全局对象jwx,现在可以直接用了。

例如在 add.vue ,在mounted处第一行添加以下代码以及其他代码:

mounted() {
    if(xxx) {
        this.$jwx.onHistoryBack(this.fn);
	wx.setNavigationBarTitle({title: '当前页面标题'});
    }
    ...
}
...
methods: {
    fn() {
        if(弹框打开) {
            this.弹框show = false;
        } else {
            uni.navi...
        }
    }
}

额外注意,如果是tabbar页面,企业微信是直接退出的!不会监听不会阻拦直接退出…

2.标题栏

通用api,原生wx对象就有(在template处引入),console.log(wx)即可看,所以直接使用,我的话会用在mounted第一行,同手势返回,代码如上图。

475BF1C923D4B7F97546586453678A0C.jpg

3.登录与账号绑定问题

需求:员工打开应用附带信息进行绑定应用账号操作,之后打开应用即自动登录

image.png

涉及OAuth2认证,首先,在应用管理页面处理回调时,回调路径选择前端入口,比如https://open.weixin.qq.com/…&redirect_uri={前端入口如http://www.test.com/nothing/login}…

正常情况下最终会回调进入前端页面,路径附带着参数,我的情况是传递了code,state,例如/nothing/login?code=xx&state=xx,获取参数后转发给后端,后端接企业微信api,回调后就可以返回获取用户当前企业id或者用户id,包括本地数据等等,之后继续走逻辑。

二、开发建议

  • 跨端问题

uniapp很强,但是还不够,开发途中确实发现一些安卓和ios的区别,例如苹果手机一些版本屏幕下有黑条感应区,对应的要添加viewport-fit=cover等。

  • 多人开发

如果是多人开发,但应用只能配一个回调路径,那其他人想使用api怎么办呢?我这边是每个人搞一个域名+内网穿透,虽然应用只能配一个回调路径,但是可以添加可信域名到白名单,允许可信域通过企业微信检查从而调用api → 直接把链接发在聊天点击进入即可(仅限于调用api比如手势返回,打开扫码这些)。

  • 2
    点赞
  • 17
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值