首先说明一点:之前碰到钉钉审批回调接口的时候发现钉钉会瞬间调用2次具体什么原因不清楚。
我的解决办法会在下面说:
直接上代码:
首先如果是内网,需要内网穿透一下把钉钉所有审批全部设置到本地,不然没办法本地DEBUG调试,(酌情考虑什么时候测试,不然同时进来的审批不是你自己的,是别人请假的或者是其他的审批流程。
【具体对不对我是这样理解的。。。如有误导请谅解】)
内网穿透 链接:https://pan.baidu.com/s/174Xe1UAZYx-K5yhxTitzHg
提取码:2hc4
复制这段内容后打开百度网盘手机App,操作更方便哦
开启之后,切地址到本地
package com.jeecg.sapoading.controller;
import com.dingtalk.api.DefaultDingTalkClient;
import com.dingtalk.api.DingTalkClient;
import com.dingtalk.api.request.OapiCallBackUpdateCallBackRequest;
import com.dingtalk.api.response.OapiCallBackUpdateCallBackResponse;
import com.jeecg.sapoading.entity.TDingOaSsqEntity;
import org.jeecgframework.core.annotation.JAuth;
import org.jeecgframework.core.common.exception.BusinessException;
import org.jeecgframework.core.common.model.json.AjaxJson;
import org.jeecgframework.core.constant.Globals;
import org.jeecgframework.core.enums.Permission;
import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.ResponseBody;
import javax.servlet.http.HttpServletRequest;
import java.util.Arrays;
@Controller
@RequestMapping("/tDi***UpdateCallBack")
@JAuth(auth= Permission.SKIP_AUTH)
public class TDingOAUpdateCallBack {
@RequestMapping(params = "updateCallBack")
@ResponseBody
public AjaxJson updateCallBack(HttpServletRequest request) {
String message = null;
AjaxJson j = new AjaxJson();
message = "OA更新回调成功";
try{
//需要开内网穿透
DingTalkClient client = new DefaultDingTalkClient("https://oapi.dingtalk.com/call_back/update_call_back");
OapiCallBackUpdateCallBackRequest requestOa = new OapiCallBackUpdateCallBackRequest();
requestOa.setUrl("http://**.**.**.**:8090/项目名/***BfController.do?insertBfFromDingding");
//本地穿透地址requestOa.setUrl("http://cfb.vaiwan.com/tAPersonassetBfController.do?insertBfFromDingding");
requestOa.setAesKey("WyGtmhbKapm*****j86boeQctWrDP7YqyTTCUf");
//key这个是一个随机字符串
requestOa.setToken("123456");
//这个好像就是123456
requestOa.setCallBackTag(Arrays.asList("bpms_instance_change", "bpms_task_change"));
// OapiCallBackUpdateCallBackResponse response = client.execute(request,"7bc30097ee5d**********205dd216ee");
OapiCallBackUpdateCallBackResponse response = client.execute(requestOa,"7bc30097ee******05dd216ee");
response.getErrcode();
System.out.println("code:"+response.getErrmsg());
}catch(Exception e){
e.printStackTrace();
message = "OA更新回调失败";
throw new BusinessException(e.getMessage());
}
j.setMsg(message);
return j;
}
}
直接上切换代码
@RequestMapping(params = "insertBfFromDingding")
@ResponseBody
public Map<String, String> insertBfFromDingding(@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,OapiCallBackRegisterCallBackRequest req ) throws DingTalkEncryptException {
DingTalkEncryptor dingTalkEncryptor = null;
List<TABfDataFromDingding> dataList = new ArrayList<>();
Map<String, String> headerMap = req.getHeaderMap();
try {
dingTalkEncryptor = new DingTalkEncryptor("123456", "WyGtmhbKapmTYja******rDP7YqyTTCUf",
"dinge3******");
//从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");
String result = obj.getString("result");
String type = obj.getString("type");
if(result!=null && 审批PROCESS_CODE找钉钉配置审批模板的人要.equals(obj.getString("processCode"))){ //大致就是PROC-4361D700-D650---******
TDingOaInfoEntity oaInfoEntity = new TDingOaInfoEntity();
SimpleDateFormat sf = new SimpleDateFormat("yyyy-MM-dd");
if("finish".equals(type) && "agree".equals(result)&& "bpms_instance_change".equals(eventType)){ //审批通过
System.out.println("回调eventType:=="+eventType);
//获取审批任务返回详情,并进行解析 z组装数据
System.out.println("-------------OA审批通过------开始------------");
DingTalkClient client = new DefaultDingTalkClient("https://oapi.dingtalk.com/topapi/processinstance/get");
OapiProcessinstanceGetRequest request = new OapiProcessinstanceGetRequest();
request.setProcessInstanceId(obj.getString("processInstanceId"));
OapiProcessinstanceGetResponse response = client.execute(request,OaCustomerAccessTokenThread.accessToken);
String body = response.getBody();
JSONObject jsonBody = JSONObject.parseObject(body);
System.out.println("jsonBody:::::"+jsonBody);
//第一层解析
String process_instance = jsonBody.getString("process_instance");
System.out.println("process_instance::::"+process_instance);
//第二层解析
JSONObject jsonProcessInstance = JSONObject.parseObject(process_instance);
String businessId = jsonProcessInstance.getString("business_id");
System.out.println("审批编号-businessId ="+businessId);
String originator_dept_id = jsonProcessInstance.getString("originator_dept_id");
System.out.println("部门ID ="+originator_dept_id);
String create_time = jsonProcessInstance.getString("create_time");
System.out.println("创建时间 ="+create_time);
oaInfoEntity.setCreateDate(new Date());
String finish_time = jsonProcessInstance.getString("finish_time");
System.out.println("审批完成时间 ="+finish_time);
oaInfoEntity.setUpdateDate(new Date());
String title = jsonProcessInstance.getString("title");
System.out.println("标题 ="+title);
oaInfoEntity.setTitle(title);
String originator_dept_name = jsonProcessInstance.getString("originator_dept_name");
System.out.println("部门名称 ="+originator_dept_name);
oaInfoEntity.setApplicantDepartment(originator_dept_name);
String originator_userid = jsonProcessInstance.getString("originator_userid");
System.out.println("userID ="+originator_userid);
oaInfoEntity.setApplyUserId(originator_userid);
if("COMPLETED".equals(jsonProcessInstance.getString("status"))){
String formValue = jsonProcessInstance.getString("form_component_values");
//第三次解析
JSONArray OaFormValueArry = JSONArray.parseArray(formValue);
// for(int i=0;i<OaFormValueArry.size();i++){
// JSONObject ra = (JSONObject) OaFormValueArry.get(i);
// String name = ra.getString("name");
// String value = ra.getString("value");
// System.out.println("name="+name +" value="+value);
// }
//审批同意处理:保存数据-----拆分json
//oaInfoEntity.set(JSONObject.parseObject(OaFormValueArry.getString(12)).getString("value"));//待用字段
System.out.println("--------------------------------------获取钉钉回调信息成功------------------------------------------\n");
//------------------------开始调用sap 插入数据接口 拿到回执编号--------------
System.out.println("------------------------------:开始调用sap 插入数据接口 拿到回执编号----------------------------------\n");
JCoDestination destination=GetSapConn.getJcoConnection();
//两着调用试着用
JCoDestination destinationsss = JCoDestinationManager
.getDestination(ABAP_AS);//所属异构系统OA或者SAP提供
JCoFunction function = destination.getRepository().getFunction(
"ZSD_FM_CREATE_CUSTOMER");//从对象仓库中获取 RFM 函数
if (function == null)
throw new RuntimeException("RFC_SYSTEM_INFO not found in SAP.");
try {
function.execute(destination);
} catch (AbapException e) {
System.out.println(e.toString());
}
JCoParameterList is_data_sum = function.getImportParameterList();
is_data_sum.setValue("IV_TYPE", "1");//--1 创建所有数据 2--仅创建通用数据 3 -- 创建公司代码数据
is_data_sum.setValue("IV_IS_COMMIT", "X");//布尔变量(X= 真,-= 假,空格 = 未知)
//IS_DATA 是SAP 结构名称 类是与JAVA Map当参数传入Funtion的参数封装
JCoStructure is_data = function.getImportParameterList().getStructure("IS_DATA");
//OaFormValueArry.getString(1)) getString 下标是从钉钉返回的jsaon 抓取的
is_data.setValue("BAHNE", JSONObject.parseObject(OaFormValueArry.getString(1)).getString("value"));//提交人-申请人
is_data.setValue("KATR1", JSONObject.parseObject(OaFormValueArry.getString(4)).getString("value").equals("null") ? "":JSONObject.parseObject(OaFormValueArry.getString(4)).getString("value"));//客户种类
System.out.println("KATR1 客户种类 "+JSONObject.parseObject(OaFormValueArry.getString(4)).getString("value"));
is_data.setValue("KATR2", JSONObject.parseObject(OaFormValueArry.getString(5)).getString("value").equals("null") ? "":JSONObject.parseObject(OaFormValueArry.getString(5)).getString("value"));//客户类别
//固定参数
is_data.setValue("KTOKD", "***");//业务伙伴分组
is_data_sum.setValue("IS_DATA", is_data);
System.out.println("---------正在调用sap请等待30秒。。。。。。。。。。。。。。");
function.execute(destination);//执行调用函数
JCoTable table2 = function.getTableParameterList().getTable("MESSTAB");//[MESSTAB 是SAP返回 数据的“表名字”]得到sap返回的参数,你就把他当作c语言的结构体理解就可以了
//有时候sap那边只是返回一个输出参数,sap比方说你这边输入一个物料号,想得到sap那边的物料描述,这是sap方是不会返回一个内表给你的
//而是只是返回一个输出参数给你这时你就要用到下面的方法来得到输出参数
//获取sap回执编号
JCoParameterList exportParameterList = function.getExportParameterList();
Object ev_kunnr = exportParameterList.getValue("EV_KUNNR");
oaInfoEntity.setClientNumber(ev_kunnr.toString()); //客户编号
oaInfoEntity.setDingApprovalNumber(businessId);//审批编号
System.out.println("----------------------获取SAP回传客户编号: " + ev_kunnr + "---------------------------------\n");
System.out.println("---------------------------------开始更新本地客户编号并保存数据----------------------------\n");
String MessageAll ="";
for (int i = 0; i < table2.getNumRows(); i++) {
table2.setRow(i);
//这里获取sap函数传出内表结构的字段 【传入的字符串为调用函数需要传入的参数名,必须为大写】
String TYPE = table2.getString("TYPE");//[消息类型:S 成功 E 错误 W警告 I信息 A 中断]记住这里参数一定是大写的,不然得不到值【如果报错说明你参数传的不对】
String MESSAGE = table2.getString("MESSAGE");//记住这里一定是大写的,不然得不到值
MessageAll= MessageAll+MESSAGE;
System.out.println("TYPE:" + TYPE + "MESSAGE:" + MESSAGE);
}
//调用sap结束
}
}else if("refuse".equals(result)){ //审批未通过
}
}else if ("其他审批请继续添加") {
} else {
// 其他类型事件处理
}
// 返回success的加密信息表示回调处理成功
return dingTalkEncryptor.getEncryptedMap("success", System.currentTimeMillis(), Utils.getRandomStr(8));
} catch (Exception e) {
//失败的情况,应用的开发者应该通过告警感知,并干预修复
// mainLogger.error("process callback failed!"+params,e);
e.printStackTrace();
return null;
}
}
发起审批:
@RequestMapping(params = "createZyProcessinstance")
@ResponseBody
public Map<String,Object> createZyProcessinstance(String jsonData,String fromUserId,String toUserId,String deptId,HttpServletRequest request){
Map<String,Object> paramMap = new HashMap<>();
try{
//数据解析
List<TABfDataFromDingding> zyData = JSONObject.parseArray(jsonData, TABfDataFromDingding.class);
String accessToken = PersonAccessTokenThread.accessToken;
//注册转移审批流程回调地址
DefaultDingTalkClient client = new DefaultDingTalkClient("https://oapi.dingtalk.com/topapi/processinstance/create");
OapiProcessinstanceCreateRequest processinstanceRequest = new OapiProcessinstanceCreateRequest();
Long aLong = Long.valueOf("41605932");
processinstanceRequest.setProcessCode(ResourceUtil.getConfigByName("PROCESS_CODE_ZY"));
List<OapiProcessinstanceCreateRequest.FormComponentValueVo> formComponentValues = new ArrayList<>();
List<List<OapiProcessinstanceCreateRequest.FormComponentValueVo>> detailFormList = new ArrayList<>();
detailFormList = formComponentValue(zyData,fromUserId,toUserId);
OapiProcessinstanceCreateRequest.FormComponentValueVo vo4 = new OapiProcessinstanceCreateRequest.FormComponentValueVo();
vo4.setName("明细");
vo4.setValue(JSON.toJSONString(detailFormList));
formComponentValues.add(vo4);
processinstanceRequest.setFormComponentValues(formComponentValues);
//获取发起审批人是不是领导
DingTalkClient getPersonClient = new DefaultDingTalkClient("https://oapi.dingtalk.com/user/get");
OapiUserGetRequest personRequest = new OapiUserGetRequest();
personRequest.setUserid(toUserId);
personRequest.setHttpMethod("GET");
OapiUserGetResponse rs = getPersonClient.execute(personRequest, accessToken);
String isLeaderInDepts = rs.getIsLeaderInDepts();
Map maps = (Map)JSON.parse(isLeaderInDepts);
boolean isLeader = (Boolean) maps.get(deptId);
//获取发起人的父部门
DingTalkClient parentDeptClient = new DefaultDingTalkClient("https://oapi.dingtalk.com/department/list_parent_depts_by_dept");
OapiDepartmentListParentDeptsByDeptRequest parentDeptRequest = new OapiDepartmentListParentDeptsByDeptRequest();
parentDeptRequest.setId(deptId);
parentDeptRequest.setHttpMethod("GET");
OapiDepartmentListParentDeptsByDeptResponse parentDeptResponse = parentDeptClient.execute(parentDeptRequest, accessToken);
List<Long> parentIds = parentDeptResponse.getParentIds();
OapiDepartmentGetResponse deptResponse = null;
OapiDepartmentGetRequest deptRequest = null;
DingTalkClient deptClient = null;
List<String> sendList = new ArrayList<>();
String approversIds = "";
if(isLeader){ //如果是主管 那么就去主管的上级
if(!parentIds.isEmpty()){
deptClient = new DefaultDingTalkClient("https://oapi.dingtalk.com/department/get");
deptRequest = new OapiDepartmentGetRequest();
deptRequest.setHttpMethod("GET");
deptRequest.setId(String.valueOf(parentIds.get(1)));
deptResponse = deptClient.execute(deptRequest, accessToken);
String deptManagerUseridList = deptResponse.getDeptManagerUseridList();
approversIds=deptManagerUseridList;
}
}else if(!isLeader){
deptClient = new DefaultDingTalkClient("https://oapi.dingtalk.com/department/get");
parentIds.remove(parentIds.size()-1);
parentIds.remove(parentIds.size()-1);
for(Long dId:parentIds){
deptRequest = new OapiDepartmentGetRequest();
deptRequest.setHttpMethod("GET");
deptRequest.setId(String.valueOf(dId));
deptResponse = deptClient.execute(deptRequest, accessToken);
String sendIds = deptResponse.getDeptManagerUseridList();
if(StringUtils.isNotBlank(sendIds)){
sendList.add(sendIds);
}
}
for(String s:sendList){
approversIds = approversIds+s;
approversIds = approversIds+",";
}
}
if(approversIds.endsWith(",")){
approversIds = approversIds.substring(0,approversIds.length()-1);
}
approversIds = toUserId+","+approversIds;
processinstanceRequest.setApprovers(approversIds); //审批人钉钉ID集合
processinstanceRequest.setOriginatorUserId(fromUserId); //发起审批人钉钉ID
// processinstanceRequest.setApprovers("21274328231170238"); //审批人钉钉ID集合
// processinstanceRequest.setOriginatorUserId("21274328231170238"); //发起审批人钉钉ID
processinstanceRequest.setDeptId(Long.valueOf(deptId)); //审批人部门ID
// processinstanceRequest.setDeptId(Long.valueOf("118496372"));
// request.setCcList(userIds);
// request.setCcPosition("START_FINISH");
System.out.println(approversIds);
if(StringUtils.isNotBlank(rs.getJobnumber())){
OapiProcessinstanceCreateResponse response = client.execute(processinstanceRequest,accessToken);
System.out.println(response.getErrmsg());
paramMap.put("msg","转移审批提交成功");
paramMap.put("success",true);
}else{
paramMap.put("msg","转移审批发起失败,该接受人没有工号信息,请通知人资部门维护该员工信息!");
paramMap.put("success",false);
}
}catch (Exception ex){
ex.printStackTrace();
paramMap.put("msg","程序异常,请检查网络连接");
paramMap.put("success",false);
}
return paramMap;
}