钉钉API-处理业务审批流程 回调爬坑记录

API钉钉接入—审批流程


最近由于业务需求需要在项目中介入钉钉审批流程,虽然不是第一次接触钉钉api,但是之前使用是借助同事的配置(爬坑经验借鉴同事的 :简书 少年丶要淡定 ),一直没有比较系统的去了解使用,正好借助这次需求的机会,去深入了解一下,记录一下爬坑经验,难免以后会再次使用到。


文章目录

    • API钉钉接入—审批流程
        • 首先是 需要使用的外部资源:
          • 钉钉开放平台
          • 钉钉官方demo
        • 项目使用源码
          • 钉钉配置
          • 项目介入使用
            • 钉钉url调用
            • 获取钉钉企业中的用户手机号:
            • 发起钉钉所用到的token
            • 发送请求
          • 发起钉钉审批
          • 回调路径
          • 注入回调
          • 内外网穿透工具
            • 启动内网穿透
        • 遇到的坑


首先是 需要使用的外部资源:

钉钉开放平台

使用钉钉开发官方工作流 钉钉开发文档

事件回调
回调是开发者在钉钉开放平台注册一个HTTP接口,并订阅相关的事件,当事件发生时,钉钉会主动调用开发者注册的HTTP接口,推送对应的事件信息。

内外网穿透工具:内外网穿透工具;
提供了一个公网代理服务,目的是方便开发测试。
钉钉API-处理业务审批流程 回调爬坑记录_第1张图片

钉钉官方demo

参考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;

以上每个参数的查看方式,请前往钉钉开发文档中查看

项目介入使用
钉钉url调用
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;
    }
发起钉钉所用到的token
    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获取这个实例的详情,详情里边有状态,通过详情中的状态才能判断这个流程有没有结束,再去操作数据库。

你可能感兴趣的:(java,钉钉api)