企业微信开发——企业内部自建应用开发(第二篇)---JS_SDK配置

news2025/1/13 13:53:19

企业微信如果想要使用企业微信的JS_SDK来实现拍照、定位等等功能,就需要预先在使用到的页面进行配置,当然你可以做全局配置。对于JS_SDK的配置设计前端和后端的统一配置。下面我来说明下具体的步骤。

特别说明:1、企业微信有的接口需要配置wx.config,有的接口需要配置wx.agentConfig,下面我将分别举例说明。

2、只要按照我的步骤进行配置,有一定代码基础的同学,就能完成。

一、wx.config配置

此配置配置完成后,一些基础功能就可以调用了,如:拍照、定位等等,还有其它的功能,需要参考企业微信开发文档。那么如何配置,直接通过代码来讲解:前端使用的时vue脚手架,后端使用的

.net web api。

首先在vue脚手架项目的index.html全局引用引入js文件:

<script src="" target="_blank">//res.wx.qq.com/open/js/jweixin-1.2.0.js"></script>

js 代码:

//首先,在created中初始化配
created() {
    this.initQyWxConfig();
}
methods: {
initQyWxConfig() {
      let that = this;
      var postData = {
        url: window.location.href,
      };
      xapi.ajax({
        url: "/api/***/****/AccessQyWxConfigBaseMessage",
        type: "POST",
        contentType: "application/json",
        data: postData,
        success: function (data, status, xhr) {
          that.configQyWx(data.Data, function () {});
        },
        error: function (XMLHttpRequest, textStatus, errorThrown) {
          alert(
            "错误:" +
              textStatus +
              ":" +
              errorThrown +
              ":" +
              XMLHttpRequest.status
          );
        },
        complete: function (xhr, status) {
          $.hideLoading();
        },
      });
    },
    configQyWx(data, callback) {
      wx.config({
        beta: false,
        debug: false,
        appId: data.appId, // 必填,企业微信的corpid,必须与当前登录的企业一致
        timestamp: data.timestamp, // 必填,生成签名的时间戳
        nonceStr: data.nonceStr, // 必填,生成签名的随机串
        signature: data.signature, // 必填,签名,见附录-JS-SDK使用权限签名算法
        jsApiList: ["chooseImage", "uploadImage"], //必填,传入需要使用的接口名称
        success: function (res) {
          callback();
        },
        fail: function (res) {
          if (res.errMsg.indexOf("function not exist") > -1) {
            alert("版本过低请升级");
          }
        },
      });
    },
    //上述配置调用成功后,就可以写一个点击事件uploadImage(),在其中就可以调用wx.chooseImage,"chooseImage"需要在上面的wx.config中进行配置。
    uploadImage() {
      var that = this;
      wx.chooseImage({
        count: 1, // 默认9
        sizeType: ["original", "compressed"], // 可以指定是原图还是压缩图,默认二者都有
        sourceType: ["album"], // 可以指定来源是相册还是相机,默认二者都有
        defaultCameraMode: "batch", //表示进入拍照界面的默认模式,目前有normal与batch两种选择,normal表示普通单拍模式,batch表示连拍模式,不传该参数则为normal模式。从3.0.26版本开始支持front和batch_front两种值,其中front表示默认为前置摄像头单拍模式,batch_front表示默认为前置摄像头连拍模式。(注:用户进入拍照界面仍然可自由切换两种模式)
        isSaveToAlbum: 1, //整型值,0表示拍照时不保存到系统相册,1表示自动保存,默认值是1
        success: function (res) {
          var localIds = res.localIds; // 返回选定照片的本地ID列表,
          console.log("localIds:" + localIds);
          wx.uploadImage({
            localId: localIds.toString(), // 需要上传的图片的本地ID,由chooseImage接口获得
            isShowProgressTips: 1, // 默认为1,显示进度提示
            success: function (res) {
              var serverId = res.serverId; // 返回图片的服务器端ID
               xapi.ajax({ //自己写个ajax方法,此处时框架封装的xapi方法。
                url: "/api/***/Common/AccessMediaImage",
                type: "POST",
                contentType: "application/json",
                data: { mediaId: serverId },
                success: function (data, status, xhr) {
                  if (data.Result) {
 
                  }
                },
                error: function (XMLHttpRequest, textStatus, errorThrown) {
                  alert(
                    "错误:" +
                      textStatus +
                      ":" +
                      errorThrown +
                      ":" +
                      XMLHttpRequest.status
                  );
                },
                complete: function (xhr, status) {
                  $.hideLoading();
                },
              });
            },
          });
          // }
        },
      });
    },
}

c#后端代码:下面的代码有的不在同一个.cs文件中,大家有c#开发经验的应该能看懂怎么调用,自己封装到项目中就行。

 [HttpPost]      
 public CommonResult AccessQyWxConfigBaseMessage([FromBody] dynamic req)
  {
///此处的url可以从前台传过来,主要就是把当前的页面进行配置,然后前端对应的页面就可以使用jsSDK
            var url = "https://www.xxx.com/TestApi/dist/index.html#/indexPage";// ((string)req.url).HasValue("页面url").Trim();
            var data = bll.AccessQyWxConfigDto(QyMpId, url);
            return new CommonResult
            {
                Result = true,
                Data = data
            };
   }

 /// 然后调用业务逻辑处理代码
        public QywxConfigDto AccessQyWxConfigDto(string mpId, string url)
        {
            var targetIndex = url.IndexOf("#");
            if (targetIndex != -1)
            {
                url = url.Split('#')[0];
            }
            string qyWxTicket = GetQyWxJsapi_Ticket(mpId);
            string nonceStr = CreatenNonce_str();
            long timestamp = CreatenTimestamp();
            GetSignature(qyWxTicket, nonceStr, timestamp, url, out string signature);
            QywxConfigDto anentConfigDto = new QywxConfigDto()
            {
                appId = "ww67c7*****806a", //企业微信的appID
                timestamp = timestamp,
                nonceStr = nonceStr,
                signature = signature
            };
            return anentConfigDto;
        }

///此处是获取token的,主要是调用次数受限,记得存缓存, MPTools.GetMPCachedAccessToken是个缓存类,可以自己写一个。
public static void GetQyWxToken(string corpid, string corpsecret, string mpId, out string token)
        {
            try
            {
                MPTools.GetMPCachedAccessToken(mpId, out token, out DateTime expTime);
                if (string.IsNullOrEmpty(token))
                {
                    lock (tokenLock)
                    {
                        string url = string.Format("https://qyapi.weixin.qq.com/cgi-bin/gettoken?corpid={0}&corpsecret={1}", corpid, corpsecret);
                        HttpHelper helper = new HttpHelper();
                        string back = helper.SendGetMessage(url, mpId);
                        var tokenDto = JsonConvert.DeserializeObject<TokenDto>(back);
                        token = tokenDto.access_token;
                        GlobalTools.WriteLog("GetQyWxToken", 0, $"token:{token}");
                        MPTools.SaveMPCachedAccessToken(mpId, token, DateTime.Now, DateTime.Now.AddMinutes(90));
                    }

                }
            }
            catch (Exception ex)
            {
                GlobalTools.WriteErrLog("GetQyWxToken", ex);
                token = "";
            }
        }
///根据mpID和MP_APP_SECRET获得token,这边我把相关数据做成了配置,根据mpId来获取,大家可以直接写死,后面再改成配置。应该比较简单!
 public string GetAccessToken(string mpId)
        {
            string contackMpId = mpId;
            var mp = _mp.Get(p => p.MP_ID == contackMpId);
            if (mp == null)
            {
                throw new ValidateException("未找到MpId信息");
            }
            CommonBll.GetQyWxToken(mp.MP_APP_ID, mp.MP_APP_SECRET, contackMpId, out string accessToken);
            return accessToken;
        }

 public string GetQyWxJsapi_Ticket(string mpId)
        {
            string accessToken = GetAccessToken(mpId);
            string reqUrl = string.Format("https://qyapi.weixin.qq.com/cgi-bin/get_jsapi_ticket?access_token={0}", accessToken);
            CommonBll.GetQyJsApiTicket(mpId, accessToken, "qyTicket", reqUrl, out string ticketValue);
            return ticketValue;

        }

public static void GetQyJsApiTicket(string mpId, string accessToken, string key, string reqUrl, out string ticketValue)
        {
            try
            {
                MPTools.GetMPCachedAccessToken(key, out ticketValue, out DateTime expTime);
                if (string.IsNullOrEmpty(ticketValue))
                {
                    lock (ticketLock)
                    {
                        string ticketUrl = reqUrl;
                        HttpHelper helper = new HttpHelper();
                        string back = helper.SendGetMessage(ticketUrl, mpId);
                        GlobalTools.WriteLog("GetQyWxToken", 0, $"back:{back}");
                        TicketDto ticketDto = JsonConvert.DeserializeObject<TicketDto>(back);
                        MPTools.SaveMPCachedAccessToken(key, ticketDto.ticket, DateTime.Now, DateTime.Now.AddMinutes(90));
                    }
                }
            }
            catch (Exception ex)
            {
                ticketValue = "";
                MPTools.RemoveMPCachedAccessToken(key);
            }
        }

public static string[] strs = new string[]
                               {
                                  "a","b","c","d","e","f","g","h","i","j","k","l","m","n","o","p","q","r","s","t","u","v","w","x","y","z",
                                  "A","B","C","D","E","F","G","H","I","J","K","L","M","N","O","P","Q","R","S","T","U","V","W","X","Y","Z"
                               };

        public string CreatenNonce_str()
        {
            Random r = new Random();
            var sb = new StringBuilder();
            var length = strs.Length;
            for (int i = 0; i < 15; i++)
            {
                sb.Append(strs[r.Next(length - 1)]);
            }
            return sb.ToString();
        }
        private long CreatenTimestamp()
        {
            return (DateTime.Now.ToUniversalTime().Ticks - 621355968000000000) / 10000000;
        }

        public static string Sha1Encrypt(string source, Encoding encoding = null)
        {
            if (encoding == null) encoding = Encoding.UTF8;

            // 第一种方式
            byte[] byteArray = encoding.GetBytes(source);
            using (HashAlgorithm hashAlgorithm = new SHA1CryptoServiceProvider())
            {
                byteArray = hashAlgorithm.ComputeHash(byteArray);
                StringBuilder stringBuilder = new StringBuilder(256);
                foreach (byte item in byteArray)
                {
                    stringBuilder.AppendFormat("{0:x2}", item);
                }
                hashAlgorithm.Clear();
                return stringBuilder.ToString();
            }
        }


        public void GetSignature(string jsapi_ticket, string noncestr, long timestamp, string url, out string signature)
        {
            var string1Builder = new StringBuilder();
            string1Builder.Append("jsapi_ticket=").Append(jsapi_ticket).Append("&")
                          .Append("noncestr=").Append(noncestr).Append("&")
                          .Append("timestamp=").Append(timestamp).Append("&")
                          .Append("url=").Append(url.IndexOf("#") >= 0 ? url.Substring(0, url.IndexOf("#")) : url);
            string string1 = string1Builder.ToString();
            signature = Sha1Encrypt(string1, Encoding.UTF8);
            GlobalTools.WriteLog("GetSignature", 0, $"signature:{signature}");
        }

现在,你的wx.config配置就完成了。

注意点:1、这些功能很多时候只能在手机真机中进行调试

2、需要耐心对着上述步骤配置,因为本身配置就比较复杂,源码写在了项目中,有时间给大家单独整理个demo。如果有不懂的地方,可以加我微信:1057359832

写在最后,下一篇我将介绍下wx.agentConfig的配置,与wx.config类似,但是也有区别。

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

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

相关文章

shader基础入门(1)

本文基于unity免费公开课“Hi Shader以及网络公开资料等书写”遵循开源协议。 MeshFilter网格过滤器 从海量资源中挑选适合的Mesh将他交给MeshRender MeshRenderer 网格渲染器 负责把MeshFilter丢过来的Mesh&#xff0c;绘制显示到我们的场景中 Material 材质球 Material…

多线程之死锁

目录&#xff1a; 1.什么是死锁&#xff1f; 2.可重入与不可重入 3.发生死锁的三个典型情况 4.发生死锁的四个必要条件 5.如何破除死锁&#xff1f; 1.什么是死锁&#xff1f; 谈到死锁&#xff0c;程序猿们都心存忌惮&#xff0c;因为程序一旦出现死锁&#xff0c;就会导…

深度学习训练营之鸟类识别

深度学习训练营之鸟类识别原文链接环境介绍前置工作设置GPU导入数据并进行查找数据处理可视化数据配置数据集残差网络的介绍构建残差网络模型训练开始编译结果可视化训练样本和测试样本预测原文链接 &#x1f368; 本文为&#x1f517;365天深度学习训练营 中的学习记录博客&am…

机器学习:如何解决类别不平衡问题

类别不平衡是一个常见问题&#xff0c;其中数据集中示例的分布是倾斜的或有偏差的。 1. 简介 类别不平衡是机器学习中的一个常见问题&#xff0c;尤其是在二元分类领域。当训练数据集的类分布不均时会发生这种情况&#xff0c;从而导致训练模型存在潜在偏差。不平衡分类问题的示…

【Unity云消散】理论基础:实现SDF的8SSEDT算法

距离元旦假期已经过去5天了&#xff08;从31号算起&#xff01;&#xff09;&#xff0c;接着开始学习&#xff01; 游戏中的很多渲染效果都离不开SDF&#xff0c;那么SDF究竟是什么呢&#xff1f;到底是个怎么样的技术&#xff1f;为什么能解决那么多问题&#xff1f; 1 SD…

git介绍及环境搭建

git介绍及环境搭建Git介绍Git安装流程配置用户信息git工作流程与常用命令问题点总结主要工作流程git工作流程与原理总结Git介绍 1.Git是什么&#xff1f; Git版本控制系统是一个分布式的系统,是用来保存工程源代码历史状态(游戏存档)的命令行工具 GIT是一个命令行工具,用于版…

基于Java+Spring+vue+element社区疫情服务平台设计和实现

基于JavaSpringvueelement社区疫情服务平台设计和实现 博主介绍&#xff1a;5年java开发经验&#xff0c;专注Java开发、定制、远程、文档编写指导等,csdn特邀作者、专注于Java技术领域 作者主页 超级帅帅吴 Java毕设项目精品实战案例《500套》 欢迎点赞 收藏 ⭐留言 文末获取源…

Django+channels -> websocket

Django+channels -> websocket 学习视频: https://www.bilibili.com/video/BV1J44y1p7NX/?p=10 workon # 查看虚拟环境 mkvirtualenv web -p python3.10 # 创建虚拟环境 workon web # 进入虚拟环境pip insatll django channelsdjango-admin startproject ws_demo python …

【NI Multisim 14.0原理图环境设置——元器件库管理】

目录 序言 一、元器件库管理 &#x1f349;1.“元器件”工具栏 &#x1f34a;&#xff08;1&#xff09;电源/信号源库 &#x1f34a;&#xff08;2&#xff09;基本器件库 &#x1f34a;&#xff08;3&#xff09;二极管库 &#x1f34a;&#xff08;4&#xff09;晶体管…

seL4 背景知识

1 seL4 演变 1.1 微内核 微内核发展到目前为止经历了三代, 这里做一些归纳。参考《现代操作系统: 原理与实现》中操作系统结构一章, 关于微内核架构发展的介绍。 第一代微内核设计将许多内核态功能放到用户态, Mach 微内核是第一代微内核的代表。第二代微内核设计将对 IPC 优…

C++学习记录——일 C++入门(1)

C入门&#xff08;1&#xff09; 文章目录C入门&#xff08;1&#xff09;一、C关键字二、C第一个程序三、命名空间1、域作用限定符2、了解命名空间3、命名空间的使用四、C输入输出五、缺省参数六、函数重载七、引用1、引用符号2、引用的部分使用场景一、C关键字 关键字有98个&…

filebeat采集nginx日志

背景我们公司项目组用的是elastic的一整套技术栈&#xff0c;es&#xff0c;kibana&#xff0c;filebeat和apm&#xff0c;目前已经可以采集网关各个微服务的日志。架构图现在需要在原来的基础上把nginx这的日志也采集上来&#xff0c;方便做链路跟踪问题与思路原先traceId是在…

数字经济时代,“8K+”开拓行业新格局

2023深圳国际8K超高清视频产业发展大会召开&#xff0c;大会以“超清互联 数智创新”为主题&#xff0c;汇聚两院院士、产业领袖、领军企业共同深入探讨超高清产业发展现状、关键问题和未来趋势&#xff0c;并集中发布《深圳市超高清视频显示产业白皮书&#xff08;2023版&…

「数据密集型系统搭建」开卷篇|什么是数据密集型系统

在我们开发的诸多系统&#xff0c;基本都可以视为“数据密集型系统”&#xff0c;数据是一切物质的载体&#xff0c;我们依靠数据做存储记录&#xff0c;通过数据进行信息传递交换&#xff0c;最终还要数据来呈现和展示等&#xff0c;从一定视角而言&#xff0c;系统中最核心、…

临时用网搞不定?别着急,5G网络“急救车”来啦

如何在1天时间内&#xff0c;用不超过5名装维人员&#xff0c;完成超过200间宿舍的网络覆盖&#xff0c;让即将踏上考场的高三学子们尽快用上网络&#xff1f; 近期&#xff0c;这个问题一直困扰着重庆电信客户经理周睿。原来&#xff0c;由于疫情原因&#xff0c;重庆市某中学…

WINDOWS安装Oracle11.2.0.4

(一)Oracle服务器端安装 1.运行Oracle11g服务器端安装程序setup.exe,弹出如下界面&#xff1a; 2.如上界面中&#xff0c;把默认打上的勾去掉&#xff0c;然后点击【下一步】&#xff0c;弹出如下界面&#xff1a; 3.如上界面中&#xff0c;选择跳过软件更新,然后点击【下一步…

指针进阶(三)再谈数组与串函数

&#x1f31e;欢迎来到C语言的世界 &#x1f308;博客主页&#xff1a;卿云阁 &#x1f48c;欢迎关注&#x1f389;点赞&#x1f44d;收藏⭐️留言&#x1f4dd; &#x1f31f;本文由卿云阁原创&#xff01; &#x1f320;本阶段属于练气阶段&#xff0c;希望各位仙友顺利完成…

【阶段二】Python数据分析数据可视化工具使用01篇:数据可视化工具介绍、数据可视化工具安装、折线图与柱形图

本篇的思维导图: 数据可视化工具介绍 Matplotlib是最著名的绘图库,主要用于二维绘图,当然也可以进行简单的三维绘图。它提供了一整套丰富的命令,让我们可以非常快捷地用Python可视化数据,而且允许输出达到出版质量的多种图像格式。 Seaborn是在matplo…

国内电容市场份额达七成,松下如何抢占高地?

01 电容市场发展 电容器是三大电子被动元器件之一&#xff0c;是电子线路中不可缺少的基础元件&#xff0c;约占全部电子元件用量的40%&#xff0c;产值的66%。中国电容器行业规模增速持续高于全球规模增速&#xff0c;中国市场的快速增长成为拉动全球电容器行业规模增长的主要…

【Python从入门到进阶】2、Python环境的安装

接上篇《1、初识Python》 上一篇我们对Python这门编程语言进行了一个基本的了解&#xff0c;本篇我们来学习如何下载安装Python编程环境&#xff0c;以及如何使用pip管理Python包。 本篇讲解的是Windows环境下安装Python编程环境的步骤。 一、Python安装包下载 想要使用Pyth…