概述
记录一个企业微信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}×tamp={$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}×tamp={$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'});}});};
看到这个窗口,前期准备功夫全不费工夫,终于可以上传文件了。
但是这仅仅是开始~图片会上传到企微服务器,还得拉下来保存到自己的服务器。又可以另外写一篇文章叙述了。