关键区别说明(指令回调 vs 数据回调)

特性指令回调数据回调
触发场景授权/取消授权等管理事件通讯录变更、应用菜单点击等业务事件
关键字段InfoTypeEvent + ChangeType
典型事件suite_auth, cancel_authchange_contact, suite_ticket
响应要求必须返回加密的"success"必须返回加密的"success"

xml: 

<dependencies><!-- Spring Boot Web --><dependency><groupId>org.springframework.boot</groupId><artifactId>spring-boot-starter-web</artifactId></dependency><!-- 企业微信官方加解密库 --><dependency><groupId>com.github.binarywang</groupId><artifactId>weixin-java-cp</artifactId><version>4.5.0</version></dependency><!-- XML处理 --><dependency><groupId>org.dom4j</groupId><artifactId>dom4j</artifactId><version>2.1.3</version></dependency>
</dependencies>

controller


import org.dom4j.Document;
import org.dom4j.DocumentException;
import org.dom4j.DocumentHelper;
import org.dom4j.Element;
import org.example.testchat.aes.WXBizMsgCrypt;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.web.bind.annotation.*;import java.util.HashMap;
import java.util.Iterator;
import java.util.Map;@RestController
@RequestMapping("/callback")
public class WxWorkCallbackController {private static final Logger logger = LoggerFactory.getLogger(WxWorkCallbackController.class);@Value("${qiyewx.token}")private String token;@Value("${qiyewx.encodingAESKey}")private String encodingAESKey;@Value("${qiyewx.corpid}")private String corpid;@Value("${qiyewx.suiteId}")private String suiteId;/*** 数据回调验证接口 (GET请求)*/@GetMapping("/data")public String validateDataCallback(@RequestParam("msg_signature") String msgSignature,@RequestParam("timestamp") String timestamp,@RequestParam("nonce") String nonce,@RequestParam("echostr") String echostr) {logger.info("收到数据回调验证请求: signature={}, timestamp={}, nonce={}, echostr={}",msgSignature, timestamp, nonce, echostr);try {WXBizMsgCrypt wxcpt = new WXBizMsgCrypt(token, encodingAESKey, corpid);String plainText = wxcpt.VerifyURL(msgSignature, timestamp, nonce, echostr);logger.info("验证成功,明文: {}", plainText);return plainText;} catch (Exception e) {logger.error("验证失败", e);return "fail";}}/*** 专门处理suite_ticket推送(数据回调)*/@PostMapping(value = "/data", produces = "text/plain;charset=UTF-8")public String handleDataCallback(@RequestParam("msg_signature") String signature,@RequestParam("timestamp") String timestamp,@RequestParam("nonce") String nonce,@RequestBody String encryptedMsg) {try {// 1. 解密消息WXBizMsgCrypt wxcpt = new WXBizMsgCrypt(token, encodingAESKey, corpid);String plainText = wxcpt.DecryptMsg(signature, timestamp, nonce, encryptedMsg);// 2. 解析XMLMap<String, String> message = parseXml(plainText);if ("suite_ticket".equals(message.get("Event"))) {String suiteTicket = message.get("SuiteTicket");String suiteId = message.get("SuiteId");// 3. 保存ticket(示例代码)saveSuiteTicket(suiteId, suiteTicket);logger.info("成功更新suite_ticket: {}", suiteTicket);}// 4. 关键点:返回加密的success!!!String encryptedSuccess = wxcpt.EncryptMsg("success", timestamp, nonce);return encryptedSuccess;} catch (Exception e) {logger.error("处理suite_ticket失败", e);return "fail";}}private void saveSuiteTicket(String suiteId, String suiteTicket) {// 实现你的存储逻辑,例如:// redisTemplate.opsForValue().set("wxwork:ticket:"+suiteId, suiteTicket, 20*60);System.out.println("suiteId: " + suiteId + "suiteTicket:" + suiteTicket);}/*** 指令回调验证接口(GET请求)* 企业微信首次配置时会触发此验证*/@GetMapping("/cmd")public String validateCmdCallback(@RequestParam("msg_signature") String msgSignature,@RequestParam("timestamp") String timestamp,@RequestParam("nonce") String nonce,@RequestParam("echostr") String echostr) {logger.info("[指令回调] 验证请求 - signature:{}, timestamp:{}, nonce:{}, echostr:{}",msgSignature, timestamp, nonce, echostr);try {WXBizMsgCrypt wxcpt = new WXBizMsgCrypt(token, encodingAESKey, suiteId);String plainText = wxcpt.VerifyURL(msgSignature, timestamp, nonce, echostr);logger.info("[指令回调] 验证成功,明文: {}", plainText);
//            return plainText; // 必须返回解密后的明文return "success";} catch (Exception e) {logger.error("[指令回调] 验证失败", e);return "fail";}}/*** 指令回调处理接口(POST请求)* 接收:授权成功、取消授权、变更授权等指令*/@PostMapping(value = "/cmd", produces = "application/xml;charset=UTF-8")public String handleCmdCallback(@RequestParam("msg_signature") String msgSignature,@RequestParam("timestamp") String timestamp,@RequestParam("nonce") String nonce,@RequestBody String encryptedMsg) {logger.info("[指令回调] 收到消息 - signature:{}, timestamp:{}, nonce:{}",msgSignature, timestamp, nonce);try {// 1. 解密消息WXBizMsgCrypt wxcpt = new WXBizMsgCrypt(token, encodingAESKey, suiteId);String plainText = wxcpt.DecryptMsg(msgSignature, timestamp, nonce, encryptedMsg);logger.info("[指令回调] 解密后消息: {}", plainText);// 2. 解析XML(复用数据回调的解析方法)Map<String, String> message = parseXml(plainText);String infoType = message.get("InfoType");String authCorpId = message.get("AuthCorpId");String SuiteTicket = message.get("SuiteTicket");saveSuiteTicket(authCorpId, SuiteTicket);// 3. 处理不同类型的指令switch (infoType) {case "suite_auth":// 授权成功事件(含临时授权码)String authCode = message.get("AuthCode");logger.info("[指令回调] 企业授权成功: corpId={}, authCode={}", authCorpId, authCode);// TODO: 调用企业微信API换取永久授权码break;case "change_auth":// 授权变更事件(如权限集变更)String state = message.get("State");logger.info("[指令回调] 授权变更: corpId={}, state={}", authCorpId, state);break;case "cancel_auth":// 取消授权事件logger.info("[指令回调] 取消授权: corpId={}", authCorpId);// TODO: 清理该企业相关数据break;default:logger.warn("[指令回调] 未知指令类型: {}", infoType);}// 4. 必须返回加密的success
//            return wxcpt.EncryptMsg("success", timestamp, nonce);return "success";} catch (Exception e) {logger.error("[指令回调] 处理失败", e);return "fail";}}/*** 解析XML到Map*/private Map<String, String> parseXml(String xml) throws DocumentException {Map<String, String> result = new HashMap<>();Document document = DocumentHelper.parseText(xml);Element root = document.getRootElement();for (Iterator<Element> it = root.elementIterator(); it.hasNext(); ) {Element element = it.next();result.put(element.getName(), element.getText());}return result;}
}

yml

server:port: 8080servlet:context-path: /wxwork:token: 你的Token # 在企业微信后台设置的回调TokenencodingAESKey: 你的EncodingAESKey # 在企业微信后台设置的EncodingAESKeycorpId: 你的CorpID # 企业微信服务商的CorpIDsuiteId: 你的suiteId # 第三方应用id

踩坑:企业微信文档写的太烂了,而且坑也特别多,企业微信指令回调用的不是corpid,而是 

suiteId!!!!!!!!!!!

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

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

相关文章

LazyLLM教程 | 第2讲:10分钟上手一个最小可用RAG系统

贴心小梗概本文将介绍使用LazyLLM搭建最基础的RAG的流程。首先介绍使用LazyLLM搭建RAG系统的必要环境配置&#xff0c;然后简单回顾RAG的基本流程&#xff0c;接下来分别介绍RAG中文档加载、检索组件、生成组件三个关键部分的参数和基本使用方法&#xff0c;最后利用LazyLLM实现…

android9-PMS-常见问题及分析步骤

以下是基于 Android 9 的 Package Manager Service (PMS) 常见问题及分析步骤&#xff0c;结合系统原理与优化实践整理&#xff1a; &#x1f527; 一、开机性能问题 现象 开机时间随应用增多显著延长&#xff0c;卡在“正在启动应用”阶段。 分析步骤 ① 确认扫描阶段耗时adb…

生成模型实战 | GLOW详解与实现

生成模型实战 | GLOW详解与实现0. 前言1. 归一化流模型1.1 归一化流与变换公式1.2 RealNVP 的通道翻转2. GLOW 架构2.1 ActNorm2.2 可逆 11 卷积2.3 仿射耦合层2.4 多尺度架构3. 使用 PyTorch 实现 GLOW3.1 数据处理3.2 模型构建3.3 模型训练0. 前言 GLOW (Generative Flow) 是…

行业案例:杰和科技为智慧教育构建数字化硬件底座

清晨8点10分&#xff0c;深圳某学生踏入校园&#xff0c;智慧门闸识别身份&#xff0c;并同步发给家长&#xff1b;走廊里的“智慧班牌”向他们展示今日的课表&#xff1b;课堂上&#xff0c;教室前方的多媒体播放器里&#xff0c;老师引导学生学习“居民楼消防隐患”知识&…

Redis与MySQL数据同步:从“双写一致性”到实战方案

Redis与MySQL数据同步&#xff1a;从“双写一致性”到实战方案 在分布式系统中&#xff0c;Redis作为高性能缓存被广泛使用——它能将热点数据从MySQL中“搬运”到内存&#xff0c;大幅降低数据库压力、提升接口响应速度。但随之而来的核心问题是&#xff1a;当MySQL数据更新时…

Java源码构建智能名片小程序

在移动互联网时代&#xff0c;纸质名片的局限性日益凸显——信息更新不便、客户管理困难、营销效果难以追踪。智能电子名片小程序以其便捷、高效、智能的特点&#xff0c;正成为商务人士的"数字营销门户"。而基于Java技术栈开发的智能名片系统&#xff0c;凭借其稳定…

如何在短时间内显著提升3D效果图渲染速度?

在建筑设计、游戏开发、影视制作等行业&#xff0c;3D效果图的渲染速度是项目进度与效率的关键瓶颈。面对复杂场景时&#xff0c;漫长的渲染等待尤为突出。要在保证质量的前提下大幅缩短渲染时间&#xff0c;以下优化策略至关重要&#xff1a; 1. 升级硬件配置&#xff1a;渲染…

配置daemon.json使得 Docker 容器能够使用服务器GPU【验证成功】

&#x1f947; 版权: 本文由【墨理学AI】原创首发、各位读者大大、敬请查阅、感谢三连 文章目录&#x1f50d;你遇到的错误&#xff1a;&#x1f50d; 根本原因✅ 解决方案&#xff1a;正确安装 NVIDIA Container Toolkit✅ 第一步&#xff1a;卸载旧版本&#xff08;如果存在&…

Linux 系统进程管理与计划任务详解

Linux 系统进程管理与计划任务详解 一、程序与进程的基本概念 程序&#xff1a;保存在外部存储介质中的可执行机器代码和数据的静态集合。进程&#xff1a;在CPU及内存中处于动态执行状态的计算机程序。关系&#xff1a;每个程序启动后&#xff0c;可创建一个或多个进程。 二、…

【图像处理】直方图均衡化c++实现

直方图均衡化是一种通过调整图像像素灰度值分布&#xff0c;来增强图像对比度的经典数字图像处理技术。其核心在于将原始图像的灰度直方图从集中的某个区间“拉伸”或“均衡”到更广泛的区间&#xff0c;让图像的明暗细节更清晰&#xff0c;关键在于利用累积分布函数实现灰度值…

Web前端实战:Vue工程化+ElementPlus

1.Vue工程化 1.1介绍 模块化&#xff1a;将js和css等&#xff0c;做成一个个可复用模块组件化&#xff1a;我们将UI组件&#xff0c;css样式&#xff0c;js行为封装成一个个的组件&#xff0c;便于管理规范化&#xff1a;我们提供一套标准的规范的目录接口和编码规范&#xff0…

ECMAScript2021(ES12)新特性

概述 ECMAScript2021于2021年6月正式发布&#xff0c; 本文会介绍ECMAScript2021(ES12)&#xff0c;即ECMAScript的第12个版本的新特性。 以下摘自官网&#xff1a;ecma-262 ECMAScript 2021, the 12th edition, introduced the replaceAll method for Strings; Promise.any,…

Tlias 案例-整体布局(前端)

开发流程前端开发和后端开发是一样的&#xff0c;都需要阅读接口文档。 准备工作&#xff1a; 1&#xff1a;导入项目中准备的基础过程到 VsCode。2&#xff1a;启动前端项目&#xff0c;访问该项目3&#xff1a;熟悉一下基本的布局<script setup></script><tem…

三十二、【Linux网站服务器】搭建httpd服务器演示虚拟主机配置、网页重定向功能

httpd服务器功能演示一、虚拟主机配置虚拟主机技术全景虚拟主机目录规范1. 基于端口的虚拟主机&#xff08;8080/8081&#xff09;2. 基于IP的虚拟主机&#xff08;192.168.1.100/192.168.1.101&#xff09;3. 基于域名的虚拟主机&#xff08;site1.com/site2.com&#xff09;二…

串行化:MYSQL事务隔离级别中的终极防护

在现代应用程序中&#xff0c;数据的一致性和可靠性至关重要。想象一下&#xff0c;如果在一个银行系统中&#xff0c;两个用户同时试图转账到同一个账户&#xff0c;最终的数据结果可能会出乎意料。为了避免这种情况&#xff0c;MYSQL提供了不同的事务隔离级别&#xff0c;其中…

RAG:检索增强生成的范式演进、技术突破与前沿挑战

1 核心定义与原始论文 RAG&#xff08;Retrieval-Augmented Generation&#xff09;由Facebook AI Research团队于2020年提出&#xff0c;核心思想是将参数化记忆&#xff08;预训练语言模型&#xff09;与非参数化记忆&#xff08;外部知识库检索&#xff09;结合&#xff0c…

2024年蓝桥杯Scratch10月图形化stema选拔赛真题——旋转的图形

旋转的图形编程实现旋转的图形。具体要求1&#xff09;点击绿旗&#xff0c;在舞台上出现滑杆形式的变量 r&#xff0c;取值范围为-1、0、1&#xff0c;默认值为 0&#xff0c;如图所示&#xff1b;2&#xff09;1秒后&#xff0c;在舞台上绘制出一个红色正方形&#xff08;边长…

【音视频】WebRTC 开发环境搭建-Web端

一、开发环境搭建 1.1 安装vscode 下载VSCode&#xff1a;https://code.visualstudio.com/&#xff0c;下载后主要用于开发Web前端页面&#xff0c;编写前端代码 安装完成后下载Live Server插件&#xff0c;用于本地开发&#xff0c;实时加载前端页面 1.1.1 前端代码测试 下…

力扣54:螺旋矩阵

力扣54:螺旋矩阵题目思路代码题目 给你一个 m 行 n 列的矩阵 matrix &#xff0c;请按照 顺时针螺旋顺序 &#xff0c;返回矩阵中的所有元素。 思路 思路很简单创建一个二维数组然后按照箭头所示的顺序一层一层的给二维数组相应的位置赋值即可。难点是我们是一层一层的赋值…

【CSS】设置表格表头固定

1.设置thead样式在thead元素中增加样式&#xff1a;position: sticky;top: 0;2.设置table样式在table元素中增加样式&#xff1a;border-collapse: separate; /* 分离边框模式 */ border-spacing: 0;3.设置表头伪元素样式增加样式&#xff1a;th::after {content: ;position: a…