博客
关于我
强烈建议你试试无所不能的chatGPT,快点击我
钉钉开发之业务事件回调
阅读量:4164 次
发布时间:2019-05-26

本文共 6591 字,大约阅读时间需要 21 分钟。

钉钉开发

一、钉钉开发之业务事件回调

简单的来说:业务事件回调就是 通过向钉钉服务器注册监听 一些指定的事件,当用户在钉钉上操作我们已经监听的事件,那么钉钉服务器就会想 我们的服务器 发送通知,我们可以得到监听事件的详细信息。

比如:我最近开发遇到的需求,需要获取用户审批实例里面的表单数据,这里我就用了钉钉的业务事件回调,我想钉钉服务器注册我需要监听的事件(这里我监听了,审批实例回调和审批任务回调)。当我向钉钉服务器注册回调接口后,一旦有用户在 钉钉上发起流程,钉钉服务器就会推动给我,而我这边也可以获取用户发起流程的详情。

1.注册业务事件回调接口

①、微应用服务器调用 注册事件回调接口(post请求)

https://oapi.dingtalk.com/call_back/register_call_back?access_token=ACCESS_TOKEN

请求参数示例:

{
"call_back_tag": ["user_add_org", "user_modify_org", "user_leave_org"], "token": "123456", "aes_key": "xxxxxxxxlvdhntotr3x9qhlbytb18zyz5zxxxxxxxxx", "url":"http://test001.vaiwan.com/eventreceive"}
参数 参数类型 必须 说明
access_token String 调用接口凭证
call_back_tag Array[String] 需要监听的事件类型
token String 加解密需要用到的token,ISV(服务提供商)推荐使用注册套件时填写的token,普通企业可以随机填写
aes_key String 数据加密密钥。用于回调数据的加密,长度固定为43个字符,从a-z, A-Z, 0-9共62个字符中选取,您可以随机生成,ISV(服务提供商)推荐使用注册套件时填写的EncodingAESKey
url String 接收事件回调的url,必须是公网可以访问的url地址

返回结果:

{
"errcode": 0, "errmsg": "ok"}

更多 查询事件回调接口、更新事件回调接口、删除事件回调接口、获取回调失败的结果等接口参考 https://ding-doc.dingtalk.com/doc#/serverapi2/pwz3r5

②.钉钉服务器会向第①步中请求参数 url 的地址推送消息

③.第 ② 和 第③ 都在下面的方法中执行了

例如:下面callback方法为回调地址,钉钉服务器会返回 signature timestamp nonce 加密后的 json 数据

package com.controller;import com.alibaba.fastjson.JSON;import com.alibaba.fastjson.JSONObject;import com.config.Constant;import com.config.URLConstant;import com.dingtalk.api.DefaultDingTalkClient;import com.dingtalk.api.DingTalkClient;import com.dingtalk.api.request.OapiCallBackDeleteCallBackRequest;import com.dingtalk.api.request.OapiCallBackGetCallBackRequest;import com.dingtalk.api.request.OapiCallBackRegisterCallBackRequest;import com.dingtalk.api.response.OapiCallBackDeleteCallBackResponse;import com.dingtalk.api.response.OapiCallBackRegisterCallBackResponse;import com.dingtalk.oapi.lib.aes.DingTalkEncryptor;import com.dingtalk.oapi.lib.aes.Utils;import com.util.AccessTokenUtil;import com.util.MessageUtil;import org.slf4j.Logger;import org.slf4j.LoggerFactory;import org.springframework.web.bind.annotation.RequestBody;import org.springframework.web.bind.annotation.RequestMapping;import org.springframework.web.bind.annotation.RequestMethod;import org.springframework.web.bind.annotation.RequestParam;import org.springframework.web.bind.annotation.ResponseBody;import org.springframework.web.bind.annotation.RestController;import java.util.Arrays;import java.util.Map;/** * E应用回调信息处理 */@RestControllerpublic class CallbackController {
private static final Logger bizLogger = LoggerFactory.getLogger("BIZ_CALLBACKCONTROLLER"); private static final Logger mainLogger = LoggerFactory.getLogger(CallbackController.class); /** * 创建套件后,验证回调URL创建有效事件(第一次保存回调URL之前) */ private static final String CHECK_URL = "check_url"; /** * 审批任务回调,更多回调类型 参考 https://ding-doc.dingtalk.com/doc#/serverapi2/skn8ld */ private static final String BPMS_TASK_CHANGE = "bpms_task_change"; /** * 审批实例回调 */ private static final String BPMS_INSTANCE_CHANGE = "bpms_instance_change"; /** * 相应钉钉回调时的值 */ private static final String CALLBACK_RESPONSE_SUCCESS = "success"; /** * 审批模板唯一标识,可以在审批管理后台的 URL 中找到 */ public static final String PROCESS_CODE = "***"; @RequestMapping(value = "/callback", method = RequestMethod.POST) @ResponseBody public Map
callback(@RequestParam(value = "signature", required = false) String signature, @RequestParam(value = "timestamp", required = false) String timestamp, @RequestParam(value = "nonce", required = false) String nonce, @RequestBody(required = false) JSONObject json) {
String params = " signature:"+signature + " timestamp:"+timestamp +" nonce:"+nonce+" json:"+json; try {
DingTalkEncryptor dingTalkEncryptor = new DingTalkEncryptor(Constant.TOKEN, Constant.ENCODING_AES_KEY, Constant.CORP_ID); //从post请求的body中获取回调信息的加密数据进行解密处理 String encryptMsg = json.getString("encrypt"); String plainText = dingTalkEncryptor.getDecryptMsg(signature, timestamp, nonce, encryptMsg); JSONObject obj = JSON.parseObject(plainText); //根据回调数据类型做不同的业务处理 String eventType = obj.getString("EventType"); if (BPMS_TASK_CHANGE.equals(eventType)) {
bizLogger.info("收到审批任务进度更新: " + plainText); // 可以根据 PROCESS_CODE 来判断这是属于哪个模板发起的流程 // 参考 https://ding-doc.dingtalk.com/doc#/serverapi2/skn8ld 得到返回的数据做业务 //todo: 实现审批的业务逻辑,如发消息 } else if (BPMS_INSTANCE_CHANGE.equals(eventType)) {
bizLogger.info("收到审批实例状态更新: " + plainText); //todo: 实现审批的业务逻辑,如发消息 String processInstanceId = obj.getString("processInstanceId"); if (obj.containsKey("result") && obj.getString("result").equals("agree")) {
MessageUtil.sendMessageToOriginator(processInstanceId); } } else {
// 其他类型事件处理 } // 返回success的加密信息表示回调处理成功【这是第 三 步,返回加密后的 “success” 给钉钉服务器,让钉钉服务器知道此次回调成功了。否则钉钉会持续推动消息的回调接口。】 return dingTalkEncryptor.getEncryptedMap(CALLBACK_RESPONSE_SUCCESS, System.currentTimeMillis(), Utils.getRandomStr(8)); } catch (Exception e) {
//失败的情况,应用的开发者应该通过告警感知,并干预修复 mainLogger.error("process callback failed!"+params,e); return null; } } public static void main(String[] args) throws Exception{
// 先删除企业已有的回调 DingTalkClient client = new DefaultDingTalkClient(URLConstant.DELETE_CALLBACK); OapiCallBackDeleteCallBackRequest request = new OapiCallBackDeleteCallBackRequest(); request.setHttpMethod("GET"); client.execute(request, AccessTokenUtil.getToken()); // 重新为企业注册回调 client = new DefaultDingTalkClient(URLConstant.REGISTER_CALLBACK); OapiCallBackRegisterCallBackRequest registerRequest = new OapiCallBackRegisterCallBackRequest(); registerRequest.setUrl(Constant.CALLBACK_URL_HOST + "/callback"); registerRequest.setAesKey(Constant.ENCODING_AES_KEY); registerRequest.setToken(Constant.TOKEN); registerRequest.setCallBackTag(Arrays.asList("bpms_instance_change", "bpms_task_change")); OapiCallBackRegisterCallBackResponse registerResponse = client.execute(registerRequest,AccessTokenUtil.getToken()); if (registerResponse.isSuccess()) {
System.out.println("回调注册成功了!!!"); } }}

转载地址:http://oqxxi.baihongyu.com/

你可能感兴趣的文章
qt中的菜单QMenu QAction
查看>>
Qt下QTableWidget的使用
查看>>
QTableWidget与QTableView的区别
查看>>
qt MVC(一)
查看>>
Qstring 与tr翻译过来的中文进行比较的问题
查看>>
QString 字符编码
查看>>
Direct3D播放RGB(通过Texture)
查看>>
qt setData()和data()
查看>>
Qt容器类(总结)(新发现的QQueue和QStack,注意全都是泛型)
查看>>
类模板和函数模板
查看>>
C++ 虚函数表解析
查看>>
const、volatile、mutable关键字
查看>>
C++中友元
查看>>
qt 5.0中HeaderView的setResiziMode无法使用的问题
查看>>
查看Python安装路径以及安装包路径小技巧
查看>>
Python中使用中文
查看>>
python import模块方法
查看>>
svn merge
查看>>
SVN版本回退
查看>>
python 可变参数传递
查看>>