钉钉 回调事件 消息加解密
官网文档:
https://developers.dingtalk.com/document/app/configure-event-subcription/title-bec-rsq-8wj
官方示例:
https://github.com/open-dingtalk/dingtalk-callback-Crypto?spm=ding_open_doc.document.0.0.692c7008rgi7iZ
依赖commons-codes包
<dependency> <groupId>commons-codec</groupId> <artifactId>commons-codec</artifactId> <version>1.15</version> </dependency>
API使用说明
- 实例化加解密类,入参是token, aesKey, ownerKey(企业回调是corpId, 三方应用回调是suiteKey) DingCallbackCrypto callbackCrypto = new DingCallbackCrypto(TOKEN, AES_KEY, OWNER_KEY);
- 解密钉钉推送的数据,从http请求中获取解密参数 String decryptMsg = callbackCrypto.getDecryptMsg(msg_signature, timeStamp, nonce, encrypt);
- 返回success的加密字符串 Map<String, String> successMap = callbackCrypto.getEncryptedMap("success");
回调处理流程
@RequestMapping(value = "/callback", method = RequestMethod.POST) public Map<String, String> callback(HttpServletRequest request, @RequestBody String paramBodyStr) throws DingCallbackCrypto.DingTalkEncryptException { // 1. 从http请求中获取加解密参数 String msg_signature = request.getParameter("msg_signature"); if (msg_signature == null) { msg_signature = request.getParameter("signature"); } String timeStamp = request.getParameter("timeStamp"); if (timeStamp == null) { timeStamp = request.getParameter("timestamp"); } String nonce = request.getParameter("nonce"); JSONObject jsonObj = JSON.parseObject(paramBodyStr); String encrypt = jsonObj.getString("encrypt"); log.info("encrypt:" + encrypt); // 2. 使用加解密类型 // DingCallbackCrypto callbackCrypto = new DingCallbackCrypto(TOKEN, AES_KEY, OWNER_KEY); DingCallbackCrypto callbackCrypto = new DingCallbackCrypto("ACfd7GB2IQMUAamb1AqbDBTr4kCjMXZgp" , "JOL6m4zOPmYUvtcNhPKWdTuJwY9DNAF39xKLm1YxJkg" , "dingh2hwao9znuoqz41d");//当使用本文档中的方式接收钉钉推送的订阅事件时,是以应用为维度推送的,OWNER_KEY为应用的AppKey final String decryptMsg = callbackCrypto.getDecryptMsg(msg_signature, timeStamp, nonce, encrypt); log.info("decryptMsg:" + decryptMsg); // 3. 反序列化回调事件json数据 JSONObject eventJson = JSON.parseObject(decryptMsg); String eventType = eventJson.getString("EventType"); // 4. 根据EventType分类处理 if ("check_url".equals(eventType)) { // 测试回调url的正确性 log.info("测试回调url的正确性"); } else if ("user_add_org".equals(eventType)) { // 处理通讯录用户增加时间 log.info("处理通讯录用户增加时间"); } else { // 添加其他已注册的 log.info("添加其他已注册的"); } // 5. 返回success的加密数据 Map<String, String> successMap = callbackCrypto.getEncryptedMap("success"); log.info("successMap:" + successMap); return successMap; }
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· AI与.NET技术实操系列:向量存储与相似性搜索在 .NET 中的实现
· 基于Microsoft.Extensions.AI核心库实现RAG应用
· Linux系列:如何用heaptrack跟踪.NET程序的非托管内存泄露
· 开发者必知的日志记录最佳实践
· SQL Server 2025 AI相关能力初探
· 震惊!C++程序真的从main开始吗?99%的程序员都答错了
· 【硬核科普】Trae如何「偷看」你的代码?零基础破解AI编程运行原理
· 单元测试从入门到精通
· 上周热点回顾(3.3-3.9)
· winform 绘制太阳,地球,月球 运作规律