vue自建h5应用,接入企业微信JDK(WECOM-JSSDK),实现跳转添加好友功能

一、项目场景:

1、使用vue开发了一套h5页面的项目
2、这个h5链接是在企业微信里某个地方打开的
3、打开页面的时候有一个好友列表,点击好友列表某一条复制手机号跳转到企业微信添加好友页面

二、实现的效果图

在这里插入图片描述

博客只允许上传gif图,所以我只能手机进行录屏,然后再拿gif录一次video给大家展示(如果他不动了,你就刷新一下页面)

三、实现方案

1、通过 npm 引入(企业微信 WECOM-JSSDK)

//第一种方式  npm引入
npm install @wecom/jssdk   (我用的这种)
//也有第二种方法(别问为啥不用这个,问就是因为我不会)
<script src="https://wwcdn.weixin.qq.com/node/open/js/wecom-jssdk-1.3.1.js"></script>

2、页面中使用

import * as ww from '@wecom/jssdk'

3、页面初始化注册企微的jdk(强度来了,非非非常烧脑,需要细看细看细看)

在看这条之前你需要先明白几点:
1、想要调用企微的东西,通俗说需要先把你自己的项目让企微进行授权,简单思路就是:
appid+url----> 换code ---->拿code---->换access_token
2、(解释第一点)你拿自己的企微id(appid)以及页面地址,去获取企微的code,拿到code后去换取access_token,拿到token后就能进行你自己页面的接口等其他操作了

created() {let appid = "wx7*************";    这是你的企微idthis.url = location.href.split("#")[0];     获取当前页面的地址,注意你的路由模式,如果路由中携带#,那么就需要截取#之前的 (有问题参考文章后参考资料第三个链接内的第六点)this.initCode(appid);   这个方法就是获取企微授权那一套
},
methods: {//初始化页面调用方法,如果没有code,就去企微进行授权(企微授权后会返回到这个页面,并且吧code赋到url后边,截取拿地址栏的参数就ok),如果有了code就走自己页面的正常逻辑async initCode(appid) {let code = this.getUrlParam("code");if (!code) {//这个地方其实就是死套路,你只需要关注给企微的链接传入appid,url就可以const urls = `https://open.weixin.qq.com/connect/oauth2/authorize?appid=${appid}&redirect_uri=${this.url}&response_type=code&scope=snsapi_base&state=highSeas#wechat_redirect`;window.location.href = urls;} else {//这块就是企微回调回code后回到这个页面,然后拿code获取access_token就可以进行后续的接口及企微jdk的初始化了let postData = {code: code,};qrLogin(postData).then((res) => {//把token存起来sessionStorage.setItem("token", res.access_token);this.wxConfig(appid);});}},// 获取url参数  (封装的一个获取ulr地址参数的方法)  getUrlParam(name) {const reg = new RegExp("(^|&)" + name + "=([^&]*)(&|$)");const result = window.location.search.substr(1).match(reg);return result ? decodeURIComponent(result[2]) : null;},最最最最关键点来了 ---- 关键 ------  ---- 关键 ------  ---- 关键 ------  ---- 关键 ------  ---- 关键 ------//初始化注册企微jdkwxConfig(appid) {let dataInfo = {url: this.url,appType: 1,};//调用企微的方法,用url去拿签名等信息  //我们请求的是这个接口  “ticket/getAgentTicket”//https://developer.work.weixin.qq.com/document/24364#%E8%8E%B7%E5%8F%96%E5%BA%94%E7%94%A8%20jsapi_ticket//企微的链接,生成签名算法,需要后端配合你一块查看,如果这个签名生成不正确就会报错,比如后续图一,getAgentTicket(dataInfo).then((res) => {this.dataVal = res.data.data;let timestamp = this.dataVal.timestamp;let nonceStr = this.dataVal.nonceStr;let signature = this.dataVal.signature;ww.register({corpId: appid, // 必填,当前用户企业所属企业IDagentId: "1000XXX",      //找后端宝贝要jsApiList: ["navigateToAddCustomer", "scanQRCode", "openUserProfile"], // 必填,需要使用的JSAPI列表  getConfigSignature, // 必填,根据url生成企业签名的回调函数getAgentConfigSignature,    // 必填,根据url生成应用签名的回调函数onConfigSuccess: (result) => {// alert(result,"success");},onConfigFail: (result) => {alert(JSON.stringify(result), "failed");},});function getConfigSignature(url) {// 根据 url 生成企业签名// 生成方法参考 https://developer.work.weixin.qq.com/document/path/90539return { timestamp, nonceStr, signature };}async function getAgentConfigSignature(url) {// 根据 url 生成应用签名,生成方法同上,但需要使用应用的 jsapi_ticketreturn { timestamp, nonceStr, signature };}});//截止到这块初始化企微jdk就结束了,接下来就可以直接做你想要的操作了,比如跳转到企微的添加好友,比如调用企微的扫一扫等},//接下来就用按钮绑定一个事件,调用你想用的方法就行了setGoto(text) {ww.navigateToAddCustomer({success(result) {// alert(JSON.stringify(result), "1111");// 成功回调,result.errMsg 固定格式为“方法名:ok”},fail(result) {alert(JSON.stringify(result), "32222");// 失败回调,通过 result.errMsg 查看失败详情},complete(result) {// alert(JSON.stringify(result), "333333");// 完成回调,无论调用成功还是失败,都会回调该方法},   });},
}

四、注意点

4.1、无效签名

在这里插入图片描述

这个代码40093问题是很常见的,当时一直在翻企微的社区文章找错误解决办法,结果改了一圈没有一个类似的,然后又重新返回去按照文章步骤去一步一步排查,终于发现了问题点在哪

在这里插入图片描述

解决点1:我用的是npm引入的方法,并且是h5自建应用,所以应该用这种方法去初始化,而我用的是上边“企业身份与权限”,没细看自己的需求直接文章都不翻去用,导致卡了很久
解决点2:后端直接扔个我一个获取签名的接口getAppTicket 说只有这么一个接口绝对没问题,然后又去拿签名验证工具重复的看也没问题,死活非说前端报错,这可一顿好找啊,后来我就一直纠结那个签名算法生成的文章,逼着后端宝贝一块看真的没问题嘛?最终发现了。又给了我一个getAgentTicket接口,说换这个试试,然后一举成功。
getAgentTicket 获取应用的jsapi_ticket
getAppTicket 获取企业的jsapi_ticket

4.2 没有权限

在这里插入图片描述

1、调到这块我信誓旦旦觉得没问题了,所以就去手机端尝试,结果又给我报这个错没有权限。
2、我以为是哪块又配置的不对,初始化的时候在jsApiList也配置了自己想要的api了啊。然后我就去调用的扫一扫的功能ww.scanQRCode({needResult: true,scanType: [‘qrCode’]}) 放到手机里直接使用,可以出来扫一扫界面,那就找到了初始化这块肯定是成功了,那就是这个跳转好友这块有问题,然后又去翻文章。

在这里插入图片描述
在这里插入图片描述

1、后台配置一下添加好友权限即可

至此全部功能已经实现,总结来说按照官方文档步步排查走踩坑少,自己想做什么都不明确,光靠一个报错去搜索解答会浪费很多时间。多看文档,少瞎胡搜报错,少走弯路
还有一个点,不管是初始化jdk还是调用后续的api方法,企微都有Success,跟Fail的回调,可以快速的帮助你找到报错原因。

4.3这个常见报错文档很有用,多看

在这里插入图片描述

参考资料

主要的参考资料链接,其实都是企微的官方文档,主要注意的点就差不多这几个
https://developer.work.weixin.qq.com/document/path/98132 (第一个肯定是企业微信的开发文档了,项目怎么接入企微的jdk)
https://developer.work.weixin.qq.com/document/24364#%E8%8E%B7%E5%8F%96%E5%BA%94%E7%94%A8%20jsapi_ticket (这个还是属于企微的文档,但也是最关键的一步,怎么生成签名——需要后端同事一块查看)
https://developer.work.weixin.qq.com/document/path/90542 (依旧企微的文档,常见错误问题排查,比如最主要的签名错误)

全部代码(如果你功能跟我一样或者类似呢,盲猜替换一下appid跟agentId就可以直接使用)

<template><van-tabs sticky v-model="active" @click-tab="onClickTab"><van-tab name="first" :title="'待添加(' + total + ')'"><van-listv-if="active == 'first'"v-model:loading="loading":finished="finished"finished-text="没有更多了":immediate-check="false"@load="getData":offset="20"class="contentList"><van-cell><template v-for="(unit, key) in list" :key="key"><div class="content"><div>{{ unit.phone }}</div><div>{{ unit.customerName }}</div><div style="display: flex"><van-buttonplainsize="small"hairlinetype="primary"@click="copyFn($event, unit.phone)">复制并添加</van-button></div></div></template></van-cell></van-list></van-tab><van-tab name="second" title="待通过"></van-tab><van-tab name="three" title="已添加"></van-tab></van-tabs>
</template><script>
import {getTypeList,setState,getAgentTicket,wcRedirect,qrLogin,
} from "../api/highSeas";
import { showNotify, closeNotify } from "vant";
import ClipboardJS from "clipboard";
import * as ww from "@wecom/jssdk";
export default {data() {return {active: "first",list: [],loading: false,finished: false,total: 0,query: {pageSize: 20,pageNum: 1,addState: 0, // 0:待添加;1:已添加;3:待通过},};},created() {let appid = "wxXXXXXXXXXXXXXXXX";this.url = location.href.split("#")[0];this.initCode(appid);},methods: {onClickTab(info) {this.active = info.name;if (info.name == "first") {this.query.pageNum = 1;this.list = [];this.loading = false;this.finished = false;getTypeList(this.query).then((res) => {this.total = res.data.total;this.list.push(...res.data.rows);});this.query.pageNum = 2;}},async initCode(appid) {let code = this.getUrlParam("code");if (!code) {const urls = `https://open.weixin.qq.com/connect/oauth2/authorize?appid=${appid}&redirect_uri=${this.url}&response_type=code&scope=snsapi_base&state=highSeas#wechat_redirect`;window.location.href = urls;} else {let postData = {code: code,};qrLogin(postData).then((res) => {this.initQueryVal = true;sessionStorage.setItem("token", res.access_token);this.init();this.wxConfig(appid);});}},// 获取url参数getUrlParam(name) {const reg = new RegExp("(^|&)" + name + "=([^&]*)(&|$)");const result = window.location.search.substr(1).match(reg);return result ? decodeURIComponent(result[2]) : null;},wxConfig(appid) {let dataInfo = {url: this.url,appType: 1,};getAgentTicket(dataInfo).then((res) => {this.dataVal = res.data.data;let timestamp = this.dataVal.timestamp;let nonceStr = this.dataVal.nonceStr;let signature = this.dataVal.signature;ww.register({corpId: appid, // 必填,当前用户企业所属企业IDagentId: "10XXXXXX",jsApiList: ["navigateToAddCustomer", "scanQRCode", "openUserProfile"], // 必填,需要使用的JSAPI列表getConfigSignature, // 必填,根据url生成企业签名的回调函数getAgentConfigSignature,onConfigSuccess: (result) => {// alert(result,"success");},onConfigFail: (result) => {alert(JSON.stringify(result), "failed");},});function getConfigSignature(url) {// 根据 url 生成企业签名// alert(this.dataVal.nonceStr, "this.dataVal.nonceStr");// alert(//   this.dataVal.signature,//   "this.dataVal.signaturesignaturesignaturesignaturesignature"// );// 生成方法参考 https://developer.work.weixin.qq.com/document/path/90539return { timestamp, nonceStr, signature };}async function getAgentConfigSignature(url) {// 根据 url 生成应用签名,生成方法同上,但需要使用应用的 jsapi_ticketreturn { timestamp, nonceStr, signature };}});},init() {getTypeList(this.query).then((res) => {this.total = res.data.total;this.list.push(...res.data.rows);});this.query.pageNum = 2;},getData() {getTypeList(this.query).then((res) => {let dataInfo = res.data.rows;this.loading = false;this.query.pageNum += 1;this.total = res.data.total;this.list.push(...dataInfo);if (this.list.length >= Number(this.total)) {this.finished = true;} else {this.finished = false;}});},setGoto(text) {setState({ phone: text }).then((res) => {ww.navigateToAddCustomer({success(result) {// alert(JSON.stringify(result), "1111");// 成功回调,result.errMsg 固定格式为“方法名:ok”},fail(result) {alert(JSON.stringify(result), "32222");// 失败回调,通过 result.errMsg 查看失败详情},complete(result) {// alert(JSON.stringify(result), "333333");// 完成回调,无论调用成功还是失败,都会回调该方法},});this.list = [];this.query.pageNum = 1;this.finished = false;this.init();});},copyFn(e, text) {const clipboard = new ClipboardJS(e.target, { text: () => text });clipboard.on("success", (e) => {this.setGoto(text);showNotify({ type: "success", message: "复制成功" });// 释放内存clipboard.off("error");clipboard.off("success");clipboard.destroy();});clipboard.on("error", (e) => {// 不支持复制// this.$toast({//   type: "fail",//   message: "该浏览器不支持自动复制",//   icon: "none",// });showNotify({ type: "warning", message: "该浏览器不支持自动复制" });// 释放内存clipboard.off("error");clipboard.off("success");clipboard.destroy();});clipboard.onClick(e);},},
};
</script>
<style scoped lang='scss'>
.content {font-size: 15px;font-weight: 500;display: flex;justify-content: space-between;align-items: center;line-height: 60px;
}
.contentList {// overflow-y: scroll;// height: calc(100vh - 60px); //
}::v-deep .van-button--info {border: none;
}
</style>

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/bicheng/32327.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

浙江工商大学24计算机考研数据,好几个专业都接收调剂,计专复试线284分!

浙江工商大学&#xff08;Zhejiang Gongshang University&#xff09;&#xff0c;简称“浙商大”&#xff08;ZJSU&#xff09;&#xff0c;坐落于浙江省杭州市&#xff0c;是中华人民共和国教育部、中华人民共和国商务部和浙江省人民政府共建的浙江省重点建设高校&#xff0c…

C#调用OpenCvSharp计算并显示带掩膜的图像直方图

之前的文章简要测试了调用OpenCvSharp的Cv2.CalcHist函数计算直方图的用法&#xff0c;不过使用过程中参数mask的值始终为null&#xff0c;也就是计算的整幅图像的直方图&#xff0c;如果mask不为空&#xff0c;则可以计算图像指定区域的直方图&#xff0c;本文学习掩膜的创建方…

css grid实现九宫格布局

常见的九宫格布局可以使用flex布局实现&#xff0c;但是flex布局有个致命的缺陷&#xff0c;比如3行3列的布局&#xff0c;当第不足3个元素的时候&#xff0c;元素依然是平局平铺的&#xff0c;这样就不满足九宫格的效果&#xff0c;这种情况&#xff0c;使用grid布局可以轻松搞…

Zigbee协议详解:低功耗无线通信的理想选择

什么是Zigbee协议 Zigbee是一种基于IEEE 802.15.4标准的无线通信协议&#xff0c;专为低功耗、低数据速率和短距离通信设计。它广泛应用于物联网&#xff08;IoT&#xff09;设备&#xff0c;如智能家居、工业自动化和健康监测等领域。Zigbee协议由Zigbee联盟维护和推广&#x…

Antd Table 表格 拖拽列宽

antd 的表格组件的列宽&#xff0c;是通过width属性去初始化的&#xff0c;有时候渲染的内容不固定&#xff0c;这个宽做不到通用所以研究怎么实现表格列宽拖动&#xff0c;主要的实现步骤如下&#xff1a; 使用table的components API修改表格头部为 react-resizable提供的组件…

C#事件详解及应用示例

简介 事件是使类具备向其它类通知发生的相关事情的能力。事件被分成两部分&#xff1a;一、引发或发送事件的类&#xff08;称发布者&#xff09;&#xff1b;二、处理或接收事件的类&#xff08;称订阅者&#xff09;。事件也是类型的成员。在 .NET 的桌面应用程序中&#xff…

Netty 入门实例

文章目录 1. 概述2. 代码实例2.1 服务端2.2 客户端2.3 运行截图 3. 整体结构4. 重要组件4.1 EventLoopGroup、EventLoop4.2 Handler & Pipeline4.3 ByteBuf 参考文献 1. 概述 Netty 是一款用于高效开发网络应用的 NIO 网络框架&#xff0c;它大大简化了网络应用的开发过程…

MySQL查询语句语法使用

目录 一、基本查询二、条件查询2.1 简单条件表达式2.2 逻辑表达式2.3 模糊查询 (LIKE)2.4 范围查询 (BETWEEN ... AND ...)2.5 列表查询 (IN)2.6 空值查询 (IS NULL 或 IS NOT NULL) 三、排序查询3.1 基本语法3.2 单列排序3.2 多列排序3.3 使用表达式排序 四、分组查询聚合函数…

mysql的安装和连接

一.数据库相关概 念 1.数据库 存储数据的仓库,数据是有组织的进行存储,简称DB。 2.数据库管理系统 操纵和管理数据库的大型软件,简称DBM。 3.SQL 操作关系型数据库的编程语言,定义了一套操作关系型数据库统一标准。简称SQL。 二.市面上流行的数据库 1.ORACLE 2.MySQL …

如何搭建一个成功的短剧制作平台

要搭建一个成功的短剧制作平台&#xff0c;需要考虑多个方面&#xff0c;包括目标定位、技术选择、内容管理、用户体验等。 1、明确目标和定位&#xff1a; 确定你的目标受众是谁&#xff0c;他们的年龄、兴趣、消费习惯等。 明确短剧制作平台的主要定位&#xff0c;是提供原创…

新能源燃气灶用的是什么燃料?无需燃料,电生明火

新能源燃气灶广义的讲就是用电生明火的烹饪灶具&#xff0c;如&#xff1a;电焰灶、电燃灶或电火灶&#xff0c;无需任何燃料和氧气助燃&#xff1b;而狭义上讲是采用出电能以外的一切新燃料烹饪灶具&#xff0c;如&#xff1a;高功率燃气灶、生物合成油灶等。在厨房革命的浪潮…

01--MySQL数据库概述

目录 第1章 MySQL数据库概述 1.1 基本概念 1.2 MySQL数据库管理系统 1.3 表的关系 第2章 MySQL卸载、安装、登录 第3章 客户端使用演示 3.1 命令行客户端 3.1.1 数据库 3.1.2 数据表 3.1.3 导入数据 3.1.4 导出数据 3.2 可视化客户端 第4章 SQL语句 4.1 SQL的分类…

Linux中的文本编辑器vi与vim

摘要&#xff1a; 本文将深入探讨VI和VIM编辑器的基本概念、特点、使用方法以及它们在Linux环境中的重要性。通过对这两款强大的文本编辑器的详细分析&#xff0c;读者将能够更全面地理解它们的功能&#xff0c;并掌握如何有效地使用它们进行日常的文本编辑和处理任务。 引言&…

【Mac】FxFactory 8 Pro for Mac(视觉特效处理包)及同类型软件介绍

软件介绍 FxFactory Pro 是一款功能强大的插件管理和创作工具&#xff0c;专为视频编辑器和特效艺术家设计&#xff0c;适用于 macOS 系统。它集成了大量的视频特效插件&#xff0c;并与多种主流视频编辑软件无缝兼容&#xff0c;如 Final Cut Pro、Premiere Pro、After Effec…

vue项目首页优化问题(前后端都要优化)

2.1 config/index.js 开启productionGzip 将其productionGzip 配置成true 2.2 配置Gzip的 插件配置 打开webpack.prod.config.js 配置一下这段代码 代码如下 if (config.build.productionGzip) { const CompressionWebpackPlugin require(‘compression-webpack-plugin’)…

kafka(五)spring-kafka(2)详解与demo

一、简单的收发消息demo 父工程pom&#xff1a; <?xml version"1.0" encoding"UTF-8"?> <project xmlns"http://maven.apache.org/POM/4.0.0"xmlns:xsi"http://www.w3.org/2001/XMLSchema-instance"xsi:schemaLocation&qu…

谷歌手机刷机教学

注意&#xff1a;手机已经解开了oem锁和bl 1、adb基础命令 连接设备adb devices&#xff1a;列出当前连接的所有设备。 adb connect <设备IP>&#xff1a;通过IP地址连接设备&#xff08;用于无线连接&#xff09;。 设备信息adb shell getprop&#xff1a;获取设备的所…

Docker部署MySQL8.3.0(保姆级图文教程)

系列文章目录 Docker部署Nginx1.21.5&#xff08;保姆级图文教程&#xff09; Docker部署MySQL8.3.0&#xff08;保姆级图文教程&#xff09; 文章目录 一、环境二、拉取镜像2.1 查找 Docker Hub 上的 MySQL 镜像2.2 拉取MySQL镜像2.3 查看MySQL镜像 三、在宿主机创建目录3.1 创…

无痛接入图像生成风格迁移能力:GAN生成对抗网络

AI应用开发相关目录 本专栏包括AI应用开发相关内容分享&#xff0c;包括不限于AI算法部署实施细节、AI应用后端分析服务相关概念及开发技巧、AI应用后端应用服务相关概念及开发技巧、AI应用前端实现路径及开发技巧 适用于具备一定算法及Python使用基础的人群 AI应用开发流程概…

【一】【算法】经典树状数组和并查集,详细解析,初步认识,【模板】树状数组 1,树状数组并查集

【模板】树状数组 1 题目描述 如题&#xff0c;已知一个数列&#xff0c;你需要进行下面两种操作&#xff1a; 将某一个数加上 x x x 求出某区间每一个数的和 输入格式 第一行包含两个正整数 n , m n,m n,m&#xff0c;分别表示该数列数字的个数和操作的总个数。 第二…