概述

记录一个企业微信jssdk的使用,因为要用到图片上传、扫描二维码等工具。项目是uniapp开发的h5项目,fastadmin(thinkphp5)后端

先看官方文档

https://developer.work.weixin.qq.com/document/path/90547#%E5%BA%94%E7%94%A8%E8%BA%AB%E4%BB%BD%E6%B3%A8%E5%86%8Chttps://developer.work.weixin.qq.com/document/path/90547#%E5%BA%94%E7%94%A8%E8%BA%AB%E4%BB%BD%E6%B3%A8%E5%86%8C

一、安装sdk

安装及使用按照官方文档的操作,安装完之后重启一下编辑器! 

二、接口鉴权

接口鉴权有两种方式,一种是企业身份注册,一种是应用身份注册。

这里我选择了应用注册。

涉及到js-sdk签名算法,见下面的官方文档:

https://developer.work.weixin.qq.com/document/path/90506

如果已经实现了可以继续往下。这里展开说说怎么做(前端的童鞋可以先回避,这里依靠后端实现)。

对应的后端代码,但是我这里实测是签名无效的,不知道问题出现在哪里,最后选择 把ticket返回给前端,用官方的签名算法去计算签名。

    /*** 企业微信JS-SDK配置接口*/public function wwregister(){$url = $this->request->post('url');if (!$url) {$this->error('缺少URL参数');}try {// 1. 获取access_token$accessToken = $this->getAccessToken();// 2. 获取企业级jsapi_ticket$jsapiTicket = $this->getJsapiTicket($accessToken);// 3. 获取应用级jsapi_ticket$appJsapiTicket = $this->getAppJsapiTicket($this->app_id, $this->app_secret);// 4. 生成企业签名和应用签名$configSignature = $this->generateConfigSignature($jsapiTicket, $url);$agentConfigSignature = $this->generateAgentConfigSignature($appJsapiTicket, $url);// 5. 构建响应数据$config = ['corpId' => $this->corpid,'agentId' => $this->app_id,'jsApiList' => ['chooseImage', 'scanQRCode'],'configSignature' => $configSignature,'agentConfigSignature' => $agentConfigSignature,'timestamp' => $configSignature['timestamp'],'nonceStr' => $configSignature['nonceStr'],'tk1'=>$jsapiTicket,'tk2'=>$appJsapiTicket];$this->success('获取成功', $config);} catch (Exception $e) {$this->error('获取失败: ' . $e->getMessage());}}/*** 生成企业级签名*/private function generateConfigSignature($jsapiTicket, $url){$timestamp = time();$nonceStr = $this->createNonceStr();// 拼接签名参数$string = "jsapi_ticket={$jsapiTicket}&noncestr={$nonceStr}&timestamp={$timestamp}&url={$url}";// 计算SHA1签名$signature = sha1($string);return ['timestamp' => $timestamp,'nonceStr' => $nonceStr,'signature' => $signature];}/*** 生成应用级签名*/private function generateAgentConfigSignature($appJsapiTicket, $url){$timestamp = time();$nonceStr = $this->createNonceStr();// 拼接签名参数$string = "jsapi_ticket={$appJsapiTicket}&noncestr={$nonceStr}&timestamp={$timestamp}&url={$url}";// 计算SHA1签名$signature = sha1($string);return ['timestamp' => $timestamp,'nonceStr' => $nonceStr,'signature' => $signature];}/*** 获取应用jsapi_ticket*/private function getAppJsapiTicket($agentid,$appsecret){// 从缓存获取或重新请求$jsapiTicket = Cache::get($agentid.'wecom_appjsapi_ticket');if (!$jsapiTicket) {// 这里应该拿应用的accesstoken$accessToken = getAppAccessToken($agentid,$appsecret);// 跟获取企业jsapi_ticket的却别在与请求的url不一样$url = "https://qyapi.weixin.qq.com/cgi-bin/ticket/get?access_token={$accessToken}&type=agent_config";$result = $this->httpGet($url);$result = json_decode($result, true);if (isset($result['ticket'])) {$jsapiTicket = $result['ticket'];Cache::set($agentid.'wecom_appjsapi_ticket', $jsapiTicket, 7100); // 提前100秒过期} else {throw new Exception('获取jsapi_ticket失败: ' . json_encode($result));}}return $jsapiTicket;}// 获取应用的accesstokenpublic function getAppAccessToken($agentid,$appsecret){$token = Cache::get($agentid.'_wecom_access_token');if (!$token) {$config = get_addon_config('wecom');$corpid = $this->corpid;$corpsecret = $appsecret;$url = "https://qyapi.weixin.qq.com/cgi-bin/gettoken?corpid={$corpid}&corpsecret={$corpsecret}";$result = $this->httpGet($url);$result = json_decode($result, true);if (isset($result['access_token'])) {$accessToken = $result['access_token'];Cache::set($agentid.'_wecom_access_token', $accessToken, 7100); // 提前100秒过期} else {throw new Exception('获取access_token失败: ' . json_encode($result));}}return $token;}/*** 获取access_token*/private function getAccessToken(){// 从缓存获取或重新请求$accessToken = Cache::get('wecom_access_token');if (!$accessToken) {$corpid = $this->corpid;$corpsecret = $this->corpsecret;$url = "https://qyapi.weixin.qq.com/cgi-bin/gettoken?corpid={$corpid}&corpsecret={$corpsecret}";$result = $this->httpGet($url);$result = json_decode($result, true);if (isset($result['access_token'])) {$accessToken = $result['access_token'];Cache::set('wecom_access_token', $accessToken, 7100); // 提前100秒过期} else {throw new Exception('获取access_token失败: ' . json_encode($result));}}return $accessToken;}

回到前端,在页面中写方法

三、遇到的问题

1、项目调试使用微信开发者工具;

2、项目本地开发,会报错“invalid url domain”

打包线上之后正常,是否只能一边改一边打包上线测试呢~我也没搞清楚是否有解决办法,不然不大方便啊!!

项目上线后,可以成功拿到jssdk权限 

3、invalid signature

上面已经提到过了,如果拿后端返回的签名是无效的(当然不排除我写的后端方法有问题~)

虽然官方文档给出排错的文档,但是对接的心好累,下回分解了~

四、接口的使用:选择图像

经过大费周章的前期准备,万事俱备,终于可以正常使用工具了,例如图像选择

	// 选择图片const chooseImage = () => {if (images.value.length >= 5) {uni.showToast({title: '最多上传5张图片',icon: 'none'});return;}ww.chooseImage({count: 5 - images.value.length, // 最多可以选择的图片张数sizeType: ['original', 'compressed'], // 可以指定是原图还是压缩图,默认二者都有sourceType: ['album', 'camera'], // 可以指定来源是相册还是相机,默认二者都有success: (res : any) => {// 返回选定照片的本地ID列表,localId可以作为img标签的src属性显示图片const localIds = res.localIds;// 上传图片到微信服务器并获取服务器IDlocalIds.forEach((localId : string) => {uploadImageToWechat(localId);});},fail: (err : any) => {console.error('选择图片失败', err);uni.showToast({title: '选择图片失败',icon: 'none'});}});};

 

看到这个窗口,前期准备功夫全不费工夫,终于可以上传文件了。

但是这仅仅是开始~图片会上传到企微服务器,还得拉下来保存到自己的服务器。又可以另外写一篇文章叙述了。

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

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

相关文章

大零售生态下开源链动2+1模式、AI智能名片与S2B2C商城小程序的协同创新研究

摘要:在流量红利消退、零售形态多元化的背景下,大零售生态成为商业发展的新趋势。本文聚焦开源链动21模式、AI智能名片与S2B2C商城小程序在零售领域的协同应用,探讨其如何打破传统零售边界,实现流量变现与用户资产化。研究表明&am…

Scrapy全流程(一)

创建一个scrapy项目:scrapy startproject mySpider 生成一个爬虫:scrapy genspider douban movie.douban.com 提取数据:完善spider,使用xpath等方法 保存数据:pipeline中保存数据 2 创建scrapy项目 下面以抓取豆瓣top250来学习scrapy的入门使用:豆瓣…

【Elasticsearch】TF-IDF 和 BM25相似性算法

在 Elasticsearch 中,TF-IDF 和 BM25 是两种常用的文本相似性评分算法,但它们的实现和应用场景有所不同。以下是对这两种算法的对比以及在 Elasticsearch 中的使用情况: TF-IDF - 定义与原理:TF-IDF 是一种经典的信息检索算法&am…

【QT】控件二(输入类控件、多元素控件、容器类控件与布局管理器)

文章目录 1.输入类控件1.1 LineEdit1.2 Text Edit1.3 Combo Box1.4 SpinBox1.5 Date Edit & Time Edit1.6 Dial1.7 Slider 2. 多元素控件2.1 List Widget2.2 Table Widget2.3 Tree Widget 3. 容器类控件3.1 Group Box3.2 Tab Widget 4. 布局管理器4.1 垂直布局4.2 水平布局…

【Docker基础】Docker镜像管理:docker pull详解

目录 1 Docker镜像基础概念 1.1 什么是Docker镜像? 1.2 镜像与容器的关系 1.3 镜像仓库(Registry) 2 docker pull命令详解 2.1 基本语法 2.2 参数解释 2.3 拉取镜像的基本流程 2.4 镜像分层结构解析 3 docker pull实战指南 3.1 基本使用示例 3.2 指定镜…

PixPin:一个强大且免费的截图贴图工具

PixPin 是一款国产免费的截图工具,支持屏幕截图、屏幕录制(GIF)、文字识别(OCR)以及贴图等功能。 高效截图 PixPin 支持自由选择或自动检测窗口,自定义截图区域,像素级精确捕捉,延时…

【测试报告】论坛系统

一、项目背景 1.1 测试目标及测试任务 测试目标旨在保障功能无漏洞、流程顺畅,实现多端显示交互一致,达成高并发场景下响应时间<2 秒等性能指标,抵御 SQL 注入等安全攻击,提升 UI 易用性与提示友好度; 背…

30天pytorch从入门到熟练(day1)

一、总体工作思路 本项目采用“从零构建”的策略,系统性地开展了深度学习模型的开发与优化工作。其目标在于通过全流程自研方式,深入理解模型构建、训练优化、推理部署的关键技术环节。整体路径分为以下核心阶段: 模型初步构建:以…

Subway Surfers Blast × 亚矩阵云手机:手游矩阵运营的终极变现方案

引爆全球:Subway Surfers Blast的流量红利​​ 随着Sybo Games最新力作《Subway Surfers Blast》全球上线,这款休闲消除游戏迅速席卷各大应用商店榜单。对于手游推广者而言,如何高效获取这波流量红利?​​亚矩阵云手机专业手游推…

mysql join的原理及过程

连接过程 每获得一条驱动表记录,就立即到被驱动表寻找匹配的记录。 对于两表连接来说,驱动表只会被访问一遍,但被驱动表却要被访问好多遍;具体访问几遍取决于对驱动表执行单表查询后的结果集中有多少条记录。 ​ 对于内连接来说&#xff0…

Hologres的EXPLAIN和EXPLAIN ANALYZE简介

文章目录 一、执行计划1、概念简介2、使用方式①、EXPLAIN②、EXPLAIN ANALYZE 二、算子解读1、SCAN2、Index Scan和 Index Seek3、Filter4、Decode5、Redistribution6、Join7、Broadcast8、Shard prune和Shards selected9、ExecuteExternalSQL10、Aggregate11、Sort12、Limit1…

49-Oracle init.ora-PFILE-SPFILE-启动参数转换实操

一早出现EMCC挂了,之后发现EMCC依赖的instance 挂了,重启startup后发现spfile无法启动。还是和小伙伴把基础问题搞清。spfile是动态文件、动态文件、动态文件,linux下vi看起来部分乱码部分是可编辑的,vi即使可以编辑也需要转换成p…

spring碎片

包的扫描过程 判断当前是否是文件夹获取文件夹里面的所有内容判断文件夹是否为空,为空的话直接返回如果文件夹不为空,则遍历文件夹里面的所有内容 遍历得到每个file对象,继续进行判断,如果还是文件,则进一步进行递归遍历得到的file对象不是文件夹,是文件得到包路径类名称-字符…

如何形成项目经验在多个项目间的高效复用?

要实现项目经验的跨项目高效复用,核心在于建立系统化总结机制、标准化知识表达、平台化共享工具。其中,标准化知识表达尤为关键,它通过统一模板和分类体系,确保不同项目的经验可以被快速理解、轻松匹配到新场景,从而提…

目标检测之YOLOV11谈谈OBB

引言:从轴对齐到定向边界框的范式转变 在计算机视觉领域,目标检测算法长期受限于轴对齐边界框(AABB)的固有缺陷——当面对航拍图像中的舰船、遥感影像中的建筑物或工业质检中的倾斜零件时,传统边界框会包含大量背景噪…

Vue2之生命周期

文章目录 Vue生命周期Vue生命周期钩子生命周期钩子小案例在created中获取数据在mounted中获取焦点 Vue生命周期 思考:什么时候可以发送初始化渲染请求?(越早越好)什么时候可以开始操作dom?(至少dom得渲染出…

Web 架构之多租户(SaaS)系统设计要点

文章目录 一、多租户系统概述定义应用场景 二、设计要点1. 数据隔离独立数据库共享数据库,独立 Schema共享数据库,共享 Schema数据访问控制 2. 资源分配计算资源存储资源 3. 租户管理租户注册与注销租户信息管理 4. 安全与合规身份验证与授权数据加密 三…

【Clickhouse系列】索引

目录 1. 主键索引 (Primary Key Index) - 核心是稀疏索引 2. 跳数索引 (Data Skipping Indexes) - 二级索引 3. 关键总结与最佳实践: ClickHouse的索引设计哲学与其他传统OLTP数据库(如MySQL)有显著不同,它更侧重于高效扫描大数…

445场周赛

第一题:检查元素频次是否为质数 给你一个整数数组 nums。 如果数组中任一元素的 频次 是 质数,返回 true;否则,返回 false。 元素 x 的 频次 是它在数组中出现的次数。 质数是一个大于 1 的自然数,并且只有两个因数…

【SQL语法汇总】

读音:MySQL —— 卖舌口 MySQL 实际上是DBMS软件系统, 并非数据库。通过系统管理维护数据库,DBMS相当于用户和数据库之间的桥梁。 MySQL是一种关系型数据库, 类似excel,用行和列的关系组织数据数据。 操作关系型数据库的DBMS系统大多数用SQL来管理数据。 SQL是编程语言…