最近由于业务需求需要在项目中介入钉钉审批流程,虽然不是第一次接触钉钉api,但是之前使用是借助同事的配置(爬坑经验借鉴同事的 :简书 少年丶要淡定 ),一直没有比较系统的去了解使用,正好借助这次需求的机会,去深入了解一下,记录一下爬坑经验,难免以后会再次使用到。
使用钉钉开发官方工作流 钉钉开发文档
事件回调
回调是开发者在钉钉开放平台注册一个HTTP接口,并订阅相关的事件,当事件发生时,钉钉会主动调用开发者注册的HTTP接口,推送对应的事件信息。
参考demo
要在钉钉企业用户信息中查看 钉钉管理后台,必须企业用户管理员才可以登录
登录开发者后台,点击左侧菜单的【移动接入应用-登录】,然后点击右上角的【创建扫码登录应用授权】,创建用于免登过程中验证身份的appId及appSecret,创建后即可看到appId和appSecret。
/**
* 企业corpid, 需要修改成开发者所在企业
*/
public static final String CORP_ID = "xxx";
/**
* 应用的AppKey,登录开发者后台,点击应用管理,进入应用详情可见
*/
public static final String APPKEY = "xxx";
/**
* 应用的AppSecret,登录开发者后台,点击应用管理,进入应用详情可见
*/
public static final String APPSECRET = "xxx";
/**
* 数据加密密钥。用于回调数据的加密,长度固定为43个字符,从a-z, A-Z, 0-9共62个字符中选取,您可以随机生成
*/
public static final String ENCODING_AES_KEY = "xxx";
/**
* 加解密需要用到的token,企业可以随机填写。如 "12345"
*/
public static final String TOKEN = "xxx";
/**
* 应用的agentdId,正式环境
*/
public static final Long AGENTID = xxx;
以上每个参数的查看方式,请前往钉钉开发文档中查看
public static String startProcessInstance(OapiProcessinstanceCreateRequest oapiProcessinstanceCreateRequest,String appKey,String appSecret) throws ApiException {
DefaultDingTalkClient client = new DefaultDingTalkClient(URLConstant.URL_PROCESSINSTANCE_START);
OapiProcessinstanceCreateResponse response = client.execute(oapiProcessinstanceCreateRequest, AccessTokenUtil.getToken(appKey,appSecret));
logger.debug("发起钉钉审批返回信息"+ new Gson().toJson(response));
return response.getProcessInstanceId();
}
URLConstant.URL_PROCESSINSTANCE_START
: 是钉钉的url配置
所用到的配置如下:具体使用的url和参数,请查看
/**
* 钉钉网关gettoken地址
*/
public static final String URL_GET_TOKKEN = "https://oapi.dingtalk.com/gettoken";
/**
*获取用户在企业内userId的接口URL
*/
public static final String URL_GET_USER_INFO = "https://oapi.dingtalk.com/user/getuserinfo";
/**
*获取用户姓名的接口url
*/
public static final String URL_USER_GET = "https://oapi.dingtalk.com/user/get";
/**
* 发起审批实例的接口url
*/
public static final String URL_PROCESSINSTANCE_START = "https://oapi.dingtalk.com/topapi/processinstance/create";
/**
* 获取审批实例的接口url
*/
public static final String URL_PROCESSINSTANCE_GET = "https://oapi.dingtalk.com/topapi/processinstance/get";
/**
* 发送企业通知消息的接口url
*/
public static final String MESSAGE_ASYNCSEND = "https://oapi.dingtalk.com/topapi/message/corpconversation/asyncsend_v2";
/**
* 删除企业回调接口url
*/
public static final String DELETE_CALLBACK = "https://oapi.dingtalk.com/call_back/delete_call_back";
/**
* 注册企业回调接口url
*/
public static final String REGISTER_CALLBACK = "https://oapi.dingtalk.com/call_back/register_call_back";
/**
* 获取用户列表
*/
public static final String GET_USER_LIST = "https://oapi.dingtalk.com/user/listbypage";
agentId
:是微应用的ID
processCode
:钉钉审批模板的ID(你需要钉钉的企业管理员的权限,去创建一个模板,创建好以后去地址栏中找)
formComponentValues
:这个就是审批的表单(这里后台中控件的Name属性要和你创建表单时的控件名称要一致)
originatorUserId
:发起流程的用户(这里看看你们项目中的用户和钉钉的用户是怎么关联的,一般应该是电话吧)
deptId
:发起人所在部门的ID
public static OapiUserGetResponse getRequestUser(String phone,String appKey,String appSecret) throws RuntimeException, ApiException {
StringBuffer buffer = new StringBuffer();
buffer.append("https://oapi.dingtalk.com/user/get_by_mobile");
buffer.append("?access_token=");
buffer.append(AccessTokenUtil.getToken(appKey,appSecret));
buffer.append("&mobile=");
buffer.append(phone);
String line = sendGet(buffer.toString());
DingDingUserId dingDingUserId = new Gson().fromJson(line, DingDingUserId.class);
DingTalkClient client = new DefaultDingTalkClient("https://oapi.dingtalk.com/user/get");
OapiUserGetRequest request = new OapiUserGetRequest();
request.setUserid(dingDingUserId.getUserid());
request.setHttpMethod("GET");
OapiUserGetResponse response = client.execute(request, AccessTokenUtil.getToken(appKey,appSecret));
return response;
}
public static String getToken(String appKey,String appSecret) throws RuntimeException {
try {
DefaultDingTalkClient client = new DefaultDingTalkClient(URL_GET_TOKKEN);
OapiGettokenRequest request = new OapiGettokenRequest();
request.setAppkey(appKey);
request.setAppsecret(appSecret);
request.setHttpMethod("GET");
OapiGettokenResponse response = client.execute(request);
String accessToken = response.getAccessToken();
logger.debug("发起钉钉所需要的accessToken:" + accessToken);
return accessToken;
} catch (ApiException e) {
logger.error("getAccessToken failed", e);
throw new RuntimeException();
}
}
public static String sendGet(String u) {
String result = "";
try {
URL url = new URL(u);
//得到connection对象。
HttpURLConnection connection = (HttpURLConnection) url.openConnection();
//设置请求方式
connection.setRequestMethod("GET");
//连接
connection.connect();
//得到响应码
int responseCode = connection.getResponseCode();
if(responseCode == HttpURLConnection.HTTP_OK){
//得到响应流
InputStream inputStream = connection.getInputStream();
//获取响应
BufferedReader reader = new BufferedReader(new InputStreamReader(inputStream));
String line;
while ((line = reader.readLine()) != null){
result = line;
}
reader.close();
//该干的都干完了,记得把连接断了
connection.disconnect();
}
} catch (Exception e) {
e.printStackTrace();
}
return result;
}
钉钉审批官方流程
方式一 指定审批人
(1)调用接口时,传入approvers或者approvers_v2参数,指定审批人。其中,approvers_v2支持或签和会签。
(2)指定审批人方式,不支持审批模板的高级设置,比如手写签名、表单操作权限等均无法使用等。
方式二 复用审批后台设置的审批流程
(1)调用接口时,不传入approvers或者approvers_v2参数,会自动复用在审批管理后台预设的审批人。流程设置页面见下图。(2)可在流程设计里设置审批人的或签会签等操作。
(3)复用审批后台设置的审批流程时,若接口填写cc_list、cc_position,参数不生效,会复用审批后台设置的抄送人员。
public String getCallBackUrl(HttpServletRequest request){
StringBuffer buffer = new StringBuffer();
buffer.append("xxxx");
return buffer.toString();
}
public static void RegisterCallBack(String callBackUrl,String appKey,String appSecret) throws RuntimeException {
try {
DingTalkClient client = new DefaultDingTalkClient("https://oapi.dingtalk.com/call_back/get_call_back");
OapiCallBackGetCallBackRequest request = new OapiCallBackGetCallBackRequest();
request.setHttpMethod("GET");
OapiCallBackGetCallBackResponse response = client.execute(request,AccessTokenUtil.getToken(appKey,appSecret));
if(!callBackUrl.equals(response.getUrl())){
client = new DefaultDingTalkClient(URLConstant.REGISTER_CALLBACK);
OapiCallBackRegisterCallBackRequest registerRequest = new OapiCallBackRegisterCallBackRequest();
registerRequest.setUrl(callBackUrl);
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(appKey,appSecret));
if (registerResponse.isSuccess()) {
logger.debug("注册回调成功了!");
}
}
} catch (ApiException e) {
e.printStackTrace();
}
}
注意:
在正式环境中,不能保留删除回调那一部分代码,如果保留的话,会造成回调部分失效。发起A流程之后,回调地址是A的回调地址,之后再发起B流程,回调地址是B流程的,如果在发起B流程的时候删除所有回调,那么A流程回调就会失效,大家要注意。大家也可以在接口注册回调之后进行记录,再一次发起该流程时进行判断是否已经注册,避免重复注册(或者保留所有的注册接口,即删除删除回调部分的代码)。
下载工具
启动工具,执行命令“
./ding -config=./ding.cfg -subdomain=域名前缀 端口
”,以mac为例:
2.启动完客户端后,你访问http://abcde.vaiwan.com/xxxxx都会映射到 http://127.0.0.1:8080/xxxxx。
注意:
1.你需要访问的域名是http://abcde.vaiwan.com/xxxxx 而不是http://abcde.vaiwan.com:8080/xxxxx
2.你启动命令的subdomain参数有可能被别人占用,尽量不要用常用字符,可以用自己公司名的拼音,例如:alibaba、dingding等。
3.可以在本地起个http-server服务,放置一个index.html文件,然后访问http://abcde.vaiwan.com/index.html测试一下。
启动成功后 不要关闭
审批流程代码 可忽略
private static final String CHECK_URL = "check_url";
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";
@RequestMapping(value = "/ddCallBack", method = RequestMethod.POST)
@ResponseBody
public Map<String, String> dingCallBack(@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) {
try {
String corpId = systemConfigServiceImpl.dynamicGetSystemConfigValueByCode("corpid");
String appKey = systemConfigServiceImpl.dynamicGetSystemConfigValueByCode("appKey");
String appSecret = systemConfigServiceImpl.dynamicGetSystemConfigValueByCode("appSecret");
if(corpId == null || corpId.equals("") || appKey ==null || appKey.equals("") || appSecret == null || appSecret.equals("")){
logger.debug("回调接口[editContractCallBack]---corpId:"+corpId+",appKey:"+appKey+",appSecret:"+appSecret);
return null;
}
DingTalkEncryptor dingTalkEncryptor = new DingTalkEncryptor(Constant.TOKEN, Constant.ENCODING_AES_KEY,corpId);
String encryptMsg = json.getString("encrypt");
String plainText = dingTalkEncryptor.getDecryptMsg(signature, timestamp, nonce, encryptMsg);
JSONObject obj = JSON.parseObject(plainText);
String eventType = obj.getString("EventType");
String processInstanceId = obj.getString("processInstanceId");
InstanceDetail instanceDetail = instanceIsFinish(processInstanceId,appKey,appSecret);
if(instanceDetail != null){
/**
* 这是框架协议的回调
*/
FrameTreaty queryFrametreaty = new FrameTreaty();
queryFrametreaty.setDdInstanceId(processInstanceId);
List<FrameTreaty> frametreatyList = frameTreatyServiceImpl.query(queryFrametreaty);
if(!frametreatyList.isEmpty()) {
FrameTreaty frametreaty = frametreatyList.get(0);
if((frametreatyList.get(0).getStatus() == FrameTreatyStatusEnum.BE_REVIEWED.getCode()
|| frametreatyList.get(0).getStatus() == FrameTreatyStatusEnum.UNDER_REVISION.getCode())){
return createFrameTreatyCallBack(instanceDetail,processInstanceId,eventType,obj,dingTalkEncryptor,frametreaty);
}
}
Contract contract = new Contract();
contract.setDdInstanceId(processInstanceId);
List<Contract> contractList = contractServiceImpl.query(contract);
/**
* 这是合同回调
*/
if(!contractList.isEmpty()) {
Contract record = contractList.get(0);
if(record.getStatus() == ContractEnum.EDIT_AUDITING.getCode()){
return edit(instanceDetail,processInstanceId,eventType,obj,dingTalkEncryptor,record);
} else if(record.getStatus() == ContractEnum.LEGAL_AUDITING.getCode()){
return createLegalContract(instanceDetail,processInstanceId,eventType,obj,dingTalkEncryptor,record);
} else if(record.getStatus() == ContractEnum.LEGAL_PROCESS_INVALIDING.getCode()){
return cancelLegalContractCallBack(instanceDetail,processInstanceId,eventType,obj,dingTalkEncryptor,record);
} else if(record.getStatus() == ContractEnum.ORDER_DISASSOCIATE.getCode()){
return cancelAssociatedOrderCallBack(instanceDetail,processInstanceId,eventType,obj,dingTalkEncryptor,record);
}
}
InvoiceRecord invoiceRecord = new InvoiceRecord();
invoiceRecord.setDdInstanceId(processInstanceId);
List<InvoiceRecord> recordList = invoiceRecordServiceImpl.query(invoiceRecord);
//当框架协议和合同都为空的时候就走发票回调
if(!recordList.isEmpty()){
/**
* 这是发票回调
*/
return createInvoiceCallBack(instanceDetail,processInstanceId,eventType,obj,dingTalkEncryptor);
}
}
return dingTalkEncryptor.getEncryptedMap(CALLBACK_RESPONSE_SUCCESS, System.currentTimeMillis(), Utils.getRandomStr(8));
} catch (Exception e) {
logger.debug("回调接口异常:", e);
return null;
}
}
/**
* 框架协议回调函数:通过就正常、不通过就是审核拒绝
* @param instanceDetail 流程详情
* @param processInstanceId 流程实例ID
* @param eventType 事件类型
* @param obj 整个对象
* @param dingTalkEncryptor 返回给钉钉数据
* @param frametreaty 自己的对象
* @return
* @throws DingTalkEncryptException
*/
private Map<String, String> createFrameTreatyCallBack(InstanceDetail instanceDetail, String processInstanceId,
String eventType, JSONObject obj, DingTalkEncryptor dingTalkEncryptor, FrameTreaty frametreaty) throws DingTalkEncryptException {
logger.debug("进入框架协议回调函数,操作事件:",eventType );
FrameTreaty instance = new FrameTreaty();
//拒绝(result)、同意(agree)、-- 这俩种情况对应BPMS_TASK_CHANGE 事件 结束保证节点(finish)
if (BPMS_TASK_CHANGE.equals(eventType)) {
//COMPLETED : 代表结束
if("COMPLETED".equals(instanceDetail.getProcess_instance().getStatus())) {
//流程同意
if (obj.containsKey("result") && obj.getString("result").equals("agree") && obj.containsKey("type") && obj.getString("type").equals("finish")) {
instance.setStatus(FrameTreatyStatusEnum.NORMAL.getCode());//同意状态改为正常
instance.setFrameTreatyId(frametreaty.getFrameTreatyId());
instance.setDdInstanceId("");
instance.setComment("");
//进行更新
boolean b = frameTreatyServiceImpl.updateFrameTreatyInfoUntilCallBack(instance);
logger.debug("进入框架协议回调函数,同意操作,更新是否成功",String.valueOf(b));
}
//将数据更新
}
//如果流程拒绝就将数据状态改为审核拒绝
if(obj.containsKey("result") && obj.getString("result").equals("refuse") && obj.containsKey("type") && obj.getString("type").equals("finish")){
instance.setFrameTreatyId(frametreaty.getFrameTreatyId());
instance.setStatus(FrameTreatyStatusEnum.AUDIT_REJECTION.getCode());//拒绝状态改为审核拒绝
instance.setDdInstanceId("");
instance.setComment("");
//进行更新
boolean b = frameTreatyServiceImpl.updateFrameTreatyInfoUntilCallBack(instance);
logger.debug("进入框架协议回调函数,拒绝操作,更新是否成功",String.valueOf(b));
}
}
//撤销(terminate)-- 这俩种情况对应 BPMS_TASK_CHANGE 事件 结束保证节点(finish)
if(BPMS_INSTANCE_CHANGE.equals(eventType)){
if(obj.containsKey("type") && obj.getString("type").equals("terminate")){
instance.setFrameTreatyId(frametreaty.getFrameTreatyId());
//如果流程撤销就将数据还原到以前状态
instance = new Gson().fromJson(frametreaty.getComment(),FrameTreaty.class);
//进行更新
boolean b = frameTreatyServiceImpl.updateFrameTreatyInfoUntilCallBack(instance);
logger.debug("进入框架协议回调函数撤回绝操作,更新是否成功",String.valueOf(b));
}
}
return dingTalkEncryptor.getEncryptedMap(CALLBACK_RESPONSE_SUCCESS, System.currentTimeMillis(), Utils.getRandomStr(8));
}
public Map<String, String> edit(InstanceDetail instanceDetail,String processInstanceId,String eventType,JSONObject obj,DingTalkEncryptor dingTalkEncryptor,Contract record) throws DingTalkEncryptException {
ApprovalProcessLog log = new ApprovalProcessLog();
log.setDdInstanceId(processInstanceId);
log.setType(ApprovalProcessLogTypeEnum.EDIT_AUDIT.getCode());
List<ApprovalProcessLog> logList = approvalProcessLogServiceImpl.query(log);
Contract instance = new Contract();
ApprovalProcessLog approvalProcessLog = new ApprovalProcessLog();
if (BPMS_TASK_CHANGE.equals(eventType)) {
if("COMPLETED".equals(instanceDetail.getProcess_instance().getStatus())) {
if (obj.containsKey("result") && obj.getString("result").equals("agree") && obj.containsKey("type") && obj.getString("type").equals("finish")) {
instance.setDdInstanceId("");
instance.setId(record.getId());
instance.setBackInfo("");
approvalProcessLog.setType(ApprovalProcessLogTypeEnum.EDIT_AUDIT.getCode());
approvalProcessLog.setResult(AuditResultEnum.AUDIT_PASS.getCode());
approvalProcessLog.setContractId(record.getId());
approvalProcessLog.setCreateTime(new Date());
if (!logList.isEmpty()) {
approvalProcessLog.setCreateUser(logList.get(0).getCreateUser());
} else {
approvalProcessLog.setCreateUser("发起钉钉记录为空!");
}
approvalProcessLog.setDdInstanceId(processInstanceId);
boolean b = contractServiceImpl.updateContractInfoUntilCallBack(instance, ServiceTypeEnum.EDIT_CONTRACT.getCode(), approvalProcessLog,null);
}
}
if(obj.containsKey("result") && obj.getString("result").equals("refuse") && obj.containsKey("type") && obj.getString("type").equals("finish")){
instance = new Gson().fromJson(record.getBackInfo(),Contract.class);
approvalProcessLog.setType(ApprovalProcessLogTypeEnum.EDIT_AUDIT.getCode());
approvalProcessLog.setResult(AuditResultEnum.AUDIT_CANCEL.getCode());
approvalProcessLog.setContractId(record.getId());
approvalProcessLog.setCreateTime(new Date());
if(!logList.isEmpty()){
approvalProcessLog.setCreateUser(logList.get(0).getCreateUser());
}else{
approvalProcessLog.setCreateUser("发起钉钉记录为空!");
}
approvalProcessLog.setDdInstanceId(processInstanceId);
boolean b = contractServiceImpl.updateContractInfoUntilCallBack(instance, ServiceTypeEnum.EDIT_CONTRACT.getCode(),approvalProcessLog,null);
}
}
if(BPMS_INSTANCE_CHANGE.equals(eventType)){
if(obj.containsKey("type") && obj.getString("type").equals("terminate")){
instance = new Gson().fromJson(record.getBackInfo(),Contract.class);
approvalProcessLog.setType(ApprovalProcessLogTypeEnum.EDIT_AUDIT.getCode());
approvalProcessLog.setResult(AuditResultEnum.BACKOUT.getCode());
approvalProcessLog.setContractId(record.getId());
approvalProcessLog.setCreateTime(new Date());
if(!logList.isEmpty()){
approvalProcessLog.setCreateUser(logList.get(0).getCreateUser());
}else{
approvalProcessLog.setCreateUser("发起钉钉记录为空!");
}
approvalProcessLog.setDdInstanceId(processInstanceId);
boolean b = contractServiceImpl.updateContractInfoUntilCallBack(instance, ServiceTypeEnum.EDIT_CONTRACT.getCode(),approvalProcessLog,null);
}
}
return dingTalkEncryptor.getEncryptedMap(CALLBACK_RESPONSE_SUCCESS, System.currentTimeMillis(), Utils.getRandomStr(8));
}
public Map<String, String> createLegalContract(InstanceDetail instanceDetail,String processInstanceId,String eventType,JSONObject obj,DingTalkEncryptor dingTalkEncryptor,Contract record) throws DingTalkEncryptException {
ApprovalProcessLog log = new ApprovalProcessLog();
log.setDdInstanceId(processInstanceId);
log.setType(ApprovalProcessLogTypeEnum.LEGAL_AUDIT.getCode());
List<ApprovalProcessLog> logList = approvalProcessLogServiceImpl.query(log);
Contract instance = new Contract();
ApprovalProcessLog approvalProcessLog = new ApprovalProcessLog();
if (BPMS_TASK_CHANGE.equals(eventType)) {
if("COMPLETED".equals(instanceDetail.getProcess_instance().getStatus())) {
if (obj.containsKey("result") && obj.getString("result").equals("agree") && obj.containsKey("type") && obj.getString("type").equals("finish")) {
instance.setDdInstanceId("");
instance.setBackInfo("");
instance.setId(record.getId());
approvalProcessLog.setType(ApprovalProcessLogTypeEnum.LEGAL_AUDIT.getCode());
approvalProcessLog.setResult(AuditResultEnum.AUDIT_PASS.getCode());
approvalProcessLog.setContractId(record.getId());
approvalProcessLog.setCreateTime(new Date());
if (!logList.isEmpty()) {
approvalProcessLog.setCreateUser(logList.get(0).getCreateUser());
} else {
approvalProcessLog.setCreateUser("发起钉钉记录为空!");
}
approvalProcessLog.setDdInstanceId(processInstanceId);
boolean b = contractServiceImpl.updateContractInfoUntilCallBack(instance, ServiceTypeEnum.CREATE_LEGAL_CONTRACT.getCode(), approvalProcessLog,null);
}
}
if(obj.containsKey("result") && obj.getString("result").equals("refuse") && obj.containsKey("type") && obj.getString("type").equals("finish")){
instance = new Gson().fromJson(record.getBackInfo(),Contract.class);
approvalProcessLog.setType(ApprovalProcessLogTypeEnum.LEGAL_AUDIT.getCode());
approvalProcessLog.setResult(AuditResultEnum.AUDIT_CANCEL.getCode());
approvalProcessLog.setContractId(record.getId());
approvalProcessLog.setCreateTime(new Date());
if(!logList.isEmpty()){
approvalProcessLog.setCreateUser(logList.get(0).getCreateUser());
}else{
approvalProcessLog.setCreateUser("发起钉钉记录为空!");
}
approvalProcessLog.setDdInstanceId(processInstanceId);
boolean b = contractServiceImpl.updateContractInfoUntilCallBack(instance, ServiceTypeEnum.CREATE_LEGAL_CONTRACT.getCode(),approvalProcessLog,null);
}
}
if(BPMS_INSTANCE_CHANGE.equals(eventType)) {
if (obj.containsKey("type") && obj.getString("type").equals("terminate")) {
instance = new Gson().fromJson(record.getBackInfo(),Contract.class);
approvalProcessLog.setType(ApprovalProcessLogTypeEnum.LEGAL_AUDIT.getCode());
approvalProcessLog.setResult(AuditResultEnum.BACKOUT.getCode());
approvalProcessLog.setContractId(record.getId());
approvalProcessLog.setCreateTime(new Date());
if(!logList.isEmpty()){
approvalProcessLog.setCreateUser(logList.get(0).getCreateUser());
}else{
approvalProcessLog.setCreateUser("发起钉钉记录为空!");
}
approvalProcessLog.setDdInstanceId(processInstanceId);
boolean b = contractServiceImpl.updateContractInfoUntilCallBack(instance, ServiceTypeEnum.CREATE_LEGAL_CONTRACT.getCode(),approvalProcessLog,null);
}
}
return dingTalkEncryptor.getEncryptedMap(CALLBACK_RESPONSE_SUCCESS, System.currentTimeMillis(), Utils.getRandomStr(8));
}
public Map<String, String> cancelLegalContractCallBack(InstanceDetail instanceDetail,String processInstanceId,String eventType,JSONObject obj,DingTalkEncryptor dingTalkEncryptor,Contract record) throws DingTalkEncryptException {
ApprovalProcessLog log = new ApprovalProcessLog();
log.setDdInstanceId(processInstanceId);
log.setType(ApprovalProcessLogTypeEnum.LEGAL_INSTANCE_INVOICING.getCode());
List<ApprovalProcessLog> logList = approvalProcessLogServiceImpl.query(log);
Contract instance = new Contract();
ApprovalProcessLog approvalProcessLog = new ApprovalProcessLog();
if (BPMS_TASK_CHANGE.equals(eventType)) {
if("COMPLETED".equals(instanceDetail.getProcess_instance().getStatus())) {
if (obj.containsKey("result") && obj.getString("result").equals("agree") && obj.containsKey("type") && obj.getString("type").equals("finish")) {
LegalContract legalContract = new LegalContract();
legalContract.setBackInfo("");
legalContract.setId(record.getLegalContractId());
instance.setDdInstanceId("");
instance.setBackInfo("");
instance.setId(record.getId());
instance.setLegalContractId(0);
approvalProcessLog.setType(ApprovalProcessLogTypeEnum.LEGAL_INSTANCE_INVOICING.getCode());
approvalProcessLog.setResult(AuditResultEnum.AUDIT_PASS.getCode());
approvalProcessLog.setContractId(record.getId());
approvalProcessLog.setCreateTime(new Date());
if (!logList.isEmpty()) {
approvalProcessLog.setCreateUser(logList.get(0).getCreateUser());
} else {
approvalProcessLog.setCreateUser("发起钉钉记录为空!");
}
approvalProcessLog.setDdInstanceId(processInstanceId);
boolean b = contractServiceImpl.updateContractInfoUntilCallBack(instance, ServiceTypeEnum.CANCEL_LEGAL_CONTRACT.getCode(), approvalProcessLog,legalContract);
}
}
if(obj.containsKey("result") && obj.getString("result").equals("refuse") && obj.containsKey("type") && obj.getString("type").equals("finish")){
LegalContract legalContract = legalContractServiceImpl.queryLegalContractById(record.getLegalContractId());
legalContract = new Gson().fromJson(legalContract.getBackInfo(),LegalContract.class);
legalContract.setBackInfo("");
instance = new Gson().fromJson(record.getBackInfo(),Contract.class);
approvalProcessLog.setType(ApprovalProcessLogTypeEnum.LEGAL_INSTANCE_INVOICING.getCode());
approvalProcessLog.setResult(AuditResultEnum.AUDIT_CANCEL.getCode());
approvalProcessLog.setContractId(record.getId());
approvalProcessLog.setCreateTime(new Date());
if(!logList.isEmpty()){
approvalProcessLog.setCreateUser(logList.get(0).getCreateUser());
}else{
approvalProcessLog.setCreateUser("发起钉钉记录为空!");
}
approvalProcessLog.setDdInstanceId(processInstanceId);
boolean b = contractServiceImpl.updateContractInfoUntilCallBack(instance, ServiceTypeEnum.CANCEL_LEGAL_CONTRACT.getCode(),approvalProcessLog,legalContract);
}
}
if(BPMS_INSTANCE_CHANGE.equals(eventType)) {
if (obj.containsKey("type") && obj.getString("type").equals("terminate")) {
LegalContract legalContract = legalContractServiceImpl.queryLegalContractById(record.getLegalContractId());
legalContract = new Gson().fromJson(legalContract.getBackInfo(),LegalContract.class);
legalContract.setBackInfo("");
instance = new Gson().fromJson(record.getBackInfo(),Contract.class);
approvalProcessLog.setType(ApprovalProcessLogTypeEnum.LEGAL_INSTANCE_INVOICING.getCode());
approvalProcessLog.setResult(AuditResultEnum.BACKOUT.getCode());
approvalProcessLog.setContractId(record.getId());
approvalProcessLog.setCreateTime(new Date());
if(!logList.isEmpty()){
approvalProcessLog.setCreateUser(logList.get(0).getCreateUser());
}else{
approvalProcessLog.setCreateUser("发起钉钉记录为空!");
}
approvalProcessLog.setDdInstanceId(processInstanceId);
boolean b = contractServiceImpl.updateContractInfoUntilCallBack(instance, ServiceTypeEnum.CANCEL_LEGAL_CONTRACT.getCode(),approvalProcessLog,legalContract);
}
}
return dingTalkEncryptor.getEncryptedMap(CALLBACK_RESPONSE_SUCCESS, System.currentTimeMillis(), Utils.getRandomStr(8));
}
public Map<String, String> cancelAssociatedOrderCallBack(InstanceDetail instanceDetail,String processInstanceId,String eventType,JSONObject obj,DingTalkEncryptor dingTalkEncryptor,Contract record) throws DingTalkEncryptException {
ApprovalProcessLog log = new ApprovalProcessLog();
log.setDdInstanceId(processInstanceId);
log.setType(ApprovalProcessLogTypeEnum.ORDER_DISASSOCIATE.getCode());
List<ApprovalProcessLog> logList = approvalProcessLogServiceImpl.query(log);
Contract instance = new Contract();
ApprovalProcessLog approvalProcessLog = new ApprovalProcessLog();
if (BPMS_TASK_CHANGE.equals(eventType)) {
if("COMPLETED".equals(instanceDetail.getProcess_instance().getStatus())) {
if (obj.containsKey("result") && obj.getString("result").equals("agree") && obj.containsKey("type") && obj.getString("type").equals("finish")) {
instance.setDdInstanceId("");
instance.setBackInfo("");
instance.setCancelAssociatedOrderArray("");
instance.setStatus(ContractEnum.NORMAL.getCode());
instance.setId(record.getId());
approvalProcessLog.setType(ApprovalProcessLogTypeEnum.ORDER_DISASSOCIATE.getCode());
approvalProcessLog.setResult(AuditResultEnum.AUDIT_PASS.getCode());
approvalProcessLog.setContractId(record.getId());
approvalProcessLog.setCreateTime(new Date());
if (!logList.isEmpty()) {
approvalProcessLog.setCreateUser(logList.get(0).getCreateUser());
} else {
approvalProcessLog.setCreateUser("发起钉钉记录为空!");
}
approvalProcessLog.setDdInstanceId(processInstanceId);
boolean b = contractServiceImpl.updateContractInfoUntilCallBack(instance, ServiceTypeEnum.CANCEL_ASSOCIATE_ORDER.getCode(), approvalProcessLog,null);
}
}
if(obj.containsKey("result") && obj.getString("result").equals("refuse") && obj.containsKey("type") && obj.getString("type").equals("finish")){
instance = new Gson().fromJson(record.getBackInfo(),Contract.class);
approvalProcessLog.setType(ApprovalProcessLogTypeEnum.ORDER_DISASSOCIATE.getCode());
approvalProcessLog.setResult(AuditResultEnum.AUDIT_CANCEL.getCode());
approvalProcessLog.setContractId(record.getId());
approvalProcessLog.setCreateTime(new Date());
if(!logList.isEmpty()){
approvalProcessLog.setCreateUser(logList.get(0).getCreateUser());
}else{
approvalProcessLog.setCreateUser("发起钉钉记录为空!");
}
approvalProcessLog.setDdInstanceId(processInstanceId);
boolean b = contractServiceImpl.updateContractInfoUntilCallBack(instance, ServiceTypeEnum.CANCEL_ASSOCIATE_ORDER.getCode(),approvalProcessLog,null);
}
}
if(BPMS_INSTANCE_CHANGE.equals(eventType)) {
if (obj.containsKey("type") && obj.getString("type").equals("terminate")) {
instance = new Gson().fromJson(record.getBackInfo(),Contract.class);
approvalProcessLog.setType(ApprovalProcessLogTypeEnum.ORDER_DISASSOCIATE.getCode());
approvalProcessLog.setResult(AuditResultEnum.BACKOUT.getCode());
approvalProcessLog.setContractId(record.getId());
approvalProcessLog.setCreateTime(new Date());
if(!logList.isEmpty()){
approvalProcessLog.setCreateUser(logList.get(0).getCreateUser());
}else{
approvalProcessLog.setCreateUser("发起钉钉记录为空!");
}
approvalProcessLog.setDdInstanceId(processInstanceId);
boolean b = contractServiceImpl.updateContractInfoUntilCallBack(instance, ServiceTypeEnum.CANCEL_ASSOCIATE_ORDER.getCode(),approvalProcessLog,null);
}
}
return dingTalkEncryptor.getEncryptedMap(CALLBACK_RESPONSE_SUCCESS, System.currentTimeMillis(), Utils.getRandomStr(8));
}
public Map<String, String> createInvoiceCallBack(InstanceDetail instanceDetail,String processInstanceId,String eventType,JSONObject obj,DingTalkEncryptor dingTalkEncryptor) throws DingTalkEncryptException {
InvoiceRecord invoiceRecord = new InvoiceRecord();
invoiceRecord.setDdInstanceId(processInstanceId);
List<InvoiceRecord> recordList = invoiceRecordServiceImpl.query(invoiceRecord);
ApprovalProcessLog log = new ApprovalProcessLog();
log.setDdInstanceId(processInstanceId);
log.setType(ApprovalProcessLogTypeEnum.CREATE_INVOICE_RECORD.getCode());
List<ApprovalProcessLog> logList = approvalProcessLogServiceImpl.query(log);
ApprovalProcessLog approvalProcessLog = new ApprovalProcessLog();
InvoiceRecord record = new InvoiceRecord();
if (BPMS_TASK_CHANGE.equals(eventType)) {
if("COMPLETED".equals(instanceDetail.getProcess_instance().getStatus())) {
if (obj.containsKey("result") && obj.getString("result").equals("agree") && obj.containsKey("type") && obj.getString("type").equals("finish")) {
approvalProcessLog.setType(ApprovalProcessLogTypeEnum.CREATE_INVOICE_RECORD.getCode());
approvalProcessLog.setResult(AuditResultEnum.AUDIT_PASS.getCode());
approvalProcessLog.setContractId(recordList.get(0).getContractId());
approvalProcessLog.setCreateTime(new Date());
if (!logList.isEmpty()) {
approvalProcessLog.setCreateUser(logList.get(0).getCreateUser());
} else {
approvalProcessLog.setCreateUser("发起钉钉记录为空!");
}
approvalProcessLog.setDdInstanceId(processInstanceId);
record.setDdInstanceId("");
record.setStatus(InvoiceStatusEnum.AUDIT_PASS.getCode());
record.setId(recordList.get(0).getId());
record.setSuccessTime(new Date());
boolean b = invoiceRecordServiceImpl.updateInvoiceStatusUntilCallBack(record, approvalProcessLog);
}
}
if(obj.containsKey("result") && obj.getString("result").equals("refuse") && obj.containsKey("type") && obj.getString("type").equals("finish")){
approvalProcessLog.setType(ApprovalProcessLogTypeEnum.CREATE_INVOICE_RECORD.getCode());
approvalProcessLog.setResult(AuditResultEnum.AUDIT_CANCEL.getCode());
approvalProcessLog.setContractId(recordList.get(0).getContractId());
approvalProcessLog.setCreateTime(new Date());
if(!logList.isEmpty()){
approvalProcessLog.setCreateUser(logList.get(0).getCreateUser());
}else{
approvalProcessLog.setCreateUser("发起钉钉记录为空!");
}
approvalProcessLog.setDdInstanceId(processInstanceId);
record.setDdInstanceId("");
record.setStatus(InvoiceStatusEnum.AUDIT_REFUSE.getCode());
record.setId(recordList.get(0).getId());
boolean b = invoiceRecordServiceImpl.updateInvoiceStatusUntilCallBack(record, approvalProcessLog);
}
}
if(BPMS_INSTANCE_CHANGE.equals(eventType)) {
if (obj.containsKey("type") && obj.getString("type").equals("terminate")) {
approvalProcessLog.setType(ApprovalProcessLogTypeEnum.CREATE_INVOICE_RECORD.getCode());
approvalProcessLog.setResult(AuditResultEnum.BACKOUT.getCode());
approvalProcessLog.setContractId(recordList.get(0).getContractId());
approvalProcessLog.setCreateTime(new Date());
if(!logList.isEmpty()){
approvalProcessLog.setCreateUser(logList.get(0).getCreateUser());
}else{
approvalProcessLog.setCreateUser("发起钉钉记录为空!");
}
approvalProcessLog.setDdInstanceId(processInstanceId);
record.setDdInstanceId("");
record.setStatus(InvoiceStatusEnum.AUDIT_BACK.getCode());
record.setId(recordList.get(0).getId());
boolean b = invoiceRecordServiceImpl.updateInvoiceStatusUntilCallBack(record, approvalProcessLog);
}
}
return dingTalkEncryptor.getEncryptedMap(CALLBACK_RESPONSE_SUCCESS, System.currentTimeMillis(), Utils.getRandomStr(8));
}
public static InstanceDetail instanceIsFinish(String ddInstanceId,String appKey,String appSecret) throws ApiException {
DingTalkClient client = new DefaultDingTalkClient(URLConstant.URL_PROCESSINSTANCE_GET);
OapiProcessinstanceGetRequest request = new OapiProcessinstanceGetRequest();
request.setProcessInstanceId(ddInstanceId);
OapiProcessinstanceGetResponse response = client.execute(request, AccessTokenUtil.getToken(appKey,appSecret));
System.out.println(response.getBody());
InstanceDetail instanceDetail = new Gson().fromJson(response.getBody(),InstanceDetail.class);
return instanceDetail;
}
}
bpms_task_change
:如果你发起的审批通过和拒绝,返回的事件类型是这个。
bpms_instance_change
:如果你发起的审批撤销了,返回的事件类型是这个。
我们如果有多个审批人,只要通过一个,他都会进回调,我们这里只关心结果,所以前边不管通过了几个,都不能去操作数据库,更改审批的状态。可是它这个接口我找了半天,返回值中没法去判断是不是最终的审批用户,怎么办呢?先去通过钉钉实例的id获取这个实例的详情,详情里边有状态,通过详情中的状态才能判断这个流程有没有结束,再去操作数据库。