使用.NET实现企业微信应用接入:域名验证与消息处理

本文将介绍如何在不依赖任何第三方库的情况下,使用纯.NET实现企业微信应用的快速接入,涵盖域名验证和消息处理两个核心功能。

1. 背景

作为.NET开发者,在开发企业内部应用的时候,我们经常需要与企业微信进行集成,实现快捷的内部登录和一些便捷的消息交互,简化一些功能的开发和重复建设。虽然市面上有一些第三方库可以帮助我们完成这些集成工作,但有时候我们希望能够直接使用.NET自带的功能来实现这些需求,以减少对外部依赖的依赖,提升代码的可维护性和安全性。

下面我们就开始使用纯.NET实现企业微信应用的快速接入,企业微信应用接入主要包含两个关键环节:

域名归属认证:验证域名所有权•消息接收处理:处理企业微信推送的事件和消息

2. 项目结构与配置

2.1 配置文件设置

首先在appsettings.json中配置企业微信相关参数:

{ "DomainVerification":{ "xxxx":"xxxxxx" }, "WeCom":{ "Token":"企业微信后台设置的Token", "EncodingAesKey":"企业微信后台设置的EncodingAesKey", "CorpId":"企业ID", "CorpSecret":"应用凭证密钥" } }

2.2 配置模型定义

使用record类型定义配置模型:

public record WeCom(stringCorpId,stringCorpSecret,stringToken,stringEncodingAesKey);

2.3 依赖注入注册

Program.cs中注册配置:

var builder =WebApplication.CreateBuilder(args); builder.Services.Configure<WeCom>(builder.Configuration.GetSection(nameof(WeCom)));

3. 域名归属认证实现

企业微信要求通过特定格式的URL验证域名归属,我们可以使用Minimal API实现:

app.MapGet("/WW_verify_{name}.txt",(string name)=> { var cfg = app.Configuration; var value = cfg.GetValue<string>($"DomainVerification:{name}"); if(string.IsNullOrEmpty(value)) { returnResults.NotFound(); } returnResults.Text(value,"text/plain"); });

可信域名

实现要点

•使用路由模板WW_verify_{name}.txt匹配企业微信的验证请求•从配置中读取对应的验证码内容•返回纯文本响应

4. 消息接收处理控制器

4.1 控制器基础结构

[ApiController] [Route("wecom/callback")] publicclassWeComController:ControllerBase { privatereadonlyILogger<WeComController> _logger; privatereadonlyWeCom _weCom; publicWeComController(ILogger<WeComController> logger,IOptionsSnapshot<WeCom> weCom) { _logger = logger; _weCom = weCom.Value; } // 后续方法实现... }

4.2 URL验证接口(GET请求)

企业微信在配置回调URL时会发送GET请求进行验证:

[HttpGet] publicIActionResultGet([FromQuery]string msg_signature,[FromQuery]string timestamp, [FromQuery]string nonce,[FromQuery]string echostr) { var token = _weCom.Token; var encodingAesKey = _weCom.EncodingAesKey; var corpId = _weCom.CorpId; // 配置验证 if(string.IsNullOrEmpty(token)||string.IsNullOrEmpty(encodingAesKey)||string.IsNullOrEmpty(corpId)) { _logger.LogWarning("WeCom config missing"); returnBadRequest("WeCom config missing"); } if(string.IsNullOrEmpty(echostr)) returnBadRequest(); // 签名验证 if(!VerifySignature(token, timestamp, nonce, echostr, msg_signature)) { _logger.LogWarning("WeCom signature invalid (GET)"); returnBadRequest("signature invalid"); } try { var plain =DecryptMessage(encodingAesKey, echostr, corpId); // 返回明文完成验证 returnContent(plain,"text/plain",Encoding.UTF8); } catch(Exception ex) { _logger.LogWarning(ex,"WeCom decrypt failed (GET)"); returnBadRequest("decrypt failed"); } }

4.3 消息处理接口(POST请求)

处理企业微信推送的各种事件和消息:

[HttpPost] public async Task<IActionResult>Post([FromQuery]string msg_signature, [FromQuery]string timestamp,[FromQuery]string nonce) { var token = _weCom.Token; var encodingAesKey = _weCom.EncodingAesKey; var corpId = _weCom.CorpId; // 配置验证 if(string.IsNullOrEmpty(token)||string.IsNullOrEmpty(encodingAesKey)||string.IsNullOrEmpty(corpId)) { _logger.LogWarning("WeCom config missing"); returnBadRequest(); } // 读取请求体 usingvar reader =newSystem.IO.StreamReader(Request.Body,Encoding.UTF8); var body = await reader.ReadToEndAsync(); var encrypt =ExtractXmlNode(body,"Encrypt"); if(string.IsNullOrEmpty(encrypt)) { // 非加密消息或格式不对,按企业微信要求返回 success _logger.LogDebug("WeCom POST without Encrypt node, return success"); returnContent("success","text/plain"); } // 签名验证 if(!VerifySignature(token, timestamp, nonce, encrypt, msg_signature)) { _logger.LogWarning("WeCom signature invalid (POST)"); returnBadRequest("signature invalid"); } string xml; try { xml =DecryptMessage(encodingAesKey, encrypt, corpId); } catch(Exception ex) { _logger.LogWarning(ex,"WeCom decrypt failed (POST)"); returnBadRequest("decrypt failed"); } // 处理XML消息内容 // 这里可以添加具体的业务逻辑处理 // 企业微信要求返回固定字符串 "success" returnContent("success","text/plain"); }

5. 核心工具方法实现

5.1 签名验证

privatestaticboolVerifySignature(string token,string timestamp,string nonce, string encrypt,string signature) { var arr =new[]{ token ??string.Empty, timestamp ??string.Empty, nonce ??string.Empty, encrypt ??string.Empty}; Array.Sort(arr,StringComparer.Ordinal); var raw =string.Join("", arr); usingvar sha1 = SHA1.Create(); var hash = sha1.ComputeHash(Encoding.UTF8.GetBytes(raw)); var computed =BitConverter.ToString(hash).Replace("-","").ToLowerInvariant(); returnstring.Equals(computed, signature ??string.Empty,StringComparison.OrdinalIgnoreCase); }

5.2 消息解密

privatestaticstringDecryptMessage(string encodingAesKey,string inputEncryptBase64,string corpId) { // 补齐 base64 填充 var pad = encodingAesKey; if(pad.Length%4!=0) pad +=newstring('=',4- pad.Length%4); var aesKey =Convert.FromBase64String(pad); var encrypted =Convert.FromBase64String(inputEncryptBase64); usingvar aes =Aes.Create(); aes.Key= aesKey; aes.IV = aesKey.Take(16).ToArray(); aes.Mode=CipherMode.CBC; aes.Padding=PaddingMode.None; usingvar decryptor = aes.CreateDecryptor(); var decrypted = decryptor.TransformFinalBlock(encrypted,0, encrypted.Length); // 移除 PKCS#7 填充 var padLen = decrypted[^1]; if(padLen <1|| padLen >32) padLen =0; var noPad = decrypted[..(decrypted.Length- padLen)]; // 结构:16 random | 4 msgLen | msg | corpId var msgLenBytes = noPad.Skip(16).Take(4).ToArray(); if(msgLenBytes.Length<4)thrownewException("invalid msg len"); // 处理字节序 if(BitConverter.IsLittleEndian) Array.Reverse(msgLenBytes); var msgLen =BitConverter.ToInt32(msgLenBytes,0); var msgBytes = noPad.Skip(20).Take(msgLen).ToArray(); var msg =Encoding.UTF8.GetString(msgBytes); var fromCorpIdBytes = noPad.Skip(20+ msgLen).ToArray(); var fromCorpId =Encoding.UTF8.GetString(fromCorpIdBytes); // 验证企业ID if(!string.IsNullOrEmpty(corpId)&&!string.IsNullOrEmpty(fromCorpId)) { if(!fromCorpId.StartsWith(corpId,StringComparison.Ordinal)) thrownewException("corpId mismatch"); } return msg; }

5.3 XML节点提取

privatestaticstringExtractXmlNode(string xml,string nodeName) { try { var doc =newXmlDocument(); doc.LoadXml(xml); var node = doc.SelectSingleNode($"/xml/{nodeName}"); return node?.InnerText; } catch { returnnull; } }

6. 测试与部署

在实际部署和测试时,请确保完成以下步骤:

1.域名验证测试:访问https://your-domain.com/WW_verify_xxxx.txt验证是否返回正确内容2.URL配置:在企业微信后台配置回调URL为https://your-domain.com/wecom/callback3.消息测试:通过企业微信的在线测试工具[1]测试集成效果

7. 最后

本文完整展示了如何使用纯.NET技术栈实现企业微信应用的接入,涵盖了从域名验证到消息处理的完整流程。这种实现方式不依赖任何第三方库,代码简洁清晰,易于理解和维护,适合需要快速接入企业微信的.NET项目使用。您可以根据实际业务需求在此基础上进行扩展,如添加消息类型处理、业务逻辑集成等功能。

References

[1]在线测试工具:https://developer.work.weixin.qq.com/resource/devtool

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

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

相关文章

智能家居大脑:一小时搭建支持中文的视觉中枢

智能家居大脑&#xff1a;一小时搭建支持中文的视觉中枢 为什么需要视觉中枢&#xff1f; 作为一名 IoT 开发者&#xff0c;你是否遇到过这样的场景&#xff1a;想为智能家居系统添加物品识别能力&#xff0c;比如让冰箱自动识别内部存放的食物&#xff0c;却苦于复杂的 AI 模型…

MCP数据加密实施路径(从入门到高阶的完整加密体系构建)

第一章&#xff1a;MCP数据加密概述在现代信息安全体系中&#xff0c;MCP&#xff08;Multi-Channel Protocol&#xff09;数据加密技术作为保障多通道通信安全的核心机制&#xff0c;广泛应用于金融、物联网和企业级网络通信场景。该技术通过集成对称与非对称加密算法&#xf…

低代码AI:用可视化工具定制你的物品识别流程

低代码AI&#xff1a;用可视化工具定制你的物品识别流程 物品识别是AI领域最实用的技术之一&#xff0c;它能自动识别图片中的物体类别&#xff0c;广泛应用于库存管理、零售分析等场景。但对于不会编程的业务人员来说&#xff0c;如何快速搭建这样的系统呢&#xff1f;本文将介…

Java Stream流与Guava工具类详解

一、Java Stream流全面解析1.1 Stream流概述Stream是Java 8引入的API&#xff0c;用于以声明式方式处理数据集合。它允许以类似SQL语句的方式对数据进行操作&#xff0c;支持顺序和并行处理。java// Stream与传统集合操作对比 List<String> names Arrays.asList("A…

Spring Batch性能优化:从30分钟到3分钟的蜕变

快速体验 打开 InsCode(快马)平台 https://www.inscode.net输入框内输入如下内容&#xff1a; 优化一个现有的Spring Batch数据迁移作业&#xff0c;原始版本处理100万条记录需要30分钟。要求重构实现&#xff1a;1) 分区处理(Partitioning)并行执行 2) 批量插入代替单条插入…

【MCP远程监考全攻略】:揭秘2024年最新合规要求与技术实现路径

第一章&#xff1a;MCP远程监考概述MCP&#xff08;Microsoft Certified Professional&#xff09;远程监考是一种基于互联网的考试认证模式&#xff0c;允许考生在符合安全规范的环境下通过个人设备完成技术能力评估。该模式依托先进的身份验证、行为监测与网络防护机制&#…

5分钟创建项目目标验证原型

快速体验 打开 InsCode(快马)平台 https://www.inscode.net输入框内输入如下内容&#xff1a; 创建一个快速原型工具&#xff0c;允许用户&#xff1a;1. 输入项目想法&#xff1b;2. 自动生成目标草案&#xff1b;3. 可视化目标结构&#xff1b;4. 分享和收集反馈。使用Reac…

AI如何帮你轻松实现红黑树?快马平台一键生成代码

快速体验 打开 InsCode(快马)平台 https://www.inscode.net输入框内输入如下内容&#xff1a; 请生成一个完整的红黑树实现代码&#xff0c;包含以下功能&#xff1a;1. 节点插入与删除操作&#xff1b;2. 自动平衡功能&#xff08;左旋、右旋、颜色调整&#xff09;&#xf…

Hunyuan-MT-7B与跨境电商独立站SEO多语言优化联动

Hunyuan-MT-7B与跨境电商独立站SEO多语言优化联动 在跨境电商竞争日益激烈的今天&#xff0c;品牌出海不再只是“把商品挂上网”那么简单。真正的挑战在于——如何让不同语言、不同文化背景的用户&#xff0c;都能流畅地理解你的产品价值&#xff0c;并愿意为之买单。而这一切&…

为什么说Hunyuan-MT-7B是当前最实用的开源翻译模型之一

为什么说Hunyuan-MT-7B是当前最实用的开源翻译模型之一 在全球化内容爆炸式增长的今天&#xff0c;跨语言沟通早已不再是“锦上添花”&#xff0c;而是企业出海、科研协作、文化传播乃至政府治理中的刚性需求。从社交媒体上的多语种评论&#xff0c;到跨国企业的内部文档流转&a…

MCP必知的Azure Stack HCI网络配置实战(专家级部署方案泄露)

第一章&#xff1a;MCP必知的Azure Stack HCI网络架构核心原理 Azure Stack HCI 是微软推出的超融合基础设施解决方案&#xff0c;其网络架构设计直接影响系统性能、可扩展性与安全性。理解其核心网络原理是实现高效部署与运维的关键。 网络平面划分原则 Azure Stack HCI 要求…

LIVEKIT vs 自建WebRTC:开发效率对比分析

快速体验 打开 InsCode(快马)平台 https://www.inscode.net输入框内输入如下内容&#xff1a; 创建一个对比演示项目&#xff0c;展示LIVEKIT与传统WebRTC开发的效率差异。实现一个简单的视频聊天应用的两个版本&#xff1a;1) 使用原生WebRTC API从头开发 2) 基于LIVEKIT SD…

STRNCPY vs 现代C++:性能对比与替代方案

快速体验 打开 InsCode(快马)平台 https://www.inscode.net输入框内输入如下内容&#xff1a; 请生成一个性能测试程序&#xff0c;对比&#xff1a;1. strncpy 2. std::string 3. std::copy 4. memcpy在不同数据量下的性能表现。要求包含&#xff1a;- 测试框架 - 计时逻辑 …

交通运输十五五规划专题汇总(2026-01-05更新)

交通运输 “十五五” 规划&#xff08;2026-2030 年&#xff09;是我国构建现代化综合交通运输体系的中长期战略部署&#xff0c;聚焦 “安全、便捷、高效、绿色、经济” 目标&#xff0c;涵盖以下核心专题&#xff1a;一是基础设施网络优化&#xff0c;包括高铁主通道贯通、国…

揭秘Azure容器部署常见陷阱:3个你必须避免的关键错误

第一章&#xff1a;揭秘Azure容器部署常见陷阱&#xff1a;3个你必须避免的关键错误 在将应用程序部署到Azure容器实例&#xff08;ACI&#xff09;或Azure Kubernetes服务&#xff08;AKS&#xff09;时&#xff0c;开发者常因配置疏忽导致服务不可用、性能下降或安全漏洞。以…

为什么你的Azure OpenAI在MCP中无法生效?深度剖析4大配置故障

第一章&#xff1a;MCP Azure OpenAI 配置概述Azure OpenAI 服务为企业提供了安全、可扩展的接口&#xff0c;用于集成先进的大语言模型到现有系统中。通过 Microsoft Cloud Platform&#xff08;MCP&#xff09;配置 Azure OpenAI&#xff0c;开发者能够利用私有化部署、数据加…

预告:2026光谷AI产业发展峰会1月25日召开 助力武汉抢抓AI浪潮

雷递网 乐天 1月6日由武汉东湖新技术开发区投资促进局指导&#xff0c;雷递网主办的《2026光谷AI产业发展峰会》将于2026年1月25日下午2点在武汉光谷皇冠假日酒店。本次《2026光谷AI产业发展峰会》的活动主旨是诚邀对武汉感兴趣的企业家、创业者、投资人到武汉交流与发展&#…

Azure容器部署性能优化,90%工程师忽略的4个关键配置

第一章&#xff1a;Azure容器部署性能优化概述在现代云原生架构中&#xff0c;Azure 容器实例&#xff08;ACI&#xff09;与 Azure Kubernetes 服务&#xff08;AKS&#xff09;已成为部署容器化应用的核心平台。为确保应用具备高响应性、低延迟和资源高效利用&#xff0c;性能…

企业级MAVEN安装最佳实践:从单机到集群

快速体验 打开 InsCode(快马)平台 https://www.inscode.net输入框内输入如下内容&#xff1a; 创建一个企业级MAVEN环境配置方案&#xff0c;包含&#xff1a;1.多版本MAVEN并行安装 2.Nexus私有仓库配置 3.基于角色的权限管理 4.CI/CD集成示例。要求输出详细的配置文档和doc…

1小时搭建XX00日志监控原型系统

快速体验 打开 InsCode(快马)平台 https://www.inscode.net输入框内输入如下内容&#xff1a; 开发一个简易的XX00系统日志监控原型&#xff0c;要求&#xff1a;1)模拟生成XX00系统日志数据流&#xff0c;2)实现实时日志显示面板&#xff0c;3)基础的关键词过滤功能&#xf…