Просмотр исходного кода

Merge remote-tracking branch 'origin/develop-test' into develop-test

shenjingwei 1 неделя назад
Родитель
Сommit
f6e43eefa9

+ 5 - 0
src/custom/restcontroller/R.java

@@ -7722,6 +7722,11 @@ public class R {
         public static class v1 {
         }
     }
+
+    public static class ID2026041516335302 {
+        public static class v1 {
+        }
+    }
 }
 
 

+ 29 - 0
src/custom/restcontroller/webmanage/sale/contracttask/EsignContractTask.java

@@ -2,6 +2,7 @@ package restcontroller.webmanage.sale.contracttask;
 
 import beans.datacontrllog.DataContrlLog;
 import com.alibaba.fastjson2.JSONObject;
+import com.tencentcloudapi.essbasic.v20210526.models.ChannelCancelFlowResponse;
 import common.Controller;
 import common.YosException;
 import common.annotation.API;
@@ -117,6 +118,21 @@ public class EsignContractTask extends Controller {
             return getErrReturnObject().setErrMsg("当前任务已发布,无需重新发布").toString();
         }
 
+        Rows rows1 = dbConnect.runSqlQuery("SELECT * from sa_esign_contract_taskmx WHERE sa_esign_contract_taskid=" + sa_esign_contract_taskid + " and (begindate is null or enddate is null)");
+        if (rows1.isNotEmpty()) {
+            return getErrReturnObject().setErrMsg("请完善合同期限").toString();
+        }
+        Rows rows2 = dbConnect.runSqlQuery("SELECT * from sa_esign_contract_taskmx WHERE sa_esign_contract_taskid=" + sa_esign_contract_taskid);
+        for (Row row : rows2) {
+            Long sys_enterpriseid = row.getLong("sys_enterpriseid");
+            Long year = rows.get(0).getLong("year");
+            Rows targetRows = dbConnect.runSqlQuery("SELECT * from sa_salestarget WHERE year=" + year + " and sys_enterpriseid='" + sys_enterpriseid + "' and type='季'");
+            if (targetRows.isEmpty()) {
+                return getErrReturnObject().setErrMsg("请完善经销商任务值").toString();
+            }
+        }
+
+
         UpdateSQL updateSQL = SQLFactory.createUpdateSQL(this, "sa_esign_contract_task");
         updateSQL.setSiteid(siteid);
         updateSQL.setUniqueid(sa_esign_contract_taskid);
@@ -150,6 +166,19 @@ public class EsignContractTask extends Controller {
 
         DataContrlLog.createLog(this, "sa_esign_contract_task", sa_esign_contract_taskid, "撤回", "撤回合同任务成功").insert();
 
+        Rows taskmxRows = dbConnect.runSqlQuery("select * from sa_esign_contract_taskmx where sa_esign_contract_taskid=" + sa_esign_contract_taskid + " and approvestatus='待签署'");
+        for (Row taskmxRow : taskmxRows) {
+            String flowid = taskmxRow.getString("flowid");
+            WeChatContractUtil.channelCancelFlow(WeChatContractUtil.setAgent(WeChatConfig.SuperProxyOperatorOpenId), flowid, "合同任务已撤回", 1L);
+//            UpdateSQL updateSQL1 = SQLFactory.createUpdateSQL(this, "sa_esign_contract_taskmx");
+//            updateSQL1.setSiteid(siteid);
+//            updateSQL1.setUniqueid(taskmxRow.getLong("sa_esign_contract_taskmxid"));
+//            updateSQL1.setValue("status", "合同撤回");
+//            updateSQL1.setValue("approvestatus", "流程已终止");
+//            updateSQL1.update();
+        }
+
+
         return detail();
     }
 

+ 145 - 3
src/custom/restcontroller/webmanage/sale/contracttask/EsignContractTaskMX.java

@@ -3,15 +3,25 @@ package restcontroller.webmanage.sale.contracttask;
 import beans.datacontrllog.DataContrlLog;
 import com.alibaba.fastjson2.JSONArray;
 import com.alibaba.fastjson2.JSONObject;
+import com.tencentcloudapi.essbasic.v20210526.models.CreateConsoleLoginUrlResponse;
+import com.tencentcloudapi.essbasic.v20210526.models.FlowApproverInfo;
+import com.tencentcloudapi.essbasic.v20210526.models.Recipient;
 import common.Controller;
 import common.YosException;
 import common.annotation.API;
 import common.data.*;
+import org.apache.commons.lang.ArrayUtils;
+import org.apache.commons.lang.StringUtils;
 import restcontroller.R;
 
 import java.lang.reflect.Array;
 import java.math.BigDecimal;
 import java.util.ArrayList;
+import java.util.Arrays;
+import java.util.Map;
+
+import static restcontroller.webmanage.sale.contracttask.WeChatConfig.ProxyOrganizationName;
+import static restcontroller.webmanage.sale.contracttask.WeChatConfig.SuperProxyOperatorOpenId;
 
 /**
  * 电子签合同任务明细
@@ -49,6 +59,7 @@ public class EsignContractTaskMX extends Controller {
             insertSQL.setSiteid(siteid);
             insertSQL.setUniqueid(createTableID("sa_esign_contract_taskmx"));
             insertSQL.setValue("sa_agentsid", sa_agentsid);
+            insertSQL.setValue("sys_enterpriseid", agentRow.getLong("sys_enterpriseid"));
             insertSQL.setValue("sa_esign_contract_taskid", sa_esign_contract_taskid);
             insertSQL.setValue("paymans", agentRow.getString("paymans"));
             insertSQL.setValue("aftersalesphonenumber", agentRow.getString("aftersalesphonenumber"));
@@ -176,7 +187,7 @@ public class EsignContractTaskMX extends Controller {
         }
 
         QuerySQL querySQL = SQLFactory.createQuerySQL(this, "sa_esign_contract_taskmx",
-                "sa_esign_contract_taskmxid", "status", "license_address", "phonenumber", "legal_rep", "begindate", "enddate").setTableAlias("t1");
+                "sa_esign_contract_taskmxid", "status", "approvestatus", "license_address", "phonenumber", "legal_rep", "begindate", "enddate", "flowid").setTableAlias("t1");
         querySQL.addJoinTable(JOINTYPE.inner, "sa_agents", "t2", "t1.siteid = t2.siteid and t1.sa_agentsid=t2.sa_agentsid",
                 "sys_enterpriseid", "agentnum");
         querySQL.addJoinTable(JOINTYPE.inner, "sys_enterprise", "t3", "t3.siteid = t2.siteid and t3.sys_enterpriseid = t2.sys_enterpriseid",
@@ -225,20 +236,151 @@ public class EsignContractTaskMX extends Controller {
             row.putIfAbsent("s3", 0);
             row.putIfAbsent("s4", 0);
             row.putIfAbsent("y1", 0);
+            String flowid = row.getString("flowid");
+            if (!StringUtils.isBlank(flowid)) {
+                row.put("downloadurl", WeChatContractUtil.describeFileUrls(flowid));
+            }
+            row.putIfAbsent("downloadurl", "");
         }
 
         return getSucReturnObject().setData(rows).toString();
     }
 
+    @API(title = "电子签合同任务明细-明细详情", apiversion = R.ID2026041516335302.v1.class)
+    public String detail() throws YosException {
+        Long sa_esign_contract_taskmxid = content.getLongValue("sa_esign_contract_taskmxid");
+        QuerySQL querySQL = SQLFactory.createQuerySQL(this, "sa_esign_contract_taskmx", "*").setTableAlias("t1");
+        querySQL.addJoinTable(JOINTYPE.inner, "sa_esign_contract_task", "t2", "t2.sa_esign_contract_taskid=t1.sa_esign_contract_taskid",
+                "taskname", "year", "senddate", "remarks");
+        querySQL.addJoinTable(JOINTYPE.inner, "sa_esign_contract_template", "t3", "t3.sa_esign_contract_templateid=t2.sa_esign_contract_templateid",
+                "name", "type");
+        querySQL.addJoinTable(JOINTYPE.inner, "sa_agents", "t4", "t4.sa_agentsid=t1.sa_agentsid");
+        querySQL.setSiteid(siteid);
+        querySQL.setWhere("t1.sa_esign_contract_taskmxid", sa_esign_contract_taskmxid);
+        Rows rows = querySQL.query();
+
+        for (Row row : rows) {
+            String flowid = row.getString("flowid");
+            if (!StringUtils.isBlank(flowid)) {
+                row.put("downloadurl", WeChatContractUtil.describeFileUrls(flowid));
+            }
+            row.putIfAbsent("downloadurl", "");
+        }
+
+        Row row = rows.isNotEmpty() ? rows.get(0) : new Row();
+
+        return getSucReturnObject().setData(row).toString();
+    }
+
 
     @API(title = "电子签合同任务明细-编辑任务明细", apiversion = R.ID2026041315410702.v1.class)
     public String edit() throws YosException {
-        return getSucReturnObject().toString();
+
+        Long sa_esign_contract_taskmxid = content.getLongValue("sa_esign_contract_taskmxid");
+        Rows rows = dbConnect.runSqlQuery("SELECT * FROM sa_esign_contract_taskmx WHERE sa_esign_contract_taskmxid=" + sa_esign_contract_taskmxid);
+
+        if (rows.isEmpty()) {
+            return getErrReturnObject().setErrMsg("合同不存在").toString();
+        }
+        String status = rows.get(0).getString("status");
+        String[] statuslist = new String[]{"合同创建", "合同签署中", "合同签署完成", "合同即将过期"};
+        if (ArrayUtils.contains(statuslist, status)) {
+            return getErrReturnObject().setErrMsg("当前状态不支持确认合同内容").toString();
+        }
+        Long sa_esign_contract_taskid = rows.get(0).getLong("sa_esign_contract_taskid");
+
+        QuerySQL querySQL = SQLFactory.createQuerySQL(this, "sa_esign_contract_template", "*").setTableAlias("t1");
+        querySQL.addJoinTable(JOINTYPE.left, "sa_esign_contract_task", "t2", "t1.sa_esign_contract_templateid=t2.sa_esign_contract_templateid");
+        querySQL.setWhere("t2.sa_esign_contract_taskid", sa_esign_contract_taskid);
+        Rows templaterows = querySQL.query();
+        if (templaterows.isEmpty()) {
+            return getErrReturnObject().setErrMsg("合同模板不存在").toString();
+        }
+
+        UpdateSQL updateSQL = SQLFactory.createUpdateSQL(this, "sa_esign_contract_taskmx");
+        updateSQL.setSiteid(siteid);
+        updateSQL.setUniqueid(sa_esign_contract_taskmxid);
+        updateSQL.setValue("license_name", content.getStringValue("license_name"));
+        updateSQL.setValue("taxno", content.getStringValue("taxno"));
+        updateSQL.setValue("license_address", content.getStringValue("license_address"));
+        updateSQL.setValue("legal_rep", content.getStringValue("legal_rep"));
+        updateSQL.setValue("mobile", content.getStringValue("mobile"));
+        updateSQL.setValue("phonenumber", content.getStringValue("phonenumber"));
+        updateSQL.setValue("presalesphonenumber", content.getStringValue("presalesphonenumber"));
+        updateSQL.setValue("aftersalesphonenumber", content.getStringValue("aftersalesphonenumber"));
+        updateSQL.setValue("paymans", content.getStringValue("paymans"));
+        updateSQL.update();
+        DataContrlLog.createLog(this, "sa_esign_contract_task", sa_esign_contract_taskid, "合同确认", "合同内容确认成功").insert();
+
+
+        //创建签署流程
+        WeChatContractUtil wccUtil = new WeChatContractUtil();
+        String flowName = templaterows.get(0).getString("name");
+        String templateId = templaterows.get(0).getString("templateid");
+        // 获取模板里面的参与方RecipientId
+        Recipient[] recipients = WeChatByTemplate.GetRecipients(templateId);
+        if (recipients == null) {
+            throw new NullPointerException("签署人不能为空");
+        }
+        //构造签署人信息
+        FlowApproverInfo[] flowApproverInfos = WeChatByTemplate.BuildApprovers(Arrays.asList(recipients));
+
+        // 发起合同 样例为BtoC
+        Map<String, String[]> resp = wccUtil.createFlowByTemplateDirectly(flowName
+                , templateId, flowApproverInfos);
+        int count = WeChatConfig.COUNT;
+        for (int i = 0; i < count; i++) {
+            // 返回合同Id
+            System.out.println("您创建的合同id为:");
+            System.out.println(resp.get("FlowIds")[i]);
+            // 返回签署的链接
+            System.out.println("签署链接为:");
+            System.out.println(resp.get("Urls")[i]);
+            // Step 3 下载合同
+            // 返回合同下载链接
+            String url = WeChatContractUtil.describeFileUrls(resp.get("FlowIds")[i]);
+            System.out.println("请访问以下地址下载您的合同:");
+            System.out.println(url);
+
+            updateSQL = SQLFactory.createUpdateSQL(this, "sa_esign_contract_taskmx");
+            updateSQL.setSiteid(siteid);
+            updateSQL.setUniqueid(sa_esign_contract_taskmxid);
+            updateSQL.setValue("flowid", resp.get("FlowIds")[i]);
+            updateSQL.setValue("signurl", resp.get("Urls")[i]);
+            updateSQL.setValue("status", "合同创建");
+            updateSQL.setValue("approvestatus", "待签署");
+            updateSQL.update();
+        }
+
+
+        return detail();
     }
 
+
     @API(title = "经销商的合同列表", apiversion = R.ID2026041315425102.v1.class)
     public String agentsList() throws YosException {
-        return getSucReturnObject().toString();
+
+
+        QuerySQL querySQL = SQLFactory.createQuerySQL(this, "sa_esign_contract_taskmx", "*").setTableAlias("t1");
+        querySQL.addJoinTable(JOINTYPE.inner, "sa_esign_contract_task", "t2", "t2.sa_esign_contract_taskid=t1.sa_esign_contract_taskid",
+                "taskname", "year", "senddate", "remarks");
+        querySQL.addJoinTable(JOINTYPE.inner, "sa_esign_contract_template", "t3", "t3.sa_esign_contract_templateid=t2.sa_esign_contract_templateid",
+                "name", "type");
+        querySQL.addJoinTable(JOINTYPE.inner, "sa_agents", "t4", "t4.sa_agentsid=t1.sa_agentsid");
+        querySQL.setSiteid(siteid);
+        querySQL.setWhere("t4.sys_enterpriseid", sys_enterpriseid);
+        querySQL.setPage(pageSize, pageNumber);
+        Rows rows = querySQL.query();
+
+        for (Row row : rows) {
+            String flowid = row.getString("flowid");
+            if (!StringUtils.isBlank(flowid)) {
+                row.put("downloadurl", WeChatContractUtil.describeFileUrls(flowid));
+            }
+            row.putIfAbsent("downloadurl", "");
+        }
+
+        return getSucReturnObject().setData(rows).toString();
     }
 
 

+ 112 - 0
src/custom/restcontroller/webmanage/sale/contracttask/WeChatByTemplate.java

@@ -0,0 +1,112 @@
+package restcontroller.webmanage.sale.contracttask;
+
+import com.tencentcloudapi.essbasic.v20210526.models.DescribeTemplatesResponse;
+import com.tencentcloudapi.essbasic.v20210526.models.FlowApproverInfo;
+import com.tencentcloudapi.essbasic.v20210526.models.FormField;
+import com.tencentcloudapi.essbasic.v20210526.models.Recipient;
+
+import java.util.ArrayList;
+import java.util.List;
+import java.util.Optional;
+
+public class WeChatByTemplate {
+    // 构造签署人 - 以B2B2C为例, 实际请根据自己的场景构造签署方、控件
+    public static FlowApproverInfo[] BuildApprovers(List<Recipient> recipients) {
+
+        List<FlowApproverInfo> approvers = new ArrayList<>();
+
+        // 个人签署方参数
+        String personName = "******";
+        String personMobile = "*************";
+
+        // 企业签署方参数
+        String organizationName = WeChatConfig.ProxyOrganizationName;
+        String organizationOpenId = WeChatConfig.ProxyOrganizationOpenId;
+        String openId = WeChatConfig.SuperProxyOperatorOpenId;
+
+        for (Recipient recipient : recipients) {
+            switch (recipient.getRecipientType()) {
+                case "ENTERPRISE":
+                    // 另一家企业签署方
+                    approvers.add(BuildOrganizationApprover(organizationName, organizationOpenId, openId, recipient.getRecipientId()));
+                    break;
+                case "INDIVIDUAL":
+                    // 个人签署方
+                    approvers.add(BuildPersonApprover(personName,personMobile, recipient.getRecipientId()));
+                    break;
+
+            }
+        }
+
+        // 转换为对象数组
+        return approvers.toArray(new FlowApproverInfo[0]);
+    }
+
+    // 打包个人签署方参与者信息
+    public static FlowApproverInfo BuildPersonApprover(String name, String mobile, String recipientId) {
+
+        // 签署参与者信息
+        // 个人签署方
+        FlowApproverInfo flowApproverInfo = new FlowApproverInfo();
+
+        flowApproverInfo.setApproverType("PERSON");
+
+        flowApproverInfo.setName(name);
+
+        flowApproverInfo.setMobile(mobile);
+
+        flowApproverInfo.setRecipientId(recipientId);
+
+        return flowApproverInfo;
+    }
+
+    // 打包企业签署方参与者信息
+    public static FlowApproverInfo BuildOrganizationApprover(String organizationName, String organizationOpenId,
+                                                             String openId, String recipientId) {
+
+        // 签署参与者信息
+        // 企业签署方
+        FlowApproverInfo flowApproverInfo = new FlowApproverInfo();
+
+        flowApproverInfo.setApproverType("ORGANIZATION");
+
+        flowApproverInfo.setOrganizationName(organizationName);
+
+        flowApproverInfo.setOrganizationOpenId(organizationOpenId);
+
+        flowApproverInfo.setOpenId(openId);
+
+        flowApproverInfo.setRecipientId(recipientId);
+
+        return flowApproverInfo;
+    }
+
+    // 打包企业静默签署方参与者信息
+    public static FlowApproverInfo BuildServerSignApprover() {
+        // 签署参与者信息
+        // 企业静默签
+        FlowApproverInfo flowApproverInfo = new FlowApproverInfo();
+
+        flowApproverInfo.setApproverType("ENTERPRISESERVER");
+
+        // 注:此时发起方会替换为接口调用的企业+经办人,所以不需要传签署方信息
+
+        return flowApproverInfo;
+    }
+
+    // 从模板中获取参与人信息,用于模板发起合同
+    public static Recipient[] GetRecipients(String templateId) {
+        DescribeTemplatesResponse templatesResponse = WeChatContractUtil.describeTemplates(WeChatContractUtil.setAgent(WeChatConfig.SuperProxyOperatorOpenId),
+                templateId);
+
+        return  Optional.ofNullable(templatesResponse).filter(template -> template.getTemplates().length > 0).
+                map(DescribeTemplatesResponse::getTemplates).map(rec -> rec[0].getRecipients()).orElse(null);
+    }
+
+    public static FormField BuildFormField(String componentName, String componentValue){
+        FormField formField = new FormField();
+        formField.setComponentName(componentName);
+        formField.setComponentValue(componentValue);
+        return formField;
+    }
+}

+ 312 - 7
src/custom/restcontroller/webmanage/sale/contracttask/WeChatContractUtil.java

@@ -8,8 +8,15 @@ import com.tencentcloudapi.common.profile.ClientProfile;
 import com.tencentcloudapi.common.profile.HttpProfile;
 import com.tencentcloudapi.essbasic.v20210526.EssbasicClient;
 import com.tencentcloudapi.essbasic.v20210526.models.*;
+import com.tencentcloudapi.tke.v20180525.models.Switch;
+import com.tencentcloudapi.tsf.v20180326.models.TerminateTaskFlowBatchRequest;
+import common.YosException;
 import org.apache.commons.codec.digest.DigestUtils;
 
+import java.util.HashMap;
+import java.util.Map;
+
+import static restcontroller.webmanage.sale.contracttask.WeChatByTemplate.BuildFormField;
 import static restcontroller.webmanage.sale.contracttask.WeChatConfig.*;
 
 /**
@@ -20,7 +27,7 @@ public class WeChatContractUtil {
     Credential cred;
     HttpProfile httpProfile;
     ClientProfile clientProfile;
-    EssbasicClient client;
+    static EssbasicClient client;
 
     public WeChatContractUtil() {
         this.cred = new Credential(WeChatConfig.SecretId, WeChatConfig.SecretKey);
@@ -31,11 +38,31 @@ public class WeChatContractUtil {
         this.client = new EssbasicClient(cred, "", clientProfile);
     }
 
-    public Agent getAgent(String ProxyOperatorOpenId) {
+    public static EssbasicClient initClient() {
+        if (client != null) {
+            return client;
+        }
+        // 实例化一个认证对象,入参需要传入腾讯云账户SecretId,SecretKey,此处还需注意密钥对的保密
+        // 密钥可前往https://console.cloud.tencent.com/cam/capi网站进行获取
+        Credential cred = new Credential(WeChatConfig.SecretId, WeChatConfig.SecretKey);
+        // 实例化一个http选项,可选的,没有特殊需求可以跳过
+        HttpProfile httpProfile = new HttpProfile();
+        httpProfile.setEndpoint(WeChatConfig.EndPoint);
+        // 实例化一个client选项,可选的,没有特殊需求可以跳过
+        ClientProfile clientProfile = new ClientProfile();
+        clientProfile.setHttpProfile(httpProfile);
+        // 实例化要请求产品的client对象,clientProfile是可选的
+        client = new EssbasicClient(cred, "", clientProfile);
+        return client;
+    }
+
+    public static Agent setAgent(String ProxyOperatorOpenId) {
         // 构建 Agent 对象
         Agent agent = new Agent();
         agent.setAppId(WeChatConfig.AppId);
+        agent.setProxyAppId(WeChatConfig.ProxyAppId);
         agent.setProxyOrganizationOpenId(ProxyOrganizationOpenId);
+
         UserInfo userInfo = new UserInfo();
         userInfo.setOpenId(ProxyOperatorOpenId);
         agent.setProxyOperator(userInfo);
@@ -44,6 +71,7 @@ public class WeChatContractUtil {
 
     //生成腾讯云电子签控制台登录URL
     public String getUserConsoleUrl(String name, String phonenumber) throws TencentCloudSDKException {
+        EssbasicClient client = initClient();
         //根据姓名和手机号生成唯一的经办人OpenId(SHA256哈希)
         String proxyOperatorOpenId = DigestUtils.sha256Hex(name + phonenumber);
 
@@ -69,6 +97,7 @@ public class WeChatContractUtil {
 
     //查询模板列表
     public DescribeTemplatesResponse getTemplateList(String proxyOperatorOpenId) throws TencentCloudSDKException {
+        EssbasicClient client = initClient();
         //根据姓名和手机号生成唯一的经办人OpenId(SHA256哈希)
         DescribeTemplatesRequest req = new DescribeTemplatesRequest();
         // --- 开始构建图片中的 JSON 数据 ---
@@ -77,7 +106,7 @@ public class WeChatContractUtil {
         // 设置 QueryAllComponents: true
         req.setQueryAllComponents(true);
         // 将 Agent 设置到请求中
-        req.setAgent(getAgent(proxyOperatorOpenId));
+        req.setAgent(setAgent(proxyOperatorOpenId));
         // --- JSON 构建结束 ---
         // 通过client对象调用对应接口
         DescribeTemplatesResponse resp = client.DescribeTemplates(req);
@@ -85,6 +114,7 @@ public class WeChatContractUtil {
     }
 
     public DescribeTemplatesResponse getTemplateDetail(String proxyOperatorOpenId, String TemplateId) throws TencentCloudSDKException {
+        EssbasicClient client = initClient();
         //根据姓名和手机号生成唯一的经办人OpenId(SHA256哈希)
         DescribeTemplatesRequest req = new DescribeTemplatesRequest();
         req.setTemplateId(TemplateId);
@@ -94,19 +124,294 @@ public class WeChatContractUtil {
         // 设置 QueryAllComponents: true
         req.setQueryAllComponents(true);
         // 将 Agent 设置到请求中
-        req.setAgent(getAgent(proxyOperatorOpenId));
+        req.setAgent(setAgent(proxyOperatorOpenId));
         // --- JSON 构建结束 ---
         // 通过client对象调用对应接口
         DescribeTemplatesResponse resp = client.DescribeTemplates(req);
         return resp;
     }
 
+    public static DescribeTemplatesResponse describeTemplates(Agent agent, String TemplateId) {
+        try {
+            EssbasicClient client = initClient();
+            // 实例化一个请求对象,每个接口都会对应一个request对象
+            DescribeTemplatesRequest req = new DescribeTemplatesRequest();
+            req.setAgent(agent);
+            req.setTemplateId(TemplateId);
+            // 返回的resp是一个DescribeTemplatesResponse的实例,与请求对象对应
+            return client.DescribeTemplates(req);
+        } catch (TencentCloudSDKException e) {
+            System.out.println(e.toString());
+        }
+        return null;
+    }
+
+    /**
+     * 设置FlowInfo
+     *
+     * @param TemplateId        模板唯一标识
+     * @param FlowName          签署流程名称
+     * @param flowApproverInfos 签署流程签约方列表
+     * @return FlowInfo
+     */
+    public static FlowInfo fillFlowInfo(String TemplateId, String FlowName, FlowApproverInfo[] flowApproverInfos) {
+        FlowInfo flowInfo = new FlowInfo();
+        flowInfo.setTemplateId(TemplateId);
+        flowInfo.setFlowName(FlowName);
+        flowInfo.setFlowApprovers(flowApproverInfos);
+        flowInfo.setFlowType("合同");
+        return flowInfo;
+    }
+
+    public static CreateSignUrlsResponse createSignUrls(String[] flowIds, Agent agent) {
+        try {
+            EssbasicClient client = initClient();
+            // 实例化一个请求对象,每个接口都会对应一个request对象
+            CreateSignUrlsRequest req = new CreateSignUrlsRequest();
+
+            req.setAgent(agent);
+
+            req.setFlowIds(flowIds);
+
+            // 返回的resp是一个CreateSignUrlsResponse的实例,与请求对象对应
+            return client.CreateSignUrls(req);
+        } catch (TencentCloudSDKException e) {
+            System.out.println(e.toString());
+        }
+        return null;
+    }
+
+    public static CreateFlowsByTemplatesResponse createFlowsByTemplates(Agent agent, FlowInfo[] flowInfos) {
+        try {
+            EssbasicClient client = initClient();
+            // 实例化一个请求对象,每个接口都会对应一个request对象
+            CreateFlowsByTemplatesRequest req = new CreateFlowsByTemplatesRequest();
+
+            req.setAgent(agent);
+
+            req.setFlowInfos(flowInfos);
+
+            // 返回的resp是一个CreateFlowsByTemplatesResponse的实例,与请求对象对应
+            return client.CreateFlowsByTemplates(req);
+        } catch (TencentCloudSDKException e) {
+            System.out.println(e.toString());
+        }
+        return null;
+    }
+
+    public static DescribeResourceUrlsByFlowsResponse describeResourceUrlsByFlows(Agent agent, String[] flowIds) {
+        try {
+            EssbasicClient client = initClient();
+            // 实例化一个请求对象,每个接口都会对应一个request对象
+            DescribeResourceUrlsByFlowsRequest req = new DescribeResourceUrlsByFlowsRequest();
+
+            req.setAgent(agent);
+
+            req.setFlowIds(flowIds);
+
+            // 返回的resp是一个DescribeResourceUrlsByFlowsResponse的实例,与请求对象对应
+            return client.DescribeResourceUrlsByFlows(req);
+        } catch (TencentCloudSDKException e) {
+            System.out.println(e.toString());
+        }
+        return null;
+    }
+
+    public static String describeFileUrls(String flowId) {
+
+        // 设置agent参数
+        Agent agent = new Agent();
+        agent.setAppId(WeChatConfig.AppId);
+        agent.setProxyAppId(WeChatConfig.ProxyAppId);
+        agent.setProxyOrganizationOpenId(WeChatConfig.ProxyOrganizationOpenId);
+        UserInfo proxyOperator = new UserInfo();
+        proxyOperator.setOpenId(SuperProxyOperatorOpenId);
+        agent.setProxyOperator(proxyOperator);
+
+        String[] flowIds = new String[1];
+        flowIds[0] = flowId;
+        DescribeResourceUrlsByFlowsResponse urlResp =
+                describeResourceUrlsByFlows(agent, flowIds);
+
+        assert urlResp != null;
+        return urlResp.getFlowResourceUrlInfos()[0].getResourceUrlInfos()[0].getUrl();
+    }
+
+    /**
+     * 通过文件base64直接发起签署流程
+     *
+     * @param flowName   签署流程名称
+     * @param templateId 模板唯一标识
+     * @return Map<String, String [ ]>
+     */
+    public static Map<String, String[]> createFlowByTemplateDirectly(String flowName,
+                                                                     String templateId,
+                                                                     FlowApproverInfo[] flowApproverInfos) {
+        Map<String, String[]> resp = new HashMap<>();
+        // 设置agent参数
+        Agent agent = setAgent(SuperProxyOperatorOpenId);
+        // 创建签署流程
+        // 签署数量
+        int count = WeChatConfig.COUNT;
+        FlowInfo[] FlowInfos = new FlowInfo[count];
+        for (int i = 0; i < count; i++) {
+            FlowInfos[i] = fillFlowInfo(templateId, flowName, flowApproverInfos);
+            // 构建内容控件填充结构(根据自己需求使用)
+            FlowInfos[i].setFormFields(new FormField[]{BuildFormField("htbh", "123456")});
+
+        }
+
+        // 发起签署
+        CreateFlowsByTemplatesResponse flowResponse = createFlowsByTemplates(agent, FlowInfos);
+        assert flowResponse != null;
+        String[] FlowIds = flowResponse.getFlowIds();
+        resp.put("FlowIds", FlowIds);
+
+        // 获取签署链接
+        CreateSignUrlsResponse createSignUrlsRes = createSignUrls(FlowIds, agent);
+        assert createSignUrlsRes != null;
+        if (createSignUrlsRes.getSignUrlInfos().length != 0) {
+            String[] Urls = new String[count];
+            for (int i = 0; i < count; i++) {
+                Urls[i] = createSignUrlsRes.getSignUrlInfos()[i].getSignUrl();
+            }
+            resp.put("Urls", Urls);
+        }
+
+        return resp;
+    }
+
+    public static ChannelCancelFlowResponse channelCancelFlow(Agent agent, String flowId, String cancelMessage,
+                                                              Long cancelMessageFormat) {
+        try {
+            // 实例化一个client
+            EssbasicClient client = initClient();
+            // 实例化一个请求对象,每个接口都会对应一个request对象
+            ChannelCancelFlowRequest req = new ChannelCancelFlowRequest();
+
+            req.setAgent(agent);
+
+            req.setFlowId(flowId);
+
+            req.setCancelMessage(cancelMessage);
+
+            req.setCancelMessageFormat(cancelMessageFormat);
+
+            // 返回的resp是一个ChannelCancelFlowResponse的实例,与请求对象对应
+            return client.ChannelCancelFlow(req);
+        } catch (TencentCloudSDKException e) {
+            System.out.println(e.toString());
+        }
+        return null;
+    }
+
+    public static ChannelBatchCancelFlowsResponse channelBatchCancelFlows(String[] flowIds, Agent agent) {
+        try {
+            // 实例化一个client
+            EssbasicClient client = initClient();
+            // 实例化一个请求对象,每个接口都会对应一个request对象
+            ChannelBatchCancelFlowsRequest req = new ChannelBatchCancelFlowsRequest();
+
+            req.setAgent(agent);
+
+            req.setFlowIds(flowIds);
+
+            // 返回的resp是一个ChannelBatchCancelFlowsResponse的实例,与请求对象对应
+            return client.ChannelBatchCancelFlows(req);
+        } catch (TencentCloudSDKException e) {
+            System.out.println(e.toString());
+        }
+        return null;
+    }
+
+    public static DescribeFlowDetailInfoResponse describeFlowDetailInfo(Agent agent, String[] flowIds) {
+        try {
+            // 实例化一个client
+            EssbasicClient client = initClient();
+            // 实例化一个请求对象,每个接口都会对应一个request对象
+            DescribeFlowDetailInfoRequest req = new DescribeFlowDetailInfoRequest();
+
+            req.setAgent(agent);
+
+            req.setFlowIds(flowIds);
+
+            // 返回的resp是一个DescribeFlowDetailInfoResponse的实例,与请求对象对应
+            return client.DescribeFlowDetailInfo(req);
+        } catch (TencentCloudSDKException e) {
+            System.out.println(e.toString());
+        }
+        return null;
+    }
+
+    public static String getFlowStatus(String flowStatus) {
+
+        switch (flowStatus) {
+            case "INIT":
+                return "合同创建";
+            case "PART":
+                return "合同签署中";
+            case "ALL":
+                return "合同签署完成  ";
+            case "REJECT":
+                return "合同拒签";
+            case "CANCEL":
+                return "合同撤回";
+            case "WILLEXPIRE":
+                return "合同即将过期";
+            case "DEADLINE":
+                return "合同流签(合同过期)";
+            case "RELIEVED":
+                return "已解除";
+            case "INVALID":
+                return "合同已失效";
+            case "EXCEPTION":
+                return "合同异常";
+            default:
+                return "";
+        }
+
+    }
+
+    public static String getApproveStatus(String approveStatus) {
+        switch (approveStatus) {
+            case "PENDING":
+                return "待签署";
+            case "ACCEPT":
+                return "已签署";
+            case "REJECT":
+                return "拒绝  ";
+            case "DEADLINE":
+                return "过期没人处理";
+            case "CANCEL":
+                return "流程已撤回";
+            case "STOP":
+                return "流程已终止";
+            case "WAITPICKUP":
+                return "待领取";
+            case "FILLPENDING":
+                return "待填写";
+            case "FILLACCEPT":
+                return "填写完成";
+            case "FORWARD":
+                return "已转他人处理";
+            case "RELIEVED":
+                return "已解除";
+            case "FILLREJECT":
+                return "拒绝填写";
+            case "EXCEPTION":
+                return "异常";
+            default:
+                return "";
+        }
+    }
+
+
     public static void main(String[] args) throws TencentCloudSDKException {
+        String[] flowIds = {"yD3g7UUckpmzhmhtU1UyFt71fypQygwg"};
 
-        WeChatContractUtil wccUtil = new WeChatContractUtil();
-        DescribeTemplatesResponse resp = wccUtil.getTemplateList(SuperProxyOperatorOpenId);
+        DescribeFlowDetailInfoResponse res = describeFlowDetailInfo(setAgent(SuperProxyOperatorOpenId), flowIds);
 
-        System.err.println(DescribeTemplatesResponse.toJsonString(resp));
+        System.err.println(DescribeTemplatesResponse.toJsonString(res));
     }
 
 }

+ 69 - 0
src/custom/service/EsignContractTaskService.java

@@ -0,0 +1,69 @@
+package service;
+
+import com.tencentcloudapi.essbasic.v20210526.models.DescribeFlowDetailInfoResponse;
+import com.tencentcloudapi.essbasic.v20210526.models.FlowDetailInfo;
+import common.ServiceController;
+import common.data.Row;
+import common.data.Rows;
+import common.data.SQLFactory;
+import common.data.UpdateSQL;
+import org.apache.commons.lang.StringUtils;
+import restcontroller.webmanage.sale.contracttask.WeChatContractUtil;
+
+import static restcontroller.webmanage.sale.contracttask.WeChatConfig.SuperProxyOperatorOpenId;
+import static restcontroller.webmanage.sale.contracttask.WeChatContractUtil.describeFlowDetailInfo;
+import static restcontroller.webmanage.sale.contracttask.WeChatContractUtil.setAgent;
+
+public class EsignContractTaskService extends ServiceController {
+
+    @Override
+    public ServiceParam paramSet() {
+        return new ServiceParam("腾讯电子签合同状态查询", 30, RunType.second);
+    }
+
+    @Override
+    public void serviceRun() throws Exception {
+        System.err.println(getDateTime_Str() + ":开始查询腾讯电子签合同状态...");
+        Rows rows = dbConnect.runSqlQuery("SELECT * from sa_esign_contract_taskmx WHERE status in ('合同创建','合同签署中','合同即将过期')");
+        for (Row row : rows) {
+            String flowid = row.getString("flowid");
+            Long sa_esign_contract_taskmxid = row.getLong("sa_esign_contract_taskmxid");
+            if (StringUtils.isBlank(flowid)) {
+                continue;
+            }
+            String flowStatus = row.getString("status");
+            String approveStatus = row.getString("approvestatus");
+            String tempflowStatus = "";
+            String tempapproveStatus = "";
+            String[] flowIds = {flowid};
+            DescribeFlowDetailInfoResponse res = describeFlowDetailInfo(setAgent(SuperProxyOperatorOpenId), flowIds);
+            if (res.getFlowInfo().length > 0) {
+                FlowDetailInfo flowDetailInfo = res.getFlowInfo()[0];
+                tempflowStatus = WeChatContractUtil.getFlowStatus(flowDetailInfo.getFlowStatus());
+                if (flowDetailInfo.getFlowApproverInfos().length > 0) {
+                    tempapproveStatus = WeChatContractUtil.getApproveStatus(flowDetailInfo.getFlowApproverInfos()[0].getApproveStatus());
+                }
+            }
+            boolean isUpdate = false;
+            UpdateSQL updateSQL = SQLFactory.createUpdateSQL(dbConnect, "sa_esign_contract_taskmx");
+            updateSQL.setUniqueid(sa_esign_contract_taskmxid);
+            if (!flowStatus.equals(tempflowStatus) && !tempflowStatus.equals("")) {
+                updateSQL.setValue("status", tempflowStatus);
+                isUpdate = true;
+                System.err.println(getDateTime_Str() + ":更新合同状态:" + tempflowStatus);
+            }
+            if (!approveStatus.equals(tempapproveStatus) && !tempapproveStatus.equals("")) {
+                updateSQL.setValue("approvestatus", tempapproveStatus);
+                isUpdate = true;
+                System.err.println(getDateTime_Str() + ":更新合同状态:" + tempapproveStatus);
+            }
+            if (isUpdate) {
+
+
+                updateSQL.update();
+            }
+        }
+        System.err.println(getDateTime_Str() + ":查询腾讯电子签合同状态完成");
+
+    }
+}