C# 企业微信:开启消息接受&接收消息&推送消息

2023-11-07

前言:微信吧!接触的人都会100%各种踩坑,就算同样东西去年做过,今年来一样踩坑,因为太多你稍微不记得一点点的细节就能让你研究N久。为此,我要把这个过程详细的记录下来。

 

一、开启消息接受


 1.拿到企业corpId,应用的Token,EncodingAESKey

2.这界面先别关,拿到 Token,EncodingAESKey后,建个接口

鉴于公司系统的架构类型,我这里创建的是一个aspx文件,代码如下:

public partial class request_WxMsgApi : System.Web.UI.Page
{
    protected void Page_Load(object sender, EventArgs e)
    {
        //开启消息接受
        if (Request.HttpMethod.ToUpper() == "GET")
        {
            string signature = HttpContext.Current.Request.QueryString["msg_signature"];
            string timestamp = HttpContext.Current.Request.QueryString["timestamp"];
            string nonce = HttpContext.Current.Request.QueryString["nonce"];
            string echostr = HttpContext.Current.Request.QueryString["echostr"];
            string decryptEchoString = "";
            WXBizMsgCrypt wxcpt = new WXBizMsgCrypt("your token", "your EncodingAESKey", System.Configuration.ConfigurationManager.AppSettings["Corpid"]);
            int ret = wxcpt.VerifyURL(signature, timestamp, nonce, echostr, ref decryptEchoString);
            if (ret != 0)
            {
                //有错误的话记录日志
                //WriteLogFile("ERR: VerifyURL fail, ret: " + ret);
            }
            HttpContext.Current.Response.Write(decryptEchoString);
            HttpContext.Current.Response.End();
            return;
        }
}
}

注意:WXBizMsgCrypt类和Cryptography类,到微信官方下载即可链接

3.写完代码,将文件更新到服务器,让这个 aspx文件能外网访问。然后再在

把这个aspx文件的链接填上去,若能正常返回,这里就会保存成功,若不能那就得再去补坑了....

 

二、接收消息


上面已经与微信那边打通了接口,接下来就是要正真接受消息了。开启消息是get请求,而正式使用接受消息则微信是post数据过来,所以  接口打通之后上面那些代码就没用了,因为数据传输模式和处理模式都不一样了

我这里的接收消息,会把各种类型的文件存到数据库或者服务器,非文本的则存到服务器,放个路径到数据库

代码如下:

public partial class request_WxMsgApi : System.Web.UI.Page
{
    protected void Page_Load(object sender, EventArgs e)
    {
        byte[] btHtml = Request.BinaryRead(Request.ContentLength);
        string strHtml = System.Text.Encoding.Default.GetString(btHtml);

        //接受消息
        if (Request.HttpMethod.ToUpper() == "POST")
        {
            string token = "your token";//从配置文件获取Token
            string encodingAESKey = "your EncodingAESKey";//从配置文件获取EncodingAESKey
            string corpId = System.Configuration.ConfigurationManager.AppSettings["corpid"];//从配置文件获取corpId

            string signature = HttpContext.Current.Request.QueryString["msg_signature"];
            string timestamp = HttpContext.Current.Request.QueryString["timestamp"];
            string nonce = HttpContext.Current.Request.QueryString["nonce"];
            string decryptEchoString = "";

            WXBizMsgCrypt wxcpt = new WXBizMsgCrypt(token, encodingAESKey, corpId);
            int ret = wxcpt.DecryptMsg(signature, timestamp, nonce, strHtml, ref decryptEchoString);
            if (ret == 0)
            {
                //WriteLogFile("ERR: VerifyURL fail, ret: " + ret);
                if (!string.IsNullOrEmpty(decryptEchoString))
                {
                    try
                    {
                        XmlDocument doc = new XmlDocument();
                        doc.LoadXml(decryptEchoString);
                        XmlNode root = doc.FirstChild;
                        var msgType = root["MsgType"].InnerText;//voice(MediaId),video(MediaId),text(Content),image(PicUrl),
                        if (msgType == "voice" || msgType == "video" || msgType == "text" || msgType == "image")
                        {
                            var msgId = root["MsgId"].InnerText;
                            var fromuser = root["FromUserName"].InnerText;
                            var timesend = root["CreateTime"].InnerText;//时间戳
                            DateTime dtStart = TimeZone.CurrentTimeZone.ToLocalTime(new DateTime(1970, 1, 1));
                            long lTime = long.Parse(timesend + "0000000");
                            TimeSpan toNow = new TimeSpan(lTime);
                            var cTime = dtStart.Add(toNow);
                            var content = "";

                            switch (msgType)
                            {
                                case "voice":
                                    content = root["MediaId"].InnerText;
                                    break;
                                case "video":
                                    content = root["MediaId"].InnerText;
                                    break;
                                case "text":
                                    content = root["Content"].InnerText;
                                    break;
                                case "image":
                                    content = root["PicUrl"].InnerText;
                                    break;
                                default:
                                    break;
                            }
                            string sql = "insert into T_CmpWxMsg([MsgId],[MsgType],[FromUser],[CreateTime],[Content]) values(@MsgId,@MsgType,@FromUser,@CreateTime,@Content)";
                            DataHelper.ExecuteNonQuery(sql, new System.Data.SqlClient.SqlParameter[]
                            {
                                new System.Data.SqlClient.SqlParameter("@MsgId", msgId),
                                new System.Data.SqlClient.SqlParameter("@MsgType", msgType),
                                new System.Data.SqlClient.SqlParameter("@FromUser", fromuser),
                                new System.Data.SqlClient.SqlParameter("@CreateTime", cTime),
                                new System.Data.SqlClient.SqlParameter("@Content", content)
                            }, conString);
                            //WriteLogFile("存入数据库成功" + cTime);

                            //异步任务-检索未下载的媒体文件
                            System.Threading.Tasks.Task.Factory.StartNew(() =>
                            {
                                //WriteLogFile("异步任务开始");
                                try
                                {
                                    //拉取媒体源文件
                                    string sql_ = "select ID,Content,MsgType from T_CmpWxMsg WHERE ISNULL(MediaSavePath,'')='' and MsgType in ('voice','video')";
                                    var mediaList = DataOperation.DataCenter.ExecuteReader(sql_, Base.ConString, new object[] { });
                                    foreach (var item in mediaList)
                                    {
                                        string corpsecret = System.Configuration.ConfigurationManager.AppSettings["corpsecret"];//你的应用对应的secrect
                                        string tocken = Base.GetCorpToken(corpsecret, corpId).Access_Token;//拿取tocken,注意有效时间,最好用缓存控制
                                        string url = string.Format("https://qyapi.weixin.qq.com/cgi-bin/media/get?access_token={0}&media_id={1}", tocken, item.Content);

                                        string upfile = Path.Combine(System.AppDomain.CurrentDomain.BaseDirectory, @"file\wxMaterial");
                                        if (!System.IO.Directory.Exists(upfile))
                                            System.IO.Directory.CreateDirectory(upfile);

                                        string filePath = upfile + "\\" + item.Content + (item.MsgType == "voice" ? ".amr" : ".mp4");
                                        WebClient client = new WebClient();
                                        client.DownloadFile(url, filePath);

                                        //更新存储的物理路径
                                        string updatesql = "update T_CmpWxMsg set MediaSavePath = '" + (@"\file\wxMaterial\" + item.Content + (item.MsgType == "voice" ? ".amr" : ".mp4")) + "' where ID='" + item.ID + "'";
                                        DataHelper.ExecuteNonQuery(updatesql, Base.ConString);
                                    }
                                }
                                catch (Exception ex) {
                                    //WriteLogFile("异步任务执行出错:" + ex.Message);
                                }
                            });
                        }
                    }
                    catch (Exception ex)
                    {
                       // WriteLogFile("程序异常:" + ex.Message);
                    }
                    finally
                    {
                        //WriteLogFile("解密消息内容:" + decryptEchoString);
                        HttpContext.Current.Response.Write(decryptEchoString);
                        HttpContext.Current.Response.End();
                    }
                }
            }
        }
    }
}

注意:这里用到的WXBizMsgCrypt类,在上面有提到可以到官方下载。

 

三、发送消息


string msg = "你好!<a href=\"https://blog.csdn.net/u012847695/article/details/102936505\">点这里查看</a>";
//按部门发送
//item = new { toparty = "438|439|471", msgtype = "text", agentid = "8", text = new { content = msg }, safe = "0" };
//按人发送
dynamic item = new { touser = "wanger|liuer", msgtype = "text", agentid = "你的应用对应的agentid", text = new { content = msg }, safe = "0" };
var body = Base.DataToJson(item);
var corpsecret = System.Configuration.ConfigurationManager.AppSettings["corpsecret"];
string tocken = Base.GetCorpToken(corpsecret).Access_Token;//获取token,注意有效时间,可用缓存控制
string url = string.Format("https://qyapi.weixin.qq.com/cgi-bin/message/send?access_token={0}", tocken);
var result = Base.InfoPost(url, body);//post request 请求
JavaScriptSerializer js = new JavaScriptSerializer();
IDictionary obj = js.DeserializeObject(result) as IDictionary;

post请求代码

 public static string InfoPost(string url, string body)
    {
        HttpWebRequest request = (HttpWebRequest)HttpWebRequest.Create(new Uri(url));
        request.Timeout = 30000;//30秒
        request.Method = "POST";
        byte[] payload = System.Text.Encoding.UTF8.GetBytes(body);
        Stream writer = request.GetRequestStream();
        writer.Write(payload, 0, payload.Length);
        writer.Close();
        HttpWebResponse response = (HttpWebResponse)request.GetResponse();
        StreamReader reader = new StreamReader(response.GetResponseStream(), Encoding.GetEncoding("utf-8"));
        var result = reader.ReadToEnd();
        return result;
    }

下次来写个支付的,自己写的看得懂点,不然每次才坑都要各种百度查资料

以上纯属个人独自研究成果,仅供参考,转载请注明出处

本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

C# 企业微信:开启消息接受&接收消息&推送消息 的相关文章

  • 不要覆盖 Azure Blob 存储

    我有一种将文件添加到 Azure Blob 存储的方法 问题是我试图指定一个条件 在该条件下它不会覆盖 blob 而只是添加到其中 我正在尝试使用参数访问条件 但是 VS 说这个方法不能采用两个参数 async void archiveNe
  • 如何使用平台调用编组 void*

    我需要从 dll 中包含的 C api 调用函数 函数原型如下 int func char name void value 其中指针值的内容可以引用依赖于传递的名称的任何类型 我不确定如何设置 Dll 输入端口以正确编组此 void 我一直
  • 改进绩效反思 - 我应该考虑哪些替代方案?

    我需要动态地设置对象上的一堆或属性的值 将其称为传输对象 将在短时间内创建相当数量的此类传输对象并设置其属性 我想避免使用反射 还有其他选择吗 如果是的话 有我可以查看的示例实现吗 Use Delegate CreateDelegate h
  • 从 C# 访问 COM vtable

    C 中有没有办法访问 COM 对象的虚拟方法表以获取函数的地址 经过大量搜索和拼凑不同的部分解决方案后 我弄清楚了如何做到这一点 首先 您需要为您尝试访问的对象定义 COM 组件类 ComImport Guid InterfaceType
  • ICSharpCode.Decompiler + Mono.Cecil -> 如何为单个方法生成代码?

    我可以使用 Mono Cecil 和 ICSharpCode Decompiler 生成类型或程序集的代码 但是 如果我尝试为单个方法生成代码 我将收到错误 对象引用未设置为对象的实例 你们能给我任何关于这个的提示吗 提前感谢您的所有帮助
  • 使用 Rhino Mocks 模拟集合

    所以我猜这是很多人想做的事情 模拟集合 过去我用 Rhino 做过这样的事情 var col mock MockRepository GenerateMock
  • C#:如何确定坐标是否在美国大陆?

    我正在获取坐标 纬度 经度 我想检查这些坐标是否位于美国大陆 有没有一种简单的方法可以在 C 中实现 我可以将坐标转换为 MGRS 或 UTM 谢谢 哇哦 他们专门为你准备了 http econym org uk gmap states x
  • ASP Net Core 属性路由和双正斜杠

    正如所指出的here https stackoverflow com a 20524044 3129340 URL 中包含双斜杠是有效的 我有一个使用属性路由的 ASP Net Core 项目 一个名为GroupController用于处理
  • 更改为通用接口对性能的影响

    我使用 Visual Studio 使用 C NET 开发应用程序 ReSharper 在我的方法原型中经常建议我用更通用的类型替换输入参数的类型 例如 如果我仅在方法主体中使用带有 foreach 的列表 则使用 List 和 IEnum
  • IOS Box2D - 身体遵循基于速度波动的点数组的特定路径

    我有一个关于身体的问题 它遵循特定的路径 首先是将身体移动到目标点的方法 const float destinationControl 0 3f b2Vec2 targetPosition path counter b2Vec2 missi
  • 在 C++ 中运行 python [关闭]

    Closed 这个问题需要多问focused help closed questions 目前不接受答案 我有一个用 C 编写的应用程序和一个测试系统 也是用 C 编写的 测试系统非常复杂并且很难改变 我只想做一些小的改变 我的班级是这样的
  • 我们可以向 ServicePointManager.SecurityProtocol 添加四个协议吗?

    我想支持从 ssl3 到 tls 1 2 的所有安全协议 但是在网上搜索时我发现代码为 ServicePointManager SecurityProtocol SecurityProtocolType Ssl3 SecurityProto
  • 是否有普遍接受的 GMP 替代方案来实现任意精度? [关闭]

    Closed 这个问题正在寻求书籍 工具 软件库等的推荐 不满足堆栈溢出指南 help closed questions 目前不接受答案 在寻找 BigInt 库的过程中 我发现了这篇文章 Microsoft Windows 上的 C 或
  • 如何同时正确使用管道和信号?

    我有 2 个孩子 我想将信号从孩子发送到父母 并将答案 随机数 为什么 为什么不 命名管道从父母发送到每个孩子 我有这个代码 include
  • 您可以从 AuthorizeAttribute 返回 HTTP 响应而不引发异常吗?

    我在各种控制器上使用 AuthorizeAttribute 可能需要根据请求本身的某些属性返回 403 或 429 请求过多 我完全在自定义 OnAuthorization 实现中实现了它 然后在必要时抛出一个带有适当响应代码的新 Http
  • 偏专业化朋友声明

    在下面的代码中 template
  • 编写一个转储屏幕像素的 RDP 客户端

    我想在中实现 RDP 客户端C 它能够获取屏幕所有像素的颜色值并将它们转储到文件中 我知道这在概念上与 RDP 的工作方式不同 但我的应用程序需要它 我正在尝试利用freerdp https github com FreeRDP FreeR
  • 即使没有任何转换,也违反了 C 中的严格别名?

    How can i and u i在此代码中打印不同的数字 即使i定义为int i u i 我只能假设我在这里触发了 UB 但我不知道具体是如何触发的 ideone演示 http ideone com Gcv5Xm如果我选择 C 作为语言
  • Windows Workflow Foundation 的替代方案?

    我已经使用 WWF 一段时间作为内部呼叫中心应用程序 ASP NET 的一部分 在学习过程中 这是了解基于状态机的工作流系统如何工作的良好实践should工作 我绝对不爱WWF本身 我认为是 过于复杂 尤其是在网络应用程序中使用 所有线程运
  • C# p/Invoke 如何使用 DirectX 游戏的 SendInput 模拟 keyPRESS 事件

    我经常为各种机器人或其他 GUI 自动化程序模拟键盘按下事件而苦苦挣扎 我已经成功地使用以下方法模拟按键事件 INPUT kInput new INPUT 1 kInput j type SendInputEventType InputKe

随机推荐

  • MATLAB怎么使用table格式读取csv文件并画图

    MATLAB中新增了一个table类型 可以很方便的读取文件中的数据 在使用这个格式的时候会默认把读取文件的第一行设置为标题 访问的时候需要通过索引值进行访问 具体怎么操作通过一个MATLAB例子进行说明 MATLAB代码 T readta
  • c 语言怎么释放链表节点,C:如何释放链表中的节点?

    我如何释放在另一个函数中分配的节点 struct node int data struct node next struct node buildList struct node head NULL struct node second N
  • 揭开数学智慧的神秘面纱:MathGPTPro使用指南带你领略数学的魅力!

    请查收一份MathGPTPro的使用指南 欢迎大家进入我们的MathGPTPro群 我们产品的链接在这 https mathgptpro com 欢迎大家踊跃提问 大家可以文字或者图片 也支持手写图片 输入问题 遇到回答中不解的问题 公式
  • MYSQL学习笔记(二)——数据库和数据表操作

    MYSQL数据库学习笔记 二 目录 MYSQL数据库学习笔记 二 一 MYSQL数据库操作 一 创建数据库 二 指定当前数据库 三 修改数据库 四 删除数据库 二 数据表操作 一 创建数据表 二 复制现成的表 三 修改数据表 1 add实例
  • 关于电脑丢失msvcr120.dll的几个修复方法

    MSVCR120 dll它是Windows系统运行某些程序所需的文件之一 如果你在运行某个程序时遇到了MSVCR120 dll丢失的错误 那么你不能简单地忽略它 因为这可能会导致程序无法正常运行 在本篇文章中 我们将为大家介绍一些解决MSV
  • MySQL高效编程学习笔记(五)--表的维护和改造

    修改表的列结构 若表中有数据最好先备份 注意转换前后的字符长度 以及是否可以互相转换等问题 改变列数据类型 ALTER TABLE visitor MODIFY nam VARCHAR 30 Eg alter table goods mod
  • 用Node.js实现一个HTTP服务器程序(文件服务器)

    http Node js开发的目的就是为了用JavaScript编写Web服务器程序 因为JavaScript实际上已经统治了浏览器端的脚本 其优势就是有世界上数量最多的前端开发人员 如果已经掌握了JavaScript前端开发 再学习一下如
  • 基于java的Mock利器-Mockito

    1 认识Mockito Mockito是java单元测试中使用率最高的Mock框架之一 特点 简明的语法和完整的文档 Mockito支持永Maven和Gradle来进行依赖引入和管理 2 Mockito Maven引入
  • 记一次Redis配置database不生效的问题

    1 先贴代码 乍一看 这个配置没问题 redis也在spring下 springboot 的 Configuration 也会默认加载redis的配置 但是一开始怎么调试都不能默认数据库为1的情况 后来我在Redis配置中发现了另一个好东东
  • Linux下重要文件不小心被删除?别着急,看这里!

    针对日常维护操作 难免会出现文件误删除的操作 大家熟知linux文件系统不同win有回收站 删除后的文件可以到垃圾箱寻回 要知道linux文件修复比较费劲 网络上面的文档也是五花八门 所以本次研究一种比较靠谱的文件和目录恢复方法 也给维护人
  • leedcode 1254. 统计封闭岛屿的数目

    题目 二维矩阵 grid 由 0 土地 和 1 水 组成 岛是由最大的4个方向连通的 0 组成的群 封闭岛是一个 完全 由1包围 左 上 右 下 的岛 思路 封闭岛屿是由1完全包围的岛 也就是说 该岛屿不能在二维矩阵的边界处 这种情况排出后
  • C语言编程中遇到Warning提示的解决方法:warning:implicit declaration of function ‘XXX‘,conflicting types for ‘XXX’

    目录 原因 解决办法 总结 在用codeblocks编写C语言代码时遇到了一个错误 implicit declaration of function XXX conflicting types for XXX 这里的 XXX 代表的是我自己
  • 案例实践:Shell定时上传文件至HDFS

    目录 一 项目需求 二 实现思路 三 具体实现流程 1 规划文件目录 2 开发shell脚本 3 给shell脚本授权 4 定时执行Shell脚本 5 查看HDFS历史访问日志 一 项目需求 公司在线服务器每天都会产生网站运行日志 为了避免
  • 机器学习_深度学习毕设题目汇总——目标检测B

    下面是该类的一些题目 题目 典型恶劣天气条件下高铁周界入侵目标检测 图模型融合时空特征的视觉显著性目标检测算法研究 基于SAR图像的舰船目标检测方法研究 基于三维点云分析的智能汽车目标检测方法研究 基于传播模型的显著目标检测方法研究 基于全
  • 如何在Ubuntu服务器上安装 QEMU/KVM 以创建虚拟机

    KVM是 Kernel based Virtual Machine 的缩写 是集成到 Linux 内核中的开源类型 1 虚拟机管理程序 裸机虚拟机管理程序 它允许您创建和管理运行 Windows Linux 或 UNIX 变体 如 Free
  • 微信小程序云开发操作全解

    云开发三大基础能力 云函数 运行在微信服务器上的函数 处理微信相关操作有天然优势 如获得用户信息异常方便 以前服务端解析很麻烦 数据库 一个小程序可以直接操作的JSON数据库 可以直接操作数据库 不在需要服务端了 存储 用来存储文件和图片
  • Vue中获取接口的方法

    在vue小黑框中输入 cnpm install axios 下载安装 可以设置成全局 引入import axios from axios 把axios放进Vue对象的原型中 Vue prototype axios axios 设置默认的地址
  • 思科模拟器基础实验完整流程-初级

    文章目录 实验拓扑 第一部分 企业总部内网 第一层 接入层 第二层 汇聚层 解决 VLAN 间通信 第三层 网络层 第二部分 企业分部内网 第三部分 外部网络路由 第四部分 NAT 地址转换 第五步 VPN 实验拓扑 由图我们可以看到这张拓
  • 【SpringCloud】用【Idea】构建Maven父子工程图文(1)

    1 概述 之前老是出现idea建springCloud的maven父子工程失败 特此写下经验和教训 springboot版本 2 2 1 2 不多逼逼 图文教程直接来 新建maven空工程 事先准备好一个空文件夹 选择刚才建好的空文件夹 不
  • C# 企业微信:开启消息接受&接收消息&推送消息

    前言 微信吧 接触的人都会100 各种踩坑 就算同样东西去年做过 今年来一样踩坑 因为太多你稍微不记得一点点的细节就能让你研究N久 为此 我要把这个过程详细的记录下来 一 开启消息接受 1 拿到企业corpId 应用的Token Encod