c# 钉钉应用实现监听审批事件以及获取审批结果的流程

oa的操作已经测试了一遍

image.png

如果是自建oa则代表发起的审批是跳转网页,否则钉钉打开后是一个表单界面,不需要调整自己搞得oa。

所以我感觉目前公司的需求更适合官方oa 表单来填写,更灵活,还支持用户配置。

但是用户点了审批,这个表单的结果怎么监听呢?
自建了应用之后
填写了一个网址测试,发现有迹可循。
其实际上的发起的请求一目两然。

验签的c#版本倒是提供了
他推荐流模式,但是只给了java,和go,我喜欢偷懒,那就直接http实现吧
java版本:

import com.alibaba.fastjson.JSONObject;
import org.springframework.web.bind.annotation.RequestBody;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestParam;
import org.springframework.web.bind.annotation.RestController;
import java.util.Map;@RestController
public class CallbackController {@PostMapping("{你注册的HTTP地址的urlpath}")public Map<String, String> callBack(@RequestParam(value = "msg_signature", required = false) String msg_signature,@RequestParam(value = "timestamp", required = false) String timeStamp,@RequestParam(value = "nonce", required = false) String nonce,@RequestBody(required = false) JSONObject json) {} 
}
image.png

c#没有提供案例
但是也可以根据上面的报错红色信息 举一反三,不懂的朋友直接复制curl到apifox里面玩吧。

//https://github.com/open-dingtalk/DingTalk-Callback-Crypto/blob/main/DingTalkEncryptor.cs[HttpPost("callback/{urlpath}")]public string CallBack([FromQuery(Name = "msg_signature")] string? msgSignature,[FromQuery(Name = "timestamp")] string? timestamp,[FromQuery(Name = "nonce")] string? nonce,[FromBody] JObject? json // 以 JObject 接收 JSON 请求体){// 示例:从 JSON 中手动取字段string? encrypt = json?["encrypt"]?.ToString();Console.WriteLine($"接收到 encrypt = {encrypt}");// 构造返回的 JObjectJObject result = new JObject {["status"] = "ok",["msg"] = "callback received",};return result.ToString(); // 返回 JSON}

DingTalk-Callback-Crypto/DingTalkEncryptor.cs at main · open-dingtalk/DingTalk-Callback-Crypto

image.png

然后我开启断点调试http://nat.xx.xx.top:1111/callback/ding
点击保存,这边立马传过来参数了,nice

image.png

验证没问题那么保存会成功,保存失败每次需要重新配置。

image.png

这是我接口直接复制curl里面的东西测试结果

image.png

下面是我自建公网转发端口映射的技术栈 实现抓取到阿里那边发起的请求

image.png

解密抓到的事件

//https://github.com/open-dingtalk/DingTalk-Callback-Crypto/blob/main/DingTalkEncryptor.cs[HttpPost("callback/{urlpath}")]public string CallBack([FromQuery(Name = "msg_signature")] string? msgSignature,[FromQuery(Name = "timestamp")] string? timestamp,[FromQuery(Name = "nonce")] string? nonce,[FromBody] JObject? json // 以 JObject 接收 JSON 请求体){// 示例:从 JSON 中手动取字段string? encrypt = json?["encrypt"]?.ToString();//    DingTalkEncryptor dingTalkEncryptor=new DingTalkEncryptor(msgSignature, timestamp, nonce);string aesKey = "jfMpfdLWzGyZAhGc3sljt9rUsEvfiuWEDmDNCcYjoUX";string signKey = "TJKIRtrgH9a6vo72W0JZjp4iU541VJpHANjzX";DingTalkEncryptor callbackCrypto = new DingTalkEncryptor(token: signKey, encodingAesKey: aesKey,corpId:"dinggfmqeejcxfh76eja");String decryptMsg = callbackCrypto.getDecryptMsg(msgSignature, timestamp, nonce, encrypt);Debug.WriteLine("decryptMsg:"+ decryptMsg);// 3. 反序列化回调事件json数据JObject eventJson = JObject.Parse(decryptMsg);String eventType = eventJson["EventType"].ToString(); //bpms_instance_change// 4. 根据EventType分类处理if ("check_url" == eventType) {// 测试回调url的正确性Debug.WriteLine("测试回调url的正确性");}else if ("user_add_org" == eventType) {// 处理通讯录用户增加事件Debug.WriteLine("发生了:" + eventType + "事件");}else {// 添加其他已注册的Debug.WriteLine("发生了:" + eventType + "事件");}// 5. 返回success的加密数据Dictionary<string, string> successMap = callbackCrypto.getEncryptedMap("success");Console.WriteLine($"接收到 encrypt = {encrypt}");return JObject.FromObject(successMap).ToString();}

然后 如果审批 被同意或者被拒绝则bpms_instance_change中的type等于finish
下面这个:
这是发起实例后,修改了审批人,这个时候type还是等于start,然后 我点了拒绝后的信息

decryptMsg:{"EventType":"check_url"}
测试回调url的正确性
decryptMsg:{"EventType":"check_url"}
测试回调url的正确性
decryptMsg:{"EventType":"check_url"}
测试回调url的正确性
线程 0x5754 已退出,返回值为 0 (0x0)。
decryptMsg:{"processInstanceId":"a3Dk0aPSRjioHwXjwvftZA03241752197014","eventId":"475679dc49894ab0866e21d49cb2fad3","corpId":"ding5769db03cf6cefd4a1320dcb25e91351","resource":"/v1.0/event/bpms_instance_change/processCode/PROC-DD3B3D23-ECA2-492F-847E-20DEB0C0AFB3/type/start","EventType":"bpms_instance_change","businessId":"202507110923000340503","title":"情迁提交的A测试","type":"start","url":"https://aflow.dingtalk.com/dingtalk/mobile/homepage.htm?corpid=ding5769db03cf6cefd4a1320dcb25e91351&dd_share=false&showmenu=false&dd_progress=false&back=native&procInstId=a3Dk0aPSRjioHwXjwvftZA03241752197014&taskId=&swfrom=isv&dinghash=approval&dtaction=os&dd_from=corp#approval","createTime":1752197015000,"processCode":"PROC-DD3B3D23-ECA2-492F-847E-20DEB0C0AFB3","bizCategoryId":"","staffId":"0716043442804764"}
发生了:bpms_instance_change事件decryptMsg:{"processInstanceId":"a3Dk0aPSRjioHwXjwvftZA03241752197014","eventId":"26d224da367e4a12872eca6f42bf82d0","finishTime":1752197095000,"corpId":"ding5769db03cf6cefd4a1320dcb25e91351","resource":"/v1.0/event/bpms_instance_change/processCode/PROC-DD3B3D23-ECA2-492F-847E-20DEB0C0AFB3/type/finish","EventType":"bpms_instance_change","businessId":"202507110923000340503","title":"情迁提交的A测试","type":"finish","url":"https://aflow.dingtalk.com/dingtalk/mobile/homepage.htm?corpid=ding5769db03cf6cefd4a1320dcb25e91351&dd_share=false&showmenu=false&dd_progress=false&back=native&procInstId=a3Dk0aPSRjioHwXjwvftZA03241752197014&taskId=&swfrom=isv&dinghash=approval&dtaction=os&dd_from=corp#approval","result":"refuse","createTime":1752197015000,"processCode":"PROC-DD3B3D23-ECA2-492F-847E-20DEB0C0AFB3","bizCategoryId":"","staffId":"0716043442804764"}
发生了:bpms_instance_change事件

虽然知道了结果但是不知道填写的具体信息包括拒绝的理由
就需要这个接口了。

curl --location --request POST 'http://api.dingtalk.com/v1.0/workflow/processInstances?processInstanceId=a3Dk0aPSRjioHwXjwvftZA03241752197014' \
--header 'x-acs-dingtalk-access-token: 5f4bab5f471635cea6bb4b3exxxxxxx' \
--header 'AppTime: 1724827203420' \
--header 'User-Agent: Apifox/1.0.0 (https://apifox.com)' \
--header 'Content-Type: application/json' \
--data-raw '{"originatorUserId" : "0716043442804764","processCode":"PROC-A13F14D1-B48E-4111-AC4F-36DF88BE5110"}'

我这边返回的结果:

{"result": {"finishTime": "2025-07-11T09:24Z","attachedProcessInstanceIds": [],"businessId": "202507110923000340503","title": "情迁提交的A测试","originatorDeptId": "-1","operationRecords": [{"date": "2025-07-11T09:23Z","result": "NONE","images": [],"showName": "提交申请","type": "START_PROCESS_INSTANCE","userId": "0716043442804764"},{"date": "2025-07-11T09:24Z","result": "REFUSE","activityId": "sid-1234_5678","images": [],"showName": "审批人","remark": "。。。。我拒绝了你","type": "EXECUTE_TASK_NORMAL","userId": "0716043442804764"}],"formComponentValues": [{"componentType": "TextField","name": "用户名","bizAlias": "TextField-bizAlias","id": "TextField-abcd","value": "单行输入框示例"}],"result": "refuse","bizAction": "NONE","createTime": "2025-07-11T09:23Z","originatorUserId": "0716043442804764","tasks": [{"result": "REFUSE","activityId": "sid-1234_5678","finishTime": "2025-07-11T09:24Z","pcUrl": "aflow.dingtalk.com?procInsId=a3Dk0aPSRjioHwXjwvftZA03241752197014&taskId=94836079594&businessId=202507110923000340503","createTime": "2025-07-11T09:24Z","mobileUrl": "aflow.dingtalk.com?procInsId=a3Dk0aPSRjioHwXjwvftZA03241752197014&taskId=94836079594&businessId=202507110923000340503","userId": "0716043442804764","taskId": 94836079594,"status": "COMPLETED"}],"originatorDeptName": "测试推送","status": "COMPLETED"},"success": true
}

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

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

相关文章

Typecho架构深度剖析:轻量级博客系统的设计哲学与实现原理

文章目录 深度解析Typecho:轻量级博客系统的架构设计与实现1. Typecho概述与技术背景1.1 发展历程1.2 核心特性2. 系统架构设计分析2.1 核心架构图2.2 核心组件3. 核心模块实现分析3.1 路由系统实现3.2 数据库抽象层4. 插件系统深度解析4.1 Hook机制实现4.2 插件开发示例5. 性…

LangChain 内存(Memory)

1. 为什么需要内存&#xff1f; 大型语言模型&#xff08;LLM&#xff09;本身是无状态的。这意味着每次你向 LLM 发送一个请求&#xff08;Prompt&#xff09;&#xff0c;它都会独立处理这个请求&#xff0c;完全不记得之前任何的交互。这在构建一次性问答应用时没问题&#…

基于定制开发开源AI智能名片S2B2C商城小程序的社群游戏定制策略研究

摘要&#xff1a;本文聚焦社群游戏定制领域&#xff0c;深入探讨以社群文化和用户偏好为导向的定制策略。通过分析互动游戏活动、社群文化塑造等关键要素&#xff0c;结合定制开发开源AI智能名片S2B2C商城小程序的技术特性&#xff0c;提出针对性游戏定制方案。研究旨在提升社群…

自动驾驶决策与规划

目录 自动驾驶决策与规划概述 决策与规划体系结构 分层递阶式决策规划 反应式体系结构 混合式体系结构 决策与规划系统的关键环节 路径规划 轨迹规划 行为决策 异常处理 自动驾驶的路径规划技术 维诺图法 栅格法 Dijkstra算法 A*算法 自动驾驶的行为决策方法 …

C++编译期计算:常量表达式(constexpr)全解析

在C性能优化领域&#xff0c;"将计算尽可能转移到编译期"是一条黄金法则。编译期计算&#xff08;Compile-Time Computation&#xff09;能显著减少程序运行时的开销&#xff0c;提升执行效率&#xff0c;同时还能在编译阶段暴露潜在错误。C11引入的constexpr关键字及…

【micro:bit】从入门到放弃(一):在线、离线版本的使用

1、离线版 micro:bit 1)下载地址 https://makecode.microbit.org/offline-app 2)双击安装包,makecode-microbit-setup-win64.exe,自动安装,安装成功后图标如下图所示 3)运行程序,查看版本信息 4)主界面如下 5)编程界面 点击“新建项目”或者“导入”进入编程界…

Flink Forward Asia 2025 主旨演讲精彩回顾

作为 Apache Flink 社区备受瞩目的年度盛会之一&#xff0c;由阿里云承办的 Flink Forward Asia 2025 于 7 月 3 日在新加坡正式拉开帷幕。From Real-Time Data Analytics to Real-Time AI&#xff0c;Flink 生态全面拥抱 AI本次大会上&#xff0c;Apache Flink 中文社区发起人…

车道偏离预警(LDW)功能介绍

车道偏离预警&#xff08;LDW&#xff09;功能介绍 LDW功能 通过摄像头监测前方车道线&#xff0c;当车辆偏离车道线时&#xff0c;系统发出报警提醒。 系统框图报警条件 最早报警线最迟报警线报警临界线 设置在 最早/最迟报警线 之间接口定义 输入/输出系统算法 横向偏离速度模…

软考(软件设计师)计算机网络-网络层

obsidian做markdown笔记太爽了&#xff0c;康奈尔模板笔记看起来舒服&#xff0c;CSDN试了几种方式&#xff0c;不支持&#xff0c;只能贴图了&#xff0c;将就看吧&#x1f60f;&#xff08;狗头保命&#xff09;工作原理图解 #mermaid-svg-e5Tgpt26jUftujKn {font-family:&qu…

nginx反向代理实现跨域请求

记录一个项目中遇到的跨域请求问题&#xff0c;解决跨域问题无非几种办法&#xff1a;1、后端解决&#xff0c;推荐的做法&#xff0c;可以看我之前写的文章&#xff0c;fastadmin的后台配置跨域&#xff1b;2、前端配置proxy代理&#xff08;开发环境用&#xff09;&#xff1…

利用Wisdom SSH高效搭建CI/CD工作流

在软件开发流程中&#xff0c;CI/CD工作流对于提升效率与确保质量起着关键作用。Wisdom SSH作为一款强大工具&#xff0c;其官网为ssh.wisdomheart.cn&#xff0c;借助AI助手能大幅简化CI/CD工作流的搭建过程。假设服务器已完成基础配置&#xff0c;下面为您介绍如何利用Wisdom…

深度学习-循环神经网络RNN

文章目录序列模型循环神经网络案例词的表示输出的表示矩阵运算表示交叉熵损失时间反向传播算法BPTT梯度消失与梯度爆炸GRULSTM总结序列模型 循环神经网络 st是上一个隐层的输出&#xff0c;体现序列数据之间有很强的关联性。 案例 > S0是初始输入&#xff0c;一般是0&#…

【Linux网络编程】Socket - TCP

目录 V1版本 - Echo Server 初始化服务器 启动服务器 客户端 一些BUG与问题 解决服务器无法一次处理多个请求的问题 多进程版本 多线程版本 线程池版本 V2版本 - 多线程远程执行命令 V1版本 - Echo Server 初始化服务器 TCP大部分内容与UDP是相同的&#xff0c;我们…

知识图谱构建简单分享

最近系统性地学习了知识图谱构建的关键技术&#xff0c;并结合医疗领域知识&#xff0c;完成了一个医疗知识图谱项目的实践。以下是整理的项目架构&#xff0c;欢迎交流指正。说明&#xff1a;当前项目实际实现主要应用了数据预处理、模型设计与预训练、模型优化与测试等核心技…

MCU中的系统控制器(System Controller)是什么?

MCU中的系统控制器&#xff08;System Controller&#xff09;是什么&#xff1f; 在微控制器&#xff08;MCU&#xff09;中&#xff0c;系统控制器&#xff08;System Controller&#xff09;是一个关键模块&#xff0c;负责管理和协调MCU内部的核心功能&#xff0c;确保系统…

【Datawhale夏令营】用AI做带货视频评论分析

文本分类、文本聚类 基础库&#xff1a; pandas, sklearn功能&#xff1a; 商品识别、情感分析、评论聚类商品识别&#xff1a; 视频文本信息&#xff0c;预测推广商品名称 & 情感分析&#xff1a;四个维度&#xff08;情感倾向、用户场景、用户疑问、用户建议&#xff09…

[Meetily后端框架] AI摘要结构化 | `SummaryResponse`模型 | Pydantic库 | vs marshmallow库

第3章&#xff1a;摘要数据结构&#xff08;Pydantic库&#xff09; 欢迎回来&#xff01; 在之前的第2章&#xff1a;API文档中&#xff0c;我们知道API网关提供了端点 而API文档准确告诉我们如何与这些端点通信&#xff0c;包括需要发送的数据格式和期望接收的数据格式。 …

深度学习 tensor及其相关操作

目录 Tensor 概念 数据类型 创建tensor 基本创建方式 1、 torch.tensor() 2、torch.Tensor() 3、torch.IntTensor() 等 创建线性张量和随机张量 1、创建线性张量 2、创建随机张量 切换设备 类型转换 与 Numpy 数据转换 1、张量转 Numpy 2、Numpy 转张量 tenso…

如何将FPGA设计的验证效率提升1000倍以上(4)

本文为系列文章的完结篇。用户应用设计中的信号&#xff0c;在经历编译器的多次迭代优化之后&#xff0c;在FPGA芯片内部运行时&#xff0c;可能已经被重新命名、“改头换面”或“机里机气”。要想以人工经验进行追踪&#xff0c;构建目标寄存器信号与RTL设计源码之间的映射关系…

Linux驱动11 --- buildroot杂项驱动开发方法

目录 一、Buildroot 1.1介绍 文件系统 1.一个完整的操作系统需要包含大量的文件 2.在嵌入式开发中目前应用最广泛的文件系统制作工具就是 buildroot&#xff0c;busybox 3.buildroot 制作文件系统&#xff08;了解&#xff09; 二、杂项驱动编程 1.1 驱动编程做的内容 2.2…