优化代码

This commit is contained in:
2026-06-12 11:35:36 +08:00
parent 36b08b0d6b
commit 907342adb4
37 changed files with 1441 additions and 922 deletions

View File

@@ -17,6 +17,7 @@
<bean id="tokenCacheManager" class="com.seeyon.apps.esign.service.TokenCacheManager" />
<bean id="esignFlowQueryService" class="com.seeyon.apps.esign.service.EsignFlowQueryService" />
<bean id="protUtil" class="com.seeyon.apps.esign.utils.ProtUtil" />
<bean id="esignAntiFakeSignNode" class="com.seeyon.apps.esign.node.EsignAntiFakeSignNode" />
<!-- 定义接口实现类 -->
<bean id="esignCallbackFlowBizService" class="com.seeyon.apps.esign.service.EsignCallbackFlowBizService"/>
<!-- 注入数组类型的Bean -->

View File

@@ -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/";
}

View File

@@ -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;

View File

@@ -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 = "签署状态";
}

View File

@@ -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";
}

View File

@@ -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){
//合同过期

View File

@@ -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<String> 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<String,Object> 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) {

View File

@@ -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<String,Object> 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){
}
}
}

View File

@@ -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<String,String> 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<String, String> getTemplateValue() {
return templateValue;
}
public void setTemplateValue(Map<String, String> templateValue) {
this.templateValue = templateValue;
}
}

View File

@@ -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<String> columns = new ArrayList<>();
columns.add("SENDER_ID");
SqlBuildParam param = new SqlBuildParam();
List<FormWhereCondition> 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<String, Object> 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<Map<String, Object>> rows = agent.resultSetToList();
if(rows.size() <= 0) {
return null;
}
Map<String, Object> 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<SignParty> buildSigners(FormDataVo formDataVo, Boolean doAutoSign, String unitName) throws NoSuchFieldException, BusinessException {
List<SignParty> 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签宝防伪签署节点";
}
}

View File

@@ -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<String, Object> 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<String, Object> 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<String, Object> config = new HashMap<>();
// config.put("signFlowTitle", contractName);
// config.put("autoFinish", true);
// config.put("notifyUrl", signCallBackUrl);
// Map<String, Object> noticeConfig = new HashMap<>();
// noticeConfig.put("noticeTypes", "1");
// config.put("noticeConfig", noticeConfig);
// Map<String,Object> 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<Signer> buildSigners(FormDataVo formDataVo, String fileId) throws Exception {
// List<String> keywords = new ArrayList<>();
// keywords.add("甲方盖章/签字");
// keywords.add("乙方盖章/签字");
// List<Object> positions = uploadFileService.getSignPosition(fileId,keywords);
// List<SignFieldPosition> bPositions = extractPosition(positions, "乙方盖章/签字");
// List<SignFieldPosition> 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<Signer> 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<String, Object> 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<String, Object> docMap = new HashMap<>();
// docMap.put("fileId", fileId);
// Thread.sleep(1000);
// List<Object> docs = new ArrayList<>();
// docs.add(docMap);
// Map<String, Object> signFlowConfig = buildSignFlowConfig(formDataVo, formDataMasterBean);
// List<Signer> signers = buildSigners(formDataVo, fileId);
// Map<String, Object> 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<FormUpdateField> updateFields = new ArrayList<>();
// updateFields.add(FormUpdateField.build().display("合同文件ID").value(fileId));
// List<FormWhereCondition> whereConditions = new ArrayList<>();
// whereConditions.add(FormWhereCondition.build().display("ID").value(formDataVo.getId()));
// FormTableExecutor.update(tableContext,updateFields,whereConditions);
// }
//
// private Map<String, Object> mapOf(Object... keyValues) {
// if (keyValues.length % 2 != 0) {
// throw new IllegalArgumentException("参数个数必须为偶数key 和 value 必须成对出现");
// }
// Map<String, Object> 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<SignFieldPosition> 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<String, Object> psnInfo = mapOf("psnAccount", phone, "psnInfo", mapOf("psnName", psnName));
// signer.setPsnSignerInfo(psnInfo);
// }
//
// List<SignField> 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<SignFieldPosition> 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<String, Object> 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<SignField> 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<SignFieldPosition> extractPosition(List<Object> positions, String keyword) {
// List<SignFieldPosition> posList = new ArrayList<>();
// for (Object obj : positions) {
// Map<String, Object> position = (Map<String, Object>) obj;
// if (Boolean.TRUE.equals(position.get("searchResult")) && keyword.equals(position.get("keyword"))) {
// Object[] posArray = (Object[]) position.get("positions");
// for (Object o : posArray) {
// Map<String, Object> posMap = (Map<String, Object>)o;
// Object[] coords = (Object[]) posMap.get("coordinates");
// for (Object coord : coords) {
// Map<String,Object> tempMap = (Map<String, Object>) 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<SignParty> buildSigners(String appId,FormDataVo formDataVo,Boolean doAutoSign,String orgName) throws NoSuchFieldException, BusinessException {
List<SignParty> 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<String> columns = new ArrayList<>();
columns.add("SENDER_ID");
SqlBuildParam param = new SqlBuildParam();
List<FormWhereCondition> 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<String, Object> 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<Map<String, Object>> rows = agent.resultSetToList();
if(rows.size() <= 0) {
return null;
}
Map<String, Object> 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<SignParty> 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() {

View File

@@ -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<String, Object> 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<String, Object> config = new HashMap<>();
// config.put("signFlowTitle", contractName);
// config.put("autoFinish", true);
// config.put("notifyUrl", signCallBackUrl);
// Map<String, Object> noticeConfig = new HashMap<>();
// noticeConfig.put("noticeTypes", "1");
// config.put("noticeConfig", noticeConfig);
// Map<String,Object> signConfig = new HashMap<>();
// signConfig.put("showBatchDropSealButton", false);
// config.put("signConfig",signConfig);
// return config;
// }
// private List<Signer> 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<SignFieldPosition> pos = new ArrayList<>();
// Map<String, List<FormDataVo>> subFormMap = formDataVo.getSubFormMap();
// List<FormDataVo> subDataVos = subFormMap.get("甲方签署位置");
// Boolean autoSign = true;
// if(subDataVos!= null && subDataVos.size() > 0 && !subDataVos.get(0).isEmpty()){
// for (FormDataVo subDataVo : subDataVos) {
// Map<String, FieldDataVo> 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<Signer> signers = new ArrayList<>();
// signers.add(aSigner);
// return signers;
// }
// private Map<String, Object> 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<String, Object> docMap = new HashMap<>();
// Thread.sleep(1000);
// docMap.put("fileId", fileId);
// List<Object> docs = new ArrayList<>();
// docs.add(docMap);
// Map<String, Object> signFlowConfig = buildSignFlowConfig(formDataVo, formDataMasterBean);
// List<Signer> signers = buildOnlyASigner(formDataVo, fileId);
// Map<String, Object> signParams = new HashMap<>();
// signParams.put("signFlowConfig", signFlowConfig);
// signParams.put("signers", signers);
// signParams.put("docs", docs);
// return signParams;
//
// }
// private Map<String, Object> mapOf(Object... keyValues) {
// if (keyValues.length % 2 != 0) {
// throw new IllegalArgumentException("参数个数必须为偶数key 和 value 必须成对出现");
// }
// Map<String, Object> 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<SignFieldPosition> 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<String, Object> psnInfo = mapOf("psnAccount", phone, "psnInfo", mapOf("psnName", psnName));
// signer.setPsnSignerInfo(psnInfo);
// }
//
// List<SignField> 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<SignFieldPosition> 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<SignField> signFields = new ArrayList<>();
// signer.setSignFields(signFields);
// if(Boolean.FALSE.equals(autoSign)){
// signer.setNoticeConfig(mapOf("noticeTypes", "1"));
//
// Map<String, Object> 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<String, Object> orgInfo = mapOf("orgName", orgName,
// "transactorInfo", mapOf(
// "psnAccount", transPhone,
// "psnInfo", mapOf(
// "psnName", psnName
// )
// )
// );
//
// signer.setOrgSignerInfo(orgInfo);
// }
//
// List<SignField> 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<SignFieldPosition> extractPosition(List<Object> positions, String keyword) {
// List<SignFieldPosition> posList = new ArrayList<>();
// for (Object obj : positions) {
// Map<String, Object> position = (Map<String, Object>) obj;
// if (Boolean.TRUE.equals(position.get("searchResult")) && keyword.equals(position.get("keyword"))) {
// Object[] posArray = (Object[]) position.get("positions");
// for (Object o : posArray) {
// Map<String, Object> posMap = (Map<String, Object>)o;
// Object[] coords = (Object[]) posMap.get("coordinates");
// for (Object coord : coords) {
// Map<String,Object> tempMap = (Map<String, Object>) 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<SignParty> buildSigners(String appId,FormDataVo formDataVo, Boolean doAutoSign, String orgName) throws NoSuchFieldException, BusinessException {
List<SignParty> 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<String> columns = new ArrayList<>();
columns.add("sender_id");
SqlBuildParam param = new SqlBuildParam();
List<FormWhereCondition> 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<String, Object> 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<Map<String, Object>> rows = agent.resultSetToList();
if(rows.size() <= 0) {
return null;
}
Map<String, Object> 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<SignParty> 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);
}
}

View File

@@ -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;

View File

@@ -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<SignParty> 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<SignParty> signerParties) {
this.signerParties = signerParties;
}
@Override
public List<SignParty> getSignerParties() throws Exception {
List<SignParty> 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;
}
}

View File

@@ -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<String,Object> oriParams;
private String callbackBaseUrl;
private List<SignParty> 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<SignParty> getSignerParties() {
String tempStr = (String)oriParams.get("signers");
String tempStr = (String)oriParams.get(JsonParamKeyConstants.SIGNERS);
List signers = JsonUtils.parseObject(tempStr, List.class);
List<SignParty> parties = new ArrayList<>();
Float qfPos = 100f;
for (Object signer : signers) {
Map<String,Object> signerMap = (Map<String,Object>) 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;
}
}

View File

@@ -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<String> fileIds,List<Object> 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<String> fileIds, List<Object> 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<String> fileIds,List<Object> keywordPos, SignParty party) {
PersonInfo psn = party.getPersonInfo();
if (psn == null) throw new IllegalStateException("个人签署方缺少 PersonInfo");
/**
* 构建个人签署方
*/
private Signer buildPersonSigner(List<String> fileIds, List<Object> 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<String> fileIds, List<Object> keywordPos,SignParty party) {
OrgInfo org = party.getOrgInfo();
/**
* 构建机构/法定代表人签署方
*/
private Signer buildOrgSigner(List<String> fileIds, List<Object> 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<SignFieldPosition> extractPosition(List<Object> positions, String keyword) {
if(StringUtils.isBlank(keyword)) {
return null;
}
List<SignFieldPosition> posList = new ArrayList<>();
for (Object obj : positions) {
Map<String, Object> position = (Map<String, Object>) obj;
if (Boolean.TRUE.equals(position.get("searchResult")) && keyword.equals(position.get("keyword"))) {
Object[] posArray = (Object[]) position.get("positions");
for (Object o : posArray) {
Map<String, Object> posMap = (Map<String, Object>)o;
Object[] coords = (Object[]) posMap.get("coordinates");
for (Object coord : coords) {
Map<String,Object> tempMap = (Map<String, Object>) 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<SignField> buildSignFields(List<String> fileIds,List<Object> keywordPos, SignParty party) {
/**
* 构建签署区集合(核心逻辑)
*/
private List<SignField> buildSignFields(List<String> fileIds, List<Object> keywordPos, SignParty party, String appId) {
List<SignField> 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<SignFieldPosition> signFieldPositions = extractPosition(keywordPos, searchKey);
List<SignFieldPosition> 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<SignField> signFields, String fileId, List<Object> keywordPos,
SignParty party, String appId) {
// 防伪章使用固定坐标,不走关键字定位
if (ANTI_COUNTERFEIT_PARTY.equals(party.getPartyId())) {
addAntiCounterfeitSignFields(signFields, fileId, party, appId);
return;
}
// 根据签署方自带的关键字提取位置
List<SignFieldPosition> 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<SignFieldPosition> extractPosition(List<Object> positions, String keyword) {
List<SignFieldPosition> posList = new ArrayList<>();
if (StringUtils.isBlank(keyword) || positions == null || positions.isEmpty()) {
return posList;
}
for (Object obj : positions) {
Map<String, Object> posMap = (Map<String, Object>) obj;
// 匹配关键字且搜索成功
if (Boolean.TRUE.equals(posMap.get("searchResult")) && keyword.equals(posMap.get("keyword"))) {
parseCoordinatePositions(posList, posMap);
return posList;
}
}
return posList;
}
/**
* 解析坐标信息
*/
private void parseCoordinatePositions(List<SignFieldPosition> posList, Map<String, Object> posMap) {
Object[] posArray = (Object[]) posMap.get("positions");
for (Object posObj : posArray) {
Map<String, Object> coordMap = (Map<String, Object>) posObj;
Object[] coords = (Object[]) coordMap.get("coordinates");
for (Object coord : coords) {
Map<String, Object> tempMap = (Map<String, Object>) 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<SignField> 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<String, Object> buildSignOrderConfig(Integer signOrder) {
return mapOf("signOrder", signOrder);
}
/**
* 构建通知配置
*/
private Map<String, Object> buildNoticeConfig() {
return mapOf("noticeTypes", NOTICE_TYPE_SMS);
}
/**
* 构建个人签署信息
*/
private Map<String, Object> buildPersonSignerInfo(PersonInfo psn) {
return mapOf(
"psnAccount", psn.getPhone(),
"psnInfo", mapOf(
"psnName", psn.getName(),
"psnIDCardNum", psn.getIdCardNo(),
"psnIDCardType", psn.getIdCardType()
)
);
}
/**
* 构建机构签署信息
*/
private Map<String, Object> 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<String, Object> 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<String, Object> data = (Map<String, Object>) 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<String, Object> mapOf(Object... keyValues) {
if (keyValues.length % 2 != 0) throw new IllegalArgumentException("key-value 必须成对出现");
if (keyValues.length % 2 != 0) {
throw new IllegalArgumentException("键值对数量必须为偶数");
}
Map<String, Object> map = new HashMap<>();
for (int i = 0; i < keyValues.length; i += 2) {
map.put((String) keyValues[i], keyValues[i + 1]);

View File

@@ -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<String> fileIds, List<Object> keywordPos, SignParty party) {
public Signer build(List<String> fileIds, List<Object> keywordPos, SignParty party,String appId) {
if (party.getSignerType() == SignerType.PERSON) {
return buildPersonSigner(fileIds,keywordPos,party);
} else if (party.getSignerType() == SignerType.ORG) {

View File

@@ -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;
}
}

View File

@@ -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;
}
}

View File

@@ -8,15 +8,15 @@ public interface SignerBuilder {
/**
* 根据签署方信息构建 Signer
*/
Signer build(List<String> fileIds, List<Object> keywordPos,SignParty party);
Signer build(List<String> fileIds, List<Object> keywordPos,SignParty party,String appId);
/**
* 批量构建(默认能力)
*/
default List<Signer> buildAll(List<String> fileIds,List<Object> keywordPos,List<SignParty> parties) {
default List<Signer> buildAll(List<String> fileIds,List<Object> keywordPos,List<SignParty> parties,String appId) {
List<Signer> 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);
}

View File

@@ -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;
}
}

View File

@@ -15,7 +15,7 @@ public class ContractCreateService {
if(factory.support(source)){
Map<String, Object> buildParam = factory.buildParam(source);
if (buildParam == null) throw new RuntimeException("签署参数构建失败");
return templateService.createBySignTemplate(buildParam);
return templateService.createBySignTemplate(source.getAppId(),buildParam);
}
}
return null;

View File

@@ -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<String,Object> authParams) throws Exception {
public void personAuth(String appId,Map<String,Object> 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);

View File

@@ -36,10 +36,10 @@ public class EsignByTemplateService {
}
}
public String createBySignTemplate(Map<String,Object> params) throws Exception {
public String createBySignTemplate(String appId,Map<String,Object> 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");

View File

@@ -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<String, Object> orgData = (Map<String, Object>) orgInfoResp.getData();
orgId = (String) orgData.get("orgId");
return (String) orgData.get("orgId");
}
//填充模板
@@ -81,19 +79,19 @@ public class EsignFileTemplateService {
}
//获取模板详细信息
public Map<String,Object> getTemplateDetail(String signTemplateId,String orgId) {
public Map<String,Object> 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<String,Object> data = (Map<String, Object>) esignBaseResp.getData();
return data;
}
public Map<String,Object> 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<String,Object> 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<String,String> 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);
}
}

View File

@@ -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);

View File

@@ -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<Object> getSignPosition(String fileId,List<String> keywords) {
public List<Object> getSignPosition(String appId,String fileId,List<String> 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<String,Object> 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<String,Object> data = (Map<String,Object>) map.get("data");
@@ -97,7 +98,7 @@ public class EsignUploadFileService {
return new ArrayList<>();
}
public List<String> uploadFileToEsign(String refId) throws Exception {
public List<String> uploadFileToEsign(String appId,String refId) throws Exception {
String tempDir = System.getProperty("java.io.tmpdir");
List<String> 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));
}
/***

View File

@@ -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<Map<String, Object>> docs = buildDocs(attachmentId);
List<Map<String, Object>> docs = buildDocs(source.getAppId(),attachmentId);
fileIds = new ArrayList<>();
for (Map<String, Object> doc : docs) {
fileIds.add((String) doc.get("fileId"));
@@ -36,22 +36,26 @@ public class FlowFormSignParamBuildFactory implements SignParamBuildFactory {
}
Map<String, Object> signFlowConfig = buildSignFlowConfig(source.getContractTitle(),source.getCallbackUrl());
DefaultSignerBuilder signerBuilder = new DefaultSignerBuilder();
List<String> 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<Object> keywordPos = getKeywordPos(fileIds, keywords);
List<SignParty> signerParties = source.getSignerParties();
List<Signer> signers = signerBuilder.buildAll(fileIds,keywordPos,signerParties);
List<Object> 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<String> 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<Signer> 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<Object> getKeywordPos(List<String> fileIds,List<String> keywords){
private List<Object> getKeywordPos(String appId,List<String> fileIds,List<String> keywords){
List<Object> pos = new ArrayList<>();
if(keywords.isEmpty()) {
return pos;
}
for (String fileId : fileIds){
List<Object> signPosition = uploadFileService.getSignPosition(fileId, keywords);
List<Object> 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<Map<String, Object>> buildDocs(String attachmentId) throws Exception {
List<String> fileIds = uploadFileService.uploadFileToEsign(attachmentId);
public List<Map<String, Object>> buildDocs(String appId,String attachmentId) throws Exception {
List<String> fileIds = uploadFileService.uploadFileToEsign(appId,attachmentId);
List<Map<String, Object>> docs = new ArrayList<>();
for (String fileId : fileIds) {
Map<String, Object> 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);

View File

@@ -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<Map<String, Object>> docs = buildDocs(attachmentId);
List<Map<String, Object>> docs = buildDocs(source.getAppId(),attachmentId);
fileIds = new ArrayList<>();
for (Map<String, Object> doc : docs) {
fileIds.add((String) doc.get("fileId"));
@@ -43,17 +42,17 @@ public class NormalFormSignParamBuildFactory implements SignParamBuildFactory {
keywords.add(party.getSignKeyword());
}
});
List<Object> keywordPos = getKeywordPos(fileIds, keywords);
List<Signer> signers = signerBuilder.buildAll(fileIds,keywordPos,signerParties);
List<Object> keywordPos = getKeywordPos(source.getAppId(),fileIds, keywords);
List<Signer> signers = signerBuilder.buildAll(fileIds,keywordPos,signerParties,source.getAppId());
signParams.put("signFlowConfig", signFlowConfig);
signParams.put("signers", signers);
return signParams;
}
private List<Object> getKeywordPos(List<String> fileIds,List<String> keywords){
private List<Object> getKeywordPos(String appId,List<String> fileIds,List<String> keywords){
List<Object> pos = new ArrayList<>();
for (String fileId : fileIds){
List<Object> signPosition = uploadFileService.getSignPosition(fileId, keywords);
List<Object> 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<Map<String, Object>> buildDocs(String attachmentId) throws Exception {
List<String> fileIds = uploadFileService.uploadFileToEsign(attachmentId);
public List<Map<String, Object>> buildDocs(String appId,String attachmentId) throws Exception {
List<String> fileIds = uploadFileService.uploadFileToEsign(appId,attachmentId);
List<Map<String, Object>> docs = new ArrayList<>();
for (String fileId : fileIds) {
Map<String, Object> docMap = new HashMap<>();

View File

@@ -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<String, Object> params) throws Exception {
public void grantSeal(String appId,Map<String, Object> 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<String> 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<FormWhereCondition> 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<String, Object> 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);

View File

@@ -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<String,Object> tempMap = (Map<String, Object>) 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<String,Object> dataMap = (Map<String, Object>) 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);

View File

@@ -48,4 +48,8 @@ public interface SignParamSource {
return "1";
}
String getAppId();
boolean useKeyWordPositioning();
}

View File

@@ -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<EsignToken> tokenRef = new AtomicReference<>();
private EsignConfigProvider configProvider = EsignConfigProvider.getInstance();
private final ConcurrentHashMap<String, EsignToken> 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<String, Object> orgData = (Map<String, Object>) 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<String, Object> orgData = (Map<String, Object>) 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<String,String> map = JsonUtils.parseObject(configMap, Map.class);
return map.get(appId);
}
public String getSecretByAppId(String appId) {
String configMap = configProvider.getBizConfigByKey(EsignConfigConstants.ESIGN_APP_SECRETMAP);
Map<String,String> map = JsonUtils.parseObject(configMap, Map.class);
return map.get(appId);
}
public String getAppIdByOrgName(String orgName) {
String configMap = configProvider.getBizConfigByKey(EsignConfigConstants.ESIGN_APP_UNITMAP);
Map<String,String> map = JsonUtils.parseObject(configMap, Map.class);
for (String key : map.keySet()) {
if(map.get(key).equals(orgName)) {
return key;
}
}
return null;
}
public List<String> getAppIds() {
String configMap = configProvider.getBizConfigByKey(EsignConfigConstants.ESIGN_APP_SECRETMAP);
Map<String,String> map = JsonUtils.parseObject(configMap, Map.class);
return map.keySet().stream().collect(Collectors.toList());
}
}

View File

@@ -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;
}
}

View File

@@ -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;

View File

@@ -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);

View File

@@ -26,7 +26,7 @@ public class EsignTemplateResource extends BaseResource {
@Path("/querypage")
public Response queryTemplates(@QueryParam("pageNum") Integer pageNum) {
try {
Map<String, Object> map = esignFileTemplateService.queryTemplates(pageNum);
Map<String, Object> 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();