From 907342adb48bb033bb7492104c742208fc7d3823 Mon Sep 17 00:00:00 2001 From: RuicyWu <1063154311@qq.com> Date: Fri, 12 Jun 2026 11:35:36 +0800 Subject: [PATCH] =?UTF-8?q?=E4=BC=98=E5=8C=96=E4=BB=A3=E7=A0=81?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../component/esign/spring/spring-bean.xml | 1 + .../apps/esign/constants/EsignApiUrl.java | 1 + .../esign/constants/EsignConfigConstants.java | 10 +- .../constants/FlowFormFieldConstants.java | 14 + .../constants/JsonParamKeyConstants.java | 26 + .../DefaultEsignCallBackController.java | 6 +- .../seeyon/apps/esign/job/SealDocSyncJob.java | 15 +- .../esign/logfile/EsignParamRecordUtils.java | 22 + .../com/seeyon/apps/esign/msg/MessageVo.java | 47 ++ .../esign/node/EsignAntiFakeSignNode.java | 187 +++++++ .../esign/node/EsignMultipleSignerNode.java | 458 ++++++++-------- .../apps/esign/node/EsignOneSignerNode.java | 488 ++++++++---------- .../esign/po/esignapi/EsignApiHeader.java | 2 +- .../apps/esign/po/param/FlowParamSource.java | 145 ++---- .../apps/esign/po/param/JsonParamSource.java | 70 +-- .../esign/po/signer/DefaultSignerBuilder.java | 458 +++++++++++----- .../esign/po/signer/JsonSignerBuilder.java | 5 +- .../seeyon/apps/esign/po/signer/OrgInfo.java | 9 + .../apps/esign/po/signer/SignParty.java | 9 + .../apps/esign/po/signer/SignerBuilder.java | 6 +- .../esign/po/upload/GetUploadUrlResp.java | 9 + .../esign/service/ContractCreateService.java | 2 +- .../apps/esign/service/EsignAuthService.java | 7 +- .../esign/service/EsignByTemplateService.java | 4 +- .../service/EsignFileTemplateService.java | 39 +- .../esign/service/EsignFlowQueryService.java | 5 +- .../esign/service/EsignUploadFileService.java | 25 +- .../FlowFormSignParamBuildFactory.java | 60 ++- .../NormalFormSignParamBuildFactory.java | 17 +- .../apps/esign/service/SealService.java | 32 +- .../apps/esign/service/SignLinkService.java | 18 +- .../apps/esign/service/SignParamSource.java | 4 + .../apps/esign/service/TokenCacheManager.java | 121 +++-- .../apps/esign/utils/CallbackUrlBuilder.java | 33 ++ .../com/seeyon/apps/esign/utils/FileUtil.java | 2 +- .../esign/EsignFlowQueryResource.java | 2 +- .../esign/EsignTemplateResource.java | 4 +- 37 files changed, 1441 insertions(+), 922 deletions(-) create mode 100644 src/main/java/com/seeyon/apps/esign/constants/FlowFormFieldConstants.java create mode 100644 src/main/java/com/seeyon/apps/esign/constants/JsonParamKeyConstants.java create mode 100644 src/main/java/com/seeyon/apps/esign/logfile/EsignParamRecordUtils.java create mode 100644 src/main/java/com/seeyon/apps/esign/node/EsignAntiFakeSignNode.java create mode 100644 src/main/java/com/seeyon/apps/esign/utils/CallbackUrlBuilder.java diff --git a/seeyon/WEB-INF/cfgHome/component/esign/spring/spring-bean.xml b/seeyon/WEB-INF/cfgHome/component/esign/spring/spring-bean.xml index 148f59e..c64e43e 100644 --- a/seeyon/WEB-INF/cfgHome/component/esign/spring/spring-bean.xml +++ b/seeyon/WEB-INF/cfgHome/component/esign/spring/spring-bean.xml @@ -17,6 +17,7 @@ + diff --git a/src/main/java/com/seeyon/apps/esign/constants/EsignApiUrl.java b/src/main/java/com/seeyon/apps/esign/constants/EsignApiUrl.java index 5c201d8..446dbbd 100644 --- a/src/main/java/com/seeyon/apps/esign/constants/EsignApiUrl.java +++ b/src/main/java/com/seeyon/apps/esign/constants/EsignApiUrl.java @@ -16,4 +16,5 @@ public class EsignApiUrl { public static final String TOKEN_GET_URL = "/v1/oauth2/access_token"; public static final String SEAL_QUERY_URL = "/v3/seals/org-own-seal-list"; public static final String SIGN_LINK_GET_URL ="/v3/sign-flow/{signFlowId}/sign-url"; + public static final String QUERY_FILEUPLOADSTATUS = "/v3/files/"; } diff --git a/src/main/java/com/seeyon/apps/esign/constants/EsignConfigConstants.java b/src/main/java/com/seeyon/apps/esign/constants/EsignConfigConstants.java index aea78a7..4899ddc 100644 --- a/src/main/java/com/seeyon/apps/esign/constants/EsignConfigConstants.java +++ b/src/main/java/com/seeyon/apps/esign/constants/EsignConfigConstants.java @@ -2,12 +2,8 @@ package com.seeyon.apps.esign.constants; public enum EsignConfigConstants { plugin("esign",""), - APP_ID("7438886882",""), - APP_SECRET("325c8cc6c2a303d6cf1fb5657a16e591",""), OA_HOST("http://cd-2.frp.one:58336",""), ESIGN_HOST("",""), - SIGN_SERVICE_PROVIDER("ESIGN",""), - UNITNAME("","平台方组织名称"), FORMEDITLOGINNAME("","表单修改登录名"), updateAccountName("表单","平台方单位名"), getTokenUrl("/seeyon/rest/token/","调用获取TOKEN地址"), @@ -15,13 +11,17 @@ public enum EsignConfigConstants { restName("",""), restPwd("",""), signAutoDate("","是否自动加盖签署日期"), - eSignOrgId("61f735dd368c45a191f43a6711c3c88a","e签宝平台方组织id"), formLoginName("2019","表单数据录入登录名"), sealInfoFormCode("","印章档案编码"), aSignPositionKeyword("甲方盖章/签字","甲方签署位置关键字"), bSignPositionKeyword("乙方盖章/签字","乙方签署位置关键字"), lpSignPositionKeyword("法定代表人","法人签署位置关键字"), signLinkSave("false","是否保存签署链接"), + ESIGN_APP_UNITMAP("","E签宝应用APPID与公司映射关系"), + ESIGN_APP_SECRETMAP("325c8cc6c2a303d6cf1fb5657a16e591","e签宝appIDSecret映射"), + ENABLEANTIFAKESIGN("","是否加盖防伪章"), + FIXAPPUNIT("true","是否固定要用的E签宝应用主体单位"), + FIXAPPUNITNAME("","固定要用的E签宝应用主体单位名称") ; private String defaultValue; diff --git a/src/main/java/com/seeyon/apps/esign/constants/FlowFormFieldConstants.java b/src/main/java/com/seeyon/apps/esign/constants/FlowFormFieldConstants.java new file mode 100644 index 0000000..fba8f53 --- /dev/null +++ b/src/main/java/com/seeyon/apps/esign/constants/FlowFormFieldConstants.java @@ -0,0 +1,14 @@ +package com.seeyon.apps.esign.constants; + +/** + * 流程表单字段显示名常量 + */ +public final class FlowFormFieldConstants { + + private FlowFormFieldConstants() {} + + public static final String CONTRACT_TITLE = "合同名称"; + public static final String CONTRACT_APPROVAL_ATTACHMENT = "合同审批附件"; + public static final String SIGNED_ATTACHMENT = "盖章后合同附件"; + public static final String SIGN_STATUS = "签署状态"; +} diff --git a/src/main/java/com/seeyon/apps/esign/constants/JsonParamKeyConstants.java b/src/main/java/com/seeyon/apps/esign/constants/JsonParamKeyConstants.java new file mode 100644 index 0000000..01fa8a5 --- /dev/null +++ b/src/main/java/com/seeyon/apps/esign/constants/JsonParamKeyConstants.java @@ -0,0 +1,26 @@ +package com.seeyon.apps.esign.constants; + +/** + * JSON 接口参数 key 常量 + */ +public final class JsonParamKeyConstants { + + private JsonParamKeyConstants() {} + + public static final String CONTRACT_TITLE = "contractTitle"; + public static final String BY_FILE = "byFile"; + public static final String FORM_ID = "formId"; + public static final String TABLE_NAME = "tableName"; + public static final String SIGN_FILE_REF_ID = "signFileRefId"; + public static final String SIGNED_FILE_FIELD = "signedFileField"; + public static final String SIGN_STATUS_FIELD = "signStatusField"; + public static final String SIGN_STATUS_ENUM_ID = "signStatusEnumId"; + public static final String SIGNERS = "signers"; + public static final String SIGNER_TYPE = "signerType"; + public static final String SIGN_ORDER = "signOrder"; + public static final String NAME = "name"; + public static final String PHONE = "phone"; + public static final String SIGN_POS_KEYWORD = "signPosKeyword"; + public static final String ORG_NAME = "orgName"; + public static final String ORG_CODE = "orgCode"; +} diff --git a/src/main/java/com/seeyon/apps/esign/controller/DefaultEsignCallBackController.java b/src/main/java/com/seeyon/apps/esign/controller/DefaultEsignCallBackController.java index dc6f93f..8706129 100644 --- a/src/main/java/com/seeyon/apps/esign/controller/DefaultEsignCallBackController.java +++ b/src/main/java/com/seeyon/apps/esign/controller/DefaultEsignCallBackController.java @@ -9,6 +9,7 @@ import com.seeyon.apps.esign.service.EsignUploadFileService; import com.seeyon.apps.esign.service.EsignCallbackFlowBizService; import com.seeyon.ctp.common.AppContext; import com.seeyon.ctp.common.controller.BaseController; +import com.seeyon.ctp.util.annotation.NeedlessCheckLogin; import javax.servlet.http.HttpServletRequest; @@ -25,7 +26,7 @@ public class DefaultEsignCallBackController extends BaseController { private EsignUploadFileService esignUploadFileService = (EsignUploadFileService) AppContext.getBean("esignUploadFileService"); private EsignCallbackFlowBizService esignCallbackFlowBizService = (EsignCallbackFlowBizService) AppContext.getBean("esignCallbackFlowBizService"); - + @NeedlessCheckLogin public void callback(HttpServletRequest request, HttpServletResponse response) { try { log.info("签署回调触发"); @@ -34,6 +35,7 @@ public class DefaultEsignCallBackController extends BaseController { String tableName = request.getParameter("tablename"); String updatefield = request.getParameter("updatefield"); String statusfield = request.getParameter("statusfield");; + String appId = request.getParameter("xId"); BufferedReader reader = request.getReader(); StringBuilder sb = new StringBuilder(); String line; @@ -50,7 +52,7 @@ public class DefaultEsignCallBackController extends BaseController { log.info("签署回调当前流程: " + flowId); if(action.equals("SIGN_FLOW_COMPLETE")) { if(callbackParams.getSignFlowStatus() == 2) { - Object[] fileInfos = esignUploadFileService.getDownloadFileInfo(flowId); + Object[] fileInfos = esignUploadFileService.getDownloadFileInfo(appId,flowId); esignCallbackFlowBizService.handleSuccessSignCallbackBiz(tableName,updatefield,statusfield,formId,fileInfos); }else if(callbackParams.getSignFlowStatus() == 5){ //合同过期 diff --git a/src/main/java/com/seeyon/apps/esign/job/SealDocSyncJob.java b/src/main/java/com/seeyon/apps/esign/job/SealDocSyncJob.java index 922fdd5..d2c56f5 100644 --- a/src/main/java/com/seeyon/apps/esign/job/SealDocSyncJob.java +++ b/src/main/java/com/seeyon/apps/esign/job/SealDocSyncJob.java @@ -16,6 +16,7 @@ import org.apache.commons.logging.Log; import org.apache.commons.logging.LogFactory; +import java.util.List; import java.util.Map; @@ -30,22 +31,24 @@ public class SealDocSyncJob extends AbstractQuartzTask { @Override public String taskRun(String s) throws Exception { log.info("开始执行印章同步任务"); - syncSeals(); + List appIds = tokenCacheManager.getAppIds(); + for (String appId : appIds) { + syncSeals(appId); + } log.info("印章同步任务完成"); return ""; } - private void syncSeals() { - String orgId = configProvider.getBizConfigByKey(EsignConfigConstants.eSignOrgId); + private void syncSeals(String appId) { 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()); + EsignApiHeader esignApiHeader = EsignApiHeader.build().appId(appId); + esignApiHeader.token(tokenCacheManager.getToken(appId)); EsignBaseResp esignBaseResp = null; Map dataMap = null; do { - String url = host + EsignApiUrl.SEAL_QUERY_URL + "?" + "orgId=" + orgId + "&pageNum=" + (pageNum++) + "&pageSize=" + pageSize; + String url = host + EsignApiUrl.SEAL_QUERY_URL + "?" + "orgId=" + tokenCacheManager.getOrgNameByAppId(appId) + "&pageNum=" + (pageNum++) + "&pageSize=" + pageSize; String respStr = HttpClient.httpGet(url, esignApiHeader.convert2Headers(),"UTF-8"); esignBaseResp = JsonUtils.parseObject(respStr, EsignBaseResp.class); if(esignBaseResp.getCode() != 0) { diff --git a/src/main/java/com/seeyon/apps/esign/logfile/EsignParamRecordUtils.java b/src/main/java/com/seeyon/apps/esign/logfile/EsignParamRecordUtils.java new file mode 100644 index 0000000..f8f7ff7 --- /dev/null +++ b/src/main/java/com/seeyon/apps/esign/logfile/EsignParamRecordUtils.java @@ -0,0 +1,22 @@ +package com.seeyon.apps.esign.logfile; + +import com.seeyon.aicloud.common.JsonUtils; +import com.seeyon.v3x.dee.util.DateUtil; +import org.apache.commons.io.FileUtils; + +import java.io.File; +import java.util.Date; +import java.util.Map; + +public class EsignParamRecordUtils { + + public static void saveEsignParamRecord(Map params) { + try { + String str = "/home/seeyon/Seeyon/A8/ApacheJetspeed/logs_sy"; + String date = DateUtil.format(new Date(), "yyyyMMddHHmmss"); + FileUtils.writeStringToFile(new File(str+"/esignParams/" + date + ".json"), JsonUtils.toJSONString(params), "UTF-8"); + }catch (Exception e){ + + } + } +} diff --git a/src/main/java/com/seeyon/apps/esign/msg/MessageVo.java b/src/main/java/com/seeyon/apps/esign/msg/MessageVo.java index 1675d50..28ec159 100644 --- a/src/main/java/com/seeyon/apps/esign/msg/MessageVo.java +++ b/src/main/java/com/seeyon/apps/esign/msg/MessageVo.java @@ -1,12 +1,19 @@ package com.seeyon.apps.esign.msg; +import java.util.Map; + public class MessageVo { + private String title; private String messageType; private String messageContent; + private String messageText; private String messageTime; private String messageReceiver; private String bizId; + private Boolean sendSubscribeMsg; + private String subscribeMsgMode; + private Map templateValue; public String getMessageType() { return messageType; @@ -47,4 +54,44 @@ public class MessageVo { public void setBizId(String bizId) { this.bizId = bizId; } + + public String getTitle() { + return title; + } + + public void setTitle(String title) { + this.title = title; + } + + public String getMessageText() { + return messageText; + } + + public void setMessageText(String messageText) { + this.messageText = messageText; + } + + public Boolean getSendSubscribeMsg() { + return sendSubscribeMsg; + } + + public void setSendSubscribeMsg(Boolean sendSubscribeMsg) { + this.sendSubscribeMsg = sendSubscribeMsg; + } + + public String getSubscribeMsgMode() { + return subscribeMsgMode; + } + + public void setSubscribeMsgMode(String subscribeMsgMode) { + this.subscribeMsgMode = subscribeMsgMode; + } + + public Map getTemplateValue() { + return templateValue; + } + + public void setTemplateValue(Map templateValue) { + this.templateValue = templateValue; + } } diff --git a/src/main/java/com/seeyon/apps/esign/node/EsignAntiFakeSignNode.java b/src/main/java/com/seeyon/apps/esign/node/EsignAntiFakeSignNode.java new file mode 100644 index 0000000..77f2312 --- /dev/null +++ b/src/main/java/com/seeyon/apps/esign/node/EsignAntiFakeSignNode.java @@ -0,0 +1,187 @@ +package com.seeyon.apps.esign.node; + +import com.seeyon.aicloud.common.JsonUtils; +import com.seeyon.apps.collaboration.po.ColSummary; +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.po.param.FlowParamSource; +import com.seeyon.apps.esign.po.signer.OrgInfo; +import com.seeyon.apps.esign.po.signer.PersonInfo; +import com.seeyon.apps.esign.po.signer.SignParty; +import com.seeyon.apps.esign.po.signer.SignerType; +import com.seeyon.apps.esign.service.ContractCreateService; +import com.seeyon.apps.esign.service.SealService; +import com.seeyon.apps.esign.service.TokenCacheManager; +import com.seeyon.apps.ext.workflow.vo.FieldDataVo; +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.ctp.common.AppContext; +import com.seeyon.ctp.common.exceptions.BusinessException; +import com.seeyon.ctp.organization.bo.V3xOrgMember; +import com.seeyon.ctp.organization.manager.OrgManager; +import com.seeyon.ctp.util.JDBCAgent; +import com.seeyon.utils.form.*; +import org.apache.commons.logging.Log; +import org.apache.commons.logging.LogFactory; + +import java.util.ArrayList; +import java.util.List; +import java.util.Map; + + +public class EsignAntiFakeSignNode extends ACommonSuperNode { + + private static final Log log = LogFactory.getLog(EsignAntiFakeSignNode.class); + private EsignConfigProvider configProvider = EsignConfigProvider.getInstance(); + private TokenCacheManager tokenCacheManager = (TokenCacheManager) AppContext.getBean("tokenCacheManager"); + private ContractCreateService contractCreateService = (ContractCreateService) AppContext.getBean("contractCreateService"); + private SealService sealService = (SealService) AppContext.getBean("sealService"); + + @Override + public String getPluginId() { + return EsignConfigConstants.getPluginId(); + } + + @Override + public String getFormParse() { + return ""; + } + + @Override + public SuperNodeContext proceed(String s, FormDataVo formDataVo, FormDataMasterBean formDataMasterBean) throws Exception { + SuperNodeContext context = new SuperNodeContext(); + context.setNeedSave(true); + log.info("进入E签宝防伪签署签署集成超级节点"); + try { + FlowParamSource source = new FlowParamSource(); + source.setConfigProvider(configProvider); + source.setFormDataVo(formDataVo); + source.setDoAutoSign(true); + String unitName = configProvider.getBizConfigByKey(EsignConfigConstants.FIXAPPUNITNAME); + String appId = tokenCacheManager.getAppIdByOrgName(unitName); + source.setAppId(appId); + source.setMasterBean(formDataMasterBean); + source.setUseKeyWordPositing(false); + source.setSignerParties(buildSigners(formDataVo,true,unitName)); + String esignFlowId = contractCreateService.startSign(source); + if(esignFlowId == null) { + return context.back("E签宝签署发起失败"); + } + log.info("E签宝签署流程ID: " + esignFlowId + " , OA超级节点ID:" + formDataVo.getToken()); + log.info("E签宝多方签署合同已发送: " + esignFlowId); + return context.wait("等待签署结束"); + } catch (Exception e) { + log.error("E签宝签署失败", e); + e.printStackTrace(); + context.setErrMsg("E签宝签署失败: " + e.getMessage()); + return context.back("E签宝签署失败: " + e.getMessage()); + } + } + + private String getStringField(FormDataVo vo, String field) { + try { + FieldDataVo fieldData = vo.getFieldData(field); + return fieldData.getStringValue(); + }catch (Exception e) { + return null; + } + } + + private V3xOrgMember getPsn(Long memberId) throws NoSuchFieldException { + OrgManager orgManager = (OrgManager) AppContext.getBean("orgManager"); + if(memberId != null) { + try { + V3xOrgMember member = orgManager.getMemberById(memberId); + return member; + }catch (Exception e){ + + } + } + return null; + } + + private String getLastSenderId(Long caseId) { + List columns = new ArrayList<>(); + columns.add("SENDER_ID"); + SqlBuildParam param = new SqlBuildParam(); + List conditions = new ArrayList<>(); + conditions.add(FormWhereCondition.build().fieldName("CASE_ID").value(caseId)); + param.setSqlType(SqlType.SELECT); + param.setTableName("ctp_affair"); + param.setQueryColumns(columns); + param.setConditions(conditions); + param.setPageNo(1); + param.setPageSize(1); + param.setOrderField("UPDATE_DATE"); + param.setSortType("DESC"); + Map sqlMap = FormTableExecutor.generateSql(param); + JDBCAgent agent = new JDBCAgent(); + try { + agent.execute((String)sqlMap.get("sql"), (List)sqlMap.get("params")); + log.info("执行sql为: " + sqlMap.get("sql")); + List> rows = agent.resultSetToList(); + if(rows.size() <= 0) { + return null; + } + Map map = rows.get(0); + return map.get("sender_id") + ""; + } catch (Exception e) { + log.error("执行sql为: " + sqlMap.get("sql")); + log.error("执行sql参数为: " + JsonUtils.toJSONString(sqlMap.get("params"))); + log.error(e.getMessage(), e); + } finally { + agent.close(); + } + + return null; + } + + private List buildSigners(FormDataVo formDataVo, Boolean doAutoSign, String unitName) throws NoSuchFieldException, BusinessException { + List parties = new ArrayList<>(); + SignParty party = new SignParty(); + ColSummary colSummary = formDataVo.getColSummary(); + Long caseId = colSummary.getCaseId(); + String senderId = getLastSenderId(caseId); + party.setPartyId("防伪章签署方"); + party.setSignOrder(2); + party.setSignerType(SignerType.ORG); + party.setSignAcrossPage(false); + party.setAutoSign(doAutoSign); + party.setSealId(sealService.getAntiFakeSealId(unitName)); + OrgInfo orgInfo = new OrgInfo(); + party.setOrgInfo(orgInfo); + if(!doAutoSign){ + if(senderId == null) { + return null; + } + V3xOrgMember psn = getPsn(Long.parseLong(senderId)); + String psnName = psn.getName(); + if(psnName == null) { + throw new RuntimeException("防伪章签署经办人为空"); + } + String psnMobile = psn.getTelNumber(); + String orgName = unitName; + PersonInfo personInfo = new PersonInfo(); + orgInfo.setOrgName(orgName); + personInfo.setName(psnName); + personInfo.setPhone(psnMobile); + orgInfo.setTransactor(personInfo); + }else { + orgInfo.setOrgId(tokenCacheManager.getOrgIdByOrgName(unitName)); + } + parties.add(party); + return parties; + } + + @Override + public String getNodeId() { + return "nd_20260508"; + } + + @Override + public String getNodeName() { + return "E签宝防伪签署节点"; + } +} diff --git a/src/main/java/com/seeyon/apps/esign/node/EsignMultipleSignerNode.java b/src/main/java/com/seeyon/apps/esign/node/EsignMultipleSignerNode.java index 819e909..fd3abb7 100644 --- a/src/main/java/com/seeyon/apps/esign/node/EsignMultipleSignerNode.java +++ b/src/main/java/com/seeyon/apps/esign/node/EsignMultipleSignerNode.java @@ -1,38 +1,44 @@ package com.seeyon.apps.esign.node; +import com.seeyon.aicloud.common.JsonUtils; +import com.seeyon.apps.collaboration.po.ColSummary; 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.po.param.FlowParamSource; -import com.seeyon.apps.esign.po.signfield.NormalSignFieldConfig; -import com.seeyon.apps.esign.po.signfield.SignField; -import com.seeyon.apps.esign.po.signfield.SignFieldPosition; -import com.seeyon.apps.esign.po.signer.Signer; +import com.seeyon.apps.esign.po.signer.OrgInfo; +import com.seeyon.apps.esign.po.signer.PersonInfo; +import com.seeyon.apps.esign.po.signer.SignParty; +import com.seeyon.apps.esign.po.signer.SignerType; import com.seeyon.apps.esign.service.*; import com.seeyon.apps.ext.workflow.vo.FieldDataVo; 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.ctp.common.AppContext; +import com.seeyon.ctp.common.exceptions.BusinessException; +import com.seeyon.ctp.organization.bo.V3xOrgMember; +import com.seeyon.ctp.organization.manager.OrgManager; +import com.seeyon.ctp.util.JDBCAgent; +import com.seeyon.utils.form.*; +import org.apache.commons.lang.StringUtils; import org.apache.commons.logging.Log; import org.apache.commons.logging.LogFactory; +import java.util.ArrayList; +import java.util.List; +import java.util.Map; public class EsignMultipleSignerNode extends ACommonSuperNode { private static final Log log = LogFactory.getLog(EsignMultipleSignerNode.class); - private static final String CONTRACT_NAME_FIELD = "合同名称"; - private static final String CONTRACT_ATTACHMENT_FIELD = "合同审批附件"; - private static final String B_UNIT_NAME_FIELD = "乙方单位名称"; private EsignConfigProvider configProvider = EsignConfigProvider.getInstance(); -// private EsignUploadFileService uploadFileService = (EsignUploadFileService) AppContext.getBean("esignByUploadFileService"); -// private EsignByTemplateService templateService = (EsignByTemplateService) AppContext.getBean("esignByTemplateService"); -// private FlowFormSignParamBuildFactory flowFormSignParamBuildFactory = new FlowFormSignParamBuildFactory(); - + private TokenCacheManager tokenCacheManager = (TokenCacheManager) AppContext.getBean("tokenCacheManager"); private SignLinkService signLinkService = (SignLinkService) AppContext.getBean("signLinkService"); private ContractCreateService contractCreateService = (ContractCreateService) AppContext.getBean("contractCreateService"); + private SealService sealService = (SealService) AppContext.getBean("sealService"); @Override public String getPluginId() { @@ -50,11 +56,20 @@ public class EsignMultipleSignerNode extends ACommonSuperNode { context.setNeedSave(true); log.info("进入E签宝多方签署集成超级节点"); try { -// Map signParams = buildSignParams(formDataVo, formDataMasterBean, true); FlowParamSource source = new FlowParamSource(); source.setConfigProvider(configProvider); source.setFormDataVo(formDataVo); source.setDoAutoSign(true); + String isFixAppUnit = configProvider.getBizConfigByKey(EsignConfigConstants.FIXAPPUNIT); + String unitName = null; + if("true".equals(isFixAppUnit)){ + unitName = configProvider.getBizConfigByKey(EsignConfigConstants.FIXAPPUNITNAME); + }else { + unitName = getStringField(formDataVo,"签订单位"); + } + String appId = tokenCacheManager.getAppIdByOrgName(unitName); + source.setSignerParties(buildSigners(appId,formDataVo,true,getStringField(formDataVo,"签订单位"))); + source.setAppId(appId); source.setMasterBean(formDataMasterBean); String esignFlowId = contractCreateService.startSign(source); if(esignFlowId == null) { @@ -62,10 +77,11 @@ public class EsignMultipleSignerNode extends ACommonSuperNode { } String isSaveSignLink = configProvider.getBizConfigByKey(EsignConfigConstants.signLinkSave); if("true".equals(isSaveSignLink)){ - signLinkService.saveGetLinkParam(formDataVo, formDataMasterBean,esignFlowId); + signLinkService.saveGetLinkParam(formDataVo,esignFlowId,source.getAppId()); } log.info("E签宝签署流程ID: " + esignFlowId + " , OA超级节点ID:" + formDataVo.getToken()); log.info("E签宝多方签署合同已发送: " + esignFlowId); + formDataVo.getNewFieldDataMap().put("电子签合同流程ID", esignFlowId); return context.wait("等待签署结束"); } catch (Exception e) { log.error("E签宝签署失败", e); @@ -75,244 +91,188 @@ public class EsignMultipleSignerNode extends ACommonSuperNode { } } -// 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); -// Map signConfig = new HashMap<>(); -// signConfig.put("showBatchDropSealButton", false); -// config.put("signConfig",signConfig); -// return config; -// } + private String getStringField(FormDataVo vo, String field) { + try { + FieldDataVo fieldData = vo.getFieldData(field); + return StringUtils.isBlank(fieldData.getStringValue()) ? null : fieldData.getStringValue(); + }catch (Exception e) { + return null; + } + } -// private List buildSigners(FormDataVo formDataVo, String fileId) throws Exception { -// List keywords = new ArrayList<>(); -// keywords.add("甲方盖章/签字"); -// keywords.add("乙方盖章/签字"); -// List positions = uploadFileService.getSignPosition(fileId,keywords); -// List bPositions = extractPosition(positions, "乙方盖章/签字"); -// List aPositions = extractPosition(positions, "甲方盖章/签字"); -// String bSignerType = formDataVo.getFieldData("乙方签署类型").getStringValue(); -// -// SignFieldPosition aQiFengposition = new SignFieldPosition(); -// aQiFengposition.setAcrossPageMode("ALL"); -// aQiFengposition.setPositionY(520f); -// SignFieldPosition bQiFengposition = new SignFieldPosition(); -// bQiFengposition.setAcrossPageMode("ALL"); -// bQiFengposition.setPositionY(720f); -// -// aPositions.add(aQiFengposition); -// bPositions.add(bQiFengposition); -// String sealId = getStringField(formDataVo,"甲方印章ID"); -// Signer bSigner = !"组织".equals(bSignerType) ? createPsnSigner(fileId,formDataVo.getFieldData("乙方姓名").getStringValue(),bPositions,1,formDataVo.getFieldData("乙方电话").getStringValue(),false) : createOrgSigner( -// fileId, -// getStringField(formDataVo, B_UNIT_NAME_FIELD), -// 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, aPositions, 2, null, null, null, null, null, null,true -// ,sealId); -// List signers = new ArrayList<>(); -// signers.add(bSigner); -// signers.add(aSigner); -// return signers; -// } + private String getPsnName(FormDataVo formDataVo) throws NoSuchFieldException { + OrgManager orgManager = (OrgManager) AppContext.getBean("orgManager"); + FieldDataVo psn = formDataVo.getFieldData("甲方签署经办人"); + String psnName = null; + if(psn != null) { + try { + V3xOrgMember member = orgManager.getMemberById(Long.parseLong((String)psn.getDbValue())); + psnName = member.getName(); + }catch (Exception e){ -// 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).get(0); -// } -// Map docMap = new HashMap<>(); -// docMap.put("fileId", fileId); -// Thread.sleep(1000); -// List docs = new ArrayList<>(); -// docs.add(docMap); -// Map signFlowConfig = buildSignFlowConfig(formDataVo, formDataMasterBean); -// List signers = buildSigners(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 { -// TableContext tableContext = new TableContext(formDataMasterBean.getFormTable()); -// List updateFields = new ArrayList<>(); -// updateFields.add(FormUpdateField.build().display("合同文件ID").value(fileId)); -// List whereConditions = new ArrayList<>(); -// whereConditions.add(FormWhereCondition.build().display("ID").value(formDataVo.getId())); -// FormTableExecutor.update(tableContext,updateFields,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) { -// try { -// FieldDataVo fieldData = vo.getFieldData(field); -// return fieldData.getStringValue(); -// }catch (Exception e) { -// log.error(e.getMessage()); -// return null; -// } -// } -// -// private Float toFloat(Object val) { -// return val instanceof Number ? ((Number) val).floatValue() : Float.parseFloat(val.toString()); -// } + } + } + return psnName; + } + + private List buildSigners(String appId,FormDataVo formDataVo,Boolean doAutoSign,String orgName) throws NoSuchFieldException, BusinessException { + List parties = new ArrayList<>(); + SignParty aParty = new SignParty(); + aParty.setPartyId("甲方"); + aParty.setSignOrder(2); + aParty.setSignerType(SignerType.ORG); + aParty.setSealId(getStringField(formDataVo,"选择甲方印章")); + aParty.setAutoSign(doAutoSign); + OrgInfo orgInfo = new OrgInfo(); + aParty.setOrgInfo(orgInfo); + if(!doAutoSign){ + String psnName = getPsnName(formDataVo); + if(psnName == null) { + throw new RuntimeException("甲方签署经办人为空"); + } + orgInfo.setOrgName(orgName); + String psnMobile = getStringField(formDataVo,"甲方签署经办人联系方式");; + PersonInfo personInfo = new PersonInfo(); + personInfo.setName(psnName); + personInfo.setPhone(psnMobile); + orgInfo.setTransactor(personInfo); + FieldDataVo isLpSign = formDataVo.getFieldData("是否盖法人章"); + if(isLpSign != null && "是".equals(isLpSign)) { + SignParty lpParty = new SignParty(); + lpParty.setPartyId("法人章"); + lpParty.setAutoSign(false); + lpParty.setSignOrder(3); + lpParty.setSignerType(SignerType.LP); + parties.add(lpParty); + } + }else { + orgInfo.setOrgId(tokenCacheManager.getOrgIdByOrgName(orgName,appId)); + } + parties.add(aParty); + String signWay = getStringField(formDataVo, "签订方式"); + String signWayText = null; + try { + signWayText = EnumMapUtils.getEnumShowValue(signWay); + }catch (Exception e) {} + if(!"甲方线上,乙方线下".equals(signWayText)){ + SignParty bParty = new SignParty(); + bParty.setPartyId("乙方"); + bParty.setSignOrder(1); + try { + String bSignerType = formDataVo.getFieldData("乙方签署类型").getStringValue(); + if(!"组织".equals(bSignerType)) { + PersonInfo bPersonInfo = new PersonInfo(); + bPersonInfo.setPhone(getStringField(formDataVo,"乙方电话")); + bPersonInfo.setName(getStringField(formDataVo,"乙方姓名")); + bParty.setPersonInfo(bPersonInfo); + bParty.setSignerType(SignerType.PERSON); + }else { + OrgInfo bOrgInfo = new OrgInfo(); + bOrgInfo.setLegalName(getStringField(formDataVo,"乙方法人姓名")); + bOrgInfo.setOrgName(getStringField(formDataVo,"乙方单位名称")); + bOrgInfo.setOrgCode(getStringField(formDataVo,"乙方统一社会信用代码")); + bOrgInfo.setLegalIdCardNo(getStringField(formDataVo,"乙方法人身份证号")); + PersonInfo transactor = new PersonInfo(); + transactor.setName(getStringField(formDataVo,"乙方经办人姓名")); + transactor.setIdCardNo(getStringField(formDataVo,"乙方经办人身份证号")); + transactor.setPhone(getStringField(formDataVo,"乙方经办人手机号")); + bOrgInfo.setTransactor(transactor); + bParty.setOrgInfo(bOrgInfo); + bParty.setSignerType(SignerType.ORG); + } + }catch (Exception e){ + e.printStackTrace(); + } + parties.add(bParty); + } + buildAntiFakeSigner(orgName,parties,formDataVo,doAutoSign); + return parties; + } + + private String getLastSenderId(Long caseId) { + List columns = new ArrayList<>(); + columns.add("SENDER_ID"); + SqlBuildParam param = new SqlBuildParam(); + List conditions = new ArrayList<>(); + conditions.add(FormWhereCondition.build().fieldName("CASE_ID").value(caseId)); + param.setSqlType(SqlType.SELECT); + param.setTableName("ctp_affair"); + param.setQueryColumns(columns); + param.setConditions(conditions); + param.setPageNo(1); + param.setPageSize(1); + param.setOrderField("UPDATE_DATE"); + param.setSortType("DESC"); + Map sqlMap = FormTableExecutor.generateSql(param); + JDBCAgent agent = new JDBCAgent(); + try { + agent.execute((String)sqlMap.get("sql"), (List)sqlMap.get("params")); + log.info("执行sql为: " + sqlMap.get("sql")); + List> rows = agent.resultSetToList(); + if(rows.size() <= 0) { + return null; + } + Map map = rows.get(0); + return map.get("sender_id") + ""; + } catch (Exception e) { + log.error("执行sql为: " + sqlMap.get("sql")); + log.error("执行sql参数为: " + JsonUtils.toJSONString(sqlMap.get("params"))); + log.error(e.getMessage(), e); + } finally { + agent.close(); + } + + return null; + } + + private V3xOrgMember getPsn(Long memberId) throws NoSuchFieldException { + OrgManager orgManager = (OrgManager) AppContext.getBean("orgManager"); + if(memberId != null) { + try { + V3xOrgMember member = orgManager.getMemberById(memberId); + return member; + }catch (Exception e){ + + } + } + return null; + } + + private void buildAntiFakeSigner(String orgName,List parties,FormDataVo formDataVo,Boolean doAutoSign) throws NoSuchFieldException, BusinessException {; + String enableAntiFakeSign = configProvider.getBizConfigByKey(EsignConfigConstants.ENABLEANTIFAKESIGN); + if(!"true".equals(enableAntiFakeSign)) { + return; + } + SignParty party = new SignParty(); + ColSummary colSummary = formDataVo.getColSummary(); + Long caseId = colSummary.getCaseId(); + String senderId = getLastSenderId(caseId); + party.setPartyId("防伪章签署方"); + party.setSignOrder(3); + party.setSignerType(SignerType.ORG); + party.setAutoSign(doAutoSign); + OrgInfo orgInfo = new OrgInfo(); + party.setOrgInfo(orgInfo); + String isFixAppUnitName = configProvider.getBizConfigByKey(EsignConfigConstants.FIXAPPUNIT); + String unitName = "true".equals(isFixAppUnitName) ? configProvider.getBizConfigByKey(EsignConfigConstants.FIXAPPUNITNAME) : orgName; + party.setSealId(sealService.getAntiFakeSealId(unitName)); + if(!doAutoSign){ + V3xOrgMember psn = getPsn(Long.parseLong(senderId)); + orgInfo.setOrgName(unitName); + String psnName = psn.getName(); + if(psnName == null) { + throw new RuntimeException("防伪章签署经办人为空"); + } + String psnMobile = psn.getTelNumber(); + PersonInfo personInfo = new PersonInfo(); + personInfo.setName(psnName); + personInfo.setPhone(psnMobile); + orgInfo.setTransactor(personInfo); + }else { + orgInfo.setOrgId(tokenCacheManager.getOrgIdByOrgName(unitName)); + } + parties.add(party); + } @Override public String getNodeId() { diff --git a/src/main/java/com/seeyon/apps/esign/node/EsignOneSignerNode.java b/src/main/java/com/seeyon/apps/esign/node/EsignOneSignerNode.java index 0899b67..9d2ca21 100644 --- a/src/main/java/com/seeyon/apps/esign/node/EsignOneSignerNode.java +++ b/src/main/java/com/seeyon/apps/esign/node/EsignOneSignerNode.java @@ -1,33 +1,44 @@ package com.seeyon.apps.esign.node; +import com.seeyon.aicloud.common.JsonUtils; +import com.seeyon.apps.collaboration.po.ColSummary; 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.po.param.FlowParamSource; +import com.seeyon.apps.esign.po.signer.OrgInfo; +import com.seeyon.apps.esign.po.signer.PersonInfo; +import com.seeyon.apps.esign.po.signer.SignParty; +import com.seeyon.apps.esign.po.signer.SignerType; import com.seeyon.apps.esign.service.ContractCreateService; +import com.seeyon.apps.esign.service.SealService; +import com.seeyon.apps.esign.service.TokenCacheManager; +import com.seeyon.apps.ext.workflow.vo.FieldDataVo; 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.ctp.common.AppContext; +import com.seeyon.ctp.common.exceptions.BusinessException; +import com.seeyon.ctp.organization.bo.V3xOrgMember; +import com.seeyon.ctp.organization.manager.OrgManager; +import com.seeyon.ctp.util.JDBCAgent; +import com.seeyon.utils.form.*; import org.apache.commons.logging.Log; import org.apache.commons.logging.LogFactory; -import java.util.*; +import java.util.ArrayList; +import java.util.List; +import java.util.Map; 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 = "乙方单位名称"; -// @Autowired -// private EsignUploadFileService uploadFileService; -// @Autowired -// private EsignByTemplateService templateService; + private TokenCacheManager tokenCacheManager = (TokenCacheManager) AppContext.getBean("tokenCacheManager"); private EsignConfigProvider configProvider = EsignConfigProvider.getInstance(); private ContractCreateService contractCreateService = (ContractCreateService) AppContext.getBean("contractCreateService"); + private SealService sealService = (SealService) AppContext.getBean("sealService"); @Override public String getPluginId() { @@ -50,6 +61,16 @@ public class EsignOneSignerNode extends ACommonSuperNode { source.setConfigProvider(configProvider); source.setFormDataVo(formDataVo); source.setDoAutoSign(false); + String isFixAppUnit = configProvider.getBizConfigByKey(EsignConfigConstants.FIXAPPUNIT); + String unitName = null; + if("true".equals(isFixAppUnit)){ + unitName = configProvider.getBizConfigByKey(EsignConfigConstants.FIXAPPUNITNAME); + }else { + unitName = getStringField(formDataVo,"签订单位"); + } + String appId = tokenCacheManager.getAppIdByOrgName(unitName); + source.setSignerParties(buildSigners(appId,formDataVo,false,getStringField(formDataVo,"签订单位"))); + source.setAppId(appId); source.setMasterBean(formDataMasterBean); String esignFlowId = contractCreateService.startSign(source); if(esignFlowId == null) { @@ -57,6 +78,7 @@ public class EsignOneSignerNode extends ACommonSuperNode { } log.info("E签宝签署流程ID: " + esignFlowId + " , OA超级节点ID:" + formDataVo.getToken()); log.info("E签宝单方签署合同已发送: " + esignFlowId); + formDataVo.getNewFieldDataMap().put("电子签合同流程ID", esignFlowId); return context.wait("等待签署结束"); } catch (Exception e) { log.error("E签宝签署失败", e); @@ -66,275 +88,6 @@ public class EsignOneSignerNode extends ACommonSuperNode { } } -// 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); -// Map signConfig = new HashMap<>(); -// signConfig.put("showBatchDropSealButton", false); -// config.put("signConfig",signConfig); -// return config; -// } - -// private List buildOnlyASigner(FormDataVo formDataVo, String fileId) throws Exception { -// -// SignFieldPosition aQiFengposition = new SignFieldPosition(); -// aQiFengposition.setAcrossPageMode("ALL"); -// aQiFengposition.setPositionY(520f); -// String sealId = getStringField(formDataVo,"甲方印章ID"); -// String psnName = getStringField(formDataVo,"甲方签署经办人"); -// String psnMobile = getStringField(formDataVo,"甲方签署经办人联系方式"); -// String orgName = configProvider.getBizConfigByKey(EsignConfigConstants.UNITNAME); -// List pos = new ArrayList<>(); -// Map> subFormMap = formDataVo.getSubFormMap(); -// List subDataVos = subFormMap.get("甲方签署位置"); -// Boolean autoSign = true; -// if(subDataVos!= null && subDataVos.size() > 0 && !subDataVos.get(0).isEmpty()){ -// for (FormDataVo subDataVo : subDataVos) { -// Map fieldDataVoMap = subDataVo.getFieldDataVoMap(); -// String pageNo = fieldDataVoMap.get("页码").getStringValue(); -// String positionX = fieldDataVoMap.get("X坐标").getStringValue(); -// String positionY = fieldDataVoMap.get("Y坐标").getStringValue(); -// SignFieldPosition position = new SignFieldPosition(); -// position.setPositionPage(pageNo); -// position.setPositionX(Float.parseFloat(positionX)); -// position.setPositionY(Float.parseFloat(positionY)); -// pos.add(position); -// } -// pos.add(aQiFengposition); -// }else { -// autoSign = false; -// } -// Signer aSigner = createOrgSigner( -// fileId,orgName, pos, 1, null, null, null, psnMobile, psnName, null,autoSign -// ,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).get(0); -// } -// Map docMap = new HashMap<>(); -// Thread.sleep(1000); -// 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 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)); -// List signFields = new ArrayList<>(); -// signer.setSignFields(signFields); -// if(Boolean.FALSE.equals(autoSign)){ -// signer.setNoticeConfig(mapOf("noticeTypes", "1")); -// -// Map orgInfo = mapOf("orgName", orgName, -// "transactorInfo", mapOf( -// "psnAccount", transPhone, -// "psnInfo", mapOf( -// "psnName", psnName -// ) -// ) -// ); -// signer.setOrgSignerInfo(orgInfo); -// NormalSignFieldConfig normalSignFieldConfig = new NormalSignFieldConfig(); -// normalSignFieldConfig.setAssignedSealId(sealId); -// normalSignFieldConfig.setFreeMode(true); -// normalSignFieldConfig.setAutoSign(false); -// normalSignFieldConfig.setAdaptableSignFieldSize(true); -// SignField field = new SignField(); -// field.setSignFieldType(0); -// field.setNormalSignFieldConfig(normalSignFieldConfig); -// field.setFileId(fileId); -// signFields.add(field); -// }else { -// for (SignFieldPosition po : pos) { -// NormalSignFieldConfig fieldConfig = new NormalSignFieldConfig(); -// fieldConfig.setAssignedSealId(sealId); -// fieldConfig.setAutoSign(autoSign); -// if("ALL".equals(po.getAcrossPageMode())){ -// fieldConfig.setSignFieldPosition(po); -// fieldConfig.setSignFieldStyle(2); -// SignField qiFengfield = new SignField(); -// qiFengfield.setSignFieldType(0); -// qiFengfield.setNormalSignFieldConfig(fieldConfig); -// qiFengfield.setFileId(fileId); -// signFields.add(qiFengfield); -// }else { -// fieldConfig.setSignFieldPosition(po); -// fieldConfig.setSignFieldStyle(1); -// SignField field = new SignField(); -// field.setSignFieldType(0); -// field.setNormalSignFieldConfig(fieldConfig); -// field.setFileId(fileId); -// signFields.add(field); -// } -// } -// } -// return signer; -// } -// -// private Signer createOrgQiFengSigner(String fileId ,String orgName, SignFieldPosition po, 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, -// "transactorInfo", mapOf( -// "psnAccount", transPhone, -// "psnInfo", mapOf( -// "psnName", psnName -// ) -// ) -// ); -// -// signer.setOrgSignerInfo(orgInfo); -// } -// -// List signFields = new ArrayList<>(); -// -// NormalSignFieldConfig normalSignFieldConfig = new NormalSignFieldConfig(); -// normalSignFieldConfig.setAssignedSealId(sealId); -// -// normalSignFieldConfig.setSignFieldPosition(po); -// normalSignFieldConfig.setAutoSign(autoSign); -// normalSignFieldConfig.setSignFieldStyle(2); -// SignField qiFengfield = new SignField(); -// qiFengfield.setSignFieldType(0); -// qiFengfield.setNormalSignFieldConfig(normalSignFieldConfig); -// qiFengfield.setFileId(fileId); -// signFields.add(qiFengfield); -// -// 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) { -// try { -// FieldDataVo fieldData = vo.getFieldData(field); -// return fieldData.getStringValue(); -// }catch (Exception e) { -// log.error(e.getMessage()); -// return null; -// } -// } -// -// private Float toFloat(Object val) { -// return val instanceof Number ? ((Number) val).floatValue() : Float.parseFloat(val.toString()); -// } - @Override public String getNodeId() { return "nd_20250702"; @@ -344,4 +97,185 @@ public class EsignOneSignerNode extends ACommonSuperNode { public String getNodeName() { return "E签宝甲方单方签署节点"; } + + private String getStringField(FormDataVo vo, String field) { + try { + FieldDataVo fieldData = vo.getFieldData(field); + return fieldData.getStringValue(); + }catch (Exception e) { + return null; + } + } + + private String getPsnName(FormDataVo formDataVo) throws NoSuchFieldException { + OrgManager orgManager = (OrgManager) AppContext.getBean("orgManager"); + FieldDataVo psn = formDataVo.getFieldData("甲方签署经办人"); + String psnName = null; + if(psn != null) { + try { + V3xOrgMember member = orgManager.getMemberById(Long.parseLong((String)psn.getDbValue())); + psnName = member.getName(); + }catch (Exception e){ + + } + } + return psnName; + } + + private List buildSigners(String appId,FormDataVo formDataVo, Boolean doAutoSign, String orgName) throws NoSuchFieldException, BusinessException { + List parties = new ArrayList<>(); + SignParty aParty = new SignParty(); + aParty.setPartyId("甲方"); + aParty.setSignOrder(2); + aParty.setSignerType(SignerType.ORG); + aParty.setAutoSign(doAutoSign); + aParty.setSealId(getStringField(formDataVo,"选择甲方印章")); + OrgInfo orgInfo = new OrgInfo(); + orgInfo.setOrgName(orgName); + aParty.setOrgInfo(orgInfo); + if(!doAutoSign){ + String psnName = getPsnName(formDataVo); + if(psnName == null) { + throw new RuntimeException("甲方签署经办人为空"); + } + String psnMobile = getStringField(formDataVo,"甲方签署经办人联系方式"); + PersonInfo personInfo = new PersonInfo(); + personInfo.setName(psnName); + personInfo.setPhone(psnMobile); + orgInfo.setTransactor(personInfo); + FieldDataVo isLpSign = formDataVo.getFieldData("是否盖法人章"); + if(isLpSign != null && "是".equals(isLpSign)) { + SignParty lpParty = new SignParty(); + lpParty.setPartyId("法人章"); + lpParty.setAutoSign(false); + lpParty.setSignOrder(3); + lpParty.setSignerType(SignerType.LP); + parties.add(lpParty); + } + } + parties.add(aParty); + String signWay = getStringField(formDataVo, "签署方式"); + String signWayText = null; + try { + signWayText = EnumMapUtils.getEnumShowValue(signWay); + }catch (Exception e) {} + if(!"甲方线上,乙方线下".equals(signWayText)){ + SignParty bParty = new SignParty(); + bParty.setPartyId("乙方"); + bParty.setSignOrder(1); + try { + String bSignerType = formDataVo.getFieldData("乙方签署类型").getStringValue(); + if(!"组织".equals(bSignerType)) { + PersonInfo bPersonInfo = new PersonInfo(); + bPersonInfo.setPhone(getStringField(formDataVo,"乙方电话")); + bPersonInfo.setName(getStringField(formDataVo,"乙方姓名")); + bParty.setPersonInfo(bPersonInfo); + bParty.setSignerType(SignerType.PERSON); + }else { + OrgInfo bOrgInfo = new OrgInfo(); + bOrgInfo.setLegalName(getStringField(formDataVo,"乙方法人姓名")); + bOrgInfo.setOrgName(getStringField(formDataVo,"乙方单位名称")); + bOrgInfo.setOrgCode(getStringField(formDataVo,"乙方统一社会信用代码")); + bOrgInfo.setLegalIdCardNo(getStringField(formDataVo,"乙方法人身份证号")); + PersonInfo transactor = new PersonInfo(); + transactor.setName(getStringField(formDataVo,"乙方经办人姓名")); + transactor.setIdCardNo(getStringField(formDataVo,"乙方经办人身份证号")); + transactor.setPhone(getStringField(formDataVo,"乙方经办人手机号")); + bOrgInfo.setTransactor(transactor); + bParty.setOrgInfo(bOrgInfo); + bParty.setSignerType(SignerType.ORG); + } + }catch (Exception e){ + e.printStackTrace(); + } + parties.add(bParty); + } + buildAntiFakeSigner(orgName,parties,formDataVo,doAutoSign); + return parties; + } + + private String getLastSenderId(Long caseId) { + List columns = new ArrayList<>(); + columns.add("sender_id"); + SqlBuildParam param = new SqlBuildParam(); + List conditions = new ArrayList<>(); + conditions.add(FormWhereCondition.build().fieldName("CASE_ID").value(caseId)); + param.setSqlType(SqlType.SELECT); + param.setTableName("ctp_affair"); + param.setQueryColumns(columns); + param.setConditions(conditions); + param.setPageNo(1); + param.setPageSize(1); + param.setOrderField("UPDATE_DATE"); + param.setSortType("DESC"); + Map sqlMap = FormTableExecutor.generateSql(param); + JDBCAgent agent = new JDBCAgent(); + try { + agent.execute((String)sqlMap.get("sql"), (List)sqlMap.get("params")); + log.info("执行sql为: " + sqlMap.get("sql")); + List> rows = agent.resultSetToList(); + if(rows.size() <= 0) { + return null; + } + Map map = rows.get(0); + return (String)map.get("SENDER_ID"); + } catch (Exception e) { + log.error("执行sql为: " + sqlMap.get("sql")); + log.error("执行sql参数为: " + JsonUtils.toJSONString(sqlMap.get("params"))); + log.error(e.getMessage(), e); + } finally { + agent.close(); + } + + return null; + } + + private V3xOrgMember getPsn(Long memberId) throws NoSuchFieldException { + OrgManager orgManager = (OrgManager) AppContext.getBean("orgManager"); + if(memberId != null) { + try { + V3xOrgMember member = orgManager.getMemberById(memberId); + return member; + }catch (Exception e){ + + } + } + return null; + } + + private void buildAntiFakeSigner(String orgName,List parties,FormDataVo formDataVo,Boolean doAutoSign) throws NoSuchFieldException, BusinessException {; + String enableAntiFakeSign = configProvider.getBizConfigByKey(EsignConfigConstants.ENABLEANTIFAKESIGN); + if(!"true".equals(enableAntiFakeSign)) { + return; + } + SignParty party = new SignParty(); + ColSummary colSummary = formDataVo.getColSummary(); + Long caseId = colSummary.getCaseId(); + String senderId = getLastSenderId(caseId); + party.setPartyId("防伪章签署方"); + party.setSignOrder(2); + party.setSignerType(SignerType.ORG); + party.setAutoSign(doAutoSign); + OrgInfo orgInfo = new OrgInfo(); + party.setOrgInfo(orgInfo); + String isFixAppUnitName = configProvider.getBizConfigByKey(EsignConfigConstants.FIXAPPUNIT); + String unitName = "true".equals(isFixAppUnitName) ? configProvider.getBizConfigByKey(EsignConfigConstants.FIXAPPUNITNAME) : orgName; + party.setSealId(sealService.getAntiFakeSealId(unitName)); + if(!doAutoSign){ + V3xOrgMember psn = getPsn(Long.parseLong(senderId)); + orgInfo.setOrgName(unitName); + String psnName = psn.getName(); + if(psnName == null) { + throw new RuntimeException("防伪章签署经办人为空"); + } + String psnMobile = psn.getTelNumber(); + PersonInfo personInfo = new PersonInfo(); + personInfo.setName(psnName); + personInfo.setPhone(psnMobile); + orgInfo.setTransactor(personInfo); + }else { + orgInfo.setOrgId(tokenCacheManager.getOrgIdByOrgName(unitName)); + } + parties.add(party); + } } diff --git a/src/main/java/com/seeyon/apps/esign/po/esignapi/EsignApiHeader.java b/src/main/java/com/seeyon/apps/esign/po/esignapi/EsignApiHeader.java index 59f8a68..b73a3fa 100644 --- a/src/main/java/com/seeyon/apps/esign/po/esignapi/EsignApiHeader.java +++ b/src/main/java/com/seeyon/apps/esign/po/esignapi/EsignApiHeader.java @@ -1,6 +1,6 @@ package com.seeyon.apps.esign.po.esignapi; -import org.apache.commons.codec.binary.Base64; +import com.seeyon.apps.mplus.util.Base64; import org.apache.commons.lang.StringUtils; import javax.crypto.Mac; diff --git a/src/main/java/com/seeyon/apps/esign/po/param/FlowParamSource.java b/src/main/java/com/seeyon/apps/esign/po/param/FlowParamSource.java index 28e07f4..e0c53aa 100644 --- a/src/main/java/com/seeyon/apps/esign/po/param/FlowParamSource.java +++ b/src/main/java/com/seeyon/apps/esign/po/param/FlowParamSource.java @@ -1,18 +1,14 @@ package com.seeyon.apps.esign.po.param; import com.seeyon.apps.esign.config.EsignConfigProvider; -import com.seeyon.apps.esign.constants.EsignConfigConstants; +import com.seeyon.apps.esign.constants.FlowFormFieldConstants; import com.seeyon.apps.esign.po.signer.*; import com.seeyon.apps.esign.service.SignParamSource; +import com.seeyon.apps.esign.utils.CallbackUrlBuilder; import com.seeyon.apps.ext.workflow.vo.FieldDataVo; import com.seeyon.apps.ext.workflow.vo.FormDataVo; import com.seeyon.cap4.form.bean.FormDataMasterBean; -import com.seeyon.ctp.common.AppContext; -import com.seeyon.ctp.organization.bo.V3xOrgMember; -import com.seeyon.ctp.organization.manager.OrgManager; -import com.seeyon.utils.form.EnumMapUtils; -import java.util.ArrayList; import java.util.List; public class FlowParamSource implements SignParamSource { @@ -22,6 +18,9 @@ public class FlowParamSource implements SignParamSource { private Boolean doAutoSign = false; private EsignConfigProvider configProvider; private String callbackBaseUrl; + private String appId; + private List signerParties; + private Boolean useKeyWordPositing = true; public FormDataVo getFormDataVo() { return formDataVo; @@ -56,7 +55,7 @@ public class FlowParamSource implements SignParamSource { @Override public String getContractTitle() { - return getStringField(formDataVo,"合同名称"); + return getStringField(formDataVo, FlowFormFieldConstants.CONTRACT_TITLE); } @Override @@ -76,22 +75,22 @@ public class FlowParamSource implements SignParamSource { @Override public String getSignFileRefId() { - return getStringField(formDataVo,"合同审批附件"); + return getStringField(formDataVo, FlowFormFieldConstants.CONTRACT_APPROVAL_ATTACHMENT); } @Override public String getSignedFileField() { - return masterBean.getFormTable().getFieldBeanByDisplay("盖章后合同附件").getColumnName(); + return masterBean.getFormTable().getFieldBeanByDisplay(FlowFormFieldConstants.SIGNED_ATTACHMENT).getColumnName(); } @Override public String getSignStatusField() { - return masterBean.getFormTable().getFieldBeanByDisplay("签署状态").getColumnName(); + return masterBean.getFormTable().getFieldBeanByDisplay(FlowFormFieldConstants.SIGN_STATUS).getColumnName(); } @Override public Long getSignStatusEnumId() { - return masterBean.getFormTable().getFieldBeanByDisplay("签署状态").getEnumId(); + return masterBean.getFormTable().getFieldBeanByDisplay(FlowFormFieldConstants.SIGN_STATUS).getEnumId(); } @Override @@ -101,99 +100,19 @@ public class FlowParamSource implements SignParamSource { @Override public String getCallbackUrl() { - return getCallbackBaseUrl() + "&formId=" + getBizFormId() + - "&tablename=" + getTableName() + - "&updatefield=" + getSignedFileField() + - "&statusfield=" + getSignStatusField() + "_" + getSignStatusEnumId() + - "&bizType=FLOW"; + return CallbackUrlBuilder.build(callbackBaseUrl, "FLOW", + getBizFormId(), getTableName(), + getSignedFileField(), getSignStatusField(), + getSignStatusEnumId(), getAppId()); } - private String getPsnName(FormDataVo formDataVo) throws NoSuchFieldException { - OrgManager orgManager = (OrgManager) AppContext.getBean("orgManager"); - FieldDataVo psn = formDataVo.getFieldData("甲方签署经办人"); - String psnName = null; - if(psn != null) { - try { - V3xOrgMember member = orgManager.getMemberById(Long.parseLong((String)psn.getDbValue())); - psnName = member.getName(); - }catch (Exception e){ - - } - } - return psnName; + public void setSignerParties(List signerParties) { + this.signerParties = signerParties; } @Override public List getSignerParties() throws Exception { - List parties = new ArrayList<>(); - SignParty aParty = new SignParty(); - aParty.setPartyId("甲方"); - aParty.setAutoSign(autoSign()); - aParty.setSignOrder(2); - aParty.setSignerType(SignerType.ORG); - aParty.setSealId(getStringField(formDataVo,"甲方印章ID")); - if(!doAutoSign){ - OrgInfo orgInfo = new OrgInfo(); - aParty.setOrgInfo(orgInfo); - String psnName = getPsnName(formDataVo); - if(psnName == null) { - throw new RuntimeException("甲方签署经办人为空"); - } - String psnMobile = getStringField(formDataVo,"甲方签署经办人联系方式"); - String orgName = configProvider.getBizConfigByKey(EsignConfigConstants.UNITNAME); - PersonInfo personInfo = new PersonInfo(); - orgInfo.setOrgName(orgName); - personInfo.setName(psnName); - personInfo.setPhone(psnMobile); - orgInfo.setTransactor(personInfo); - FieldDataVo isLpSign = formDataVo.getFieldData("是否盖法人章"); - if(isLpSign != null && "是".equals(isLpSign)) { - SignParty lpParty = new SignParty(); - lpParty.setPartyId("法人章"); - lpParty.setAutoSign(false); - lpParty.setSignOrder(3); - lpParty.setSignerType(SignerType.LP); - parties.add(lpParty); - } - } - parties.add(aParty); - String signWay = getStringField(formDataVo, "签署方式"); - String signWayText = null; - try { - signWayText = EnumMapUtils.getEnumShowValue(signWay); - }catch (Exception e) {} - if(!"甲方线上,乙方线下".equals(signWayText)){ - SignParty bParty = new SignParty(); - bParty.setPartyId("乙方"); - bParty.setSignOrder(1); - try { - String bSignerType = formDataVo.getFieldData("乙方签署类型").getStringValue(); - if(!"组织".equals(bSignerType)) { - PersonInfo bPersonInfo = new PersonInfo(); - bPersonInfo.setPhone(getStringField(formDataVo,"乙方电话")); - bPersonInfo.setName(getStringField(formDataVo,"乙方姓名")); - bParty.setPersonInfo(bPersonInfo); - bParty.setSignerType(SignerType.PERSON); - }else { - OrgInfo bOrgInfo = new OrgInfo(); - bOrgInfo.setLegalName(getStringField(formDataVo,"乙方法人姓名")); - bOrgInfo.setOrgName(getStringField(formDataVo,"乙方单位名称")); - bOrgInfo.setOrgCode(getStringField(formDataVo,"乙方统一社会信用代码")); - bOrgInfo.setLegalIdCardNo(getStringField(formDataVo,"乙方法人身份证号")); - PersonInfo transactor = new PersonInfo(); - transactor.setName(getStringField(formDataVo,"乙方经办人姓名")); - transactor.setIdCardNo(getStringField(formDataVo,"乙方经办人身份证号")); - transactor.setPhone(getStringField(formDataVo,"乙方经办人手机号")); - bOrgInfo.setTransactor(transactor); - bParty.setOrgInfo(bOrgInfo); - bParty.setSignerType(SignerType.ORG); - } - }catch (Exception e){ - e.printStackTrace(); - } - parties.add(bParty); - } - return parties; + return signerParties; } @@ -202,6 +121,15 @@ public class FlowParamSource implements SignParamSource { return SignParamSource.super.noticeTypes(); } + @Override + public String getAppId() { + return appId; + } + + public void setAppId(String appId) { + this.appId = appId; + } + private String getStringField(FormDataVo vo, String field) { try { FieldDataVo fieldData = vo.getFieldData(field); @@ -219,11 +147,24 @@ public class FlowParamSource implements SignParamSource { this.configProvider = configProvider; } - public String getCallbackBaseUrl() { - return callbackBaseUrl == null ? "/seeyon/esigncallback.do?method=callback": "/seeyon" + callbackBaseUrl; - } - public void setCallbackBaseUrl(String callbackBaseUrl) { this.callbackBaseUrl = callbackBaseUrl; } + + @Override + public boolean useKeyWordPositioning() { + return useKeyWordPositing; + } + + public String getCallbackBaseUrl() { + return callbackBaseUrl; + } + + public Boolean getUseKeyWordPositing() { + return useKeyWordPositing; + } + + public void setUseKeyWordPositing(Boolean useKeyWordPositing) { + this.useKeyWordPositing = useKeyWordPositing; + } } diff --git a/src/main/java/com/seeyon/apps/esign/po/param/JsonParamSource.java b/src/main/java/com/seeyon/apps/esign/po/param/JsonParamSource.java index ae7fee1..7253707 100644 --- a/src/main/java/com/seeyon/apps/esign/po/param/JsonParamSource.java +++ b/src/main/java/com/seeyon/apps/esign/po/param/JsonParamSource.java @@ -1,11 +1,13 @@ package com.seeyon.apps.esign.po.param; import com.seeyon.aicloud.common.JsonUtils; +import com.seeyon.apps.esign.constants.JsonParamKeyConstants; import com.seeyon.apps.esign.po.signer.OrgInfo; import com.seeyon.apps.esign.po.signer.PersonInfo; import com.seeyon.apps.esign.po.signer.SignParty; import com.seeyon.apps.esign.po.signer.SignerType; import com.seeyon.apps.esign.service.SignParamSource; +import com.seeyon.apps.esign.utils.CallbackUrlBuilder; import java.util.ArrayList; import java.util.List; @@ -16,6 +18,7 @@ public class JsonParamSource implements SignParamSource { private Map oriParams; private String callbackBaseUrl; private List parties; + private String appId; public JsonParamSource(){} public JsonParamSource(String jsonStr){ this.oriParams = JsonUtils.parseObject(jsonStr,Map.class); @@ -26,42 +29,42 @@ public class JsonParamSource implements SignParamSource { @Override public String getContractTitle() { - return (String)oriParams.get("contractTitle"); + return (String)oriParams.get(JsonParamKeyConstants.CONTRACT_TITLE); } @Override public boolean isByFile() { - return (Boolean) oriParams.get("byFile"); + return (Boolean) oriParams.get(JsonParamKeyConstants.BY_FILE); } @Override public String getBizFormId() { - return (String)oriParams.get("formId"); + return (String)oriParams.get(JsonParamKeyConstants.FORM_ID); } @Override public String getTableName() { - return (String)oriParams.get("tableName"); + return (String)oriParams.get(JsonParamKeyConstants.TABLE_NAME); } @Override public String getSignFileRefId() { - return (String)oriParams.get("signFileRefId"); + return (String)oriParams.get(JsonParamKeyConstants.SIGN_FILE_REF_ID); } @Override public String getSignedFileField() { - return (String)oriParams.get("signedFileField"); + return (String)oriParams.get(JsonParamKeyConstants.SIGNED_FILE_FIELD); } @Override public String getSignStatusField() { - return (String)oriParams.get("signStatusField"); + return (String)oriParams.get(JsonParamKeyConstants.SIGN_STATUS_FIELD); } @Override public Long getSignStatusEnumId() { - return oriParams.get("signStatusEnumId") == null ? null : (Long) oriParams.get("signStatusEnumId"); + return oriParams.get(JsonParamKeyConstants.SIGN_STATUS_ENUM_ID) == null ? null : (Long) oriParams.get(JsonParamKeyConstants.SIGN_STATUS_ENUM_ID); } @Override @@ -69,53 +72,48 @@ public class JsonParamSource implements SignParamSource { return false; } - private String getCallbackBaseUrl() { - return callbackBaseUrl == null ? "/seeyon/esigncallback.do?method=callback": "/seeyon" + callbackBaseUrl; - } - @Override public String getCallbackUrl() { - return getCallbackBaseUrl() + "&formId=" + getBizFormId() + - "&tablename=" + getTableName() + - "&updatefield=" + getSignedFileField() + - "&statusfield=" + getSignStatusField() + "_" + getSignStatusEnumId() + - "&bizType=FORM"; + return CallbackUrlBuilder.build(callbackBaseUrl, "FORM", + getBizFormId(), getTableName(), + getSignedFileField(), getSignStatusField(), + getSignStatusEnumId(), getAppId()); } @Override public List getSignerParties() { - String tempStr = (String)oriParams.get("signers"); + String tempStr = (String)oriParams.get(JsonParamKeyConstants.SIGNERS); List signers = JsonUtils.parseObject(tempStr, List.class); List parties = new ArrayList<>(); Float qfPos = 100f; for (Object signer : signers) { Map signerMap = (Map) signer; SignParty signParty = new SignParty(); - SignerType signerType = SignerType.valueOf((String) signerMap.get("signerType")); + SignerType signerType = SignerType.valueOf((String) signerMap.get(JsonParamKeyConstants.SIGNER_TYPE)); signParty.setSignerType(signerType); - signParty.setSignOrder((Integer) signerMap.get("signOrder")); + signParty.setSignOrder((Integer) signerMap.get(JsonParamKeyConstants.SIGN_ORDER)); signParty.setAutoSign(false); signParty.setFreeSign(true); signParty.setQfPos(qfPos); qfPos += 100f; - signParty.setPartyId((String)signerMap.get("name")); - if(signerMap.get("signPosKeyword") != null) { - signParty.setSignKeyword((String)signerMap.get("signPosKeyword")); + signParty.setPartyId((String)signerMap.get(JsonParamKeyConstants.NAME)); + if(signerMap.get(JsonParamKeyConstants.SIGN_POS_KEYWORD) != null) { + signParty.setSignKeyword((String)signerMap.get(JsonParamKeyConstants.SIGN_POS_KEYWORD)); signParty.setFreeSign(false); } if(signerType == SignerType.PERSON) { PersonInfo personInfo = new PersonInfo(); - personInfo.setName((String)signerMap.get("name")); - personInfo.setPhone((String)signerMap.get("phone")); + personInfo.setName((String)signerMap.get(JsonParamKeyConstants.NAME)); + personInfo.setPhone((String)signerMap.get(JsonParamKeyConstants.PHONE)); signParty.setPersonInfo(personInfo); }else { OrgInfo orgInfo = new OrgInfo(); PersonInfo transactor = new PersonInfo(); orgInfo.setTransactor(transactor); - orgInfo.setOrgName((String)signerMap.get("orgName")); - orgInfo.setOrgCode((String)signerMap.get("orgCode")); - transactor.setName((String)signerMap.get("name")); - transactor.setPhone((String)signerMap.get("phone")); + orgInfo.setOrgName((String)signerMap.get(JsonParamKeyConstants.ORG_NAME)); + orgInfo.setOrgCode((String)signerMap.get(JsonParamKeyConstants.ORG_CODE)); + transactor.setName((String)signerMap.get(JsonParamKeyConstants.NAME)); + transactor.setPhone((String)signerMap.get(JsonParamKeyConstants.PHONE)); signParty.setOrgInfo(orgInfo); } parties.add(signParty); @@ -123,7 +121,21 @@ public class JsonParamSource implements SignParamSource { return parties; } + public void setAppId(String appId) { + this.appId = appId; + } + + @Override + public String getAppId() { + return appId; + } + public void setCallbackBaseUrl(String callbackBaseUrl) { this.callbackBaseUrl = callbackBaseUrl; } + + @Override + public boolean useKeyWordPositioning() { + return true; + } } diff --git a/src/main/java/com/seeyon/apps/esign/po/signer/DefaultSignerBuilder.java b/src/main/java/com/seeyon/apps/esign/po/signer/DefaultSignerBuilder.java index 38875d0..dc4a0b8 100644 --- a/src/main/java/com/seeyon/apps/esign/po/signer/DefaultSignerBuilder.java +++ b/src/main/java/com/seeyon/apps/esign/po/signer/DefaultSignerBuilder.java @@ -1,167 +1,381 @@ package com.seeyon.apps.esign.po.signer; +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.esignapi.EsignApiHeader; +import com.seeyon.apps.esign.po.esignapi.EsignBaseResp; import com.seeyon.apps.esign.po.signfield.NormalSignFieldConfig; import com.seeyon.apps.esign.po.signfield.SignField; import com.seeyon.apps.esign.po.signfield.SignFieldPosition; -import org.apache.commons.lang3.StringUtils; +import com.seeyon.apps.esign.service.TokenCacheManager; +import com.seeyon.apps.esign.utils.HttpClient; +import com.seeyon.ctp.common.AppContext; +import org.apache.commons.lang.StringUtils; import java.util.ArrayList; import java.util.HashMap; import java.util.List; import java.util.Map; +/** + * 默认签署方构建器 + * 负责根据签署方类型(个人/机构/法定代表人)构建 e 签宝对接所需的 Signer 对象 + * + * @author seeyon + */ public class DefaultSignerBuilder implements SignerBuilder { - private EsignConfigProvider esignConfigProvider = EsignConfigProvider.getInstance(); + /** 配置提供者 */ + private final EsignConfigProvider esignConfigProvider = EsignConfigProvider.getInstance(); + + /** Token 缓存管理器 */ + private final TokenCacheManager tokenCacheManager = (TokenCacheManager) AppContext.getBean("tokenCacheManager"); + + // 常量定义 + private static final String NOTICE_TYPE_SMS = "1"; + private static final String ORG_ID_CARD_TYPE = "CRED_ORG_USCC"; + private static final String ACROSS_PAGE_MODE_ALL = "ALL"; + private static final String PARTY_A = "甲方"; + private static final String PARTY_B = "乙方"; + private static final String ANTI_COUNTERFEIT_PARTY = "防伪章签署方"; + private static final int SIGN_FIELD_STYLE_NORMAL = 1; + private static final int SIGN_FIELD_STYLE_ACROSS_PAGE = 2; @Override - public Signer build(List fileIds,List keywordPos, SignParty party) { - if (party.getSignerType() == SignerType.PERSON) { - return buildPersonSigner(fileIds, keywordPos,party); - } else if (party.getSignerType() == SignerType.ORG || party.getSignerType() == SignerType.LP) { - return buildOrgSigner(fileIds,keywordPos, party); + public Signer build(List fileIds, List keywordPos, SignParty party, String appId) { + // 校验入参 + validateSignParty(party); + + SignerType signerType = party.getSignerType(); + if (SignerType.PERSON == signerType) { + return buildPersonSigner(fileIds, keywordPos, party, appId); + } else if (SignerType.ORG == signerType || SignerType.LP == signerType) { + return buildOrgSigner(fileIds, keywordPos, party, appId); } else { - throw new IllegalArgumentException("不支持的签署方类型"); + throw new IllegalArgumentException("不支持的签署方类型:" + signerType); } } - private Signer buildPersonSigner(List fileIds,List keywordPos, SignParty party) { - PersonInfo psn = party.getPersonInfo(); - if (psn == null) throw new IllegalStateException("个人签署方缺少 PersonInfo"); + /** + * 构建个人签署方 + */ + private Signer buildPersonSigner(List fileIds, List keywordPos, SignParty party, String appId) { + PersonInfo personInfo = party.getPersonInfo(); + if (personInfo == null) { + throw new IllegalStateException("个人签署方缺少 PersonInfo 信息"); + } + Signer signer = new Signer(); signer.setSignerType(0); - signer.setSignConfig(mapOf("signOrder", party.getSignOrder())); + signer.setSignConfig(buildSignOrderConfig(party.getSignOrder())); + + // 非自动签署,设置通知信息和个人信息 if (!party.getAutoSign()) { - signer.setNoticeConfig(mapOf("noticeTypes", "1")); - signer.setPsnSignerInfo(mapOf( - "psnAccount", psn.getPhone(), - "psnInfo", mapOf( - "psnName", psn.getName(), - "psnIDCardNum", psn.getIdCardNo(), - "psnIDCardType", psn.getIdCardType() - ) - )); + signer.setNoticeConfig(buildNoticeConfig()); + signer.setPsnSignerInfo(buildPersonSignerInfo(personInfo)); } - signer.setSignFields(buildSignFields(fileIds, keywordPos, party)); + + signer.setSignFields(buildSignFields(fileIds, keywordPos, party, appId)); return signer; } - private Signer buildOrgSigner(List fileIds, List keywordPos,SignParty party) { - OrgInfo org = party.getOrgInfo(); + /** + * 构建机构/法定代表人签署方 + */ + private Signer buildOrgSigner(List fileIds, List keywordPos, SignParty party, String appId) { + OrgInfo orgInfo = party.getOrgInfo(); Signer signer = new Signer(); - if(SignerType.ORG.equals(party.getSignerType())) { - signer.setSignerType(1); + + // 设置签署方类型 + signer.setSignerType(SignerType.ORG == party.getSignerType() ? 1 : 2); + signer.setSignConfig(buildSignOrderConfig(party.getSignOrder())); + + // 非自动签署,设置通知信息和机构信息 + if (!party.getAutoSign() && orgInfo != null) { + signer.setNoticeConfig(buildNoticeConfig()); + signer.setOrgSignerInfo(buildOrgSignerInfo(orgInfo)); }else { - signer.setSignerType(2); + signer.setOrgSignerInfo(buildOrgSignerInfoWithNoPsn(orgInfo)); } - signer.setSignConfig(mapOf("signOrder", party.getSignOrder())); - if (!party.getAutoSign() && org != null) { - signer.setNoticeConfig(mapOf("noticeTypes", "1")); - signer.setOrgSignerInfo(mapOf( - "orgName", org.getOrgName(), - "orgInfo", mapOf( - "legalRepName", org.getLegalName(), - "legalRepIDCardNum", org.getLegalIdCardNo(), - "orgIDCardNum", org.getOrgCode(), - "orgIDCardType", "CRED_ORG_USCC" - ), - "transactorInfo", mapOf( - "psnAccount", org.getTransactor().getPhone(), - "psnInfo", mapOf( - "psnName", org.getTransactor().getName(), - "psnIDCardNum", org.getTransactor().getIdCardNo() - ) - ) - )); - } - signer.setSignFields(buildSignFields(fileIds,keywordPos,party)); + signer.setSignFields(buildSignFields(fileIds, keywordPos, party, appId)); return signer; } - private List extractPosition(List positions, String keyword) { - if(StringUtils.isBlank(keyword)) { - return null; - } - 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")) + 160f); - sfp.setPositionY(toFloat(tempMap.get("positionY"))); - posList.add(sfp); - } - } - return posList; - } - } - return new ArrayList<>(); - } - - private Float toFloat(Object val) { - return val instanceof Number ? ((Number) val).floatValue() : Float.parseFloat(val.toString()); - } - - private List buildSignFields(List fileIds,List keywordPos, SignParty party) { + /** + * 构建签署区集合(核心逻辑) + */ + private List buildSignFields(List fileIds, List keywordPos, SignParty party, String appId) { List signFields = new ArrayList<>(); + for (String fileId : fileIds) { - if(!party.getFreeSign()) { - String searchKey = null; - SignFieldPosition qiFengposition = new SignFieldPosition(); - qiFengposition.setAcrossPageMode("ALL"); - if("甲方".equals(party.getPartyId())) { - searchKey = esignConfigProvider.getBizConfigByKey(EsignConfigConstants.aSignPositionKeyword); - qiFengposition.setPositionY(520f); - }else { - searchKey = esignConfigProvider.getBizConfigByKey(EsignConfigConstants.bSignPositionKeyword); - qiFengposition.setPositionY(720f); - } - List signFieldPositions = extractPosition(keywordPos, searchKey); - List lpSignFieldPositions = extractPosition(keywordPos, esignConfigProvider.getBizConfigByKey(EsignConfigConstants.lpSignPositionKeyword)); - if(lpSignFieldPositions != null && lpSignFieldPositions.size() > 0) { - signFieldPositions.addAll(lpSignFieldPositions); - } - if(signFieldPositions.size() > 0 && !SignerType.PERSON.equals(party.getSignerType())) { - signFieldPositions.add(qiFengposition); - } - for (SignFieldPosition position : signFieldPositions) { - NormalSignFieldConfig fieldConfig = new NormalSignFieldConfig(); - fieldConfig.setSignFieldPosition(position); - fieldConfig.setAutoSign(party.getAutoSign()); - fieldConfig.setSignFieldStyle("ALL".equals(position.getAcrossPageMode()) ? 2 : 1); - SignField field = new SignField(); - field.setSignFieldType(0); - field.setNormalSignFieldConfig(fieldConfig); - field.setFileId(fileId); - signFields.add(field); - } - }else { - NormalSignFieldConfig normalSignFieldConfig = new NormalSignFieldConfig(); - normalSignFieldConfig.setAssignedSealId(party.getSealId()); - normalSignFieldConfig.setFreeMode(true); - normalSignFieldConfig.setAutoSign(false); - normalSignFieldConfig.setAdaptableSignFieldSize(true); - SignField field = new SignField(); - field.setSignFieldType(0); - field.setNormalSignFieldConfig(normalSignFieldConfig); - field.setFileId(fileId); - signFields.add(field); + if (party.getFreeSign()) { + // 自由签署模式 + signFields.add(buildFreeSignField(fileId, party)); + } else { + // 关键字定位 + 骑缝章 + 防伪章模式 + buildNormalSignFields(signFields, fileId, keywordPos, party, appId); } } + return signFields; } + /** + * 构建普通关键字定位签署区(含骑缝章、防伪章) + */ + private void buildNormalSignFields(List signFields, String fileId, List keywordPos, + SignParty party, String appId) { + // 防伪章使用固定坐标,不走关键字定位 + if (ANTI_COUNTERFEIT_PARTY.equals(party.getPartyId())) { + addAntiCounterfeitSignFields(signFields, fileId, party, appId); + return; + } + + // 根据签署方自带的关键字提取位置 + List positions = extractPosition(keywordPos, party.getSignKeyword()); + + // 机构签署 + 骑缝签署,追加骑缝位置 + if (!positions.isEmpty() && !SignerType.PERSON.equals(party.getSignerType()) && party.getSignAcrossPage()) { + SignFieldPosition acrossPagePosition = buildAcrossPagePosition(party); + if (acrossPagePosition != null) { + positions.add(acrossPagePosition); + } + } + + // 生成签署区 + for (SignFieldPosition position : positions) { + signFields.add(buildNormalSignField(fileId, party, position)); + } + } + + /** + * 提取关键字坐标位置 + */ + private List extractPosition(List positions, String keyword) { + List posList = new ArrayList<>(); + if (StringUtils.isBlank(keyword) || positions == null || positions.isEmpty()) { + return posList; + } + + for (Object obj : positions) { + Map posMap = (Map) obj; + // 匹配关键字且搜索成功 + if (Boolean.TRUE.equals(posMap.get("searchResult")) && keyword.equals(posMap.get("keyword"))) { + parseCoordinatePositions(posList, posMap); + return posList; + } + } + return posList; + } + + /** + * 解析坐标信息 + */ + private void parseCoordinatePositions(List posList, Map posMap) { + Object[] posArray = (Object[]) posMap.get("positions"); + for (Object posObj : posArray) { + Map coordMap = (Map) posObj; + Object[] coords = (Object[]) coordMap.get("coordinates"); + + for (Object coord : coords) { + Map tempMap = (Map) coord; + SignFieldPosition position = new SignFieldPosition(); + position.setPositionPage(String.valueOf(coordMap.get("pageNum"))); + position.setPositionX(safeToFloat(tempMap.get("positionX")) + 160f); + position.setPositionY(safeToFloat(tempMap.get("positionY"))); + posList.add(position); + } + } + } + + /** + * 构建防伪章签署区 + */ + private void addAntiCounterfeitSignFields(List signFields, String fileId, SignParty party, String appId) { + int totalPage = getFileTotalPage(fileId, appId); + for (int page = 1; page <= totalPage; page++) { + SignFieldPosition position = new SignFieldPosition(); + position.setPositionPage(String.valueOf(page)); + position.setPositionX(549f); + position.setPositionY(830f); + signFields.add(buildNormalSignField(fileId, party, position)); + } + } + + /** + * 构建自由签署模式签署区 + */ + private SignField buildFreeSignField(String fileId, SignParty party) { + NormalSignFieldConfig config = new NormalSignFieldConfig(); + config.setAssignedSealId(party.getSealId()); + config.setFreeMode(true); + config.setAutoSign(false); + config.setAdaptableSignFieldSize(true); + + SignField field = new SignField(); + field.setSignFieldType(0); + field.setNormalSignFieldConfig(config); + field.setFileId(fileId); + return field; + } + + /** + * 构建普通签署区 + */ + private SignField buildNormalSignField(String fileId, SignParty party, SignFieldPosition position) { + NormalSignFieldConfig config = new NormalSignFieldConfig(); + config.setSignFieldPosition(position); + config.setAssignedSealId(party.getSealId()); + config.setAutoSign(party.getAutoSign()); + config.setSignFieldStyle(ACROSS_PAGE_MODE_ALL.equals(position.getAcrossPageMode()) + ? SIGN_FIELD_STYLE_ACROSS_PAGE : SIGN_FIELD_STYLE_NORMAL); + + SignField field = new SignField(); + field.setSignFieldType(0); + field.setNormalSignFieldConfig(config); + field.setFileId(fileId); + return field; + } + + /** + * 构建骑缝章位置 + */ + private SignFieldPosition buildAcrossPagePosition(SignParty party) { + SignFieldPosition position = new SignFieldPosition(); + position.setAcrossPageMode(ACROSS_PAGE_MODE_ALL); + if (PARTY_A.equals(party.getPartyId())) { + position.setPositionY(520f); + } else if (PARTY_B.equals(party.getPartyId())) { + position.setPositionY(720f); + } + return null; + } + + /** + * 构建签署顺序配置 + */ + private Map buildSignOrderConfig(Integer signOrder) { + return mapOf("signOrder", signOrder); + } + + /** + * 构建通知配置 + */ + private Map buildNoticeConfig() { + return mapOf("noticeTypes", NOTICE_TYPE_SMS); + } + + /** + * 构建个人签署信息 + */ + private Map buildPersonSignerInfo(PersonInfo psn) { + return mapOf( + "psnAccount", psn.getPhone(), + "psnInfo", mapOf( + "psnName", psn.getName(), + "psnIDCardNum", psn.getIdCardNo(), + "psnIDCardType", psn.getIdCardType() + ) + ); + } + + /** + * 构建机构签署信息 + */ + private Map buildOrgSignerInfo(OrgInfo org) { + return mapOf( + "orgName", org.getOrgName(), + "orgIg",org.getOrgId(), + "orgInfo", mapOf( + "legalRepName", org.getLegalName(), + "legalRepIDCardNum", org.getLegalIdCardNo(), + "orgIDCardNum", org.getOrgCode(), + "orgIDCardType", ORG_ID_CARD_TYPE + ), + "transactorInfo", mapOf( + "psnAccount", org.getTransactor().getPhone(), + "psnInfo", mapOf( + "psnName", org.getTransactor().getName(), + "psnIDCardNum", org.getTransactor().getIdCardNo() + ) + ) + ); + } + + /** + * 构建机构签署信息 + */ + private Map buildOrgSignerInfoWithNoPsn(OrgInfo org) { + return mapOf( + "orgName", org.getOrgName(), + "orgIg",org.getOrgId(), + "orgInfo", mapOf( + "legalRepName", org.getLegalName(), + "legalRepIDCardNum", org.getLegalIdCardNo(), + "orgIDCardNum", org.getOrgCode(), + "orgIDCardType", ORG_ID_CARD_TYPE + ) + ); + } + + /** + * 查询文件总页数 + */ + private Integer getFileTotalPage(String fileId, String appId) { + try { + EsignApiHeader header = EsignApiHeader.build() + .appId(appId) + .token(tokenCacheManager.getToken(appId)); + + String host = esignConfigProvider.getBizConfigByKey(EsignConfigConstants.ESIGN_HOST); + String url = host + EsignApiUrl.QUERY_FILEUPLOADSTATUS + "/" + fileId; + + String respStr = HttpClient.httpGet(url, header.convert2Headers(), "UTF-8"); + EsignBaseResp resp = JsonUtils.parseObject(respStr, EsignBaseResp.class); + + if (!"0".equals(String.valueOf(resp.getCode()))) { + throw new RuntimeException("查询文件上传状态失败:" + resp.getMessage()); + } + + Map data = (Map) resp.getData(); + Object pageCount = data.get("fileTotalPageCount"); + return pageCount == null ? 10 : Integer.parseInt(String.valueOf(pageCount)); + } catch (Exception e) { + throw new RuntimeException("获取文件页数异常", e); + } + } + + /** + * 安全转换为 Float + */ + private Float safeToFloat(Object val) { + if (val == null) { + return 0f; + } + return val instanceof Number ? ((Number) val).floatValue() : Float.parseFloat(val.toString()); + } + + /** + * 校验签署方参数 + */ + private void validateSignParty(SignParty party) { + if (party == null) { + throw new IllegalArgumentException("签署方信息不能为空"); + } + if (party.getSignerType() == null) { + throw new IllegalArgumentException("签署方类型不能为空"); + } + } + + /** + * 快速构建 Map + */ private Map mapOf(Object... keyValues) { - if (keyValues.length % 2 != 0) throw new IllegalArgumentException("key-value 必须成对出现"); + if (keyValues.length % 2 != 0) { + throw new IllegalArgumentException("键值对数量必须为偶数"); + } Map map = new HashMap<>(); for (int i = 0; i < keyValues.length; i += 2) { map.put((String) keyValues[i], keyValues[i + 1]); diff --git a/src/main/java/com/seeyon/apps/esign/po/signer/JsonSignerBuilder.java b/src/main/java/com/seeyon/apps/esign/po/signer/JsonSignerBuilder.java index 5fc96d5..aa11565 100644 --- a/src/main/java/com/seeyon/apps/esign/po/signer/JsonSignerBuilder.java +++ b/src/main/java/com/seeyon/apps/esign/po/signer/JsonSignerBuilder.java @@ -1,11 +1,10 @@ package com.seeyon.apps.esign.po.signer; import com.seeyon.apps.esign.config.EsignConfigProvider; -import com.seeyon.apps.esign.constants.EsignConfigConstants; import com.seeyon.apps.esign.po.signfield.NormalSignFieldConfig; import com.seeyon.apps.esign.po.signfield.SignField; import com.seeyon.apps.esign.po.signfield.SignFieldPosition; -import org.apache.commons.lang3.StringUtils; +import org.apache.commons.lang.StringUtils; import java.util.ArrayList; import java.util.HashMap; @@ -17,7 +16,7 @@ public class JsonSignerBuilder implements SignerBuilder{ private EsignConfigProvider esignConfigProvider = EsignConfigProvider.getInstance(); @Override - public Signer build(List fileIds, List keywordPos, SignParty party) { + public Signer build(List fileIds, List keywordPos, SignParty party,String appId) { if (party.getSignerType() == SignerType.PERSON) { return buildPersonSigner(fileIds,keywordPos,party); } else if (party.getSignerType() == SignerType.ORG) { diff --git a/src/main/java/com/seeyon/apps/esign/po/signer/OrgInfo.java b/src/main/java/com/seeyon/apps/esign/po/signer/OrgInfo.java index 20b9ad4..b71efeb 100644 --- a/src/main/java/com/seeyon/apps/esign/po/signer/OrgInfo.java +++ b/src/main/java/com/seeyon/apps/esign/po/signer/OrgInfo.java @@ -4,6 +4,7 @@ public class OrgInfo { /** 企业名称 */ private String orgName; + private String orgId; /** 统一社会信用代码 */ private String orgCode; @@ -56,4 +57,12 @@ public class OrgInfo { public void setTransactor(PersonInfo transactor) { this.transactor = transactor; } + + public String getOrgId() { + return orgId; + } + + public void setOrgId(String orgId) { + this.orgId = orgId; + } } \ No newline at end of file diff --git a/src/main/java/com/seeyon/apps/esign/po/signer/SignParty.java b/src/main/java/com/seeyon/apps/esign/po/signer/SignParty.java index 21b565c..3c35c42 100644 --- a/src/main/java/com/seeyon/apps/esign/po/signer/SignParty.java +++ b/src/main/java/com/seeyon/apps/esign/po/signer/SignParty.java @@ -38,6 +38,7 @@ public class SignParty { private Float qfPos; private Boolean freeSign = false; + private Boolean signAcrossPage = true; //是否盖骑缝章 public Boolean getFreeSign() { return freeSign; @@ -134,4 +135,12 @@ public class SignParty { public void setQfPos(Float qfPos) { this.qfPos = qfPos; } + + public Boolean getSignAcrossPage() { + return signAcrossPage; + } + + public void setSignAcrossPage(Boolean signAcrossPage) { + this.signAcrossPage = signAcrossPage; + } } \ No newline at end of file diff --git a/src/main/java/com/seeyon/apps/esign/po/signer/SignerBuilder.java b/src/main/java/com/seeyon/apps/esign/po/signer/SignerBuilder.java index dcc8287..9965845 100644 --- a/src/main/java/com/seeyon/apps/esign/po/signer/SignerBuilder.java +++ b/src/main/java/com/seeyon/apps/esign/po/signer/SignerBuilder.java @@ -8,15 +8,15 @@ public interface SignerBuilder { /** * 根据签署方信息构建 Signer */ - Signer build(List fileIds, List keywordPos,SignParty party); + Signer build(List fileIds, List keywordPos,SignParty party,String appId); /** * 批量构建(默认能力) */ - default List buildAll(List fileIds,List keywordPos,List parties) { + default List buildAll(List fileIds,List keywordPos,List parties,String appId) { List signers = new ArrayList<>(); for (SignParty party : parties) { - Signer signer = build(fileIds,keywordPos, party); + Signer signer = build(fileIds,keywordPos, party, appId); if (signer != null) { signers.add(signer); } diff --git a/src/main/java/com/seeyon/apps/esign/po/upload/GetUploadUrlResp.java b/src/main/java/com/seeyon/apps/esign/po/upload/GetUploadUrlResp.java index 5ce149a..e0282ba 100644 --- a/src/main/java/com/seeyon/apps/esign/po/upload/GetUploadUrlResp.java +++ b/src/main/java/com/seeyon/apps/esign/po/upload/GetUploadUrlResp.java @@ -4,6 +4,7 @@ public class GetUploadUrlResp { private String fileId; private String fileUploadUrl; + private Integer totalPageCount; public String getFileId() { return fileId; @@ -20,4 +21,12 @@ public class GetUploadUrlResp { public void setFileUploadUrl(String fileUploadUrl) { this.fileUploadUrl = fileUploadUrl; } + + public Integer getTotalPageCount() { + return totalPageCount; + } + + public void setTotalPageCount(Integer totalPageCount) { + this.totalPageCount = totalPageCount; + } } diff --git a/src/main/java/com/seeyon/apps/esign/service/ContractCreateService.java b/src/main/java/com/seeyon/apps/esign/service/ContractCreateService.java index 19a48e6..cc31e92 100644 --- a/src/main/java/com/seeyon/apps/esign/service/ContractCreateService.java +++ b/src/main/java/com/seeyon/apps/esign/service/ContractCreateService.java @@ -15,7 +15,7 @@ public class ContractCreateService { if(factory.support(source)){ Map buildParam = factory.buildParam(source); if (buildParam == null) throw new RuntimeException("签署参数构建失败"); - return templateService.createBySignTemplate(buildParam); + return templateService.createBySignTemplate(source.getAppId(),buildParam); } } return null; diff --git a/src/main/java/com/seeyon/apps/esign/service/EsignAuthService.java b/src/main/java/com/seeyon/apps/esign/service/EsignAuthService.java index 049cb15..b1f1164 100644 --- a/src/main/java/com/seeyon/apps/esign/service/EsignAuthService.java +++ b/src/main/java/com/seeyon/apps/esign/service/EsignAuthService.java @@ -15,16 +15,17 @@ import java.util.Map; public class EsignAuthService { private EsignConfigProvider configProvider = (EsignConfigProvider) AppContext.getBean("esignConfigProvider"); + private TokenCacheManager tokenCacheManager = (TokenCacheManager) AppContext.getBean("tokenCacheManager"); - public void personAuth(Map authParams) throws Exception { + public void personAuth(String appId,Map authParams) throws Exception { EsignApiHeader esignApiHeader = EsignApiHeader.build(); String jsonBody = JsonUtils.toJSONString(authParams); - esignApiHeader.appId(configProvider.getBizConfigByKey(EsignConfigConstants.APP_ID)) + esignApiHeader.appId(appId) .httpMethod("POST") .heads("") .pathAndParameters(EsignApiUrl.PERSON_AUTH_URL) .contentMD5(jsonBody) - .signature(configProvider.getBizConfigByKey(EsignConfigConstants.APP_SECRET)); + .signature(tokenCacheManager.getSecretByAppId(appId)); String url = configProvider.getBizConfigByKey(EsignConfigConstants.ESIGN_HOST) + EsignApiUrl.PERSON_AUTH_URL; String respStr = HttpClient.httpPostRaw(url, jsonBody, esignApiHeader.convert2Headers(), "UTF-8"); EsignBaseResp esignBaseResp = JsonUtils.parseObject(respStr, EsignBaseResp.class); diff --git a/src/main/java/com/seeyon/apps/esign/service/EsignByTemplateService.java b/src/main/java/com/seeyon/apps/esign/service/EsignByTemplateService.java index 4586930..4597379 100644 --- a/src/main/java/com/seeyon/apps/esign/service/EsignByTemplateService.java +++ b/src/main/java/com/seeyon/apps/esign/service/EsignByTemplateService.java @@ -36,10 +36,10 @@ public class EsignByTemplateService { } } - public String createBySignTemplate(Map params) throws Exception { + public String createBySignTemplate(String appId,Map params) throws Exception { EsignApiHeader esignApiHeader = EsignApiHeader.build(); String jsonBody = JsonCleaner.removeEmptyObjects(JsonUtils.toJSONString(params)); - esignApiHeader.token(tokenCacheManager.getToken()).appId(configProvider.getBizConfigByKey(EsignConfigConstants.APP_ID)); + esignApiHeader.token(tokenCacheManager.getToken(appId)).appId(appId); String url = configProvider.getBizConfigByKey(EsignConfigConstants.ESIGN_HOST) + EsignApiUrl.SIGN_BY_FILE_URL; log.info("合同发起入参: " + jsonBody); String respStr = HttpClient.httpPostRaw(url, jsonBody, esignApiHeader.convert2Headers(), "UTF-8"); diff --git a/src/main/java/com/seeyon/apps/esign/service/EsignFileTemplateService.java b/src/main/java/com/seeyon/apps/esign/service/EsignFileTemplateService.java index d78a47c..31d2470 100644 --- a/src/main/java/com/seeyon/apps/esign/service/EsignFileTemplateService.java +++ b/src/main/java/com/seeyon/apps/esign/service/EsignFileTemplateService.java @@ -12,7 +12,6 @@ import com.seeyon.apps.esign.utils.HttpClient; import com.seeyon.ctp.common.AppContext; import org.apache.commons.logging.Log; import org.apache.commons.logging.LogFactory; -import org.springframework.beans.factory.annotation.Autowired; import java.util.ArrayList; import java.util.HashMap; @@ -27,22 +26,21 @@ public class EsignFileTemplateService { private EsignConfigProvider configProvider = EsignConfigProvider.getInstance(); private TokenCacheManager tokenCacheManager = (TokenCacheManager) AppContext.getBean("tokenCacheManager"); private EsignUploadFileService uploadFileService = (EsignUploadFileService) AppContext.getBean("esignUploadFileService"); - private String orgId; - private void fillOrgId() { + private String getOrgId(String appId) { EsignApiHeader esignApiHeader = EsignApiHeader.build(); try { - esignApiHeader.token(tokenCacheManager.getToken()).appId(configProvider.getBizConfigByKey(EsignConfigConstants.APP_ID)); + esignApiHeader.token(tokenCacheManager.getToken(appId)).appId(appId); } catch (Exception e) { e.printStackTrace(); } //获取orgId - String queryStr = EsignApiUrl.QUERY_ORGINFO + "?orgName=" + configProvider.getBizConfigByKey(EsignConfigConstants.UNITNAME); + String queryStr = EsignApiUrl.QUERY_ORGINFO + "?orgName=" + tokenCacheManager.getOrgNameByAppId(appId); String reqUrl = configProvider.getBizConfigByKey(EsignConfigConstants.ESIGN_HOST) + queryStr; String orgInfoRespStr = HttpClient.httpGet(reqUrl, esignApiHeader.convert2Headers(), "UTF-8"); EsignBaseResp orgInfoResp = JsonUtils.parseObject(orgInfoRespStr, EsignBaseResp.class); Map orgData = (Map) orgInfoResp.getData(); - orgId = (String) orgData.get("orgId"); + return (String) orgData.get("orgId"); } //填充模板 @@ -81,19 +79,19 @@ public class EsignFileTemplateService { } //获取模板详细信息 - public Map getTemplateDetail(String signTemplateId,String orgId) { + public Map getTemplateDetail(String appId,String signTemplateId,String orgId) { String url = configProvider.getBizConfigByKey(EsignConfigConstants.ESIGN_HOST) + EsignApiUrl.QUERY_TEMPLATE_DETAIL_URL + "?" +"orgId=" + orgId + "&signTemplateId=" + signTemplateId; - EsignApiHeader apiHeader = EsignApiHeader.build().token(tokenCacheManager.getToken()).appId(configProvider.getBizConfigByKey(EsignConfigConstants.APP_ID)); + EsignApiHeader apiHeader = EsignApiHeader.build().token(tokenCacheManager.getToken(appId)).appId(appId); String resp = HttpClient.httpGet(url, apiHeader.convert2Headers(), "UTF-8"); EsignBaseResp esignBaseResp = JsonUtils.parseObject(resp, EsignBaseResp.class); Map data = (Map) esignBaseResp.getData(); return data; } - public Map queryTemplates(Integer pageNo) throws Exception { - EsignApiHeader esignApiHeader = EsignApiHeader.build().appId(configProvider.getBizConfigByKey(EsignConfigConstants.APP_ID)); - String queryStr = EsignApiUrl.QUERY_TEMPLATES_URL + "?" + "orgId=" + obtainOrgId() + "&pageNum=" + pageNo + "&pageSize=" + 20 + "&status=" + 1; - esignApiHeader.token(tokenCacheManager.getToken()); + public Map queryTemplates(String appId,Integer pageNo) throws Exception { + EsignApiHeader esignApiHeader = EsignApiHeader.build().appId(appId); + String queryStr = EsignApiUrl.QUERY_TEMPLATES_URL + "?" + "orgId=" + obtainOrgId(appId) + "&pageNum=" + pageNo + "&pageSize=" + 20 + "&status=" + 1; + esignApiHeader.token(tokenCacheManager.getToken(appId)); String url = configProvider.getBizConfigByKey(EsignConfigConstants.ESIGN_HOST) + queryStr; String templateListRespStr = HttpClient.httpGet(url, esignApiHeader.convert2Headers(), "UTF-8"); EsignBaseResp templateListResp = JsonUtils.parseObject(templateListRespStr, EsignBaseResp.class); @@ -106,16 +104,16 @@ public class EsignFileTemplateService { return pageMap; } - public String getCompareDetailUrl(String templateRefId,String contractRefId) throws Exception { - String templateFileId = uploadFileService.uploadFileToEsign(templateRefId).get(0); - String contractFileId = uploadFileService.uploadFileToEsign(contractRefId).get(0); + public String getCompareDetailUrl(String appId,String templateRefId,String contractRefId) throws Exception { + String templateFileId = uploadFileService.uploadFileToEsign(appId,templateRefId).get(0); + String contractFileId = uploadFileService.uploadFileToEsign(appId,contractRefId).get(0); String url = configProvider.getBizConfigByKey(EsignConfigConstants.ESIGN_HOST) + EsignApiUrl.CONTRACT_COMPARE_GETURL; Map params = new HashMap<>(); params.put("standardFileId",templateFileId); params.put("comparativeFileId",contractFileId); String jsonString = JsonUtils.toJSONString(params); - EsignApiHeader esignApiHeader = EsignApiHeader.build().appId(configProvider.getBizConfigByKey(EsignConfigConstants.APP_ID)); - esignApiHeader.token(tokenCacheManager.getToken()); + EsignApiHeader esignApiHeader = EsignApiHeader.build().appId(appId); + esignApiHeader.token(tokenCacheManager.getToken(appId)); String respStr = HttpClient.httpPostRaw(url, jsonString, esignApiHeader.convert2Headers(), null); EsignBaseResp esignBaseResp = JsonUtils.parseObject(respStr, EsignBaseResp.class); log.info("调用获取合同比对链接接口返回值: " + JsonUtils.toJSONString(esignBaseResp)); @@ -124,10 +122,7 @@ public class EsignFileTemplateService { return contractCompareUrl; } - private String obtainOrgId() { - if(orgId == null) { - fillOrgId(); - } - return orgId; + private String obtainOrgId(String appId) { + return getOrgId(appId); } } diff --git a/src/main/java/com/seeyon/apps/esign/service/EsignFlowQueryService.java b/src/main/java/com/seeyon/apps/esign/service/EsignFlowQueryService.java index 0645893..08ca30a 100644 --- a/src/main/java/com/seeyon/apps/esign/service/EsignFlowQueryService.java +++ b/src/main/java/com/seeyon/apps/esign/service/EsignFlowQueryService.java @@ -16,9 +16,10 @@ public class EsignFlowQueryService { private TokenCacheManager tokenCacheManager = (TokenCacheManager) AppContext.getBean("tokenCacheManager"); private EsignConfigProvider esignConfigProvider = EsignConfigProvider.getInstance(); - public Integer queryFlow(String eFlowId){ + public Integer queryFlow(String orgName,String eFlowId){ EsignApiHeader esignApiHeader = EsignApiHeader.build(); - esignApiHeader.token(tokenCacheManager.getToken()).appId(esignConfigProvider.getBizConfigByKey(EsignConfigConstants.APP_ID)); + String appId = tokenCacheManager.getAppIdByOrgName(orgName); + esignApiHeader.token(tokenCacheManager.getToken(appId)).appId(appId); String url = esignConfigProvider.getBizConfigByKey(EsignConfigConstants.ESIGN_HOST) + EsignApiUrl.SIGN_FLOW_QUERY.replace("{signFlowId}",eFlowId); String respStr = HttpClient.httpGet(url, esignApiHeader.convert2Headers(), "UTF-8"); EsignBaseResp esignBaseResp = JsonUtils.parseObject(respStr, EsignBaseResp.class); diff --git a/src/main/java/com/seeyon/apps/esign/service/EsignUploadFileService.java b/src/main/java/com/seeyon/apps/esign/service/EsignUploadFileService.java index 4128b94..246ab76 100644 --- a/src/main/java/com/seeyon/apps/esign/service/EsignUploadFileService.java +++ b/src/main/java/com/seeyon/apps/esign/service/EsignUploadFileService.java @@ -13,8 +13,9 @@ import com.seeyon.apps.esign.utils.EsignHttpHelper; import com.seeyon.apps.esign.utils.EsignRequestType; import com.seeyon.apps.esign.utils.FileUtil; import com.seeyon.apps.esign.utils.HttpClient; +import com.seeyon.apps.mplus.util.Base64; import com.seeyon.ctp.common.AppContext; -import org.apache.commons.codec.binary.Base64; + import java.io.File; import java.io.FileInputStream; @@ -32,10 +33,10 @@ public class EsignUploadFileService { protected TokenCacheManager tokenCacheManager = (TokenCacheManager) AppContext.getBean("tokenCacheManager"); - public Object[] getDownloadFileInfo(String flowId) throws Exception { + public Object[] getDownloadFileInfo(String appId,String flowId) throws Exception { String reqPath = EsignApiUrl.CONTRACT_DOWNLOAD_URL.replace("{signFlowId}", flowId); String getDownloadUrl = configProvider.getBizConfigByKey(EsignConfigConstants.ESIGN_HOST) + reqPath; - EsignApiHeader esignApiHeader = EsignApiHeader.build().appId(configProvider.getBizConfigByKey(EsignConfigConstants.APP_ID)).token(tokenCacheManager.getToken()); + EsignApiHeader esignApiHeader = EsignApiHeader.build().appId(appId).token(tokenCacheManager.getToken(appId)); String respStr = HttpClient.httpGet(getDownloadUrl, esignApiHeader.convert2Headers(), null); EsignBaseResp esignBaseResp = JsonUtils.parseObject(respStr, EsignBaseResp.class); if(esignBaseResp.getCode() != 0 || esignBaseResp.getData() == null){ @@ -49,11 +50,11 @@ public class EsignUploadFileService { return files; } - public GetUploadUrlResp getUploadFileUrl(String fileName,String fileMd5,Long fileSize,boolean convert2Pdf) throws Exception { + public GetUploadUrlResp getUploadFileUrl(String appId,String fileName,String fileMd5,Long fileSize,boolean convert2Pdf) throws Exception { String url = configProvider.getBizConfigByKey(EsignConfigConstants.ESIGN_HOST) + EsignApiUrl.GET_UPLOAD_FILE_URL; GetUploadUrlResp resp = new GetUploadUrlResp(); - EsignApiHeader esignApiHeader = EsignApiHeader.build().appId(configProvider.getBizConfigByKey(EsignConfigConstants.APP_ID)); - esignApiHeader.token(tokenCacheManager.getToken()); + EsignApiHeader esignApiHeader = EsignApiHeader.build().appId(appId); + esignApiHeader.token(tokenCacheManager.getToken(appId)); EsignFileUploadParams params = new EsignFileUploadParams(); params.setFileName(fileName); params.setContentMd5(fileMd5); @@ -74,14 +75,14 @@ public class EsignUploadFileService { } - public List getSignPosition(String fileId,List keywords) { + public List getSignPosition(String appId,String fileId,List keywords) { try { String reqPath = EsignApiUrl.SIGN_POSITION_URL.replace("{fileId}", fileId); String url = configProvider.getBizConfigByKey(EsignConfigConstants.ESIGN_HOST) + reqPath; - EsignApiHeader esignApiHeader = EsignApiHeader.build().appId(configProvider.getBizConfigByKey(EsignConfigConstants.APP_ID)); + EsignApiHeader esignApiHeader = EsignApiHeader.build().appId(appId); Map params = new HashMap<>(); params.put("keywords",keywords); - esignApiHeader.token(tokenCacheManager.getToken()); + esignApiHeader.token(tokenCacheManager.getToken(appId)); String respStr = HttpClient.httpPostRaw(url,JsonUtils.toJSONString(params),esignApiHeader.convert2Headers(),null); Map map = JsonUtils.parseObject(respStr, Map.class); Map data = (Map) map.get("data"); @@ -97,7 +98,7 @@ public class EsignUploadFileService { return new ArrayList<>(); } - public List uploadFileToEsign(String refId) throws Exception { + public List uploadFileToEsign(String appId,String refId) throws Exception { String tempDir = System.getProperty("java.io.tmpdir"); List fileIds = new ArrayList<>(); File file = null; @@ -107,7 +108,7 @@ public class EsignUploadFileService { for (String path : paths) { file = new File(path); String contentMD5 = EsignUploadFileService.getFileContentMD5(path); - GetUploadUrlResp uploadResp = getUploadFileUrl(file.getName(), contentMD5, file.length(),true); + GetUploadUrlResp uploadResp = getUploadFileUrl(appId,file.getName(), contentMD5, file.length(),true); uploadFile(uploadResp.getFileUploadUrl(), contentMD5, file.getName(), path); fileIds.add(uploadResp.getFileId()); } @@ -123,7 +124,7 @@ public class EsignUploadFileService { // 获取文件MD5的二进制数组(128位) byte[] bytes = getFileMD5Bytes128(filePath); // 对文件MD5的二进制数组进行base64编码 - return new String(Base64.encodeBase64String(bytes)); + return new String(Base64.encodeBase64(bytes)); } /*** diff --git a/src/main/java/com/seeyon/apps/esign/service/FlowFormSignParamBuildFactory.java b/src/main/java/com/seeyon/apps/esign/service/FlowFormSignParamBuildFactory.java index 3151f3d..9d3eccc 100644 --- a/src/main/java/com/seeyon/apps/esign/service/FlowFormSignParamBuildFactory.java +++ b/src/main/java/com/seeyon/apps/esign/service/FlowFormSignParamBuildFactory.java @@ -9,7 +9,7 @@ import com.seeyon.apps.esign.po.signer.Signer; import com.seeyon.apps.ext.workflow.vo.FieldDataVo; import com.seeyon.apps.ext.workflow.vo.FormDataVo; import com.seeyon.ctp.common.AppContext; -import org.apache.commons.lang3.StringUtils; +import org.apache.commons.lang.StringUtils; import java.util.ArrayList; import java.util.HashMap; @@ -27,7 +27,7 @@ public class FlowFormSignParamBuildFactory implements SignParamBuildFactory { if (source.isByFile()) { String attachmentId = source.getSignFileRefId(); if (attachmentId == null) throw new RuntimeException("合同文件不能为空"); - List> docs = buildDocs(attachmentId); + List> docs = buildDocs(source.getAppId(),attachmentId); fileIds = new ArrayList<>(); for (Map doc : docs) { fileIds.add((String) doc.get("fileId")); @@ -36,22 +36,26 @@ public class FlowFormSignParamBuildFactory implements SignParamBuildFactory { } Map signFlowConfig = buildSignFlowConfig(source.getContractTitle(),source.getCallbackUrl()); DefaultSignerBuilder signerBuilder = new DefaultSignerBuilder(); - List keywords = new ArrayList<>(); - String aSignPosKeyword = configProvider.getBizConfigByKey(EsignConfigConstants.aSignPositionKeyword); - String bSignPosKeyword = configProvider.getBizConfigByKey(EsignConfigConstants.bSignPositionKeyword); - String lpSignPosKeyword = configProvider.getBizConfigByKey(EsignConfigConstants.lpSignPositionKeyword); - if(StringUtils.isNotBlank(aSignPosKeyword)){ - keywords.add(aSignPosKeyword); - } - if(StringUtils.isNotBlank(bSignPosKeyword)){ - keywords.add(bSignPosKeyword); - } - if(StringUtils.isNotBlank(lpSignPosKeyword)) { - keywords.add(lpSignPosKeyword); - } - List keywordPos = getKeywordPos(fileIds, keywords); List signerParties = source.getSignerParties(); - List signers = signerBuilder.buildAll(fileIds,keywordPos,signerParties); + List keywordPos = new ArrayList<>(); + if (source.useKeyWordPositioning()) { + String aSignPosKeyword = configProvider.getBizConfigByKey(EsignConfigConstants.aSignPositionKeyword); + String bSignPosKeyword = configProvider.getBizConfigByKey(EsignConfigConstants.bSignPositionKeyword); + String lpSignPosKeyword = configProvider.getBizConfigByKey(EsignConfigConstants.lpSignPositionKeyword); + List keywords = new ArrayList<>(); + for (SignParty party : signerParties) { + if ("防伪章签署方".equals(party.getPartyId())) { + continue; + } + String keyword = getKeywordByPartyId(party.getPartyId(), aSignPosKeyword, bSignPosKeyword, lpSignPosKeyword); + if (StringUtils.isNotBlank(keyword)) { + party.setSignKeyword(keyword); + keywords.add(keyword); + } + } + keywordPos = getKeywordPos(source.getAppId(), fileIds, keywords); + } + List signers = signerBuilder.buildAll(fileIds,keywordPos,signerParties,source.getAppId()); signParams.put("signFlowConfig", signFlowConfig); signParams.put("signers", signers); return signParams; @@ -62,10 +66,13 @@ public class FlowFormSignParamBuildFactory implements SignParamBuildFactory { return source instanceof FlowParamSource; } - private List getKeywordPos(List fileIds,List keywords){ + private List getKeywordPos(String appId,List fileIds,List keywords){ List pos = new ArrayList<>(); + if(keywords.isEmpty()) { + return pos; + } for (String fileId : fileIds){ - List signPosition = uploadFileService.getSignPosition(fileId, keywords); + List signPosition = uploadFileService.getSignPosition(appId,fileId, keywords); pos.addAll(signPosition); } return pos; @@ -75,8 +82,8 @@ public class FlowFormSignParamBuildFactory implements SignParamBuildFactory { * 构建文档列表 * @param attachmentId 如果 byFile=true,则上传并返回 fileId */ - public List> buildDocs(String attachmentId) throws Exception { - List fileIds = uploadFileService.uploadFileToEsign(attachmentId); + public List> buildDocs(String appId,String attachmentId) throws Exception { + List fileIds = uploadFileService.uploadFileToEsign(appId,attachmentId); List> docs = new ArrayList<>(); for (String fileId : fileIds) { Map docMap = new HashMap<>(); @@ -103,6 +110,17 @@ public class FlowFormSignParamBuildFactory implements SignParamBuildFactory { return config; } + private String getKeywordByPartyId(String partyId, String aKeyword, String bKeyword, String lpKeyword) { + if ("甲方".equals(partyId)) { + return aKeyword; + } else if ("乙方".equals(partyId)) { + return bKeyword; + } else if ("法定代表人".equals(partyId)) { + return lpKeyword; + } + return null; + } + private String getStringField(FormDataVo vo, String field) { try { FieldDataVo fieldData = vo.getFieldData(field); diff --git a/src/main/java/com/seeyon/apps/esign/service/NormalFormSignParamBuildFactory.java b/src/main/java/com/seeyon/apps/esign/service/NormalFormSignParamBuildFactory.java index 51d0988..b9ef1e9 100644 --- a/src/main/java/com/seeyon/apps/esign/service/NormalFormSignParamBuildFactory.java +++ b/src/main/java/com/seeyon/apps/esign/service/NormalFormSignParamBuildFactory.java @@ -4,14 +4,13 @@ package com.seeyon.apps.esign.service; import com.seeyon.apps.esign.config.EsignConfigProvider; import com.seeyon.apps.esign.constants.EsignConfigConstants; import com.seeyon.apps.esign.po.param.JsonParamSource; -import com.seeyon.apps.esign.po.signer.DefaultSignerBuilder; import com.seeyon.apps.esign.po.signer.JsonSignerBuilder; import com.seeyon.apps.esign.po.signer.SignParty; import com.seeyon.apps.esign.po.signer.Signer; import com.seeyon.apps.ext.workflow.vo.FieldDataVo; import com.seeyon.apps.ext.workflow.vo.FormDataVo; import com.seeyon.ctp.common.AppContext; -import org.apache.commons.lang3.StringUtils; +import org.apache.commons.lang.StringUtils; import java.util.*; @@ -27,7 +26,7 @@ public class NormalFormSignParamBuildFactory implements SignParamBuildFactory { if (source.isByFile()) { String attachmentId = source.getSignFileRefId(); if (attachmentId == null) throw new RuntimeException("合同文件不能为空"); - List> docs = buildDocs(attachmentId); + List> docs = buildDocs(source.getAppId(),attachmentId); fileIds = new ArrayList<>(); for (Map doc : docs) { fileIds.add((String) doc.get("fileId")); @@ -43,17 +42,17 @@ public class NormalFormSignParamBuildFactory implements SignParamBuildFactory { keywords.add(party.getSignKeyword()); } }); - List keywordPos = getKeywordPos(fileIds, keywords); - List signers = signerBuilder.buildAll(fileIds,keywordPos,signerParties); + List keywordPos = getKeywordPos(source.getAppId(),fileIds, keywords); + List signers = signerBuilder.buildAll(fileIds,keywordPos,signerParties,source.getAppId()); signParams.put("signFlowConfig", signFlowConfig); signParams.put("signers", signers); return signParams; } - private List getKeywordPos(List fileIds,List keywords){ + private List getKeywordPos(String appId,List fileIds,List keywords){ List pos = new ArrayList<>(); for (String fileId : fileIds){ - List signPosition = uploadFileService.getSignPosition(fileId, keywords); + List signPosition = uploadFileService.getSignPosition(appId,fileId, keywords); pos.addAll(signPosition); } return pos.size() > 0 ? pos : null; @@ -68,8 +67,8 @@ public class NormalFormSignParamBuildFactory implements SignParamBuildFactory { * 构建文档列表 * @param attachmentId 如果 byFile=true,则上传并返回 fileId */ - public List> buildDocs(String attachmentId) throws Exception { - List fileIds = uploadFileService.uploadFileToEsign(attachmentId); + public List> buildDocs(String appId,String attachmentId) throws Exception { + List fileIds = uploadFileService.uploadFileToEsign(appId,attachmentId); List> docs = new ArrayList<>(); for (String fileId : fileIds) { Map docMap = new HashMap<>(); diff --git a/src/main/java/com/seeyon/apps/esign/service/SealService.java b/src/main/java/com/seeyon/apps/esign/service/SealService.java index 63e88f3..3483e98 100644 --- a/src/main/java/com/seeyon/apps/esign/service/SealService.java +++ b/src/main/java/com/seeyon/apps/esign/service/SealService.java @@ -1,7 +1,7 @@ package com.seeyon.apps.esign.service; import cn.hutool.json.JSONObject; -import com.cedarsoftware.util.io.JsonObject; +import com.cedarsoftware.io.JsonObject; import com.seeyon.aicloud.common.JsonUtils; import com.seeyon.apps.esign.config.EsignConfigProvider; import com.seeyon.apps.esign.constants.EsignApiUrl; @@ -11,6 +11,7 @@ import com.seeyon.apps.esign.po.esignapi.EsignBaseResp; import com.seeyon.apps.esign.po.seal.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.utils.form.*; import com.seeyon.v3x.services.form.FormFactory; @@ -23,6 +24,7 @@ public class SealService { private static final Log log = LogFactory.getLog(SealService.class); private EsignConfigProvider configProvider = EsignConfigProvider.getInstance(); + private TokenCacheManager tokenCacheManager = (TokenCacheManager) AppContext.getBean("tokenCacheManager"); private FormFactory formFactory; public FormFactory getFormFactory() { @@ -32,9 +34,9 @@ public class SealService { return formFactory; } - public void grantSeal(Map params) throws Exception { + public void grantSeal(String appId,Map params) throws Exception { JsonObject reqParams = new JsonObject(); - String sealId = getSealId((String) params.get("orgId"), (String) params.get("sealName")); + String sealId = getSealId(appId,(String) params.get("orgId"), (String) params.get("sealName")); reqParams.put("sealId", sealId); List authorizedPsnIds = new ArrayList<>(); authorizedPsnIds.add((String) params.get("accountId")); @@ -47,27 +49,41 @@ public class SealService { sealAuthScope.put("templateIds", templateIds); reqParams.put("sealAuthScope", sealAuthScope); EsignApiHeader esignApiHeader = EsignApiHeader.build(); - esignApiHeader.appId(configProvider.getBizConfigByKey(EsignConfigConstants.APP_ID)) + esignApiHeader.appId(appId) .httpMethod("POST") .heads("") .pathAndParameters(EsignApiUrl.SEAL_GRANT_URL) .contentMD5(reqParams.toString()) - .signature(configProvider.getBizConfigByKey(EsignConfigConstants.APP_SECRET)); + .signature(tokenCacheManager.getSecretByAppId(appId)); String url = configProvider.getBizConfigByKey(EsignConfigConstants.ESIGN_HOST) + EsignApiUrl.SEAL_GRANT_URL; HttpClient.httpPostRaw(url, reqParams.toString(), esignApiHeader.convert2Headers(), null); } - private String getSealId(String orgId, String sealName) throws Exception { + public String getAntiFakeSealId(String orgName) throws BusinessException { + List conditions = new ArrayList<>(); + String formNo = configProvider.getBizConfigByKey(EsignConfigConstants.sealInfoFormCode); + conditions.add(FormWhereCondition.build().display("印章类型").value("防伪章")); + conditions.add(FormWhereCondition.build().display("所属组织").value(orgName)); + TableContext master = FormTableExecutor.master(formNo); + FormColumn formColumn = FormTableExecutor.queryOne(master, conditions, true); + if(formColumn == null) { + return null; + } + Map fieldsMap = formColumn.getFieldsMap(); + return (String) fieldsMap.get("印章ID"); + } + + private String getSealId(String appId,String orgId, String sealName) throws Exception { String host = configProvider.getBizConfigByKey(EsignConfigConstants.ESIGN_HOST); int pageNo = 1; int pageSize = 20; EsignApiHeader esignApiHeader = EsignApiHeader.build(); - esignApiHeader.appId(configProvider.getBizConfigByKey(EsignConfigConstants.APP_ID)) + esignApiHeader.appId(appId) .httpMethod("GET") .heads("") .pathAndParameters(EsignApiUrl.SEAL_QUERY_URL + "?" + HttpClient.sortQueryString("orgId=" + orgId + "&pageNo=" + pageNo + "&pageSize=" + pageSize)) .contentMD5("") - .signature(configProvider.getBizConfigByKey(EsignConfigConstants.APP_SECRET)); + .signature(tokenCacheManager.getSecretByAppId(appId)); 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); diff --git a/src/main/java/com/seeyon/apps/esign/service/SignLinkService.java b/src/main/java/com/seeyon/apps/esign/service/SignLinkService.java index 464a394..17f69c8 100644 --- a/src/main/java/com/seeyon/apps/esign/service/SignLinkService.java +++ b/src/main/java/com/seeyon/apps/esign/service/SignLinkService.java @@ -27,7 +27,7 @@ public class SignLinkService { private EsignConfigProvider esignConfigProvider = (EsignConfigProvider) AppContext.getBean("esignConfigProvider"); private TokenCacheManager tokenCacheManager = (TokenCacheManager) AppContext.getBean("tokenCacheManager"); - public void saveGetLinkParam(FormDataVo formDataVo, FormDataMasterBean formDataMasterBean,String eFlowId) { + public void saveGetLinkParam(FormDataVo formDataVo,String eFlowId,String appId) { try { String bSignerType = formDataVo.getFieldData("乙方签署类型").getStringValue(); String psnAccount = null; @@ -43,7 +43,7 @@ public class SignLinkService { param.put("signFlowId",eFlowId); param.put("operator",operator); String paramStr = JsonUtils.toJSONString(param); - saveDb(paramStr,eFlowId,contractNo); + saveDb(paramStr,eFlowId,contractNo,appId); }catch (Exception e) { log.error(e.getMessage(),e); } @@ -64,8 +64,8 @@ public class SignLinkService { } } - private void saveDb(String jsonStr,String eFlowId,String contractNo) { - String sqlInsert = "insert into SIGN_LINK_PARAM (id,param,eFlowId,contractNo) values (?,?,?,?)"; + private void saveDb(String jsonStr,String eFlowId,String contractNo,String appId) { + String sqlInsert = "insert into SIGN_LINK_PARAM (id,param,eFlowId,contractNo,appId) values (?,?,?,?,?)"; String sqlQuery = "select * FROM SIGN_LINK_PARAM where contractNo = ?"; String sqlUpdate = "update SIGN_LINK_PARAM set param = ?,eFlowId = ? where id = ?"; JDBCAgent jdbcAgent = new JDBCAgent(); @@ -81,6 +81,7 @@ public class SignLinkService { param.add(jsonStr); param.add(eFlowId); param.add(contractNo); + param.add(appId); jdbcAgent.execute(sqlInsert,param); }else { param.clear(); @@ -108,12 +109,13 @@ public class SignLinkService { if(list.size() > 0) { Map tempMap = (Map) list.get(0); String paramStr = (String)tempMap.get("param"); - if(!checkContractVaild(eFlowId)) { + String appId = (String)tempMap.get("appid"); + if(!checkContractVaild(appId,eFlowId)) { throw new RuntimeException("当前合同无效"); } String url = esignConfigProvider.getBizConfigByKey(EsignConfigConstants.ESIGN_HOST) + EsignApiUrl.SIGN_LINK_GET_URL.replace("{signFlowId}",eFlowId); EsignApiHeader esignApiHeader = EsignApiHeader.build(); - esignApiHeader.token(tokenCacheManager.getToken()).appId(esignConfigProvider.getBizConfigByKey(EsignConfigConstants.APP_ID)); + esignApiHeader.token(tokenCacheManager.getToken(appId)).appId(appId); String respStr = HttpClient.httpPostRaw(url, paramStr,esignApiHeader.convert2Headers(), "UTF-8"); EsignBaseResp esignBaseResp = JsonUtils.parseObject(respStr, EsignBaseResp.class); Map dataMap = (Map) esignBaseResp.getData(); @@ -132,9 +134,9 @@ public class SignLinkService { return null; } - private boolean checkContractVaild(String eFlowId) { + private boolean checkContractVaild(String appId,String eFlowId) { EsignApiHeader esignApiHeader = EsignApiHeader.build(); - esignApiHeader.token(tokenCacheManager.getToken()).appId(esignConfigProvider.getBizConfigByKey(EsignConfigConstants.APP_ID)); + esignApiHeader.token(tokenCacheManager.getToken(appId)).appId(appId); String url = esignConfigProvider.getBizConfigByKey(EsignConfigConstants.ESIGN_HOST) + EsignApiUrl.SIGN_FLOW_QUERY.replace("{signFlowId}",eFlowId); String respStr = HttpClient.httpGet(url, esignApiHeader.convert2Headers(), "UTF-8"); EsignBaseResp esignBaseResp = JsonUtils.parseObject(respStr, EsignBaseResp.class); diff --git a/src/main/java/com/seeyon/apps/esign/service/SignParamSource.java b/src/main/java/com/seeyon/apps/esign/service/SignParamSource.java index 7d6247f..6e213a4 100644 --- a/src/main/java/com/seeyon/apps/esign/service/SignParamSource.java +++ b/src/main/java/com/seeyon/apps/esign/service/SignParamSource.java @@ -48,4 +48,8 @@ public interface SignParamSource { return "1"; } + String getAppId(); + + boolean useKeyWordPositioning(); + } \ No newline at end of file diff --git a/src/main/java/com/seeyon/apps/esign/service/TokenCacheManager.java b/src/main/java/com/seeyon/apps/esign/service/TokenCacheManager.java index 9c0e88e..5227d7d 100644 --- a/src/main/java/com/seeyon/apps/esign/service/TokenCacheManager.java +++ b/src/main/java/com/seeyon/apps/esign/service/TokenCacheManager.java @@ -9,36 +9,33 @@ import com.seeyon.apps.esign.po.esignapi.EsignBaseResp; import com.seeyon.apps.esign.po.esignapi.EsignToken; import com.seeyon.apps.esign.utils.HttpClient; +import java.util.List; import java.util.Map; +import java.util.concurrent.ConcurrentHashMap; import java.util.concurrent.Executors; import java.util.concurrent.ScheduledExecutorService; import java.util.concurrent.TimeUnit; import java.util.concurrent.atomic.AtomicReference; +import java.util.stream.Collectors; public class TokenCacheManager { - private EsignConfigProvider esignConfigProvider = EsignConfigProvider.getInstance(); - private final AtomicReference tokenRef = new AtomicReference<>(); + private EsignConfigProvider configProvider = EsignConfigProvider.getInstance(); + private final ConcurrentHashMap tokenRef = new ConcurrentHashMap<>(); private final ScheduledExecutorService scheduler = Executors.newSingleThreadScheduledExecutor(); private static final long CHECK_INTERVAL = 2 * 60 * 60 * 1000; // 120分钟检查一次 - - public TokenCacheManager() { - // 启动定期检查任务 - scheduler.scheduleAtFixedRate(this::checkTokenExpiry, - CHECK_INTERVAL, CHECK_INTERVAL, TimeUnit.MILLISECONDS); - } - private boolean checkExpired(String token) { + private boolean checkExpired(String token,String appId) { EsignApiHeader esignApiHeader = EsignApiHeader.build(); try { - esignApiHeader.token(token).appId(esignConfigProvider.getBizConfigByKey(EsignConfigConstants.APP_ID)); + esignApiHeader.token(token).appId(appId); } catch (Exception e) { e.printStackTrace(); } //获取orgId - String queryStr = EsignApiUrl.QUERY_ORGINFO + "?orgName=" + esignConfigProvider.getBizConfigByKey(EsignConfigConstants.UNITNAME); - String reqUrl = esignConfigProvider.getBizConfigByKey(EsignConfigConstants.ESIGN_HOST) + queryStr; + String queryStr = EsignApiUrl.QUERY_ORGINFO + "?orgName=" + getOrgNameByAppId(appId); + String reqUrl = configProvider.getBizConfigByKey(EsignConfigConstants.ESIGN_HOST) + queryStr; String orgInfoRespStr = HttpClient.httpGet(reqUrl, esignApiHeader.convert2Headers(), "UTF-8"); EsignBaseResp orgInfoResp = JsonUtils.parseObject(orgInfoRespStr, EsignBaseResp.class); if(orgInfoResp.getCode() == 401) { @@ -46,36 +43,69 @@ public class TokenCacheManager { } return false; } - - public String getToken() { - EsignToken current = tokenRef.get(); - if (current != null && !checkExpired(current.getTokenStr())) { + + public String getOrgIdByOrgName(String orgName) { + EsignApiHeader esignApiHeader = EsignApiHeader.build(); + String appId = getAppIdByOrgName(orgName); + try { + esignApiHeader.token(getToken(appId)).appId(appId); + } catch (Exception e) { + e.printStackTrace(); + } + //获取orgId + String queryStr = EsignApiUrl.QUERY_ORGINFO + "?orgName=" + orgName; + String reqUrl = configProvider.getBizConfigByKey(EsignConfigConstants.ESIGN_HOST) + queryStr; + String orgInfoRespStr = HttpClient.httpGet(reqUrl, esignApiHeader.convert2Headers(), "UTF-8"); + EsignBaseResp orgInfoResp = JsonUtils.parseObject(orgInfoRespStr, EsignBaseResp.class); + Map orgData = (Map) orgInfoResp.getData(); + return (String) orgData.get("orgId"); + } + + public String getOrgIdByOrgName(String orgName,String appId) { + EsignApiHeader esignApiHeader = EsignApiHeader.build(); + try { + esignApiHeader.token(getToken(appId)).appId(appId); + } catch (Exception e) { + e.printStackTrace(); + } + //获取orgId + String queryStr = EsignApiUrl.QUERY_ORGINFO + "?orgName=" + orgName; + String reqUrl = configProvider.getBizConfigByKey(EsignConfigConstants.ESIGN_HOST) + queryStr; + String orgInfoRespStr = HttpClient.httpGet(reqUrl, esignApiHeader.convert2Headers(), "UTF-8"); + EsignBaseResp orgInfoResp = JsonUtils.parseObject(orgInfoRespStr, EsignBaseResp.class); + Map orgData = (Map) orgInfoResp.getData(); + return (String) orgData.get("orgId"); + } + + public String getToken(String appId) { + EsignToken current = tokenRef.get(appId); + if (current != null && !checkExpired(current.getTokenStr(),appId)) { return current.getTokenStr(); } - return refreshToken(); + return refreshToken(appId); } - - private String refreshToken() { - EsignToken newToken = fetchNewToken(); - tokenRef.set(newToken); + + private String refreshToken(String appId) { + EsignToken newToken = fetchNewToken(appId); + tokenRef.put(appId,newToken); return newToken.getTokenStr(); } - - private void checkTokenExpiry() { - EsignToken current = tokenRef.get(); + + private void checkTokenExpiry(String appId) { + EsignToken current = tokenRef.get(appId); if (current != null && isTokenExpired(current)) { - refreshToken(); + refreshToken(appId); } } - + private boolean isTokenExpired(EsignToken token) { return System.currentTimeMillis() >= token.getTtl(); } - - private EsignToken fetchNewToken() { + + private EsignToken fetchNewToken(String appId) { // 实际获取token的逻辑 - String queryStr = "?appId=" + esignConfigProvider.getBizConfigByKey(EsignConfigConstants.APP_ID) + "&secret=" + esignConfigProvider.getBizConfigByKey(EsignConfigConstants.APP_SECRET) + "&grantType=client_credentials"; - String url = esignConfigProvider.getBizConfigByKey(EsignConfigConstants.ESIGN_HOST) + EsignApiUrl.TOKEN_GET_URL + queryStr; + String queryStr = "?appId=" + appId + "&secret=" + getSecretByAppId(appId) + "&grantType=client_credentials"; + String url = configProvider.getBizConfigByKey(EsignConfigConstants.ESIGN_HOST) + EsignApiUrl.TOKEN_GET_URL + queryStr; String respStr = HttpClient.httpGet(url, null, null); EsignBaseResp esignBaseResp = JsonUtils.parseObject(respStr, EsignBaseResp.class); if(esignBaseResp.getCode() != 0) { @@ -91,8 +121,37 @@ public class TokenCacheManager { esignToken.setRefreshToken(refreshToken); return esignToken; } - + public void shutdown() { scheduler.shutdown(); } + + public String getOrgNameByAppId(String appId) { + String configMap = configProvider.getBizConfigByKey(EsignConfigConstants.ESIGN_APP_UNITMAP); + Map map = JsonUtils.parseObject(configMap, Map.class); + return map.get(appId); + } + + public String getSecretByAppId(String appId) { + String configMap = configProvider.getBizConfigByKey(EsignConfigConstants.ESIGN_APP_SECRETMAP); + Map map = JsonUtils.parseObject(configMap, Map.class); + return map.get(appId); + } + + public String getAppIdByOrgName(String orgName) { + String configMap = configProvider.getBizConfigByKey(EsignConfigConstants.ESIGN_APP_UNITMAP); + Map map = JsonUtils.parseObject(configMap, Map.class); + for (String key : map.keySet()) { + if(map.get(key).equals(orgName)) { + return key; + } + } + return null; + } + + public List getAppIds() { + String configMap = configProvider.getBizConfigByKey(EsignConfigConstants.ESIGN_APP_SECRETMAP); + Map map = JsonUtils.parseObject(configMap, Map.class); + return map.keySet().stream().collect(Collectors.toList()); + } } \ No newline at end of file diff --git a/src/main/java/com/seeyon/apps/esign/utils/CallbackUrlBuilder.java b/src/main/java/com/seeyon/apps/esign/utils/CallbackUrlBuilder.java new file mode 100644 index 0000000..1b06286 --- /dev/null +++ b/src/main/java/com/seeyon/apps/esign/utils/CallbackUrlBuilder.java @@ -0,0 +1,33 @@ +package com.seeyon.apps.esign.utils; + +/** + * 签署回调 URL 构建工具 + */ +public final class CallbackUrlBuilder { + + private CallbackUrlBuilder() {} + + public static final String DEFAULT_CALLBACK_PATH = "/seeyon/esigncallback.do?method=callback"; + private static final String SEEYON_PREFIX = "/seeyon"; + + private static final String PARAM_FORM_ID = "&formId="; + private static final String PARAM_TABLE_NAME = "&tablename="; + private static final String PARAM_UPDATE_FIELD = "&updatefield="; + private static final String PARAM_STATUS_FIELD = "&statusfield="; + private static final String PARAM_BIZ_TYPE = "&bizType="; + private static final String PARAM_X_ID = "&xId="; + + public static String build(String callbackBaseUrl, String bizType, + String formId, String tableName, + String updateField, String statusField, + Long statusEnumId, String appId) { + String basePath = callbackBaseUrl == null ? DEFAULT_CALLBACK_PATH : SEEYON_PREFIX + callbackBaseUrl; + return basePath + + PARAM_FORM_ID + formId + + PARAM_TABLE_NAME + tableName + + PARAM_UPDATE_FIELD + updateField + + PARAM_STATUS_FIELD + statusField + "_" + statusEnumId + + PARAM_BIZ_TYPE + bizType + + PARAM_X_ID + appId; + } +} diff --git a/src/main/java/com/seeyon/apps/esign/utils/FileUtil.java b/src/main/java/com/seeyon/apps/esign/utils/FileUtil.java index ff1b528..381e847 100644 --- a/src/main/java/com/seeyon/apps/esign/utils/FileUtil.java +++ b/src/main/java/com/seeyon/apps/esign/utils/FileUtil.java @@ -12,7 +12,7 @@ import com.seeyon.ctp.organization.bo.V3xOrgAccount; import com.seeyon.ctp.organization.bo.V3xOrgMember; import com.seeyon.ctp.organization.manager.OrgManager; import com.seeyon.ctp.services.FileUploadExporter; -import org.apache.commons.lang3.StringUtils; +import org.apache.commons.lang.StringUtils; import org.apache.poi.hssf.usermodel.HSSFWorkbook; import org.apache.poi.ss.usermodel.Cell; import org.apache.poi.ss.usermodel.Row; diff --git a/src/main/java/com/seeyon/ctp/rest/resources/esign/EsignFlowQueryResource.java b/src/main/java/com/seeyon/ctp/rest/resources/esign/EsignFlowQueryResource.java index 8958dec..8c88782 100644 --- a/src/main/java/com/seeyon/ctp/rest/resources/esign/EsignFlowQueryResource.java +++ b/src/main/java/com/seeyon/ctp/rest/resources/esign/EsignFlowQueryResource.java @@ -24,7 +24,7 @@ public class EsignFlowQueryResource extends BaseResource { @Path("/queryFlowStatus") public Response queryTemplates() { try { - return success(esignFlowQueryService.queryFlow(req.getParameter("eFlowId"))); + return success(esignFlowQueryService.queryFlow(req.getParameter("orgName"),req.getParameter("eFlowId"))); }catch (Exception e) { e.printStackTrace(); log.error(e.getMessage(),e); diff --git a/src/main/java/com/seeyon/ctp/rest/resources/esign/EsignTemplateResource.java b/src/main/java/com/seeyon/ctp/rest/resources/esign/EsignTemplateResource.java index fbaa53d..32339ab 100644 --- a/src/main/java/com/seeyon/ctp/rest/resources/esign/EsignTemplateResource.java +++ b/src/main/java/com/seeyon/ctp/rest/resources/esign/EsignTemplateResource.java @@ -26,7 +26,7 @@ public class EsignTemplateResource extends BaseResource { @Path("/querypage") public Response queryTemplates(@QueryParam("pageNum") Integer pageNum) { try { - Map map = esignFileTemplateService.queryTemplates(pageNum); + Map map = esignFileTemplateService.queryTemplates("",pageNum); return success(map); }catch (Exception e) { e.printStackTrace(); @@ -41,7 +41,7 @@ public class EsignTemplateResource extends BaseResource { @Path("/compareurl") public Response compare(@QueryParam("templateRefId") String templateRefId,@QueryParam("contractRefId") String contractRefId) { try { - String compareDetailUrl = esignFileTemplateService.getCompareDetailUrl(templateRefId, contractRefId); + String compareDetailUrl = esignFileTemplateService.getCompareDetailUrl("",templateRefId, contractRefId); return success(compareDetailUrl); }catch (Exception e) { e.printStackTrace();