diff --git a/esign/src/main/java/com/seeyon/apps/esign/constants/EsignApiUrl.java b/esign/src/main/java/com/seeyon/apps/esign/constants/EsignApiUrl.java index 289e49b..4213a6e 100644 --- a/esign/src/main/java/com/seeyon/apps/esign/constants/EsignApiUrl.java +++ b/esign/src/main/java/com/seeyon/apps/esign/constants/EsignApiUrl.java @@ -1,7 +1,6 @@ package com.seeyon.apps.esign.constants; public class EsignApiUrl { - public static final String QUERY_SEAL_URL = "/v3/seals/org-own-seal-list"; public static final String SEAL_GRANT_URL = "/v3/seals/org-seals/internal-auth"; public static final String SIGN_START_URL = "/v3/sign-flow/{signFlowId}/start"; public static final String SIGN_BY_FILE_URL = "/v3/sign-flow/create-by-file"; @@ -14,4 +13,5 @@ public class EsignApiUrl { public static final String QUERY_ORGINFO = "/v3/organizations/identity-info"; public static final String CONTRACT_COMPARE_GETURL = "/v3/contract-compare-url"; public static final String TOKEN_GET_URL = "/v1/oauth2/access_token"; + public static final String SEAL_QUERY_URL = "/v3/seals/org-own-seal-list"; } diff --git a/esign/src/main/java/com/seeyon/apps/esign/constants/EsignConfigConstants.java b/esign/src/main/java/com/seeyon/apps/esign/constants/EsignConfigConstants.java index 91c768f..e1b214b 100644 --- a/esign/src/main/java/com/seeyon/apps/esign/constants/EsignConfigConstants.java +++ b/esign/src/main/java/com/seeyon/apps/esign/constants/EsignConfigConstants.java @@ -14,6 +14,10 @@ public enum EsignConfigConstants { nodeTokenUrl("/seeyon/rest/flow/notification/","超级节点回调URL"), restName("",""), restPwd("",""), + signAutoDate("","是否自动加盖签署日期"), + eSignOrgId("61f735dd368c45a191f43a6711c3c88a","e签宝平台方组织id"), + formLoginName("2019","表单数据录入登录名"), + sealInfoFormCode("","印章档案编码"), ; private String defaultValue; diff --git a/esign/src/main/java/com/seeyon/apps/esign/form/FormDataOperator.java b/esign/src/main/java/com/seeyon/apps/esign/form/FormDataOperator.java index 3fefdda..cb9bf93 100644 --- a/esign/src/main/java/com/seeyon/apps/esign/form/FormDataOperator.java +++ b/esign/src/main/java/com/seeyon/apps/esign/form/FormDataOperator.java @@ -83,7 +83,36 @@ public class FormDataOperator { } } - public FormColumn queryOneRowFormData(String formNo, List queryColumnVos, List conditionVos) throws BusinessException { + public void deleteByCondition(String formNo, List conditionVos) throws Exception { + FormApi4Cap4 formApi4Cap4 = (FormApi4Cap4) AppContext.getBean("formApi4Cap4"); + FormBean cap4FormBean = formApi4Cap4.getFormByFormCode(formNo); + List queryColumns = new ArrayList<>(); + FormTableBean masterTableBean = cap4FormBean.getMasterTableBean(); + String tableName = masterTableBean.getTableName(); + Map fieldMap4Name = masterTableBean.getFieldMap4Name(); + for (FormWhereCondition conditionVo : conditionVos) { + FormFieldBean fieldBeanByDisplay = masterTableBean.getFieldBeanByDisplay(conditionVo.getDisplay()); + if (fieldBeanByDisplay == null) { + if (conditionVo.getDisplay().equals("ID") || conditionVo.getDisplay().equals("id")) { + conditionVo.setFieldName(conditionVo.getDisplay()); + } + continue; + } + conditionVo.setFieldName(fieldBeanByDisplay.getColumnName()); + } + + Map generateSql = generateDelSql(conditionVos, tableName); + String sql = (String) generateSql.get("sql"); + List params = (List) generateSql.get("params"); + JDBCAgent jdbcAgent = new JDBCAgent(); + try { + jdbcAgent.execute(sql, params); + } finally { + jdbcAgent.close(); + } + } + + public FormColumn queryOneRowFormData(String formNo, List queryColumnVos, List conditionVos) throws Exception { FormApi4Cap4 formApi4Cap4 = (FormApi4Cap4) AppContext.getBean("formApi4Cap4"); FormBean cap4FormBean = formApi4Cap4.getFormByFormCode(formNo); List queryColumns = new ArrayList<>(); @@ -138,13 +167,10 @@ public class FormDataOperator { } columns.add(column); } - return columns.get(0); - } catch (Exception e) { - System.out.println(e.getMessage()); + return columns.size() > 0 ? columns.get(0) : null; } finally { jdbcAgent.close(); } - return null; } public List queryFormDataCondition(String formNo, List queryColumnVos, List conditionVos) throws BusinessException { @@ -256,6 +282,20 @@ public class FormDataOperator { return result; } + private Map generateDelSql(List conditions, String tableName) { + if (tableName == null) { + throw new IllegalArgumentException("tableName cannot be null or empty"); + } + StringBuilder sqlBuilder = new StringBuilder("DELETE "); + sqlBuilder.append(" from " + tableName); + List params = new ArrayList<>(); + sqlBuilder.append(buildWhereClause(conditions,params)); + Map result = new HashMap<>(); + result.put("sql", sqlBuilder.toString()); + result.put("params", params); + return result; + } + private Map generateSql(List fieldValues, String tableName,List conditions) { if (fieldValues == null || fieldValues.isEmpty()) { throw new IllegalArgumentException("Field values cannot be null or empty"); diff --git a/esign/src/main/java/com/seeyon/apps/esign/job/SealDocSyncJob.java b/esign/src/main/java/com/seeyon/apps/esign/job/SealDocSyncJob.java new file mode 100644 index 0000000..66d18e0 --- /dev/null +++ b/esign/src/main/java/com/seeyon/apps/esign/job/SealDocSyncJob.java @@ -0,0 +1,74 @@ +package com.seeyon.apps.esign.job; + +import com.seeyon.aicloud.common.JsonUtils; +import com.seeyon.apps.esign.config.EsignConfigProvider; +import com.seeyon.apps.esign.constants.EsignApiUrl; +import com.seeyon.apps.esign.constants.EsignConfigConstants; +import com.seeyon.apps.esign.po.EsignApiHeader; +import com.seeyon.apps.esign.po.EsignBaseResp; +import com.seeyon.apps.esign.po.SealInfoVo; +import com.seeyon.apps.esign.service.SealService; +import com.seeyon.apps.esign.service.TokenCacheManager; +import com.seeyon.apps.esign.utils.HttpClient; +import com.seeyon.apps.ext.quartz.AbstractQuartzTask; +import org.apache.commons.logging.Log; +import org.apache.commons.logging.LogFactory; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.stereotype.Component; + +import java.util.List; +import java.util.Map; + +@Component +public class SealDocSyncJob extends AbstractQuartzTask { + + private static final Log log = LogFactory.getLog(SealDocSyncJob.class); + @Autowired + private EsignConfigProvider configProvider; + @Autowired + private TokenCacheManager tokenCacheManager; + @Autowired + private SealService sealService; + + @Override + public String taskRun(String s) throws Exception { + log.info("开始执行印章同步任务"); + syncSeals(); + log.info("印章同步任务完成"); + return ""; + } + + private void syncSeals() { + String orgId = configProvider.getBizConfigByKey(EsignConfigConstants.eSignOrgId); + String host = configProvider.getBizConfigByKey(EsignConfigConstants.ESIGN_HOST); + Integer pageNum = 1; + Integer pageSize = 20; + EsignApiHeader esignApiHeader = EsignApiHeader.build().appId(configProvider.getBizConfigByKey(EsignConfigConstants.APP_ID)); + esignApiHeader.token(tokenCacheManager.getToken()); + EsignBaseResp esignBaseResp = null; + Map dataMap = null; + do { + String url = host + EsignApiUrl.SEAL_QUERY_URL + "?" + "orgId=" + orgId + "&pageNum=" + (pageNum++) + "&pageSize=" + pageSize; + String respStr = HttpClient.httpGet(url, esignApiHeader.convert2Headers(),"UTF-8"); + esignBaseResp = JsonUtils.parseObject(respStr, EsignBaseResp.class); + if(esignBaseResp.getCode() != 0) { + break; + } + dataMap = (Map)esignBaseResp.getData(); + Object[] sealArray = (Object[]) dataMap.get("seals"); + if(sealArray == null || sealArray.length == 0) { + break; + } + for (Object o : sealArray) { + SealInfoVo sealInfoVo = JsonUtils.parseObject(JsonUtils.toJSONString(o), SealInfoVo.class); + sealService.upsertOaSealDoc(sealInfoVo); + } + }while (true); + + } + + @Override + public String getName() { + return "E签宝印章信息同步任务"; + } +} diff --git a/esign/src/main/java/com/seeyon/apps/esign/node/EsignNode.java b/esign/src/main/java/com/seeyon/apps/esign/node/EsignMultipleSignerNode.java similarity index 70% rename from esign/src/main/java/com/seeyon/apps/esign/node/EsignNode.java rename to esign/src/main/java/com/seeyon/apps/esign/node/EsignMultipleSignerNode.java index 3a48a52..62c3180 100644 --- a/esign/src/main/java/com/seeyon/apps/esign/node/EsignNode.java +++ b/esign/src/main/java/com/seeyon/apps/esign/node/EsignMultipleSignerNode.java @@ -6,7 +6,10 @@ import com.seeyon.apps.esign.constants.EsignConfigConstants; import com.seeyon.apps.esign.form.FormDataOperator; import com.seeyon.apps.esign.form.FormUpdateField; import com.seeyon.apps.esign.form.FormWhereCondition; -import com.seeyon.apps.esign.po.*; +import com.seeyon.apps.esign.po.NormalSignFieldConfig; +import com.seeyon.apps.esign.po.SignField; +import com.seeyon.apps.esign.po.SignFieldPosition; +import com.seeyon.apps.esign.po.Signer; import com.seeyon.apps.esign.service.EsignByTemplateService; import com.seeyon.apps.esign.service.EsignByUploadFileService; import com.seeyon.apps.ext.workflow.vo.FormDataVo; @@ -21,12 +24,15 @@ import org.apache.commons.logging.LogFactory; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.stereotype.Component; -import java.util.*; +import java.util.ArrayList; +import java.util.HashMap; +import java.util.List; +import java.util.Map; @Component -public class EsignNode extends ACommonSuperNode { +public class EsignMultipleSignerNode extends ACommonSuperNode { - private static final Log log = LogFactory.getLog(EsignNode.class); + private static final Log log = LogFactory.getLog(EsignMultipleSignerNode.class); private static final String CONTRACT_NAME_FIELD = "合同名称"; private static final String CONTRACT_ATTACHMENT_FIELD = "合同审批附件"; @@ -53,14 +59,14 @@ public class EsignNode extends ACommonSuperNode { public SuperNodeContext proceed(String s, FormDataVo formDataVo, FormDataMasterBean formDataMasterBean) { SuperNodeContext context = new SuperNodeContext(); context.setNeedSave(true); - log.info("进入 E签宝签署集成超级节点"); + log.info("进入 E签宝多方签署集成超级节点"); try { Map signParams = buildSignParams(formDataVo, formDataMasterBean, true); if (signParams == null) throw new RuntimeException("签署参数构建失败"); String esignFlowId = templateService.createBySignTemplate(signParams); log.info("E签宝签署流程ID: " + esignFlowId + " , OA超级节点ID:" + formDataVo.getToken()); - log.info("E签宝合同已发送: " + esignFlowId); + log.info("E签宝多方签署合同已发送: " + esignFlowId); return context.wait("等待签署结束"); } catch (Exception e) { log.error("E签宝签署失败", e); @@ -87,8 +93,8 @@ public class EsignNode extends ACommonSuperNode { private List buildSigners(FormDataVo formDataVo, String fileId,boolean qifengSign) throws Exception { List positions = uploadFileService.getSignPosition(fileId); - SignFieldPosition bPosition = extractPosition(positions, "乙方盖章/签字"); - SignFieldPosition aPosition = extractPosition(positions, "甲方盖章/签字"); + List bPositions = extractPosition(positions, "乙方盖章/签字"); + List aPositions = extractPosition(positions, "甲方盖章/签字"); String bSignerType = formDataVo.getFieldData("乙方签署类型").getStringValue(); SignFieldPosition aQiFengposition = new SignFieldPosition(); @@ -98,27 +104,23 @@ public class EsignNode extends ACommonSuperNode { bQiFengposition.setAcrossPageMode("ALL"); bQiFengposition.setPositionY(720f); - List aPos = new ArrayList<>(); - aPos.add(aPosition); - aPos.add(aQiFengposition); - List bPos = new ArrayList<>(); - bPos.add(bPosition); - bPos.add(bQiFengposition); - - Signer bSigner = !"组织".equals(bSignerType) ? createPsnSigner(fileId,formDataVo.getFieldData("乙方姓名").getStringValue(),bPos,1,formDataVo.getFieldData("乙方电话").getStringValue(),false) : createOrgSigner( + aPositions.add(aQiFengposition); + bPositions.add(bQiFengposition); + String sealId = formDataVo.getFieldData("甲方印章ID").getStringValue(); + Signer bSigner = !"组织".equals(bSignerType) ? createPsnSigner(fileId,formDataVo.getFieldData("乙方姓名").getStringValue(),bPositions,1,formDataVo.getFieldData("乙方电话").getStringValue(),false) : createOrgSigner( fileId, getStringField(formDataVo, B_UNIT_NAME_FIELD), - bPos, 1, formDataVo.getFieldData("乙方法人姓名").getStringValue(), + bPositions, 1, formDataVo.getFieldData("乙方法人姓名").getStringValue(), formDataVo.getFieldData("乙方法人身份证号").getStringValue(), formDataVo.getFieldData("乙方企业社会信用代码").getStringValue(), formDataVo.getFieldData("乙方经办人手机号").getStringValue(), formDataVo.getFieldData("乙方经办人姓名").getStringValue(), formDataVo.getFieldData("乙方经办人身份证号").getStringValue(),false - ); + ,null); Signer aSigner = createOrgSigner( - fileId,null, aPos, 2, null, null, null, null, null, null,true - ); + fileId,null, aPositions, 2, null, null, null, null, null, null,true + ,sealId); List signers = new ArrayList<>(); signers.add(bSigner); signers.add(aSigner); @@ -139,7 +141,6 @@ public class EsignNode extends ACommonSuperNode { docs.add(docMap); Map signFlowConfig = buildSignFlowConfig(formDataVo, formDataMasterBean); List signers = buildSigners(formDataVo, fileId,true); - Map signParams = new HashMap<>(); signParams.put("signFlowConfig", signFlowConfig); signParams.put("signers", signers); @@ -188,32 +189,37 @@ public class EsignNode extends ACommonSuperNode { signer.setPsnSignerInfo(psnInfo); } - NormalSignFieldConfig fieldConfig = new NormalSignFieldConfig(); - fieldConfig.setSignFieldPosition(pos.get(0)); - fieldConfig.setAutoSign(autoSign); - fieldConfig.setSignFieldStyle(1); - SignField field = new SignField(); - field.setSignFieldType(0); - field.setNormalSignFieldConfig(fieldConfig); - field.setSignDateConfig(new SignDateConfig()); - field.setFileId(fileId); + List signFields = new ArrayList<>(); + for (SignFieldPosition po : pos) { + NormalSignFieldConfig fieldConfig = new NormalSignFieldConfig(); + if("ALL".equals(po.getAcrossPageMode())){ + fieldConfig.setSignFieldPosition(po); + fieldConfig.setAutoSign(autoSign); + fieldConfig.setSignFieldStyle(2); + SignField qiFengfield = new SignField(); + qiFengfield.setSignFieldType(0); + qiFengfield.setNormalSignFieldConfig(fieldConfig); + qiFengfield.setFileId(fileId); + signFields.add(qiFengfield); + }else { + fieldConfig.setSignFieldPosition(po); + fieldConfig.setAutoSign(autoSign); + fieldConfig.setSignFieldStyle(1); + SignField field = new SignField(); + field.setSignFieldType(0); + field.setNormalSignFieldConfig(fieldConfig); + field.setFileId(fileId); + signFields.add(field); + } + } - NormalSignFieldConfig qiFengfieldConfig = new NormalSignFieldConfig(); - qiFengfieldConfig.setSignFieldPosition(pos.get(1)); - qiFengfieldConfig.setAutoSign(autoSign); - qiFengfieldConfig.setSignFieldStyle(2); - SignField qiFengfield = new SignField(); - qiFengfield.setSignFieldType(0); - qiFengfield.setNormalSignFieldConfig(qiFengfieldConfig); - qiFengfield.setFileId(fileId); - - signer.setSignFields(Arrays.asList(field,qiFengfield)); + signer.setSignFields(signFields); return signer; } private Signer createOrgSigner(String fileId ,String orgName, List pos, int order, String legalName, String legalId, String orgCode, - String transPhone, String psnName, String psnId,Boolean autoSign) { + String transPhone, String psnName, String psnId,Boolean autoSign,String sealId) { Signer signer = new Signer(); signer.setSignerType(1); signer.setSignConfig(mapOf("signOrder", order)); @@ -238,41 +244,54 @@ public class EsignNode extends ACommonSuperNode { signer.setOrgSignerInfo(orgInfo); } - NormalSignFieldConfig fieldConfig = new NormalSignFieldConfig(); - fieldConfig.setSignFieldPosition(pos.get(0)); - fieldConfig.setAutoSign(autoSign); - fieldConfig.setSignFieldStyle(1); - SignField field = new SignField(); - field.setSignFieldType(0); - field.setNormalSignFieldConfig(fieldConfig); - field.setSignDateConfig(new SignDateConfig()); - field.setFileId(fileId); + List signFields = new ArrayList<>(); + for (SignFieldPosition po : pos) { + NormalSignFieldConfig fieldConfig = new NormalSignFieldConfig(); + fieldConfig.setAssignedSealId(sealId); + if("ALL".equals(po.getAcrossPageMode())){ + fieldConfig.setSignFieldPosition(po); + fieldConfig.setAutoSign(autoSign); + fieldConfig.setSignFieldStyle(2); + SignField qiFengfield = new SignField(); + qiFengfield.setSignFieldType(0); + qiFengfield.setNormalSignFieldConfig(fieldConfig); + qiFengfield.setFileId(fileId); + signFields.add(qiFengfield); + }else { + fieldConfig.setSignFieldPosition(po); + fieldConfig.setAutoSign(autoSign); + fieldConfig.setSignFieldStyle(1); + SignField field = new SignField(); + field.setSignFieldType(0); + field.setNormalSignFieldConfig(fieldConfig); + field.setFileId(fileId); + signFields.add(field); + } + } - NormalSignFieldConfig qiFengfieldConfig = new NormalSignFieldConfig(); - qiFengfieldConfig.setSignFieldPosition(pos.get(1)); - qiFengfieldConfig.setAutoSign(autoSign); - qiFengfieldConfig.setSignFieldStyle(2); - SignField qiFengfield = new SignField(); - qiFengfield.setSignFieldType(0); - qiFengfield.setNormalSignFieldConfig(qiFengfieldConfig); - qiFengfield.setFileId(fileId); - - signer.setSignFields(Arrays.asList(field,qiFengfield)); + signer.setSignFields(signFields); return signer; } - private SignFieldPosition extractPosition(List positions, String keyword) { + private List extractPosition(List positions, String keyword) { + List posList = new ArrayList<>(); for (Object obj : positions) { Map position = (Map) obj; if (Boolean.TRUE.equals(position.get("searchResult")) && keyword.equals(position.get("keyword"))) { Object[] posArray = (Object[]) position.get("positions"); - Map posMap = (Map) posArray[0]; - Map coord = (Map) ((Object[])posMap.get("coordinates"))[0]; - SignFieldPosition sfp = new SignFieldPosition(); - sfp.setPositionPage(posMap.get("pageNum") + ""); - sfp.setPositionX(toFloat(coord.get("positionX")) + 150f); - sfp.setPositionY(toFloat(coord.get("positionY"))); - return sfp; + for (Object o : posArray) { + Map posMap = (Map)o; + Object[] coords = (Object[]) posMap.get("coordinates"); + for (Object coord : coords) { + Map tempMap = (Map) coord; + SignFieldPosition sfp = new SignFieldPosition(); + sfp.setPositionPage(posMap.get("pageNum") + ""); + sfp.setPositionX(toFloat(tempMap.get("positionX")) + 150f); + sfp.setPositionY(toFloat(tempMap.get("positionY"))); + posList.add(sfp); + } + } + return posList; } } throw new RuntimeException("未找到关键字位置: " + keyword); @@ -288,11 +307,11 @@ public class EsignNode extends ACommonSuperNode { @Override public String getNodeId() { - return "nd_20250702"; + return "nd_20250703"; } @Override public String getNodeName() { - return "E签宝签署节点"; + return "E签宝甲乙双方签署节点"; } } diff --git a/esign/src/main/java/com/seeyon/apps/esign/node/EsignOneSignerNode.java b/esign/src/main/java/com/seeyon/apps/esign/node/EsignOneSignerNode.java new file mode 100644 index 0000000..20bcfef --- /dev/null +++ b/esign/src/main/java/com/seeyon/apps/esign/node/EsignOneSignerNode.java @@ -0,0 +1,292 @@ +package com.seeyon.apps.esign.node; + +import com.seeyon.apps.common.workflow.node.ACommonSuperNode; +import com.seeyon.apps.esign.config.EsignConfigProvider; +import com.seeyon.apps.esign.constants.EsignConfigConstants; +import com.seeyon.apps.esign.form.FormDataOperator; +import com.seeyon.apps.esign.form.FormUpdateField; +import com.seeyon.apps.esign.form.FormWhereCondition; +import com.seeyon.apps.esign.po.*; +import com.seeyon.apps.esign.service.EsignByTemplateService; +import com.seeyon.apps.esign.service.EsignByUploadFileService; +import com.seeyon.apps.ext.workflow.vo.FormDataVo; +import com.seeyon.apps.ext.workflow.vo.SuperNodeContext; +import com.seeyon.cap4.form.bean.FormDataMasterBean; +import com.seeyon.cap4.form.bean.FormFieldBean; +import com.seeyon.cap4.form.service.CAP4FormManager; +import com.seeyon.ctp.common.AppContext; +import com.seeyon.ctp.common.exceptions.BusinessException; +import org.apache.commons.logging.Log; +import org.apache.commons.logging.LogFactory; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.stereotype.Component; + +import java.util.*; + +@Component +public class EsignOneSignerNode extends ACommonSuperNode { + + private static final Log log = LogFactory.getLog(EsignOneSignerNode.class); + + private static final String CONTRACT_NAME_FIELD = "合同名称"; + private static final String CONTRACT_ATTACHMENT_FIELD = "合同审批附件"; + private static final String B_UNIT_NAME_FIELD = "乙方单位名称"; + private static CAP4FormManager cap4FormManager = (CAP4FormManager) AppContext.getBean("cap4FormManager"); + @Autowired + private EsignConfigProvider configProvider; + @Autowired + private EsignByUploadFileService uploadFileService; + @Autowired + private EsignByTemplateService templateService; + + @Override + public String getPluginId() { + return EsignConfigConstants.getPluginId(); + } + + @Override + public String getFormParse() { + return ""; + } + + @Override + public SuperNodeContext proceed(String s, FormDataVo formDataVo, FormDataMasterBean formDataMasterBean) { + SuperNodeContext context = new SuperNodeContext(); + context.setNeedSave(true); + log.info("进入 E签宝单方签署集成超级节点"); + + try { + Map signParams = buildSignParams(formDataVo, formDataMasterBean, true); + if (signParams == null) throw new RuntimeException("签署参数构建失败"); + String esignFlowId = templateService.createBySignTemplate(signParams); + log.info("E签宝签署流程ID: " + esignFlowId + " , OA超级节点ID:" + formDataVo.getToken()); + log.info("E签宝单方签署合同已发送: " + esignFlowId); + return context.wait("等待签署结束"); + } catch (Exception e) { + log.error("E签宝签署失败", e); + context.setErrMsg("E签宝签署失败: " + e.getMessage()); + return context.back("E签宝签署失败: " + e.getMessage()); + } + } + + private Map buildSignFlowConfig(FormDataVo formDataVo,FormDataMasterBean masterBean) throws Exception { + String contractName = getStringField(formDataVo, CONTRACT_NAME_FIELD); + if (contractName == null) throw new RuntimeException("合同名称不能为空"); + String formId = formDataVo.getToken() +"_" + formDataVo.getId(); + Long enumId = masterBean.getFormTable().getFieldBeanByDisplay("E签宝签署状态").getEnumId(); + String signCallBackUrl = configProvider.getBizConfigByKey(EsignConfigConstants.OA_HOST) + "/seeyon/esigncallback.do?method=callback&formId=" + formId + "&tablename=" + masterBean.getFormTable().getTableName() + "&updatefield=" + masterBean.getFormTable().getFieldBeanByDisplay("盖章后合同附件").getColumnName() + "&statusfield=" + masterBean.getFormTable().getFieldBeanByDisplay("E签宝签署状态").getColumnName() + "_" + enumId; + Map config = new HashMap<>(); + config.put("signFlowTitle", contractName); + config.put("autoFinish", true); + config.put("notifyUrl", signCallBackUrl); + Map noticeConfig = new HashMap<>(); + noticeConfig.put("noticeTypes", "1"); + config.put("noticeConfig", noticeConfig); + return config; + } + + private List buildOnlyASigner(FormDataVo formDataVo, String fileId) throws Exception { + List positions = uploadFileService.getSignPosition(fileId); + List aPositions = extractPosition(positions, "甲方盖章/签字"); + + SignFieldPosition aQiFengposition = new SignFieldPosition(); + aQiFengposition.setAcrossPageMode("ALL"); + aQiFengposition.setPositionY(520f); + String sealId = formDataVo.getFieldData("甲方印章ID").getStringValue(); + aPositions.add(aQiFengposition); + Signer aSigner = createOrgSigner( + fileId,null, aPositions, 1, null, null, null, null, null, null,true + ,sealId); + List signers = new ArrayList<>(); + signers.add(aSigner); + return signers; + } + + private Map buildSignParams(FormDataVo formDataVo, FormDataMasterBean formDataMasterBean, boolean byFile) throws Exception { + + String fileId = null; + if (byFile) { + String attachmentId = getStringField(formDataVo, CONTRACT_ATTACHMENT_FIELD); + if (attachmentId == null) throw new RuntimeException("合同附件不能为空"); + fileId = uploadFileService.uploadFileToEsign(attachmentId); + } + Map docMap = new HashMap<>(); + docMap.put("fileId", fileId); + List docs = new ArrayList<>(); + docs.add(docMap); + Map signFlowConfig = buildSignFlowConfig(formDataVo, formDataMasterBean); + List signers = buildOnlyASigner(formDataVo, fileId); + Map signParams = new HashMap<>(); + signParams.put("signFlowConfig", signFlowConfig); + signParams.put("signers", signers); + signParams.put("docs", docs); + return signParams; + + } + + private void fillFileId(String fileId,FormDataVo formDataVo,FormDataMasterBean formDataMasterBean) throws NoSuchFieldException, BusinessException { + String tableName = formDataVo.getTableName(); + FormFieldBean fieldBeanByDisplay = formDataMasterBean.getFormTable().getFieldBeanByDisplay("合同文件ID"); + FormDataOperator formDataOperator = new FormDataOperator(); + List updateFields = new ArrayList<>(); + updateFields.add(FormUpdateField.build().fieldName(fieldBeanByDisplay.getColumnName()).value(fileId)); + List whereConditions = new ArrayList<>(); + FormWhereCondition condition = FormWhereCondition.build().value(formDataVo.getId()); + condition.setFieldName("ID"); + whereConditions.add(condition); + formDataOperator.updateMasterForm(updateFields,tableName,whereConditions); + } + + private Map mapOf(Object... keyValues) { + if (keyValues.length % 2 != 0) { + throw new IllegalArgumentException("参数个数必须为偶数:key 和 value 必须成对出现"); + } + Map map = new HashMap<>(); + for (int i = 0; i < keyValues.length; i += 2) { + Object key = keyValues[i]; + Object value = keyValues[i + 1]; + if (!(key instanceof String)) { + throw new IllegalArgumentException("key 必须是 String 类型,当前为:" + key.getClass()); + } + map.put((String) key, value); + } + return map; + } + + private Signer createPsnSigner( String fileId, String psnName,List pos, int order, String phone,Boolean autoSign) { + Signer signer = new Signer(); + signer.setSignerType(0); + signer.setSignConfig(mapOf("signOrder", order)); + if(Boolean.FALSE.equals(autoSign)){ + signer.setNoticeConfig(mapOf("noticeTypes", "1")); + + Map psnInfo = mapOf("psnAccount", phone, "psnInfo", mapOf("psnName", psnName)); + signer.setPsnSignerInfo(psnInfo); + } + + List signFields = new ArrayList<>(); + for (SignFieldPosition po : pos) { + NormalSignFieldConfig fieldConfig = new NormalSignFieldConfig(); + if("ALL".equals(po.getAcrossPageMode())){ + fieldConfig.setSignFieldPosition(po); + fieldConfig.setAutoSign(autoSign); + fieldConfig.setSignFieldStyle(2); + SignField qiFengfield = new SignField(); + qiFengfield.setSignFieldType(0); + qiFengfield.setNormalSignFieldConfig(fieldConfig); + qiFengfield.setFileId(fileId); + signFields.add(qiFengfield); + }else { + fieldConfig.setSignFieldPosition(po); + fieldConfig.setAutoSign(autoSign); + fieldConfig.setSignFieldStyle(1); + SignField field = new SignField(); + field.setSignFieldType(0); + field.setNormalSignFieldConfig(fieldConfig); + field.setFileId(fileId); + signFields.add(field); + } + } + + signer.setSignFields(signFields); + return signer; + } + + private Signer createOrgSigner(String fileId ,String orgName, List pos, int order, + String legalName, String legalId, String orgCode, + String transPhone, String psnName, String psnId,Boolean autoSign,String sealId) { + Signer signer = new Signer(); + signer.setSignerType(1); + signer.setSignConfig(mapOf("signOrder", order)); + if(Boolean.FALSE.equals(autoSign)){ + signer.setNoticeConfig(mapOf("noticeTypes", "1")); + + Map orgInfo = mapOf("orgName", orgName, "orgInfo", mapOf( + "legalRepName", legalName, + "legalRepIDCardNum", legalId, + "orgIDCardNum", orgCode, + "orgIDCardType", "CRED_ORG_USCC" + ), + "transactorInfo", mapOf( + "psnAccount", transPhone, + "psnInfo", mapOf( + "psnName", psnName, + "psnIDCardNum", psnId + ) + ) + ); + + signer.setOrgSignerInfo(orgInfo); + } + + List signFields = new ArrayList<>(); + for (SignFieldPosition po : pos) { + NormalSignFieldConfig fieldConfig = new NormalSignFieldConfig(); + fieldConfig.setAssignedSealId(sealId); + if("ALL".equals(po.getAcrossPageMode())){ + fieldConfig.setSignFieldPosition(po); + fieldConfig.setAutoSign(autoSign); + fieldConfig.setSignFieldStyle(2); + SignField qiFengfield = new SignField(); + qiFengfield.setSignFieldType(0); + qiFengfield.setNormalSignFieldConfig(fieldConfig); + qiFengfield.setFileId(fileId); + signFields.add(qiFengfield); + }else { + fieldConfig.setSignFieldPosition(po); + fieldConfig.setAutoSign(autoSign); + fieldConfig.setSignFieldStyle(1); + SignField field = new SignField(); + field.setSignFieldType(0); + field.setNormalSignFieldConfig(fieldConfig); + field.setFileId(fileId); + signFields.add(field); + } + } + + signer.setSignFields(signFields); + return signer; + } + + private List extractPosition(List positions, String keyword) { + List posList = new ArrayList<>(); + for (Object obj : positions) { + Map position = (Map) obj; + if (Boolean.TRUE.equals(position.get("searchResult")) && keyword.equals(position.get("keyword"))) { + Object[] posArray = (Object[]) position.get("positions"); + for (Object o : posArray) { + Map posMap = (Map)o; + Object[] coords = (Object[]) posMap.get("coordinates"); + for (Object coord : coords) { + Map tempMap = (Map) coord; + SignFieldPosition sfp = new SignFieldPosition(); + sfp.setPositionPage(posMap.get("pageNum") + ""); + sfp.setPositionX(toFloat(tempMap.get("positionX")) + 150f); + sfp.setPositionY(toFloat(tempMap.get("positionY"))); + posList.add(sfp); + } + } + return posList; + } + } + throw new RuntimeException("未找到关键字位置: " + keyword); + } + + private String getStringField(FormDataVo vo, String field) throws NoSuchFieldException { + return vo.getFieldData(field) != null ? vo.getFieldData(field).getStringValue() : null; + } + + private Float toFloat(Object val) { + return val instanceof Number ? ((Number) val).floatValue() : Float.parseFloat(val.toString()); + } + + @Override + public String getNodeId() { + return "nd_20250702"; + } + + @Override + public String getNodeName() { + return "E签宝甲方单方签署节点"; + } +} diff --git a/esign/src/main/java/com/seeyon/apps/esign/po/NormalSignFieldConfig.java b/esign/src/main/java/com/seeyon/apps/esign/po/NormalSignFieldConfig.java index 85e435d..40d8795 100644 --- a/esign/src/main/java/com/seeyon/apps/esign/po/NormalSignFieldConfig.java +++ b/esign/src/main/java/com/seeyon/apps/esign/po/NormalSignFieldConfig.java @@ -4,6 +4,7 @@ public class NormalSignFieldConfig { private Boolean autoSign; private Integer signFieldStyle; private SignFieldPosition signFieldPosition; + private String assignedSealId; //指定签章id public Boolean getAutoSign() { return autoSign; @@ -28,4 +29,12 @@ public class NormalSignFieldConfig { public void setSignFieldPosition(SignFieldPosition signFieldPosition) { this.signFieldPosition = signFieldPosition; } + + public String getAssignedSealId() { + return assignedSealId; + } + + public void setAssignedSealId(String assignedSealId) { + this.assignedSealId = assignedSealId; + } } diff --git a/esign/src/main/java/com/seeyon/apps/esign/po/SealInfoVo.java b/esign/src/main/java/com/seeyon/apps/esign/po/SealInfoVo.java new file mode 100644 index 0000000..327bdc4 --- /dev/null +++ b/esign/src/main/java/com/seeyon/apps/esign/po/SealInfoVo.java @@ -0,0 +1,50 @@ +package com.seeyon.apps.esign.po; + +public class SealInfoVo { + + private String sealId; //印章ID + private String sealName; //印章名称 + private String sealBizTypeDescription; //印章描述 + private String statusDescription; //印章状态描述 + private String sealImageDownloadUrl; //印章图片下载地址 + + public String getSealId() { + return sealId; + } + + public void setSealId(String sealId) { + this.sealId = sealId; + } + + public String getSealName() { + return sealName; + } + + public void setSealName(String sealName) { + this.sealName = sealName; + } + + public String getSealBizTypeDescription() { + return sealBizTypeDescription; + } + + public void setSealBizTypeDescription(String sealBizTypeDescription) { + this.sealBizTypeDescription = sealBizTypeDescription; + } + + public String getStatusDescription() { + return statusDescription; + } + + public void setStatusDescription(String statusDescription) { + this.statusDescription = statusDescription; + } + + public String getSealImageDownloadUrl() { + return sealImageDownloadUrl; + } + + public void setSealImageDownloadUrl(String sealImageDownloadUrl) { + this.sealImageDownloadUrl = sealImageDownloadUrl; + } +} diff --git a/esign/src/main/java/com/seeyon/apps/esign/po/SignField.java b/esign/src/main/java/com/seeyon/apps/esign/po/SignField.java index e725da3..915551e 100644 --- a/esign/src/main/java/com/seeyon/apps/esign/po/SignField.java +++ b/esign/src/main/java/com/seeyon/apps/esign/po/SignField.java @@ -6,7 +6,6 @@ public class SignField { private Integer signFieldType; private NormalSignFieldConfig normalSignFieldConfig; private RemarkSignFieldConfig remarkSignFieldConfig; - private SignDateConfig signDateConfig; public String getFileId() { return fileId; @@ -40,11 +39,4 @@ public class SignField { this.remarkSignFieldConfig = remarkSignFieldConfig; } - public SignDateConfig getSignDateConfig() { - return signDateConfig; - } - - public void setSignDateConfig(SignDateConfig signDateConfig) { - this.signDateConfig = signDateConfig; - } } diff --git a/esign/src/main/java/com/seeyon/apps/esign/service/SealService.java b/esign/src/main/java/com/seeyon/apps/esign/service/SealService.java index a7d6eb7..38ebc43 100644 --- a/esign/src/main/java/com/seeyon/apps/esign/service/SealService.java +++ b/esign/src/main/java/com/seeyon/apps/esign/service/SealService.java @@ -6,37 +6,56 @@ import com.seeyon.aicloud.common.JsonUtils; import com.seeyon.apps.esign.config.EsignConfigProvider; import com.seeyon.apps.esign.constants.EsignApiUrl; import com.seeyon.apps.esign.constants.EsignConfigConstants; +import com.seeyon.apps.esign.form.FormColumn; +import com.seeyon.apps.esign.form.FormDataOperator; +import com.seeyon.apps.esign.form.FormExportUtil; +import com.seeyon.apps.esign.form.FormWhereCondition; import com.seeyon.apps.esign.po.EsignApiHeader; import com.seeyon.apps.esign.po.EsignBaseResp; +import com.seeyon.apps.esign.po.SealInfoVo; import com.seeyon.apps.esign.utils.HttpClient; +import com.seeyon.ctp.common.AppContext; +import com.seeyon.ctp.common.exceptions.BusinessException; +import com.seeyon.ctp.services.ServiceException; +import com.seeyon.v3x.services.form.FormFactory; +import com.seeyon.v3x.services.form.bean.FormExport; +import com.seeyon.v3x.services.form.bean.ValueExport; +import org.apache.commons.logging.Log; +import org.apache.commons.logging.LogFactory; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.stereotype.Component; -import java.util.ArrayList; -import java.util.LinkedList; -import java.util.List; -import java.util.Map; +import java.util.*; @Component public class SealService { + private static final Log log = LogFactory.getLog(SealService.class); @Autowired private EsignConfigProvider configProvider; + private FormFactory formFactory; - public void grantSeal(Map params) throws Exception { + public FormFactory getFormFactory() { + if (formFactory == null) { + formFactory = (FormFactory) AppContext.getBean("formFactory"); + } + return formFactory; + } + + public void grantSeal(Map params) throws Exception { JsonObject reqParams = new JsonObject(); String sealId = getSealId((String) params.get("orgId"), (String) params.get("sealName")); - reqParams.put("sealId",sealId); + reqParams.put("sealId", sealId); List authorizedPsnIds = new ArrayList<>(); authorizedPsnIds.add((String) params.get("accountId")); - reqParams.put("authorizedPsnIds",authorizedPsnIds); - reqParams.put("sealRole","SEAL_USER"); - reqParams.put("transactorPsnId",params.get("managerId")); + reqParams.put("authorizedPsnIds", authorizedPsnIds); + reqParams.put("sealRole", "SEAL_USER"); + reqParams.put("transactorPsnId", params.get("managerId")); JSONObject sealAuthScope = new JSONObject(); List templateIds = new ArrayList<>(); templateIds.add("ALL"); - sealAuthScope.put("templateIds",templateIds); - reqParams.put("sealAuthScope",sealAuthScope); + sealAuthScope.put("templateIds", templateIds); + reqParams.put("sealAuthScope", sealAuthScope); EsignApiHeader esignApiHeader = EsignApiHeader.build(); esignApiHeader.appId(configProvider.getBizConfigByKey(EsignConfigConstants.APP_ID)) .httpMethod("POST") @@ -45,7 +64,7 @@ public class SealService { .contentMD5(reqParams.toString()) .signature(configProvider.getBizConfigByKey(EsignConfigConstants.APP_SECRET)); String url = configProvider.getBizConfigByKey(EsignConfigConstants.ESIGN_HOST) + EsignApiUrl.SEAL_GRANT_URL; - HttpClient.httpPostRaw(url,reqParams.toString(),esignApiHeader.convert2Headers(),null); + HttpClient.httpPostRaw(url, reqParams.toString(), esignApiHeader.convert2Headers(), null); } private String getSealId(String orgId, String sealName) throws Exception { @@ -56,20 +75,62 @@ public class SealService { esignApiHeader.appId(configProvider.getBizConfigByKey(EsignConfigConstants.APP_ID)) .httpMethod("GET") .heads("") - .pathAndParameters(EsignApiUrl.QUERY_SEAL_URL + "?" + HttpClient.sortQueryString("orgId=" + orgId + "&pageNo=" + pageNo + "&pageSize=" + pageSize)) + .pathAndParameters(EsignApiUrl.SEAL_QUERY_URL + "?" + HttpClient.sortQueryString("orgId=" + orgId + "&pageNo=" + pageNo + "&pageSize=" + pageSize)) .contentMD5("") .signature(configProvider.getBizConfigByKey(EsignConfigConstants.APP_SECRET)); - String url = host + EsignApiUrl.QUERY_SEAL_URL + "?orgId=" + orgId + "&pageNo=" + pageNo + "&pageSize=" + pageSize; + String url = host + EsignApiUrl.SEAL_QUERY_URL + "?orgId=" + orgId + "&pageNo=" + pageNo + "&pageSize=" + pageSize; String respStr = HttpClient.httpGet(url, esignApiHeader.convert2Headers(), "UTF-8"); EsignBaseResp esignBaseResp = JsonUtils.parseObject(respStr, EsignBaseResp.class); - Map data = (Map) esignBaseResp.getData(); - LinkedList seals = (LinkedList) data.get("seals"); + Map data = (Map) esignBaseResp.getData(); + LinkedList seals = (LinkedList) data.get("seals"); for (Object seal : seals) { - Map sealMap = (Map) seal; - if(sealMap.get("sealName").equals(sealName)){ + Map sealMap = (Map) seal; + if (sealMap.get("sealName").equals(sealName)) { return (String) sealMap.get("sealId"); } } return null; } + + public void upsertOaSealDoc(SealInfoVo vo) { + FormDataOperator formDataOperator = new FormDataOperator(); + String formNo = configProvider.getBizConfigByKey(EsignConfigConstants.sealInfoFormCode); + List conditions = new ArrayList<>(); + conditions.add(FormWhereCondition.build().display("印章ID").value(vo.getSealId())); + FormColumn formColumn = null; + try { + formColumn = formDataOperator.queryOneRowFormData(formNo, null, conditions); + } catch (Exception e) { + log.error("查询印章信息失败: " + e.getMessage(), e); + } + if (formColumn == null) { + if ("已启用".equals(vo.getStatusDescription())) { + Map params = new HashMap<>(); + params.put("印章ID", vo.getSealId()); + params.put("印章名称", vo.getSealName()); + params.put("印章类型", vo.getSealBizTypeDescription()); + params.put("印章状态", vo.getStatusDescription()); +// params.put("印章图片地址",vo.getSealImageDownloadUrl()); + + FormExport formExport = new FormExport(); + FormExportUtil formExportUtil = new FormExportUtil(); + List valueExport = formExportUtil.setFormValue(params); + formExport.setValues(valueExport); + try { + getFormFactory().importBusinessFormData(configProvider.getBizConfigByKey(EsignConfigConstants.formLoginName), configProvider.getBizConfigByKey(EsignConfigConstants.sealInfoFormCode), + formExport, new String[]{}); + } catch (ServiceException e) { + log.error(vo.getSealName() + "信息写入OA档案失败," + e.getMessage(), e); + } + } + } else { + if (!"已启用".equals(vo.getSealBizTypeDescription())) { + try { + formDataOperator.deleteByCondition(formNo, conditions); + } catch (Exception e) { + log.error("删除停用印章失败" + e.getMessage(), e); + } + } + } + } }