diff --git a/esign/pom.xml b/esign/pom.xml new file mode 100644 index 0000000..48c00c6 --- /dev/null +++ b/esign/pom.xml @@ -0,0 +1,17 @@ + + + 4.0.0 + + com.seeyon.apps + esign + 1.0-SNAPSHOT + + + 8 + 8 + UTF-8 + + + \ No newline at end of file diff --git a/esign/src/main/java/com/seeyon/apps/esign/GtlyEsignPluginApi.java b/esign/src/main/java/com/seeyon/apps/esign/GtlyEsignPluginApi.java new file mode 100644 index 0000000..792835f --- /dev/null +++ b/esign/src/main/java/com/seeyon/apps/esign/GtlyEsignPluginApi.java @@ -0,0 +1,44 @@ +package com.seeyon.apps.esign; + +import com.seeyon.apps.common.plugin.api.APluginInfoApi; +import com.seeyon.apps.common.plugin.vo.ConfigVo; +import com.seeyon.apps.esign.constants.EsignConfigConstants; +import org.springframework.stereotype.Component; + +@Component +public class GtlyEsignPluginApi extends APluginInfoApi { + public GtlyEsignPluginApi() { + } + + public String getPluginId() { + System.out.println(EsignConfigConstants.getPluginId()); + return EsignConfigConstants.getPluginId(); + } + + public String getCreateUser() { + return "橙阳科技"; + } + + public String getDescription() { + return "长数鸿翼网盘集成"; + } + + public ConfigVo getDefaultConfig() { + ConfigVo configVo = new ConfigVo(); + EsignConfigConstants[] var2 = EsignConfigConstants.values(); + int var3 = var2.length; + + for(int var4 = 0; var4 < var3; ++var4) { + EsignConfigConstants value = var2[var4]; + if (value != EsignConfigConstants.plugin) { + configVo.getDevParams().put(value.name(), value.getDefaultValue()); + configVo.getProdParams().put(value.name(), value.getDefaultValue()); + configVo.getParamMap().put(value.name(), value.getDescription()); + } + } + + return configVo; + } + +} + diff --git a/esign/src/main/java/com/seeyon/apps/esign/config/EsignConfigProvider.java b/esign/src/main/java/com/seeyon/apps/esign/config/EsignConfigProvider.java new file mode 100644 index 0000000..40ff2a7 --- /dev/null +++ b/esign/src/main/java/com/seeyon/apps/esign/config/EsignConfigProvider.java @@ -0,0 +1,20 @@ +package com.seeyon.apps.esign.config; + +import com.seeyon.apps.common.config.ICstConfigApi; +import com.seeyon.apps.common.plugin.vo.ConfigVo; +import com.seeyon.apps.esign.constants.EsignConfigConstants; +import com.seeyon.ctp.common.AppContext; +import org.springframework.stereotype.Component; + +import static com.seeyon.apps.esign.constants.EsignConfigConstants.getPluginId; + +@Component +public class EsignConfigProvider { + + protected ICstConfigApi cstConfigApi = (ICstConfigApi) AppContext.getBean("cstConfigApi"); + + public String getBizConfigByKey(EsignConfigConstants key) { + ConfigVo config = cstConfigApi.getConfig(getPluginId()); + return config.getParamVal(key.name()); + } +} diff --git a/esign/src/main/java/com/seeyon/apps/esign/constants/EsignApiUrl.java b/esign/src/main/java/com/seeyon/apps/esign/constants/EsignApiUrl.java new file mode 100644 index 0000000..289e49b --- /dev/null +++ b/esign/src/main/java/com/seeyon/apps/esign/constants/EsignApiUrl.java @@ -0,0 +1,17 @@ +package com.seeyon.apps.esign.constants; + +public class EsignApiUrl { + public static final String QUERY_SEAL_URL = "/v3/seals/org-own-seal-list"; + public static final String SEAL_GRANT_URL = "/v3/seals/org-seals/internal-auth"; + public static final String SIGN_START_URL = "/v3/sign-flow/{signFlowId}/start"; + public static final String SIGN_BY_FILE_URL = "/v3/sign-flow/create-by-file"; + public static final String GET_UPLOAD_FILE_URL = "/v3/files/file-upload-url"; + public static final String CONTRACT_DOWNLOAD_URL= "/v3/sign-flow/{signFlowId}/file-download-url"; + public static final String PERSON_AUTH_URL = "/v3/psn-auth-url"; + public static final String SIGN_POSITION_URL = "/v3/files/{fileId}/keyword-positions"; + public static final String QUERY_TEMPLATES_URL = "/v3/sign-templates"; + public static final String QUERY_TEMPLATE_DETAIL_URL = "/v3/sign-templates/detail"; + public static final String QUERY_ORGINFO = "/v3/organizations/identity-info"; + public static final String CONTRACT_COMPARE_GETURL = "/v3/contract-compare-url"; + public static final String TOKEN_GET_URL = "/v1/oauth2/access_token"; +} diff --git a/esign/src/main/java/com/seeyon/apps/esign/constants/EsignConfigConstants.java b/esign/src/main/java/com/seeyon/apps/esign/constants/EsignConfigConstants.java new file mode 100644 index 0000000..91c768f --- /dev/null +++ b/esign/src/main/java/com/seeyon/apps/esign/constants/EsignConfigConstants.java @@ -0,0 +1,37 @@ +package com.seeyon.apps.esign.constants; + +public enum EsignConfigConstants { + plugin("src_esign",""), + APP_ID("7438886882",""), + APP_SECRET("325c8cc6c2a303d6cf1fb5657a16e591",""), + OA_HOST("",""), + ESIGN_HOST("",""), + SIGN_SERVICE_PROVIDER("ESIGN",""), + UNITNAME("","平台方组织名称"), + FORMEDITLOGINNAME("","表单修改登录名"), + updateAccountName("表单",""), + getTokenUrl("/seeyon/rest/token/","调用获取TOKEN地址"), + nodeTokenUrl("/seeyon/rest/flow/notification/","超级节点回调URL"), + restName("",""), + restPwd("",""), + ; + + private String defaultValue; + private String description; + + EsignConfigConstants(String defaultValue,String description) { + this.defaultValue = defaultValue; + this.description = description; + } + + public String getDescription() { + return description; + } + + public String getDefaultValue() { + return defaultValue; + } + public static String getPluginId() { + return plugin.defaultValue; + } +} diff --git a/esign/src/main/java/com/seeyon/apps/esign/controller/EsignCallBackController.java b/esign/src/main/java/com/seeyon/apps/esign/controller/EsignCallBackController.java new file mode 100644 index 0000000..4eb1941 --- /dev/null +++ b/esign/src/main/java/com/seeyon/apps/esign/controller/EsignCallBackController.java @@ -0,0 +1,86 @@ +package com.seeyon.apps.esign.controller; + +import cn.hutool.log.Log; +import com.fasterxml.jackson.core.type.TypeReference; +import com.fasterxml.jackson.databind.DeserializationFeature; +import com.fasterxml.jackson.databind.ObjectMapper; +import com.seeyon.apps.esign.po.EsignCallbackParams; +import com.seeyon.apps.esign.service.EsignByUploadFileService; +import com.seeyon.apps.esign.service.EsignCallbackBizService; +import com.seeyon.ctp.common.AppContext; +import com.seeyon.ctp.common.controller.BaseController; + + +import javax.servlet.http.HttpServletRequest; +import javax.servlet.http.HttpServletResponse; + +import java.io.BufferedReader; +import java.io.OutputStream; +import java.nio.charset.StandardCharsets; +import java.util.Map; +import java.util.concurrent.ConcurrentHashMap; + +public class EsignCallBackController extends BaseController { + + private static final Log log = Log.get(EsignCallBackController.class); + + private EsignByUploadFileService esignByUploadFileService = (EsignByUploadFileService) AppContext.getBean("esignByUploadFileService"); + private EsignCallbackBizService esignCallbackBizService = (EsignCallbackBizService) AppContext.getBean("esignCallbackBizService"); + private ConcurrentHashMap callbackMap = new ConcurrentHashMap<>(); + + + public void callback(HttpServletRequest request, HttpServletResponse response) { + try { + log.info("签署回调触发"); + // 签署回调处理,改变超级节点状态 + String formId = request.getParameter("formId"); + String tableName = request.getParameter("tablename"); + String updatefield = request.getParameter("updatefield"); + String statusfield = request.getParameter("statusfield"); + BufferedReader reader = request.getReader(); + StringBuilder sb = new StringBuilder(); + String line; + while ((line = reader.readLine()) != null) { + sb.append(line); + } + String body = sb.toString(); + ObjectMapper mapper = new ObjectMapper(); + mapper.configure(DeserializationFeature.FAIL_ON_UNKNOWN_PROPERTIES, false); + EsignCallbackParams callbackParams = mapper.readValue(body, new TypeReference() { + }); + String flowId = callbackParams.getSignFlowId(); + String action = callbackParams.getAction(); + if(!action.equals("SIGN_MISSON_COMPLETE")) { + response.setStatus(HttpServletResponse.SC_OK); + return; + } + if(callbackMap.contains(flowId)) { + response.setStatus(HttpServletResponse.SC_OK); + return; + }else { + callbackMap.put(flowId, "1"); + } + if(callbackParams.getSignResult() == 2) { + Map fileInfo = esignByUploadFileService.getDownloadFileInfo(flowId); + esignCallbackBizService.handleSuccessSignCallbackBiz(tableName,updatefield,statusfield,formId,(String)fileInfo.get("downloadUrl"),(String)fileInfo.get("fileName")); + }else { + esignCallbackBizService.handleFailSignCallbackBiz(tableName,statusfield,formId,callbackParams.getResultDescription()); + } + //下载合同 + response.setContentType("application/json;charset=UTF-8"); + response.setCharacterEncoding("UTF-8"); + response.setStatus(HttpServletResponse.SC_OK); + try (OutputStream out = response.getOutputStream()) { + out.write("{\"code\":\"200\",\"msg\":\"success\"}".getBytes(StandardCharsets.UTF_8)); + out.flush(); + } + log.info("回调处理完成"); + callbackMap.remove(flowId); + return; + } catch (Exception e) { + log.error("回调处理失败", e); + } + response.setStatus(HttpServletResponse.SC_OK); +// response.setStatus(HttpServletResponse.SC_INTERNAL_SERVER_ERROR); + } +} diff --git a/esign/src/main/java/com/seeyon/apps/esign/core/SignApiClient.java b/esign/src/main/java/com/seeyon/apps/esign/core/SignApiClient.java new file mode 100644 index 0000000..2a0a944 --- /dev/null +++ b/esign/src/main/java/com/seeyon/apps/esign/core/SignApiClient.java @@ -0,0 +1,10 @@ +package com.seeyon.apps.esign.core; + +public interface SignApiClient { + + public String signByFile(); + public String signByTemplate(); + public String downloadContract(); + + +} diff --git a/esign/src/main/java/com/seeyon/apps/esign/core/SignApiClientFactory.java b/esign/src/main/java/com/seeyon/apps/esign/core/SignApiClientFactory.java new file mode 100644 index 0000000..775426a --- /dev/null +++ b/esign/src/main/java/com/seeyon/apps/esign/core/SignApiClientFactory.java @@ -0,0 +1,21 @@ +package com.seeyon.apps.esign.core; + +import com.seeyon.apps.esign.config.EsignConfigProvider; +import com.seeyon.apps.esign.constants.EsignConfigConstants; +import com.seeyon.apps.esign.service.EsignApiClient; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.stereotype.Component; + +@Component +public class SignApiClientFactory { + + @Autowired + private EsignConfigProvider configProvider; + + public SignApiClient getSignApiClient() { + if(configProvider.getBizConfigByKey(EsignConfigConstants.SIGN_SERVICE_PROVIDER).equals("ESIGN")) { + return new EsignApiClient(); + } + return null; + } +} diff --git a/esign/src/main/java/com/seeyon/apps/esign/core/SignParams.java b/esign/src/main/java/com/seeyon/apps/esign/core/SignParams.java new file mode 100644 index 0000000..8ce28a3 --- /dev/null +++ b/esign/src/main/java/com/seeyon/apps/esign/core/SignParams.java @@ -0,0 +1,22 @@ +package com.seeyon.apps.esign.core; + +public abstract class SignParams { + private String appKey; + private String appSecret; + + public String getAppKey() { + return appKey; + } + + public void setAppKey(String appKey) { + this.appKey = appKey; + } + + public String getAppSecret() { + return appSecret; + } + + public void setAppSecret(String appSecret) { + this.appSecret = appSecret; + } +} diff --git a/esign/src/main/java/com/seeyon/apps/esign/fieldCtrl/ContractCompareFieldCtrl.java b/esign/src/main/java/com/seeyon/apps/esign/fieldCtrl/ContractCompareFieldCtrl.java new file mode 100644 index 0000000..77a38dd --- /dev/null +++ b/esign/src/main/java/com/seeyon/apps/esign/fieldCtrl/ContractCompareFieldCtrl.java @@ -0,0 +1,64 @@ +package com.seeyon.apps.esign.fieldCtrl; + +import com.seeyon.cap4.form.bean.ParamDefinition; +import com.seeyon.cap4.form.bean.fieldCtrl.FormFieldCustomCtrl; +import com.seeyon.cap4.form.util.Enums; +import org.springframework.stereotype.Component; + +import java.util.UUID; + +@Component +public class ContractCompareFieldCtrl extends FormFieldCustomCtrl { + @Override + public String getPCInjectionInfo() { + return "{path:'apps_res/cap/customCtrlResources/esignContractCompareBtnResources',jsUri:'/js/compareinit.js',initMethod:'init',nameSpace:'" + getNameSpace() + "'}"; + } + + @Override + public String getMBInjectionInfo() { + return "{path:'http://mapResource.v5.cmp/v1.0.0/',weixinpath:'invoice',jsUri:'js/location.js',initMethod:'init',nameSpace:'"+getNameSpace()+"'}"; + } + + @Override + public String getKey() { + return "8899554679928334458"; + } + + @Override + public boolean canUse(Enums.FormType formType) { + return true; + } + + @Override + public String[] getDefaultVal(String s) { + return new String[0]; + } + + public String getNameSpace() { + return "field_" + this.getKey(); + } + + public String getFieldLength() { + return "20"; + } + @Override + public String getText() { + return "e签宝合同比对按钮"; + } + + /** + * 控件初始化接口,此接口在控件初始化的时候,会调用,主要用于定义控件所属插件id、在表单编辑器中的图标、表单编辑器中有哪些属性可以设置。 + * 使用举例:在接口中定义自定义控件在在表单编辑器中有哪些控件属性需要配置 + */ + @Override + public void init() { + //设置图标和插件ID + setPluginId("src_esign"); + setIcon("cap-icon-custom-button"); + // 自定义参数 + + ParamDefinition esignContractCompareBtnParam = new ParamDefinition(); + esignContractCompareBtnParam.setParamType(Enums.ParamType.button); + addDefinition(esignContractCompareBtnParam); + } +} diff --git a/esign/src/main/java/com/seeyon/apps/esign/form/ClauseFactor.java b/esign/src/main/java/com/seeyon/apps/esign/form/ClauseFactor.java new file mode 100644 index 0000000..769468d --- /dev/null +++ b/esign/src/main/java/com/seeyon/apps/esign/form/ClauseFactor.java @@ -0,0 +1,19 @@ +package com.seeyon.apps.esign.form; + +public enum ClauseFactor { + EQ, //相等 + GT, //大于 + GE, //大于等于 + LT, //小于 + LE, //小于等于 + NULL, //空 + NOT_NULL, //非空 + LIKE, //模糊 + AND, + OR + ; + + public boolean isNullType() { + return this == NULL || this == NOT_NULL; + } +} diff --git a/esign/src/main/java/com/seeyon/apps/esign/form/EnumMapUtils.java b/esign/src/main/java/com/seeyon/apps/esign/form/EnumMapUtils.java new file mode 100644 index 0000000..ed49334 --- /dev/null +++ b/esign/src/main/java/com/seeyon/apps/esign/form/EnumMapUtils.java @@ -0,0 +1,108 @@ +package com.seeyon.apps.esign.form; + +import com.seeyon.cap4.form.api.FormApi4Cap4; +import com.seeyon.cap4.form.bean.FormBean; +import com.seeyon.cap4.form.bean.FormFieldBean; +import com.seeyon.cap4.form.bean.FormTableBean; +import com.seeyon.ctp.common.AppContext; +import com.seeyon.ctp.common.ctpenumnew.manager.EnumManager; +import com.seeyon.ctp.common.exceptions.BusinessException; +import com.seeyon.ctp.common.po.ctpenumnew.CtpEnumBean; +import com.seeyon.ctp.common.po.ctpenumnew.CtpEnumItem; +import com.seeyon.ctp.util.JDBCAgent; + +import java.util.Arrays; +import java.util.List; +import java.util.Map; + +public class EnumMapUtils { + + public static String getMasterTableEnumItemValue(String formNo,String fieldDisplay, String targetValue) { + if(targetValue == null || "null".equals(targetValue) || "".equals(targetValue)){ + return ""; + } + try { + FormApi4Cap4 formApi4Cap4 = (FormApi4Cap4) AppContext.getBean("formApi4Cap4"); + FormBean cap4FormBean = formApi4Cap4.getFormByFormCode(formNo); + FormTableBean masterTableBean = cap4FormBean.getMasterTableBean(); + FormFieldBean beanByDisplay = masterTableBean.getFieldBeanByDisplay(fieldDisplay); + if(beanByDisplay == null || beanByDisplay.getEnumId() == 0l) { + return ""; + } + return getEnumItemValueByEnumId(targetValue, beanByDisplay.getEnumId()); + } catch (Exception e) { + return ""; + } + } + + public static String getEnumItemValue(String rootPCode, String groupValue, String targetValue) { + if(targetValue == null || "null".equals(targetValue) || "".equals(targetValue)){ + return ""; + } + String queryIdSql = "SELECT ce.ID FROM ctp_enum ce inner join ctp_enum cei on ce.`PARENT_ID` = cei.ID where CEI.`PROGRAM_CODE` = ? and ce.`ENUMNAME` = ?"; + Long enumId = null; + JDBCAgent agent = new JDBCAgent(); + try { + agent.execute(queryIdSql, Arrays.asList(rootPCode,groupValue)); + List> list = (List>) agent.resultSetToList(); + if(list == null || list.size() == 0) { + return ""; + } + Map map = list.get(0); + enumId = (Long)map.get("ID"); + } catch (Exception e) { + return ""; + }finally { + agent.close(); + } + EnumManager enumManagerNew = (EnumManager) AppContext.getBean("enumManagerNew"); + CtpEnumBean ctpEnumBean = enumManagerNew.getEnum(enumId); + if(ctpEnumBean == null) { + return ""; + } + List ctpEnumItems = ctpEnumBean.getItems(); + if(ctpEnumBean.getItems() == null) { + return ""; + } + for (CtpEnumItem enumItem : ctpEnumItems) { + if(enumItem.getShowvalue().equals(targetValue)) { + return enumItem.getId() + ""; + } + } + return ""; + } + + public static String getEnumItemValueByEnumId(String showValue,long enumId) { + EnumManager enumManagerNew = (EnumManager) AppContext.getBean("enumManagerNew"); + CtpEnumBean ctpEnumBean = enumManagerNew.getEnum(enumId); + if(ctpEnumBean == null) { + return ""; + } + List ctpEnumItems = ctpEnumBean.getItems(); + if(ctpEnumBean.getItems() == null) { + return ""; + } + for (CtpEnumItem enumItem : ctpEnumItems) { + if(enumItem.getShowvalue().equals(showValue)) { + return enumItem.getId() + ""; + } + } + return ""; + } + + public static String getEnumShowValue(Object enumItemId) throws BusinessException { + if(enumItemId == null) { + return ""; + } + Long temp = enumItemId instanceof Long ? (Long)enumItemId : (enumItemId instanceof String ? Long.parseLong((String)enumItemId) : null); + if(temp == null) { + return ""; + } + EnumManager enumManagerNew = (EnumManager) AppContext.getBean("enumManagerNew"); + CtpEnumItem ctpEnumItem = enumManagerNew.getCtpEnumItem(temp); + if(ctpEnumItem == null) { + return ""; + } + return ctpEnumItem.getShowvalue(); + } +} diff --git a/esign/src/main/java/com/seeyon/apps/esign/form/FormColumn.java b/esign/src/main/java/com/seeyon/apps/esign/form/FormColumn.java new file mode 100644 index 0000000..db4a22c --- /dev/null +++ b/esign/src/main/java/com/seeyon/apps/esign/form/FormColumn.java @@ -0,0 +1,32 @@ +package com.seeyon.apps.esign.form; + +import java.util.HashMap; +import java.util.List; +import java.util.Map; + +public class FormColumn { + private String id; + private List vos; + + public String getId() { + return id; + } + + public void setId(String id) { + this.id = id; + } + + public List getVos() { + return vos; + } + + public void setVos(List vos) { + this.vos = vos; + } + + public Map getFieldsMap() { + Map map = new HashMap<>(); + vos.forEach(vo -> map.put(vo.getDisplayName(),vo.getValue())); + return map; + } +} diff --git a/esign/src/main/java/com/seeyon/apps/esign/form/FormDataOperator.java b/esign/src/main/java/com/seeyon/apps/esign/form/FormDataOperator.java new file mode 100644 index 0000000..3fefdda --- /dev/null +++ b/esign/src/main/java/com/seeyon/apps/esign/form/FormDataOperator.java @@ -0,0 +1,630 @@ +package com.seeyon.apps.esign.form; + + +import com.seeyon.cap4.form.api.FormApi4Cap4; +import com.seeyon.cap4.form.bean.FormBean; +import com.seeyon.cap4.form.bean.FormFieldBean; +import com.seeyon.cap4.form.bean.FormTableBean; +import com.seeyon.ctp.common.AppContext; +import com.seeyon.ctp.common.exceptions.BusinessException; +import com.seeyon.ctp.util.JDBCAgent; +import org.apache.commons.logging.Log; +import org.apache.commons.logging.LogFactory; + +import java.util.ArrayList; +import java.util.Arrays; +import java.util.HashMap; +import java.util.HashSet; +import java.util.List; +import java.util.Map; +import java.util.Set; +import java.util.UUID; +import java.util.stream.Collectors; + +public class FormDataOperator { + + private static final Log log = LogFactory.getLog(FormDataOperator.class); + + public void updateMasterForm(String formNo, List updateFieldVos, List conditionVos) throws BusinessException { + FormApi4Cap4 formApi4Cap4 = (FormApi4Cap4) AppContext.getBean("formApi4Cap4"); + FormBean cap4FormBean = formApi4Cap4.getFormByFormCode(formNo); + FormTableBean masterTableBean = cap4FormBean.getMasterTableBean(); + + if (updateFieldVos == null) { + throw new IllegalArgumentException("要修改的字段为空"); + } + for (FormUpdateField fieldVo : updateFieldVos) { + FormFieldBean bean = masterTableBean.getFieldBeanByDisplay(fieldVo.getDisplay()); + if (bean == null) { + continue; + } + if(bean.getInputType().equals("image") || bean.getInputType().equals("attachment")){} + fieldVo.fieldName(bean.getColumnName()); + } + List updateFields = updateFieldVos.stream().filter(u -> u.getFieldName() != null).collect(Collectors.toList()); + for (FormWhereCondition conditionVo : conditionVos) { + FormFieldBean bean = masterTableBean.getFieldBeanByDisplay(conditionVo.getDisplay()); + if (bean == null) { + if (conditionVo.getDisplay().equals("ID") || conditionVo.getDisplay().equals("id")) { + conditionVo.setFieldName(conditionVo.getDisplay()); + } + continue; + } + conditionVo.setFieldName(bean.getColumnName()); + } + List conditions = conditionVos.stream().filter(c -> c.getFieldName() != null).collect(Collectors.toList()); + Map map = generateSql(updateFields, masterTableBean.getTableName(), conditions); + JDBCAgent agent = new JDBCAgent(); + try { + agent.execute((String) map.get("sql"), (List) map.get("params")); + return; + } catch (Exception e) { + e.printStackTrace(); + } finally { + agent.close(); + } + } + + public void updateMasterForm(List updateFields,String tableName, List conditionVos) throws BusinessException { + if (updateFields == null) { + throw new IllegalArgumentException("要修改的字段为空"); + } + List conditions = conditionVos.stream().filter(c -> c.getFieldName() != null).collect(Collectors.toList()); + Map map = generateSql(updateFields, tableName, conditions); + JDBCAgent agent = new JDBCAgent(); + try { + agent.execute((String) map.get("sql"), (List) map.get("params")); + log.info("sql: " + map.get("sql") + " 更新表单执行成功"); + return; + } catch (Exception e) { + e.printStackTrace(); + } finally { + agent.close(); + } + } + + public FormColumn queryOneRowFormData(String formNo, List queryColumnVos, List conditionVos) throws BusinessException { + FormApi4Cap4 formApi4Cap4 = (FormApi4Cap4) AppContext.getBean("formApi4Cap4"); + FormBean cap4FormBean = formApi4Cap4.getFormByFormCode(formNo); + List queryColumns = new ArrayList<>(); + FormTableBean masterTableBean = cap4FormBean.getMasterTableBean(); + String tableName = masterTableBean.getTableName(); + Map fieldMap4Display = masterTableBean.getFieldMap4Display(); + Map fieldMap4Name = masterTableBean.getFieldMap4Name(); + if (queryColumnVos != null) { + for (String queryColumnVo : queryColumnVos) { + FormFieldBean fieldBeanByDisplay = masterTableBean.getFieldBeanByDisplay(queryColumnVo); + if (fieldBeanByDisplay == null) { + continue; + } + queryColumns.add(fieldBeanByDisplay.getColumnName()); + } + } + for (FormWhereCondition conditionVo : conditionVos) { + FormFieldBean fieldBeanByDisplay = masterTableBean.getFieldBeanByDisplay(conditionVo.getDisplay()); + if (fieldBeanByDisplay == null) { + if (conditionVo.getDisplay().equals("ID") || conditionVo.getDisplay().equals("id")) { + conditionVo.setFieldName(conditionVo.getDisplay()); + } + continue; + } + conditionVo.setFieldName(fieldBeanByDisplay.getColumnName()); + } + + Map generateSql = generateSql(queryColumns, conditionVos, tableName); + String sql = (String) generateSql.get("sql"); + List params = (List) generateSql.get("params"); + JDBCAgent jdbcAgent = new JDBCAgent(); + List columns = new ArrayList<>(); + try { + jdbcAgent.execute(sql, params); + List list = jdbcAgent.resultSetToList(); + for (Object o : list) { + FormColumn column = new FormColumn(); + Map columnMap = (Map) o; + List vos = new ArrayList<>(); + for (String key : columnMap.keySet()) { + FormFieldVo fieldVo = new FormFieldVo(); + if (fieldMap4Name.containsKey(key)) { + FormFieldBean fieldBean = fieldMap4Name.get(key); + fieldVo.setDisplayName(fieldBean.getDisplay()); + fieldVo.setValue(columnMap.get(key)); + vos.add(fieldVo); + } + } + column.setVos(vos); + if (columnMap.get("id") != null) { + column.setId(columnMap.get("id") + ""); + } + columns.add(column); + } + return columns.get(0); + } catch (Exception e) { + System.out.println(e.getMessage()); + } finally { + jdbcAgent.close(); + } + return null; + } + + public List queryFormDataCondition(String formNo, List queryColumnVos, List conditionVos) throws BusinessException { + FormApi4Cap4 formApi4Cap4 = (FormApi4Cap4) AppContext.getBean("formApi4Cap4"); + FormBean cap4FormBean = formApi4Cap4.getFormByFormCode(formNo); + List queryColumns = new ArrayList<>(); + FormTableBean masterTableBean = cap4FormBean.getMasterTableBean(); + String tableName = masterTableBean.getTableName(); + Map fieldMap4Display = masterTableBean.getFieldMap4Display(); + Map fieldMap4Name = masterTableBean.getFieldMap4Name(); + if (queryColumnVos != null) { + for (String queryColumnVo : queryColumnVos) { + FormFieldBean fieldBeanByDisplay = masterTableBean.getFieldBeanByDisplay(queryColumnVo); + if (fieldBeanByDisplay == null) { + continue; + } + queryColumns.add(fieldBeanByDisplay.getColumnName()); + } + } + for (FormWhereCondition conditionVo : conditionVos) { + FormFieldBean fieldBeanByDisplay = masterTableBean.getFieldBeanByDisplay(conditionVo.getDisplay()); + if (fieldBeanByDisplay == null) { + if (conditionVo.getDisplay().equals("ID") || conditionVo.getDisplay().equals("id")) { + conditionVo.setFieldName(conditionVo.getDisplay()); + } + continue; + } + conditionVo.setFieldName(fieldBeanByDisplay.getColumnName()); + } + + Map generateSql = generateSql(queryColumns, conditionVos, tableName); + String sql = (String) generateSql.get("sql"); + List params = (List) generateSql.get("params"); + JDBCAgent jdbcAgent = new JDBCAgent(); + List columns = new ArrayList<>(); + try { + jdbcAgent.execute(sql, params); + List list = jdbcAgent.resultSetToList(); + for (Object o : list) { + FormColumn column = new FormColumn(); + Map columnMap = (Map) o; + List vos = new ArrayList<>(); + for (String key : columnMap.keySet()) { + FormFieldVo fieldVo = new FormFieldVo(); + if (fieldMap4Name.containsKey(key)) { + FormFieldBean fieldBean = fieldMap4Name.get(key); + fieldVo.setDisplayName(fieldBean.getDisplay()); + fieldVo.setValue(columnMap.get(key)); + vos.add(fieldVo); + } + } + column.setVos(vos); + if (columnMap.get("id") != null) { + column.setId(columnMap.get("id") + ""); + } + columns.add(column); + } + return columns; + } catch (Exception e) { + System.out.println(e.getMessage()); + } finally { + jdbcAgent.close(); + } + return null; + } + + public boolean queryExist(List conditionVos,String tableName) throws BusinessException { + String sql = "select 1 from " + tableName + " where 1=1 " + " AND " + conditionVos.get(0).getFieldName() + " =? " + " AND " + conditionVos.get(1).getFieldName() + " is not null;"; + JDBCAgent jdbcAgent = new JDBCAgent(); + List params = new ArrayList<>(); + params.add(conditionVos.get(0).getValue()); + try { + jdbcAgent.execute(sql, params); + List list = jdbcAgent.resultSetToList(); + return list.size() > 0; + } catch (Exception e) { + System.out.println(e.getMessage()); + } finally { + jdbcAgent.close(); + } + return false; + } + private Map generateSql(List queryColumn, List conditions, String tableName) { + if (tableName == null) { + throw new IllegalArgumentException("tableName cannot be null or empty"); + } + StringBuilder sqlBuilder = new StringBuilder("SELECT "); + if (queryColumn == null || queryColumn.isEmpty()) { + sqlBuilder.append("*"); + } + + for (int i = 0; i < queryColumn.size(); i++) { + sqlBuilder.append(queryColumn.get(i)); + if (queryColumn.size() > 1 && i >= 0 && i < queryColumn.size() - 1) { + sqlBuilder.append(","); + } + } + + if (queryColumn.size() > 0) { + sqlBuilder.append(",`ID`"); + } + + sqlBuilder.append(" from " + tableName); + List params = new ArrayList<>(); + sqlBuilder.append(buildWhereClause(conditions,params)); + Map result = new HashMap<>(); + result.put("sql", sqlBuilder.toString()); + result.put("params", params); + return result; + } + + private Map generateSql(List fieldValues, String tableName,List conditions) { + if (fieldValues == null || fieldValues.isEmpty()) { + throw new IllegalArgumentException("Field values cannot be null or empty"); + } + if (tableName == null || tableName.trim().isEmpty()) { + throw new IllegalArgumentException("Table name cannot be null or empty"); + } + StringBuilder sqlBuilder = new StringBuilder("UPDATE ").append(tableName).append(" SET "); + List params = new ArrayList<>(); + // Build the SET clause + int fieldCount = 0; + for (FormUpdateField updateField : fieldValues) { + if (updateField.getValue() == null || "".equals(updateField.getValue()) || "null".equals(updateField.getValue())) { + continue; + } + if (fieldCount > 0) { + sqlBuilder.append(", "); + } + if (updateField.getValue() instanceof String && ((String) updateField.getValue()).startsWith("DATE>")) { + String oldValue = (String) updateField.getValue(); + sqlBuilder.append(updateField.getFieldName()).append(" = TO_DATE( ?, 'YYYY-MM-DD')"); + updateField.setValue(oldValue.substring(oldValue.indexOf(">") + 1)); + } else { + sqlBuilder.append(updateField.getFieldName()).append(" = ?"); + } + params.add(updateField.getValue()); + fieldCount++; + } + String whereClauseStr = buildWhereClause(conditions,params); + // Append the WHERE clause + sqlBuilder.append(whereClauseStr); + // Create result map + Map result = new HashMap<>(); + result.put("sql", sqlBuilder.toString()); + result.put("params", params); + return result; + } + + public Map> getMainFormTableAttachments(String formNo,Map sourceMap) throws BusinessException { + FormApi4Cap4 formApi4Cap4 = (FormApi4Cap4) AppContext.getBean("formApi4Cap4"); + FormBean cap4FormBean = formApi4Cap4.getFormByFormCode(formNo); + FormTableBean masterTableBean = cap4FormBean.getMasterTableBean(); + Map> attachmentTempMap = new HashMap<>(); + Set removeKey = new HashSet<>(); + for (String key : sourceMap.keySet()) { + FormFieldBean fieldBeanByDisplay = masterTableBean.getFieldBeanByDisplay(key); + if(fieldBeanByDisplay == null ){ + continue; + } + if(fieldBeanByDisplay.getInputType().equals("image") || + fieldBeanByDisplay.getInputType().equals("attachment")) { + attachmentTempMap.put(fieldBeanByDisplay.getDisplay(),(List)sourceMap.get(key)); + removeKey.add(key); + } + } + for (String key : removeKey) { + sourceMap.remove(key); + } + return attachmentTempMap; + } + + public Map> getSubFormTableAttachments(String formNo,Map sourceMap) throws BusinessException { + FormApi4Cap4 formApi4Cap4 = (FormApi4Cap4) AppContext.getBean("formApi4Cap4"); + FormBean cap4FormBean = formApi4Cap4.getFormByFormCode(formNo); + List subTableBean = cap4FormBean.getSubTableBean(); + Map> attachmentTempMap = new HashMap<>(); + String tableName = null; + for (String key : sourceMap.keySet()) { + tableName = key; + } + String finalTableName = tableName; + FormTableBean tableBean = subTableBean.stream().filter(s->s.getTableName().equals(finalTableName)).collect(Collectors.toList()).get(0); + List> tableData = (List>)sourceMap.get(tableName); + Set removeKey = new HashSet<>(); + for (Map rowData : tableData) { + for (String key : rowData.keySet()) { + FormFieldBean fieldBeanByDisplay = tableBean.getFieldBeanByDisplay(key); + if(fieldBeanByDisplay == null ){ + continue; + } + if(fieldBeanByDisplay.getInputType().equals("image") || + fieldBeanByDisplay.getInputType().equals("attachment")) { + attachmentTempMap.put(fieldBeanByDisplay.getDisplay(),(List)sourceMap.get(key)); + removeKey.add(key); + } + } + for (String key : removeKey) { + rowData.remove(key); + } + removeKey.clear(); + } + return attachmentTempMap; + } + + public void addSubTableRecord(String subTableName,List data,String formNo,String formId) { + JDBCAgent agent = new JDBCAgent(); + try { + FormApi4Cap4 formApi4Cap4 = (FormApi4Cap4) AppContext.getBean("formApi4Cap4"); + FormBean cap4FormBean = formApi4Cap4.getFormByFormCode(formNo); + List tableBean = cap4FormBean.getSubTableBean(); + for (FormTableBean bean : tableBean) { + if(!bean.getTableName().equals(subTableName)) { + continue; + } + for (Object column : data) { + Map map = (Map) column; + Map tempMap = new HashMap<>(); + for (String key : map.keySet()) { + FormFieldBean fieldBeanByDisplay = bean.getFieldBeanByDisplay(key); + if(fieldBeanByDisplay == null) { + continue; + } + tempMap.put(fieldBeanByDisplay.getColumnName(),map.get(key)); + } + tempMap.put("formmain_id",formId); + tempMap.put("sort",1); + tempMap.put("ID",Math.abs(UUID.randomUUID().getLeastSignificantBits())); + Map insertSql = generateInsertSql(tempMap, subTableName); + agent.execute((String)insertSql.get("sql"),(List)insertSql.get("params")); + } + } + } catch (Exception e) { + + } finally { + agent.close(); + } + } + + public void rebuildSubTableRecord(String subTableName,List data,String formNo,String formId) { + String deleteSql = "delete from " + subTableName + " where formmain_id = ? "; + JDBCAgent agent = new JDBCAgent(); + try { + agent.execute(deleteSql, Arrays.asList(formId)); + FormApi4Cap4 formApi4Cap4 = (FormApi4Cap4) AppContext.getBean("formApi4Cap4"); + FormBean cap4FormBean = formApi4Cap4.getFormByFormCode(formNo); + List tableBean = cap4FormBean.getSubTableBean(); + for (FormTableBean bean : tableBean) { + if(!bean.getTableName().equals(subTableName)) { + continue; + } + for (Object column : data) { + Map map = (Map) column; + Map tempMap = new HashMap<>(); + for (String key : map.keySet()) { + FormFieldBean fieldBeanByDisplay = bean.getFieldBeanByDisplay(key); + if(fieldBeanByDisplay == null) { + continue; + } + tempMap.put(fieldBeanByDisplay.getColumnName(),map.get(key)); + } + tempMap.put("formmain_id",formId); + tempMap.put("sort",1); + tempMap.put("ID",Math.abs(UUID.randomUUID().getLeastSignificantBits())); + Map insertSql = generateInsertSql(tempMap, subTableName); + agent.execute((String)insertSql.get("sql"),(List)insertSql.get("params")); + } + } + } catch (Exception e) { + + } finally { + agent.close(); + } + } + + public void handleEnumDeptEtc(Map map,String formNo) throws BusinessException { + FormApi4Cap4 formApi4Cap4 = (FormApi4Cap4) AppContext.getBean("formApi4Cap4"); + FormBean cap4FormBean = formApi4Cap4.getFormByFormCode(formNo); + FormTableBean masterTableBean = cap4FormBean.getMasterTableBean(); + for (String key : map.keySet()) { + FormFieldBean fieldBean = masterTableBean.getFieldBeanByDisplay(key); + if(fieldBean == null) { + continue; + } + switch (fieldBean.getInputType()) { + case "select": if(fieldBean.getEnumId() != 0l) { + String enumItemId = EnumMapUtils.getEnumItemValueByEnumId((String)map.get(key),fieldBean.getEnumId()); + map.put(key,enumItemId); + } break; + case "image":break; + case "attachment": break; + case "account": break; + case "department": break; + case "radio": break; + case "member":break; + case "checkbox": + case "date": + case "text":break; + default: break; + + } + } + } + + public void handleSubTableEnumDeptEtc(Map map,String formNo) throws BusinessException { + FormApi4Cap4 formApi4Cap4 = (FormApi4Cap4) AppContext.getBean("formApi4Cap4"); + FormBean cap4FormBean = formApi4Cap4.getFormByFormCode(formNo); + List subTableBean = cap4FormBean.getSubTableBean(); + for (FormTableBean tableBean : subTableBean) { + String tableName = null; + for (String key : map.keySet()) { + tableName = key; + } + if(!tableBean.getTableName().equals(tableName)) { + continue; + } + List> subDatas = (List>) map.get(tableName); + for (Map subData : subDatas) { + for (String key : subData.keySet()) { + FormFieldBean fieldBean = tableBean.getFieldBeanByDisplay(key); + if(fieldBean == null) { + continue; + } + switch (fieldBean.getInputType()) { + case "select": if(fieldBean.getEnumId() != 0l) { + String enumItemId = EnumMapUtils.getEnumItemValueByEnumId((String)subData.get(key),fieldBean.getEnumId()); + subData.put(key,enumItemId); + } break; + case "image":break; + case "attachment": break; + case "account": break; + case "department": break; + case "radio": break; + case "member":break; + case "checkbox": + case "date": + case "text":break; + default: break; + + } + } + } + } + } + + public boolean isMasterTableFile(String displayName,String formNo) { + FormApi4Cap4 formApi4Cap4 = (FormApi4Cap4) AppContext.getBean("formApi4Cap4"); + try { + FormBean cap4FormBean = formApi4Cap4.getFormByFormCode(formNo); + FormTableBean masterTableBean = cap4FormBean.getMasterTableBean(); + FormFieldBean fieldBeanByDisplay = masterTableBean.getFieldBeanByDisplay(displayName); + return fieldBeanByDisplay.getInputType().equals("image") || fieldBeanByDisplay.getInputType().equals("attachment"); + } catch (BusinessException e) { + + } + return false; + } + + private Map generateInsertSql(Map data, String tableName) { + if (tableName == null || tableName.isEmpty()) { + throw new IllegalArgumentException("tableName cannot be null or empty"); + } + if (data == null || data.isEmpty()) { + throw new IllegalArgumentException("data cannot be null or empty"); + } + StringBuilder sqlBuilder = new StringBuilder("INSERT INTO " + tableName + " ("); + List params = new ArrayList<>(); + // 拼接字段名 + StringBuilder columns = new StringBuilder(); + // 拼接字段值 + StringBuilder values = new StringBuilder(); + for (Map.Entry entry : data.entrySet()) { + // 拼接字段名 + if (columns.length() > 0) { + columns.append(", "); + } + columns.append(entry.getKey()); + // 拼接值,使用占位符 ? + if (values.length() > 0) { + values.append(", "); + } + values.append("?"); + // 将值加入 params 列表 + params.add(entry.getValue()); + } + // 完善 SQL 语句 + sqlBuilder.append(columns).append(") VALUES (").append(values).append(");"); + Map result = new HashMap<>(); + result.put("sql", sqlBuilder.toString()); + result.put("params", params); + return result; + } + + /** + * 动态生成 WHERE 子句 + * @param conditions 条件集合 + * @param params 参数列表(引用传递) + * @return 拼接后的 WHERE 子句(包含 WHERE 关键字) + */ + private String buildWhereClause(List conditions, List params) { + if (conditions == null || conditions.isEmpty()) { + return ""; + } + + StringBuilder whereClause = new StringBuilder(" WHERE "); + int conditionIndex = 0; + + for (FormWhereCondition condition : conditions) { + // 处理括号起始 + if (condition.isStartWithBracket()) { + whereClause.append("("); + } + + // 字段名校验 + String fieldName = condition.getFieldName(); + ClauseFactor factor = condition.getClauseFactor(); + String operator = parseOperator(factor); + + // 构建条件表达式 + String conditionExpr; + if (factor.isNullType()) { + // 处理 NULL/NOT NULL 条件(无需参数) + conditionExpr = String.format("%s %s", fieldName, operator); + } else { + // 处理普通条件(带占位符) + conditionExpr = String.format("%s %s ?", fieldName, operator); + // 处理函数模板(如 TO_DATE) + if (condition.getIndex() != null) { + conditionExpr = conditionExpr.replace("?", condition.getIndex()); + } + // 添加参数值 + params.add(condition.getValue()); + } + + whereClause.append(conditionExpr); + + // 处理括号闭合 + if (condition.isEndWithBracket()) { + whereClause.append(")"); + } + + // 添加连接符(AND/OR) + if (conditionIndex < conditions.size() - 1) { + whereClause.append(" ").append(condition.getConcatFactor()).append(" "); + } + conditionIndex++; + } + + return whereClause.toString(); + } + + /** + * 校验字段名合法性(防止 SQL 注入) + */ + private String validateFieldName(String fieldName) { + if (!fieldName.matches("^[a-zA-Z_][a-zA-Z0-9_]*$")) { + throw new IllegalArgumentException("非法字段名: " + fieldName); + } + return fieldName; + } + + /** + * 解析运算符映射(eq -> =, lt -> < 等) + */ + private String parseOperator(ClauseFactor factor) { + if(factor == null) { + return "="; + } + switch (factor) { + case EQ: return "="; + case GT: return ">"; + case GE: return ">="; + case LT: return "<"; + case LE: return "<="; + case LIKE: return "LIKE"; + case NULL: return "IS NULL"; // 空值判断 + case NOT_NULL: return "IS NOT NULL"; // 非空判断 + default: throw new UnsupportedOperationException("不支持的运算符: " + factor); + } + } + + +} diff --git a/esign/src/main/java/com/seeyon/apps/esign/form/FormExportUtil.java b/esign/src/main/java/com/seeyon/apps/esign/form/FormExportUtil.java new file mode 100644 index 0000000..c5ed930 --- /dev/null +++ b/esign/src/main/java/com/seeyon/apps/esign/form/FormExportUtil.java @@ -0,0 +1,64 @@ +package com.seeyon.apps.esign.form; + +import com.seeyon.v3x.services.form.bean.RecordExport; +import com.seeyon.v3x.services.form.bean.SubordinateFormExport; +import com.seeyon.v3x.services.form.bean.ValueExport; + +import java.util.ArrayList; +import java.util.List; +import java.util.Map; +import java.util.Set; + +//创建无流程表单数据处理工具类 +public class FormExportUtil { + + /** + * 设置主表信息 + * @param map 设置主表字段。Map<主表显示名称,主表数据> + * @return + */ + public static List setFormValue(Map map){ +// 创建返回值对象 + List valueExports = new ArrayList(); + ValueExport valueExport ; +// 获取参数信息(显示名称) + Set keys = map.keySet(); + if(keys.size()>0) { +// 对控件赋值 + for (String key : keys) { + valueExport = new ValueExport(); + valueExport.setDisplayName(key); + valueExport.setValue("null".equals(map.get(key)) ? "" : map.get(key)); + valueExports.add(valueExport); + } + } + return valueExports; + } + + /** + * 设置从表信息 + * @param map 设置主表字段。List> + */ + public static List setSubordinateFormValue(Map map){ + List subordinateFormExports = new ArrayList(); + SubordinateFormExport subordinateFormExport = new SubordinateFormExport(); + List> lists = new ArrayList<>(); + lists.add(map); + List recordExports = new ArrayList(); + List valueExports; + RecordExport recordExport; + for(int i = 0 ; i < lists.size() ; i++) { + recordExport = new RecordExport(); + valueExports = setFormValue(lists.get(i)); + recordExport.setRecord(valueExports); + recordExports.add(recordExport); + } + subordinateFormExport.setValues(recordExports); + subordinateFormExports.add(subordinateFormExport); + + return subordinateFormExports; + } + + + +} diff --git a/esign/src/main/java/com/seeyon/apps/esign/form/FormFieldVo.java b/esign/src/main/java/com/seeyon/apps/esign/form/FormFieldVo.java new file mode 100644 index 0000000..ae726ab --- /dev/null +++ b/esign/src/main/java/com/seeyon/apps/esign/form/FormFieldVo.java @@ -0,0 +1,22 @@ +package com.seeyon.apps.esign.form; + +public class FormFieldVo { + private String displayName; + private Object value; + + public String getDisplayName() { + return displayName; + } + + public void setDisplayName(String displayName) { + this.displayName = displayName; + } + + public Object getValue() { + return value; + } + + public void setValue(Object value) { + this.value = value; + } +} diff --git a/esign/src/main/java/com/seeyon/apps/esign/form/FormUpdateField.java b/esign/src/main/java/com/seeyon/apps/esign/form/FormUpdateField.java new file mode 100644 index 0000000..a15d47c --- /dev/null +++ b/esign/src/main/java/com/seeyon/apps/esign/form/FormUpdateField.java @@ -0,0 +1,57 @@ +package com.seeyon.apps.esign.form; + +public class FormUpdateField { + private String display; + private String fieldName; + private Object value; + + public FormUpdateField(Object value) { + this.value = value; + } + + public FormUpdateField() { + } + + public static FormUpdateField build() { + return new FormUpdateField(); + } + + public FormUpdateField display(String display) { + this.display = display; + return this; + } + + public FormUpdateField value(String value) { + this.value = value; + return this; + } + + public FormUpdateField fieldName(String fieldName) { + this.fieldName = fieldName; + return this; + } + + public Object getValue() { + return value; + } + + public void setValue(Object value) { + this.value = value; + } + + public String getDisplay() { + return display; + } + + public void setDisplay(String display) { + this.display = display; + } + + public String getFieldName() { + return fieldName; + } + + public void setFieldName(String fieldName) { + this.fieldName = fieldName; + } +} diff --git a/esign/src/main/java/com/seeyon/apps/esign/form/FormWhereCondition.java b/esign/src/main/java/com/seeyon/apps/esign/form/FormWhereCondition.java new file mode 100644 index 0000000..24cb801 --- /dev/null +++ b/esign/src/main/java/com/seeyon/apps/esign/form/FormWhereCondition.java @@ -0,0 +1,127 @@ +package com.seeyon.apps.esign.form; + + +public class FormWhereCondition { + private String display; + private String fieldName; //字段名 + private Object value; //值 + private ClauseFactor clauseFactor = ClauseFactor.EQ; //条件因子 eq lt gt not_null null + private ClauseFactor concatFactor = ClauseFactor.AND; //拼接因子 + private boolean startWithBracket = false; //是否以括号开头生成子条件 + private boolean endWithBracket = false; //是否以括号结尾结束子条件 + private String index; + + public FormWhereCondition() { + } + + public String getDisplay() { + return display; + } + + public void setDisplay(String display) { + this.display = display; + } + + public static FormWhereCondition build() { + return new FormWhereCondition(); + } + + public FormWhereCondition fieldName(String fieldName) { + this.fieldName = fieldName; + return this; + } + + public FormWhereCondition display(String display) { + this.display = display; + return this; + } + public FormWhereCondition value(Object value) { + this.value = value; + return this; + } + public FormWhereCondition clauseFactor(ClauseFactor clauseFactor) { + this.clauseFactor = clauseFactor; + return this; + } + public FormWhereCondition index(String index) { + this.index = index; + return this; + } + + public FormWhereCondition startWithBracket(boolean startWithBracket) { + this.startWithBracket = startWithBracket; + return this; + } + + public FormWhereCondition endWithBracket(boolean endWithBracket) { + this.endWithBracket = endWithBracket; + return this; + } + + public FormWhereCondition concatFactor(ClauseFactor concatFactor) { + this.concatFactor = concatFactor; + return this; + } + + + public FormWhereCondition(Object value, ClauseFactor clauseFactor) { + this.value = value; + this.clauseFactor = clauseFactor; + } + + public boolean isStartWithBracket() { + return startWithBracket; + } + + public void setStartWithBracket(boolean startWithBracket) { + this.startWithBracket = startWithBracket; + } + + public String getFieldName() { + return fieldName; + } + + public void setFieldName(String fieldName) { + this.fieldName = fieldName; + } + + public Object getValue() { + return value; + } + + public void setValue(Object value) { + this.value = value; + } + + public ClauseFactor getClauseFactor() { + return clauseFactor; + } + + public void setClauseFactor(ClauseFactor clauseFactor) { + this.clauseFactor = clauseFactor; + } + + public ClauseFactor getConcatFactor() { + return concatFactor; + } + + public void setConcatFactor(ClauseFactor concatFactor) { + this.concatFactor = concatFactor; + } + + public String getIndex() { + return index; + } + + public void setIndex(String index) { + this.index = index; + } + + public boolean isEndWithBracket() { + return endWithBracket; + } + + public void setEndWithBracket(boolean endWithBracket) { + this.endWithBracket = endWithBracket; + } +} diff --git a/esign/src/main/java/com/seeyon/apps/esign/form/QueryWhereCondition.java b/esign/src/main/java/com/seeyon/apps/esign/form/QueryWhereCondition.java new file mode 100644 index 0000000..182886e --- /dev/null +++ b/esign/src/main/java/com/seeyon/apps/esign/form/QueryWhereCondition.java @@ -0,0 +1,154 @@ +package com.seeyon.apps.esign.form; + +public class QueryWhereCondition { + private String display; + private String fieldName; //字段名 + private Object value; //值 + private ClauseFactor clauseFactor = ClauseFactor.EQ; //条件因子 eq lt gt not_null null + private ClauseFactor concatFactor = ClauseFactor.AND; //拼接因子 + private boolean startWithBracket = false; //是否以括号开头生成子条件 + private boolean endWithBracket = false; //是否以括号结尾结束子条件 + private String index; + private Integer limit = null; + private Integer offset = null; + + public QueryWhereCondition() { + } + + public String getDisplay() { + return display; + } + + public void setDisplay(String display) { + this.display = display; + } + + public static QueryWhereCondition build() { + return new QueryWhereCondition(); + } + + public QueryWhereCondition fieldName(String fieldName) { + this.fieldName = fieldName; + return this; + } + + public QueryWhereCondition display(String display) { + this.display = display; + return this; + } + public QueryWhereCondition value(Object value) { + this.value = value; + return this; + } + public QueryWhereCondition clauseFactor(ClauseFactor clauseFactor) { + this.clauseFactor = clauseFactor; + return this; + } + public QueryWhereCondition index(String index) { + this.index = index; + return this; + } + + public QueryWhereCondition limit(Integer limit) { + this.limit = limit; + return this; + } + + public QueryWhereCondition offset(Integer offset) { + this.offset = offset; + return this; + } + + public QueryWhereCondition startWithBracket(boolean startWithBracket) { + this.startWithBracket = startWithBracket; + return this; + } + + public QueryWhereCondition endWithBracket(boolean endWithBracket) { + this.endWithBracket = endWithBracket; + return this; + } + + public QueryWhereCondition concatFactor(ClauseFactor concatFactor) { + this.concatFactor = concatFactor; + return this; + } + + + public QueryWhereCondition(Object value, ClauseFactor clauseFactor) { + this.value = value; + this.clauseFactor = clauseFactor; + } + + public boolean isStartWithBracket() { + return startWithBracket; + } + + public void setStartWithBracket(boolean startWithBracket) { + this.startWithBracket = startWithBracket; + } + + public String getFieldName() { + return fieldName; + } + + public void setFieldName(String fieldName) { + this.fieldName = fieldName; + } + + public Object getValue() { + return value; + } + + public void setValue(Object value) { + this.value = value; + } + + public ClauseFactor getClauseFactor() { + return clauseFactor; + } + + public void setClauseFactor(ClauseFactor clauseFactor) { + this.clauseFactor = clauseFactor; + } + + public ClauseFactor getConcatFactor() { + return concatFactor; + } + + public void setConcatFactor(ClauseFactor concatFactor) { + this.concatFactor = concatFactor; + } + + public String getIndex() { + return index; + } + + public void setIndex(String index) { + this.index = index; + } + + public boolean isEndWithBracket() { + return endWithBracket; + } + + public void setEndWithBracket(boolean endWithBracket) { + this.endWithBracket = endWithBracket; + } + + public Integer getLimit() { + return limit; + } + + public void setLimit(Integer limit) { + this.limit = limit; + } + + public Integer getOffset() { + return offset; + } + + public void setOffset(Integer offset) { + this.offset = offset; + } +} diff --git a/esign/src/main/java/com/seeyon/apps/esign/interceptor/AuthExcludeInterceptor.java b/esign/src/main/java/com/seeyon/apps/esign/interceptor/AuthExcludeInterceptor.java new file mode 100644 index 0000000..eea9c9d --- /dev/null +++ b/esign/src/main/java/com/seeyon/apps/esign/interceptor/AuthExcludeInterceptor.java @@ -0,0 +1,22 @@ +package com.seeyon.apps.esign.interceptor; + +import org.springframework.stereotype.Component; +import org.springframework.web.servlet.handler.HandlerInterceptorAdapter; + +import javax.servlet.http.HttpServletRequest; +import javax.servlet.http.HttpServletResponse; + +@Component +public class AuthExcludeInterceptor extends HandlerInterceptorAdapter { + + @Override + public boolean preHandle(HttpServletRequest request, + HttpServletResponse response, + Object handler) throws Exception { + String uri = request.getRequestURI(); + if(uri.contains("/public/")) { + return true; // 放行公共接口 + } + return super.preHandle(request, response, handler); + } +} \ No newline at end of file diff --git a/esign/src/main/java/com/seeyon/apps/esign/node/EsignNode.java b/esign/src/main/java/com/seeyon/apps/esign/node/EsignNode.java new file mode 100644 index 0000000..0a0be16 --- /dev/null +++ b/esign/src/main/java/com/seeyon/apps/esign/node/EsignNode.java @@ -0,0 +1,296 @@ +package com.seeyon.apps.esign.node; + +import com.seeyon.apps.common.workflow.node.ACommonSuperNode; +import com.seeyon.apps.esign.config.EsignConfigProvider; +import com.seeyon.apps.esign.constants.EsignConfigConstants; +import com.seeyon.apps.esign.form.FormDataOperator; +import com.seeyon.apps.esign.form.FormUpdateField; +import com.seeyon.apps.esign.form.FormWhereCondition; +import com.seeyon.apps.esign.po.*; +import com.seeyon.apps.esign.service.EsignByTemplateService; +import com.seeyon.apps.esign.service.EsignByUploadFileService; +import com.seeyon.apps.ext.workflow.vo.FormDataVo; +import com.seeyon.apps.ext.workflow.vo.SuperNodeContext; +import com.seeyon.cap4.form.bean.FormDataMasterBean; +import com.seeyon.cap4.form.bean.FormFieldBean; +import com.seeyon.cap4.form.service.CAP4FormManager; +import com.seeyon.ctp.common.AppContext; +import com.seeyon.ctp.common.exceptions.BusinessException; +import org.apache.commons.logging.Log; +import org.apache.commons.logging.LogFactory; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.stereotype.Component; + +import java.util.*; + +@Component +public class EsignNode extends ACommonSuperNode { + + private static final Log log = LogFactory.getLog(EsignNode.class); + + private static final String CONTRACT_NAME_FIELD = "合同名称"; + private static final String CONTRACT_ATTACHMENT_FIELD = "合同审批附件"; + private static final String B_UNIT_NAME_FIELD = "乙方单位名称"; + private static CAP4FormManager cap4FormManager = (CAP4FormManager) AppContext.getBean("cap4FormManager"); + @Autowired + private EsignConfigProvider configProvider; + @Autowired + private EsignByUploadFileService uploadFileService; + @Autowired + private EsignByTemplateService templateService; + + @Override + public String getPluginId() { + return EsignConfigConstants.getPluginId(); + } + + @Override + public String getFormParse() { + return ""; + } + + @Override + public SuperNodeContext proceed(String s, FormDataVo formDataVo, FormDataMasterBean formDataMasterBean) { + SuperNodeContext context = new SuperNodeContext(); + context.setNeedSave(true); + log.info("进入 E签宝签署集成超级节点"); + + try { + Map signParams = buildSignParams(formDataVo, formDataMasterBean, true); + if (signParams == null) throw new RuntimeException("签署参数构建失败"); + String esignFlowId = templateService.createBySignTemplate(signParams); + log.info("E签宝签署流程ID: " + esignFlowId); + log.info("E签宝合同已发送: " + esignFlowId); + return context.wait("等待签署结束"); + } catch (Exception e) { + log.error("E签宝签署失败", e); + context.setErrMsg("E签宝签署失败: " + e.getMessage()); + return context.back("E签宝签署失败: " + e.getMessage()); + } + } + + private Map buildSignFlowConfig(FormDataVo formDataVo,FormDataMasterBean masterBean) throws Exception { + String contractName = getStringField(formDataVo, CONTRACT_NAME_FIELD); + if (contractName == null) throw new RuntimeException("合同名称不能为空"); + String formId = formDataVo.getToken() +"_" + formDataVo.getId(); + Long enumId = masterBean.getFormTable().getFieldBeanByDisplay("E签宝签署状态").getEnumId(); + String signCallBackUrl = configProvider.getBizConfigByKey(EsignConfigConstants.OA_HOST) + "/seeyon/esigncallback.do?method=callback&formId=" + formId + "&tablename=" + masterBean.getFormTable().getTableName() + "&updatefield=" + masterBean.getFormTable().getFieldBeanByDisplay("盖章后合同附件").getColumnName() + "&statusfield=" + masterBean.getFormTable().getFieldBeanByDisplay("E签宝签署状态").getColumnName() + "_" + enumId; + Map config = new HashMap<>(); + config.put("signFlowTitle", contractName); + config.put("autoFinish", true); + config.put("notifyUrl", signCallBackUrl); + Map noticeConfig = new HashMap<>(); + noticeConfig.put("noticeTypes", "1"); + config.put("noticeConfig", noticeConfig); + return config; + } + + private List buildSigners(FormDataVo formDataVo, String fileId,boolean qifengSign) throws Exception { + List positions = uploadFileService.getSignPosition(fileId); + SignFieldPosition bPosition = extractPosition(positions, "乙方盖章/签字"); + SignFieldPosition aPosition = extractPosition(positions, "甲方盖章/签字"); + String bSignerType = formDataVo.getFieldData("乙方签署类型").getStringValue(); + + SignFieldPosition aQiFengposition = new SignFieldPosition(); + aQiFengposition.setAcrossPageMode("ALL"); + aQiFengposition.setPositionY(348f); + SignFieldPosition bQiFengposition = new SignFieldPosition(); + bQiFengposition.setAcrossPageMode("ALL"); + bQiFengposition.setPositionY(500f); + + List aPos = new ArrayList<>(); + aPos.add(aPosition); + aPos.add(aQiFengposition); + List bPos = new ArrayList<>(); + bPos.add(bPosition); + bPos.add(bQiFengposition); + + Signer bSigner = !"组织".equals(bSignerType) ? createPsnSigner(fileId,formDataVo.getFieldData("乙方姓名").getStringValue(),bPos,1,formDataVo.getFieldData("乙方电话").getStringValue(),false) : createOrgSigner( + fileId, + getStringField(formDataVo, B_UNIT_NAME_FIELD), + bPos, 1, formDataVo.getFieldData("乙方法人姓名").getStringValue(), + formDataVo.getFieldData("乙方法人身份证号").getStringValue(), + formDataVo.getFieldData("乙方企业社会信用代码").getStringValue(), + formDataVo.getFieldData("乙方经办人手机号").getStringValue(), + formDataVo.getFieldData("乙方经办人姓名").getStringValue(), + formDataVo.getFieldData("乙方经办人身份证号").getStringValue(),false + ); + + Signer aSigner = createOrgSigner( + fileId,null, aPos, 2, null, null, null, null, null, null,true + ); + List signers = new ArrayList<>(); + signers.add(bSigner); + signers.add(aSigner); + return signers; + } + + private Map buildSignParams(FormDataVo formDataVo, FormDataMasterBean formDataMasterBean, boolean byFile) throws Exception { + + String fileId = null; + if (byFile) { + String attachmentId = getStringField(formDataVo, CONTRACT_ATTACHMENT_FIELD); + if (attachmentId == null) throw new RuntimeException("合同附件不能为空"); + fileId = uploadFileService.uploadFileToEsign(attachmentId); + } + Map docMap = new HashMap<>(); + docMap.put("fileId", fileId); + List docs = new ArrayList<>(); + docs.add(docMap); + Map signFlowConfig = buildSignFlowConfig(formDataVo, formDataMasterBean); + List signers = buildSigners(formDataVo, fileId,true); + + Map signParams = new HashMap<>(); + signParams.put("signFlowConfig", signFlowConfig); + signParams.put("signers", signers); + signParams.put("docs", docs); + return signParams; + + } + + private void fillFileId(String fileId,FormDataVo formDataVo,FormDataMasterBean formDataMasterBean) throws NoSuchFieldException, BusinessException { + String tableName = formDataVo.getTableName(); + FormFieldBean fieldBeanByDisplay = formDataMasterBean.getFormTable().getFieldBeanByDisplay("合同文件ID"); + FormDataOperator formDataOperator = new FormDataOperator(); + List updateFields = new ArrayList<>(); + updateFields.add(FormUpdateField.build().fieldName(fieldBeanByDisplay.getColumnName()).value(fileId)); + List whereConditions = new ArrayList<>(); + FormWhereCondition condition = FormWhereCondition.build().value(formDataVo.getId()); + condition.setFieldName("ID"); + whereConditions.add(condition); + formDataOperator.updateMasterForm(updateFields,tableName,whereConditions); + } + + private Map mapOf(Object... keyValues) { + if (keyValues.length % 2 != 0) { + throw new IllegalArgumentException("参数个数必须为偶数:key 和 value 必须成对出现"); + } + Map map = new HashMap<>(); + for (int i = 0; i < keyValues.length; i += 2) { + Object key = keyValues[i]; + Object value = keyValues[i + 1]; + if (!(key instanceof String)) { + throw new IllegalArgumentException("key 必须是 String 类型,当前为:" + key.getClass()); + } + map.put((String) key, value); + } + return map; + } + + private Signer createPsnSigner( String fileId, String psnName,List pos, int order, String phone,Boolean autoSign) { + Signer signer = new Signer(); + signer.setSignerType(0); + signer.setSignConfig(mapOf("signOrder", order)); + if(Boolean.FALSE.equals(autoSign)){ + signer.setNoticeConfig(mapOf("noticeTypes", "1")); + + Map psnInfo = mapOf("psnAccount", phone, "psnInfo", mapOf("psnName", psnName)); + signer.setPsnSignerInfo(psnInfo); + } + + NormalSignFieldConfig fieldConfig = new NormalSignFieldConfig(); + fieldConfig.setSignFieldPosition(pos.get(0)); + fieldConfig.setAutoSign(autoSign); + fieldConfig.setSignFieldStyle(1); + SignField field = new SignField(); + field.setSignFieldType(0); + field.setNormalSignFieldConfig(fieldConfig); + field.setFileId(fileId); + + NormalSignFieldConfig qiFengfieldConfig = new NormalSignFieldConfig(); + qiFengfieldConfig.setSignFieldPosition(pos.get(1)); + qiFengfieldConfig.setAutoSign(autoSign); + qiFengfieldConfig.setSignFieldStyle(2); + SignField qiFengfield = new SignField(); + qiFengfield.setSignFieldType(0); + qiFengfield.setNormalSignFieldConfig(qiFengfieldConfig); + qiFengfield.setFileId(fileId); + + signer.setSignFields(Arrays.asList(field,qiFengfield)); + return signer; + } + + private Signer createOrgSigner(String fileId ,String orgName, List pos, int order, + String legalName, String legalId, String orgCode, + String transPhone, String psnName, String psnId,Boolean autoSign) { + Signer signer = new Signer(); + signer.setSignerType(1); + signer.setSignConfig(mapOf("signOrder", order)); + if(Boolean.FALSE.equals(autoSign)){ + signer.setNoticeConfig(mapOf("noticeTypes", "1")); + + Map orgInfo = mapOf("orgName", orgName, "orgInfo", mapOf( + "legalRepName", legalName, + "legalRepIDCardNum", legalId, + "orgIDCardNum", orgCode, + "orgIDCardType", "CRED_ORG_USCC" + ), + "transactorInfo", mapOf( + "psnAccount", transPhone, + "psnInfo", mapOf( + "psnName", psnName, + "psnIDCardNum", psnId + ) + ) + ); + + signer.setOrgSignerInfo(orgInfo); + } + + NormalSignFieldConfig fieldConfig = new NormalSignFieldConfig(); + fieldConfig.setSignFieldPosition(pos.get(0)); + fieldConfig.setAutoSign(autoSign); + fieldConfig.setSignFieldStyle(1); + SignField field = new SignField(); + field.setSignFieldType(0); + field.setNormalSignFieldConfig(fieldConfig); + field.setFileId(fileId); + + NormalSignFieldConfig qiFengfieldConfig = new NormalSignFieldConfig(); + qiFengfieldConfig.setSignFieldPosition(pos.get(1)); + qiFengfieldConfig.setAutoSign(autoSign); + qiFengfieldConfig.setSignFieldStyle(2); + SignField qiFengfield = new SignField(); + qiFengfield.setSignFieldType(0); + qiFengfield.setNormalSignFieldConfig(qiFengfieldConfig); + qiFengfield.setFileId(fileId); + + signer.setSignFields(Arrays.asList(field,qiFengfield)); + return signer; + } + + private SignFieldPosition extractPosition(List positions, String keyword) { + for (Object obj : positions) { + Map position = (Map) obj; + if (Boolean.TRUE.equals(position.get("searchResult")) && keyword.equals(position.get("keyword"))) { + Object[] posArray = (Object[]) position.get("positions"); + Map posMap = (Map) posArray[0]; + Map coord = (Map) ((Object[])posMap.get("coordinates"))[0]; + SignFieldPosition sfp = new SignFieldPosition(); + sfp.setPositionPage(posMap.get("pageNum") + ""); + sfp.setPositionX(toFloat(coord.get("positionX")) + 150f); + sfp.setPositionY(toFloat(coord.get("positionY"))); + return sfp; + } + } + throw new RuntimeException("未找到关键字位置: " + keyword); + } + + private String getStringField(FormDataVo vo, String field) throws NoSuchFieldException { + return vo.getFieldData(field) != null ? vo.getFieldData(field).getStringValue() : null; + } + + private Float toFloat(Object val) { + return val instanceof Number ? ((Number) val).floatValue() : Float.parseFloat(val.toString()); + } + + @Override + public String getNodeId() { + return "nd_20250702"; + } + + @Override + public String getNodeName() { + return "E签宝签署节点"; + } +} diff --git a/esign/src/main/java/com/seeyon/apps/esign/node/EsignOrgAuthNode.java b/esign/src/main/java/com/seeyon/apps/esign/node/EsignOrgAuthNode.java new file mode 100644 index 0000000..3733b9f --- /dev/null +++ b/esign/src/main/java/com/seeyon/apps/esign/node/EsignOrgAuthNode.java @@ -0,0 +1,38 @@ +package com.seeyon.apps.esign.node; + +import com.seeyon.apps.common.workflow.node.ACommonSuperNode; +import com.seeyon.apps.ext.workflow.vo.FormDataVo; +import com.seeyon.apps.ext.workflow.vo.SuperNodeContext; +import com.seeyon.cap4.form.bean.FormDataMasterBean; + +public class EsignOrgAuthNode extends ACommonSuperNode { + @Override + public String getPluginId() { + return ""; + } + + @Override + public String getFormParse() { + return ""; + } + + @Override + public SuperNodeContext proceed(String s, FormDataVo formDataVo, FormDataMasterBean formDataMasterBean) throws Exception { + //个人实名认证、企业认证处理 + return null; + } + + public void personAuth() { + // /v3/psn-auth-url + } + + @Override + public String getNodeId() { + return ""; + } + + @Override + public String getNodeName() { + return ""; + } +} diff --git a/esign/src/main/java/com/seeyon/apps/esign/node/EsignPersonAuthNode.java b/esign/src/main/java/com/seeyon/apps/esign/node/EsignPersonAuthNode.java new file mode 100644 index 0000000..7d43d5f --- /dev/null +++ b/esign/src/main/java/com/seeyon/apps/esign/node/EsignPersonAuthNode.java @@ -0,0 +1,56 @@ +package com.seeyon.apps.esign.node; + +import com.seeyon.apps.common.workflow.node.ACommonSuperNode; +import com.seeyon.apps.esign.po.AuthPsnInfo; +import com.seeyon.apps.esign.po.PsnAuthConfig; +import com.seeyon.apps.ext.workflow.vo.FormDataVo; +import com.seeyon.apps.ext.workflow.vo.SuperNodeContext; +import com.seeyon.cap4.form.bean.FormDataMasterBean; + +import java.util.HashMap; +import java.util.Map; + +public class EsignPersonAuthNode extends ACommonSuperNode { + @Override + public String getPluginId() { + return ""; + } + + @Override + public String getFormParse() { + return ""; + } + + @Override + public SuperNodeContext proceed(String s, FormDataVo formDataVo, FormDataMasterBean formDataMasterBean) throws Exception { + Map authParams = new HashMap<>(); + PsnAuthConfig psnAuthConfig = buildPsnAuthConfig(formDataVo,formDataMasterBean); + String notifyUrl= ""; + authParams.put("psnAuthConfig",psnAuthConfig); + authParams.put("notifyUrl",notifyUrl); + + return null; + } + + private PsnAuthConfig buildPsnAuthConfig(FormDataVo formDataVo, FormDataMasterBean formDataMasterBean) throws Exception { + PsnAuthConfig psnAuthConfig = new PsnAuthConfig(); + psnAuthConfig.setPsnAccount(formDataVo.getFieldData("客户联系电话").getStringValue()); + AuthPsnInfo authPsnInfo = new AuthPsnInfo(); + authPsnInfo.setPsnName(formDataVo.getFieldData("客户联系人姓名").getStringValue()); + authPsnInfo.setPsnMobile(formDataVo.getFieldData("客户联系电话").getStringValue()); + authPsnInfo.setPsnIDCardType("CRED_PSN_CH_IDCARD"); + authPsnInfo.setPsnIDCardNum(formDataVo.getFieldData("客户身份证号").getStringValue()); + authPsnInfo.setPsnIdentityVerify(true); + return psnAuthConfig; + } + + @Override + public String getNodeId() { + return ""; + } + + @Override + public String getNodeName() { + return ""; + } +} diff --git a/esign/src/main/java/com/seeyon/apps/esign/po/AuthPsnInfo.java b/esign/src/main/java/com/seeyon/apps/esign/po/AuthPsnInfo.java new file mode 100644 index 0000000..dfdf759 --- /dev/null +++ b/esign/src/main/java/com/seeyon/apps/esign/po/AuthPsnInfo.java @@ -0,0 +1,61 @@ +package com.seeyon.apps.esign.po; + +import com.fasterxml.jackson.annotation.JsonInclude; + +@JsonInclude(JsonInclude.Include.NON_EMPTY) +public class AuthPsnInfo { + private String psnName; + private String psnIDCardNum; + private String psnIDCardType; + private String psnMobile; + private String bankCardNum; + private Boolean psnIdentityVerify; + + public String getPsnName() { + return psnName; + } + + public void setPsnName(String psnName) { + this.psnName = psnName; + } + + public String getPsnIDCardNum() { + return psnIDCardNum; + } + + public void setPsnIDCardNum(String psnIDCardNum) { + this.psnIDCardNum = psnIDCardNum; + } + + public String getPsnIDCardType() { + return psnIDCardType; + } + + public void setPsnIDCardType(String psnIDCardType) { + this.psnIDCardType = psnIDCardType; + } + + public String getPsnMobile() { + return psnMobile; + } + + public void setPsnMobile(String psnMobile) { + this.psnMobile = psnMobile; + } + + public String getBankCardNum() { + return bankCardNum; + } + + public void setBankCardNum(String bankCardNum) { + this.bankCardNum = bankCardNum; + } + + public Boolean getPsnIdentityVerify() { + return psnIdentityVerify; + } + + public void setPsnIdentityVerify(Boolean psnIdentityVerify) { + this.psnIdentityVerify = psnIdentityVerify; + } +} diff --git a/esign/src/main/java/com/seeyon/apps/esign/po/ContractFile.java b/esign/src/main/java/com/seeyon/apps/esign/po/ContractFile.java new file mode 100644 index 0000000..90a4e94 --- /dev/null +++ b/esign/src/main/java/com/seeyon/apps/esign/po/ContractFile.java @@ -0,0 +1,61 @@ +package com.seeyon.apps.esign.po; + +import com.fasterxml.jackson.annotation.JsonInclude; + +@JsonInclude(JsonInclude.Include.NON_EMPTY) +public class ContractFile { + private String fileId; + private String fileName; + private Boolean neededPwd; + private String fileEditPwd; + private String contractBizTypeId; + private int order; + + public String getFileId() { + return fileId; + } + + public void setFileId(String fileId) { + this.fileId = fileId; + } + + public String getFileName() { + return fileName; + } + + public void setFileName(String fileName) { + this.fileName = fileName; + } + + public Boolean getNeededPwd() { + return neededPwd; + } + + public void setNeededPwd(Boolean neededPwd) { + this.neededPwd = neededPwd; + } + + public String getFileEditPwd() { + return fileEditPwd; + } + + public void setFileEditPwd(String fileEditPwd) { + this.fileEditPwd = fileEditPwd; + } + + public String getContractBizTypeId() { + return contractBizTypeId; + } + + public void setContractBizTypeId(String contractBizTypeId) { + this.contractBizTypeId = contractBizTypeId; + } + + public int getOrder() { + return order; + } + + public void setOrder(int order) { + this.order = order; + } +} diff --git a/esign/src/main/java/com/seeyon/apps/esign/po/EsignApiHeader.java b/esign/src/main/java/com/seeyon/apps/esign/po/EsignApiHeader.java new file mode 100644 index 0000000..0000c76 --- /dev/null +++ b/esign/src/main/java/com/seeyon/apps/esign/po/EsignApiHeader.java @@ -0,0 +1,220 @@ +package com.seeyon.apps.esign.po; + +import com.seeyon.apps.esign.constants.EsignConfigConstants; +import org.apache.commons.codec.binary.Base64; +import org.apache.commons.lang.StringUtils; + +import javax.crypto.Mac; +import javax.crypto.spec.SecretKeySpec; +import java.io.UnsupportedEncodingException; +import java.nio.charset.StandardCharsets; +import java.security.InvalidKeyException; +import java.security.MessageDigest; +import java.security.NoSuchAlgorithmException; +import java.text.MessageFormat; +import java.util.HashMap; +import java.util.Map; + +public class EsignApiHeader { + private String xTsignOpenAppId; + private String xTsignOpenAuthMode; + private String xTsignOpenCaSignature; + private String xTsignOpenCaTimestamp; + private String accept; + private String contentType = "application/json; charset=UTF-8"; + private String contentMd5; + private String httpMethod; + private String date; + private String headers; + private String pathAndParameters; + private String token; + + public String getxTsignOpenAppId() { + return xTsignOpenAppId; + } + + public void setxTsignOpenAppId(String xTsignOpenAppId) { + this.xTsignOpenAppId = xTsignOpenAppId; + } + + public String getX_Tsign_Open_Auth_Mode() { + return xTsignOpenAuthMode; + } + + public void setX_Tsign_Open_Auth_Mode(String x_Tsign_Open_Auth_Mode) { + this.xTsignOpenAuthMode = x_Tsign_Open_Auth_Mode; + } + + public String getxTsignOpenCaSignature() { + return xTsignOpenCaSignature; + } + + public void setxTsignOpenCaSignature(String xTsignOpenCaSignature) { + this.xTsignOpenCaSignature = xTsignOpenCaSignature; + } + + public String getxTsignOpenCaTimestamp() { + return xTsignOpenCaTimestamp; + } + + public void setxTsignOpenCaTimestamp(String xTsignOpenCaTimestamp) { + this.xTsignOpenCaTimestamp = xTsignOpenCaTimestamp; + } + + public String getAccept() { + return accept; + } + + public void setAccept(String accept) { + this.accept = accept; + } + + public String getContentType() { + return contentType; + } + + public void setContentType(String contentType) { + this.contentType = contentType; + } + + public String getContentMd5() { + return contentMd5; + } + + public void setContentMd5(String contentMd5) { + this.contentMd5 = contentMd5; + } + + public static EsignApiHeader build() { + EsignApiHeader header = new EsignApiHeader(); + header.setAccept("*/*"); + header.setX_Tsign_Open_Auth_Mode("Signature"); + return header; + } + + public EsignApiHeader pathAndParameters(String pathAndParameters) { + this.pathAndParameters = pathAndParameters; + return this; + } + + public EsignApiHeader appId(String appId) { + this.xTsignOpenAppId = appId; + return this; + } + + public EsignApiHeader heads(String headers) { + this.headers = headers; + return this; + } + + public EsignApiHeader timeStamp() { + this.xTsignOpenCaTimestamp = System.currentTimeMillis() + ""; + return this; + } + + public EsignApiHeader token(String token) { + this.token = token; + return this; + } + + public EsignApiHeader contentMD5(String body) { + this.contentMd5 = getBodyContentMD5(body); + return this; + } + + public EsignApiHeader httpMethod(String httpMethod) { + this.httpMethod = httpMethod; + return this; + } + + public EsignApiHeader signature(String secret) throws Exception { + StringBuffer strBuff = new StringBuffer(); + strBuff.append(httpMethod).append("\n").append(accept).append("\n").append(contentMd5).append("\n") + .append(contentType).append("\n").append("").append("\n"); + if ("".equals(headers)) { + strBuff.append(headers).append(pathAndParameters); + } else { + strBuff.append(headers).append("\n").append(pathAndParameters); + } + String StringToSign = strBuff.toString(); + this.setxTsignOpenCaSignature(doSignatureBase64(StringToSign, secret)); + return this; + } + + + public String doSignatureBase64(String message, String secret) throws Exception { + String algorithm = "HmacSHA256"; + Mac hmacSha256; + String digestBase64 = null; + try { + hmacSha256 = Mac.getInstance(algorithm); + byte[] keyBytes = secret.getBytes("UTF-8"); + byte[] messageBytes = message.getBytes("UTF-8"); + hmacSha256.init(new SecretKeySpec(keyBytes, 0, keyBytes.length, algorithm)); + // 使用HmacSHA256对二进制数据消息Bytes计算摘要 + byte[] digestBytes = hmacSha256.doFinal(messageBytes); + // 把摘要后的结果digestBytes使用Base64进行编码 + digestBase64 = new String(Base64.encodeBase64(digestBytes), "UTF-8"); + } catch (NoSuchAlgorithmException e) { + String msg = MessageFormat.format("不支持此算法: {0}", e.getMessage()); + Exception ex = new Exception(msg); + ex.initCause(e); + throw ex; + } catch (UnsupportedEncodingException e) { + String msg = MessageFormat.format("不支持的字符编码: {0}", e.getMessage()); + Exception ex = new Exception(msg); + ex.initCause(e); + throw ex; + } catch (InvalidKeyException e) { + String msg = MessageFormat.format("无效的密钥规范: {0}", e.getMessage()); + Exception ex = new Exception(msg); + ex.initCause(e); + throw ex; + } + return digestBase64; + } + + /*** + * 计算请求Body体的Content-MD5 + * @param bodyData 请求Body体数据 + * @return + */ + public String getBodyContentMD5(String bodyData) { + if("".equals(bodyData)) { + return bodyData; + } + // 获取Body体的MD5的二进制数组(128位) + byte[] bytes = getBodyMD5Bytes128(bodyData); + // 对Body体MD5的二进制数组进行Base64编码 + return new String(Base64.encodeBase64(bytes)); + } + + public byte[] getBodyMD5Bytes128(String bodyData) { + byte[] md5Bytes = null; + try { + MessageDigest md5 = MessageDigest.getInstance("MD5"); + md5.update(bodyData.getBytes(StandardCharsets.UTF_8)); + md5Bytes = md5.digest(); + } catch (NoSuchAlgorithmException e) { + e.printStackTrace(); + } + return md5Bytes; + } + + public Map convert2Headers(){ + Map headers = new HashMap<>(); + if(xTsignOpenAppId != null) { + headers.put("X-Tsign-Open-App-Id", xTsignOpenAppId); + } + if(token != null) { + headers.put("X-Tsign-Open-Token", token); + } + if(contentType != null) { + headers.put("Content-Type", contentType); + } + if(!StringUtils.isBlank(contentMd5)) { + headers.put("Content-MD5", contentMd5); + } + return headers; + } +} diff --git a/esign/src/main/java/com/seeyon/apps/esign/po/EsignBaseResp.java b/esign/src/main/java/com/seeyon/apps/esign/po/EsignBaseResp.java new file mode 100644 index 0000000..3dab836 --- /dev/null +++ b/esign/src/main/java/com/seeyon/apps/esign/po/EsignBaseResp.java @@ -0,0 +1,31 @@ +package com.seeyon.apps.esign.po; + +public class EsignBaseResp { + private int code; + private String message; + private Object data; + + public String getMessage() { + return message; + } + + public void setMessage(String message) { + this.message = message; + } + + public int getCode() { + return code; + } + + public void setCode(int code) { + this.code = code; + } + + public Object getData() { + return data; + } + + public void setData(Object data) { + this.data = data; + } +} diff --git a/esign/src/main/java/com/seeyon/apps/esign/po/EsignCallbackParams.java b/esign/src/main/java/com/seeyon/apps/esign/po/EsignCallbackParams.java new file mode 100644 index 0000000..ba9e6dd --- /dev/null +++ b/esign/src/main/java/com/seeyon/apps/esign/po/EsignCallbackParams.java @@ -0,0 +1,46 @@ +package com.seeyon.apps.esign.po; + +import com.fasterxml.jackson.annotation.JsonIgnoreProperties; + +import java.io.Serializable; + +@JsonIgnoreProperties(ignoreUnknown = true) +public class EsignCallbackParams implements Serializable { + + private String signFlowId; + private String action; + private String resultDescription; //签署结果描述 + private Integer signResult; //签署结果 + + public String getSignFlowId() { + return signFlowId; + } + + public void setSignFlowId(String signFlowId) { + this.signFlowId = signFlowId; + } + + public String getAction() { + return action; + } + + public void setAction(String action) { + this.action = action; + } + + public String getResultDescription() { + return resultDescription; + } + + public void setResultDescription(String resultDescription) { + this.resultDescription = resultDescription; + } + + public Integer getSignResult() { + return signResult; + } + + public void setSignResult(Integer signResult) { + this.signResult = signResult; + } +} diff --git a/esign/src/main/java/com/seeyon/apps/esign/po/EsignException.java b/esign/src/main/java/com/seeyon/apps/esign/po/EsignException.java new file mode 100644 index 0000000..a054a6c --- /dev/null +++ b/esign/src/main/java/com/seeyon/apps/esign/po/EsignException.java @@ -0,0 +1,36 @@ +package com.seeyon.apps.esign.po; + +/** + * description 自定义全局异常 + * @author 澄泓 + * datetime 2019年7月1日上午10:43:24 + */ +public class EsignException extends Exception { + + private static final long serialVersionUID = 4359180081622082792L; + private Exception e; + + public EsignException(String msg) { + super(msg); + } + + public EsignException(String msg, Throwable cause) { + super(msg,cause); + } + + public EsignException(){ + + } + + public Exception getE() { + return e; + } + + public void setE(Exception e) { + this.e = e; + } + + + + +} diff --git a/esign/src/main/java/com/seeyon/apps/esign/po/EsignFileUploadParams.java b/esign/src/main/java/com/seeyon/apps/esign/po/EsignFileUploadParams.java new file mode 100644 index 0000000..872cd21 --- /dev/null +++ b/esign/src/main/java/com/seeyon/apps/esign/po/EsignFileUploadParams.java @@ -0,0 +1,49 @@ +package com.seeyon.apps.esign.po; + +public class EsignFileUploadParams { + private String contentMd5; + private String contentType; + private String fileName; + private Long fileSize; + private Boolean convertToPDF = false; + + public String getContentMd5() { + return contentMd5; + } + + public void setContentMd5(String contentMd5) { + this.contentMd5 = contentMd5; + } + + public String getContentType() { + return contentType; + } + + public void setContentType(String contentType) { + this.contentType = contentType; + } + + public String getFileName() { + return fileName; + } + + public void setFileName(String fileName) { + this.fileName = fileName; + } + + public Long getFileSize() { + return fileSize; + } + + public void setFileSize(Long fileSize) { + this.fileSize = fileSize; + } + + public Boolean getConvertToPDF() { + return convertToPDF; + } + + public void setConvertToPDF(Boolean convertToPDF) { + this.convertToPDF = convertToPDF; + } +} diff --git a/esign/src/main/java/com/seeyon/apps/esign/po/EsignHttpResponse.java b/esign/src/main/java/com/seeyon/apps/esign/po/EsignHttpResponse.java new file mode 100644 index 0000000..2cfb708 --- /dev/null +++ b/esign/src/main/java/com/seeyon/apps/esign/po/EsignHttpResponse.java @@ -0,0 +1,27 @@ +package com.seeyon.apps.esign.po; +/** + * 网络请求的response类 + * @author 澄泓 + * @date 2022/2/21 17:28 + * @version + */ +public class EsignHttpResponse { + private int status; + private String body; + + public int getStatus() { + return status; + } + + public void setStatus(int status) { + this.status = status; + } + + public String getBody() { + return body; + } + + public void setBody(String body) { + this.body = body; + } +} diff --git a/esign/src/main/java/com/seeyon/apps/esign/po/EsignToken.java b/esign/src/main/java/com/seeyon/apps/esign/po/EsignToken.java new file mode 100644 index 0000000..292d1ae --- /dev/null +++ b/esign/src/main/java/com/seeyon/apps/esign/po/EsignToken.java @@ -0,0 +1,34 @@ +package com.seeyon.apps.esign.po; + +import java.io.Serializable; + +public class EsignToken implements Serializable { + + private String tokenStr; + private Long ttl; + private String refreshToken; + + public String getTokenStr() { + return tokenStr; + } + + public void setTokenStr(String tokenStr) { + this.tokenStr = tokenStr; + } + + public Long getTtl() { + return ttl; + } + + public void setTtl(Long ttl) { + this.ttl = ttl; + } + + public String getRefreshToken() { + return refreshToken; + } + + public void setRefreshToken(String refreshToken) { + this.refreshToken = refreshToken; + } +} diff --git a/esign/src/main/java/com/seeyon/apps/esign/po/GetUploadUrlResp.java b/esign/src/main/java/com/seeyon/apps/esign/po/GetUploadUrlResp.java new file mode 100644 index 0000000..5be6b7f --- /dev/null +++ b/esign/src/main/java/com/seeyon/apps/esign/po/GetUploadUrlResp.java @@ -0,0 +1,23 @@ +package com.seeyon.apps.esign.po; + +public class GetUploadUrlResp { + + private String fileId; + private String fileUploadUrl; + + public String getFileId() { + return fileId; + } + + public void setFileId(String fileId) { + this.fileId = fileId; + } + + public String getFileUploadUrl() { + return fileUploadUrl; + } + + public void setFileUploadUrl(String fileUploadUrl) { + this.fileUploadUrl = fileUploadUrl; + } +} diff --git a/esign/src/main/java/com/seeyon/apps/esign/po/NormalSignFieldConfig.java b/esign/src/main/java/com/seeyon/apps/esign/po/NormalSignFieldConfig.java new file mode 100644 index 0000000..85e435d --- /dev/null +++ b/esign/src/main/java/com/seeyon/apps/esign/po/NormalSignFieldConfig.java @@ -0,0 +1,31 @@ +package com.seeyon.apps.esign.po; + +public class NormalSignFieldConfig { + private Boolean autoSign; + private Integer signFieldStyle; + private SignFieldPosition signFieldPosition; + + public Boolean getAutoSign() { + return autoSign; + } + + public void setAutoSign(Boolean autoSign) { + this.autoSign = autoSign; + } + + public Integer getSignFieldStyle() { + return signFieldStyle; + } + + public void setSignFieldStyle(Integer signFieldStyle) { + this.signFieldStyle = signFieldStyle; + } + + public SignFieldPosition getSignFieldPosition() { + return signFieldPosition; + } + + public void setSignFieldPosition(SignFieldPosition signFieldPosition) { + this.signFieldPosition = signFieldPosition; + } +} diff --git a/esign/src/main/java/com/seeyon/apps/esign/po/OrgInitiator.java b/esign/src/main/java/com/seeyon/apps/esign/po/OrgInitiator.java new file mode 100644 index 0000000..4c8649a --- /dev/null +++ b/esign/src/main/java/com/seeyon/apps/esign/po/OrgInitiator.java @@ -0,0 +1,22 @@ +package com.seeyon.apps.esign.po; + +public class OrgInitiator { + private String orgId; + private Transactor transactor; + + public String getOrgId() { + return orgId; + } + + public void setOrgId(String orgId) { + this.orgId = orgId; + } + + public Transactor getTransactor() { + return transactor; + } + + public void setTransactor(Transactor transactor) { + this.transactor = transactor; + } +} diff --git a/esign/src/main/java/com/seeyon/apps/esign/po/PsnAuthConfig.java b/esign/src/main/java/com/seeyon/apps/esign/po/PsnAuthConfig.java new file mode 100644 index 0000000..a1cdefc --- /dev/null +++ b/esign/src/main/java/com/seeyon/apps/esign/po/PsnAuthConfig.java @@ -0,0 +1,40 @@ +package com.seeyon.apps.esign.po; + +public class PsnAuthConfig { + private String psnAccount; + private String psnId; + private AuthPsnInfo psnInfo; + private PsnAuthPageConfig psnAuthPageConfig; + + public String getPsnAccount() { + return psnAccount; + } + + public void setPsnAccount(String psnAccount) { + this.psnAccount = psnAccount; + } + + public String getPsnId() { + return psnId; + } + + public void setPsnId(String psnId) { + this.psnId = psnId; + } + + public AuthPsnInfo getPsnInfo() { + return psnInfo; + } + + public void setPsnInfo(AuthPsnInfo psnInfo) { + this.psnInfo = psnInfo; + } + + public PsnAuthPageConfig getPsnAuthPageConfig() { + return psnAuthPageConfig; + } + + public void setPsnAuthPageConfig(PsnAuthPageConfig psnAuthPageConfig) { + this.psnAuthPageConfig = psnAuthPageConfig; + } +} diff --git a/esign/src/main/java/com/seeyon/apps/esign/po/PsnAuthPageConfig.java b/esign/src/main/java/com/seeyon/apps/esign/po/PsnAuthPageConfig.java new file mode 100644 index 0000000..636c0e0 --- /dev/null +++ b/esign/src/main/java/com/seeyon/apps/esign/po/PsnAuthPageConfig.java @@ -0,0 +1,45 @@ +package com.seeyon.apps.esign.po; + +import com.fasterxml.jackson.annotation.JsonInclude; + +import java.util.List; + +@JsonInclude(JsonInclude.Include.NON_EMPTY) +public class PsnAuthPageConfig { + private String psnDefaultAuthMode; + private List psnAvailableAuthModes; + private List advancedVersion; + private List psnEditableFields; + + public String getPsnDefaultAuthMode() { + return psnDefaultAuthMode; + } + + public void setPsnDefaultAuthMode(String psnDefaultAuthMode) { + this.psnDefaultAuthMode = psnDefaultAuthMode; + } + + public List getPsnAvailableAuthModes() { + return psnAvailableAuthModes; + } + + public void setPsnAvailableAuthModes(List psnAvailableAuthModes) { + this.psnAvailableAuthModes = psnAvailableAuthModes; + } + + public List getAdvancedVersion() { + return advancedVersion; + } + + public void setAdvancedVersion(List advancedVersion) { + this.advancedVersion = advancedVersion; + } + + public List getPsnEditableFields() { + return psnEditableFields; + } + + public void setPsnEditableFields(List psnEditableFields) { + this.psnEditableFields = psnEditableFields; + } +} diff --git a/esign/src/main/java/com/seeyon/apps/esign/po/PsnInitiator.java b/esign/src/main/java/com/seeyon/apps/esign/po/PsnInitiator.java new file mode 100644 index 0000000..4aa0c12 --- /dev/null +++ b/esign/src/main/java/com/seeyon/apps/esign/po/PsnInitiator.java @@ -0,0 +1,13 @@ +package com.seeyon.apps.esign.po; + +public class PsnInitiator { + private String psnId; + + public String getPsnId() { + return psnId; + } + + public void setPsnId(String psnId) { + this.psnId = psnId; + } +} diff --git a/esign/src/main/java/com/seeyon/apps/esign/po/RemarkSignFieldConfig.java b/esign/src/main/java/com/seeyon/apps/esign/po/RemarkSignFieldConfig.java new file mode 100644 index 0000000..121fded --- /dev/null +++ b/esign/src/main/java/com/seeyon/apps/esign/po/RemarkSignFieldConfig.java @@ -0,0 +1,32 @@ +package com.seeyon.apps.esign.po; + +public class RemarkSignFieldConfig { + + private boolean freeMode = false; + private int inputType = 1; + private String remarkContent = ""; + + public boolean isFreeMode() { + return freeMode; + } + + public void setFreeMode(boolean freeMode) { + this.freeMode = freeMode; + } + + public int getInputType() { + return inputType; + } + + public void setInputType(int inputType) { + this.inputType = inputType; + } + + public String getRemarkContent() { + return remarkContent; + } + + public void setRemarkContent(String remarkContent) { + this.remarkContent = remarkContent; + } +} diff --git a/esign/src/main/java/com/seeyon/apps/esign/po/RestUser.java b/esign/src/main/java/com/seeyon/apps/esign/po/RestUser.java new file mode 100644 index 0000000..0886674 --- /dev/null +++ b/esign/src/main/java/com/seeyon/apps/esign/po/RestUser.java @@ -0,0 +1,32 @@ +package com.seeyon.apps.esign.po; + +public class RestUser { + + private String restName; + private String restPassword; + private String loginName; + + public String getRestName() { + return restName; + } + + public void setRestName(String restName) { + this.restName = restName; + } + + public String getRestPassword() { + return restPassword; + } + + public void setRestPassword(String restPassword) { + this.restPassword = restPassword; + } + + public String getLoginName() { + return loginName; + } + + public void setLoginName(String loginName) { + this.loginName = loginName; + } +} diff --git a/esign/src/main/java/com/seeyon/apps/esign/po/SignField.java b/esign/src/main/java/com/seeyon/apps/esign/po/SignField.java new file mode 100644 index 0000000..c109332 --- /dev/null +++ b/esign/src/main/java/com/seeyon/apps/esign/po/SignField.java @@ -0,0 +1,41 @@ +package com.seeyon.apps.esign.po; + +public class SignField { + + private String fileId; + private Integer signFieldType; + private NormalSignFieldConfig normalSignFieldConfig; + private RemarkSignFieldConfig remarkSignFieldConfig; + + public String getFileId() { + return fileId; + } + + public void setFileId(String fileId) { + this.fileId = fileId; + } + + public Integer getSignFieldType() { + return signFieldType; + } + + public void setSignFieldType(Integer signFieldType) { + this.signFieldType = signFieldType; + } + + public NormalSignFieldConfig getNormalSignFieldConfig() { + return normalSignFieldConfig; + } + + public void setNormalSignFieldConfig(NormalSignFieldConfig normalSignFieldConfig) { + this.normalSignFieldConfig = normalSignFieldConfig; + } + + public RemarkSignFieldConfig getRemarkSignFieldConfig() { + return remarkSignFieldConfig; + } + + public void setRemarkSignFieldConfig(RemarkSignFieldConfig remarkSignFieldConfig) { + this.remarkSignFieldConfig = remarkSignFieldConfig; + } +} diff --git a/esign/src/main/java/com/seeyon/apps/esign/po/SignFieldPosition.java b/esign/src/main/java/com/seeyon/apps/esign/po/SignFieldPosition.java new file mode 100644 index 0000000..b4ce20f --- /dev/null +++ b/esign/src/main/java/com/seeyon/apps/esign/po/SignFieldPosition.java @@ -0,0 +1,41 @@ +package com.seeyon.apps.esign.po; + +public class SignFieldPosition { + + private String acrossPageMode; + private String positionPage; + private Float positionX; + private Float positionY; + + public String getAcrossPageMode() { + return acrossPageMode; + } + + public void setAcrossPageMode(String acrossPageMode) { + this.acrossPageMode = acrossPageMode; + } + + public String getPositionPage() { + return positionPage; + } + + public void setPositionPage(String positionPage) { + this.positionPage = positionPage; + } + + public Float getPositionX() { + return positionX; + } + + public void setPositionX(Float positionX) { + this.positionX = positionX; + } + + public Float getPositionY() { + return positionY; + } + + public void setPositionY(Float positionY) { + this.positionY = positionY; + } +} diff --git a/esign/src/main/java/com/seeyon/apps/esign/po/SignFile.java b/esign/src/main/java/com/seeyon/apps/esign/po/SignFile.java new file mode 100644 index 0000000..d7adfcf --- /dev/null +++ b/esign/src/main/java/com/seeyon/apps/esign/po/SignFile.java @@ -0,0 +1,22 @@ +package com.seeyon.apps.esign.po; + +public class SignFile { + private String fileName; + private String fileId; + + public String getFileName() { + return fileName; + } + + public void setFileName(String fileName) { + this.fileName = fileName; + } + + public String getFileId() { + return fileId; + } + + public void setFileId(String fileId) { + this.fileId = fileId; + } +} diff --git a/esign/src/main/java/com/seeyon/apps/esign/po/SignFlowConfig.java b/esign/src/main/java/com/seeyon/apps/esign/po/SignFlowConfig.java new file mode 100644 index 0000000..bbafc95 --- /dev/null +++ b/esign/src/main/java/com/seeyon/apps/esign/po/SignFlowConfig.java @@ -0,0 +1,127 @@ +package com.seeyon.apps.esign.po; + +import com.fasterxml.jackson.annotation.JsonInclude; + +import java.util.List; +import java.util.Map; + +@JsonInclude(JsonInclude.Include.NON_EMPTY) +public class SignFlowConfig { + private String signFlowTitle; + private Long signFlowExpireTime; + private Boolean autoStart; + private Boolean autoFinish; + private Boolean identifyVerify; + private String notifyUrl; + private Map redirectConfig; + private Map signConfig; + private Map noticeConfig; + private Map authConfig; + private Map contractConfig; + private List contractGroupIds; + private Boolean docsViewLimited; + + public String getSignFlowTitle() { + return signFlowTitle; + } + + public void setSignFlowTitle(String signFlowTitle) { + this.signFlowTitle = signFlowTitle; + } + + public Long getSignFlowExpireTime() { + return signFlowExpireTime; + } + + public void setSignFlowExpireTime(Long signFlowExpireTime) { + this.signFlowExpireTime = signFlowExpireTime; + } + + public Boolean getAutoStart() { + return autoStart; + } + + public void setAutoStart(Boolean autoStart) { + this.autoStart = autoStart; + } + + public Boolean getAutoFinish() { + return autoFinish; + } + + public void setAutoFinish(Boolean autoFinish) { + this.autoFinish = autoFinish; + } + + public Boolean getIdentifyVerify() { + return identifyVerify; + } + + public void setIdentifyVerify(Boolean identifyVerify) { + this.identifyVerify = identifyVerify; + } + + public String getNotifyUrl() { + return notifyUrl; + } + + public void setNotifyUrl(String notifyUrl) { + this.notifyUrl = notifyUrl; + } + + public Map getRedirectConfig() { + return redirectConfig; + } + + public void setRedirectConfig(Map redirectConfig) { + this.redirectConfig = redirectConfig; + } + + public Map getSignConfig() { + return signConfig; + } + + public void setSignConfig(Map signConfig) { + this.signConfig = signConfig; + } + + public Map getNoticeConfig() { + return noticeConfig; + } + + public void setNoticeConfig(Map noticeConfig) { + this.noticeConfig = noticeConfig; + } + + public Map getAuthConfig() { + return authConfig; + } + + public void setAuthConfig(Map authConfig) { + this.authConfig = authConfig; + } + + public Map getContractConfig() { + return contractConfig; + } + + public void setContractConfig(Map contractConfig) { + this.contractConfig = contractConfig; + } + + public List getContractGroupIds() { + return contractGroupIds; + } + + public void setContractGroupIds(List contractGroupIds) { + this.contractGroupIds = contractGroupIds; + } + + public Boolean getDocsViewLimited() { + return docsViewLimited; + } + + public void setDocsViewLimited(Boolean docsViewLimited) { + this.docsViewLimited = docsViewLimited; + } +} diff --git a/esign/src/main/java/com/seeyon/apps/esign/po/SignFlowInitiator.java b/esign/src/main/java/com/seeyon/apps/esign/po/SignFlowInitiator.java new file mode 100644 index 0000000..287b046 --- /dev/null +++ b/esign/src/main/java/com/seeyon/apps/esign/po/SignFlowInitiator.java @@ -0,0 +1,37 @@ +package com.seeyon.apps.esign.po; + +import com.fasterxml.jackson.annotation.JsonInclude; + +import java.util.List; + +@JsonInclude(JsonInclude.Include.NON_EMPTY) +public class SignFlowInitiator { + + private OrgInitiator orgInitiator; + private PsnInitiator psnInitiator; + private List initialRemarks; + + public PsnInitiator getPsnInitiator() { + return psnInitiator; + } + + public void setPsnInitiator(PsnInitiator psnInitiator) { + this.psnInitiator = psnInitiator; + } + + public List getInitialRemarks() { + return initialRemarks; + } + + public void setInitialRemarks(List initialRemarks) { + this.initialRemarks = initialRemarks; + } + + public OrgInitiator getOrgInitiator() { + return orgInitiator; + } + + public void setOrgInitiator(OrgInitiator orgInitiator) { + this.orgInitiator = orgInitiator; + } +} diff --git a/esign/src/main/java/com/seeyon/apps/esign/po/Signer.java b/esign/src/main/java/com/seeyon/apps/esign/po/Signer.java new file mode 100644 index 0000000..f5ff29b --- /dev/null +++ b/esign/src/main/java/com/seeyon/apps/esign/po/Signer.java @@ -0,0 +1,64 @@ +package com.seeyon.apps.esign.po; + +import com.fasterxml.jackson.annotation.JsonInclude; + +import java.util.List; +import java.util.Map; + +@JsonInclude(JsonInclude.Include.NON_EMPTY) +public class Signer { + private int signerType; + private Map signConfig; + private Map noticeConfig; + private Map orgSignerInfo; + private Map psnSignerInfo; + private List signFields; + + public int getSignerType() { + return signerType; + } + + public void setSignerType(int signerType) { + this.signerType = signerType; + } + + public Map getNoticeConfig() { + return noticeConfig; + } + + public void setNoticeConfig(Map noticeConfig) { + this.noticeConfig = noticeConfig; + } + + public Map getOrgSignerInfo() { + return orgSignerInfo; + } + + public void setOrgSignerInfo(Map orgSignerInfo) { + this.orgSignerInfo = orgSignerInfo; + } + + public Map getPsnSignerInfo() { + return psnSignerInfo; + } + + public void setPsnSignerInfo(Map psnSignerInfo) { + this.psnSignerInfo = psnSignerInfo; + } + + public List getSignFields() { + return signFields; + } + + public void setSignFields(List signFields) { + this.signFields = signFields; + } + + public Map getSignConfig() { + return signConfig; + } + + public void setSignConfig(Map signConfig) { + this.signConfig = signConfig; + } +} diff --git a/esign/src/main/java/com/seeyon/apps/esign/po/TemplateComponent.java b/esign/src/main/java/com/seeyon/apps/esign/po/TemplateComponent.java new file mode 100644 index 0000000..ed64f79 --- /dev/null +++ b/esign/src/main/java/com/seeyon/apps/esign/po/TemplateComponent.java @@ -0,0 +1,31 @@ +package com.seeyon.apps.esign.po; + +public class TemplateComponent { + private String componentId; + private String componentKey; + private String componentValue; + + public String getComponentId() { + return componentId; + } + + public void setComponentId(String componentId) { + this.componentId = componentId; + } + + public String getComponentKey() { + return componentKey; + } + + public void setComponentKey(String componentKey) { + this.componentKey = componentKey; + } + + public String getComponentValue() { + return componentValue; + } + + public void setComponentValue(String componentValue) { + this.componentValue = componentValue; + } +} diff --git a/esign/src/main/java/com/seeyon/apps/esign/po/TemplateInfo.java b/esign/src/main/java/com/seeyon/apps/esign/po/TemplateInfo.java new file mode 100644 index 0000000..43b2b18 --- /dev/null +++ b/esign/src/main/java/com/seeyon/apps/esign/po/TemplateInfo.java @@ -0,0 +1,22 @@ +package com.seeyon.apps.esign.po; + +public class TemplateInfo { + private String signTemplateName; + private String signTemplateId; + + public String getSignTemplateName() { + return signTemplateName; + } + + public void setSignTemplateName(String signTemplateName) { + this.signTemplateName = signTemplateName; + } + + public String getSignTemplateId() { + return signTemplateId; + } + + public void setSignTemplateId(String signTemplateId) { + this.signTemplateId = signTemplateId; + } +} diff --git a/esign/src/main/java/com/seeyon/apps/esign/po/Transactor.java b/esign/src/main/java/com/seeyon/apps/esign/po/Transactor.java new file mode 100644 index 0000000..6b95be3 --- /dev/null +++ b/esign/src/main/java/com/seeyon/apps/esign/po/Transactor.java @@ -0,0 +1,13 @@ +package com.seeyon.apps.esign.po; + +public class Transactor { + private String psnId; + + public String getPsnId() { + return psnId; + } + + public void setPsnId(String psnId) { + this.psnId = psnId; + } +} diff --git a/esign/src/main/java/com/seeyon/apps/esign/service/EsignApiClient.java b/esign/src/main/java/com/seeyon/apps/esign/service/EsignApiClient.java new file mode 100644 index 0000000..0e9bef2 --- /dev/null +++ b/esign/src/main/java/com/seeyon/apps/esign/service/EsignApiClient.java @@ -0,0 +1,25 @@ +package com.seeyon.apps.esign.service; + +import com.seeyon.apps.esign.core.SignApiClient; +import org.springframework.stereotype.Component; + +@Component +public class EsignApiClient implements SignApiClient { + + public static final String providerFlag ="ESIGN"; + + @Override + public String signByFile() { + return ""; + } + + @Override + public String signByTemplate() { + return ""; + } + + @Override + public String downloadContract() { + return ""; + } +} diff --git a/esign/src/main/java/com/seeyon/apps/esign/service/EsignAuthService.java b/esign/src/main/java/com/seeyon/apps/esign/service/EsignAuthService.java new file mode 100644 index 0000000..90ac7bf --- /dev/null +++ b/esign/src/main/java/com/seeyon/apps/esign/service/EsignAuthService.java @@ -0,0 +1,35 @@ +package com.seeyon.apps.esign.service; + +import com.seeyon.aicloud.common.JsonUtils; +import com.seeyon.apps.esign.config.EsignConfigProvider; +import com.seeyon.apps.esign.constants.EsignApiUrl; +import com.seeyon.apps.esign.constants.EsignConfigConstants; +import com.seeyon.apps.esign.po.EsignApiHeader; +import com.seeyon.apps.esign.po.EsignBaseResp; +import com.seeyon.apps.esign.utils.HttpClient; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.stereotype.Component; + +import java.util.Map; + +@Component +public class EsignAuthService { + + @Autowired + private EsignConfigProvider configProvider; + + public void personAuth(Map authParams) throws Exception { + EsignApiHeader esignApiHeader = EsignApiHeader.build(); + String jsonBody = JsonUtils.toJSONString(authParams); + esignApiHeader.appId(configProvider.getBizConfigByKey(EsignConfigConstants.APP_ID)) + .httpMethod("POST") + .heads("") + .pathAndParameters(EsignApiUrl.PERSON_AUTH_URL) + .contentMD5(jsonBody) + .signature(configProvider.getBizConfigByKey(EsignConfigConstants.APP_SECRET)); + 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); + Map dataMap = (Map) esignBaseResp.getData(); + } +} diff --git a/esign/src/main/java/com/seeyon/apps/esign/service/EsignByTemplateService.java b/esign/src/main/java/com/seeyon/apps/esign/service/EsignByTemplateService.java new file mode 100644 index 0000000..9c566bb --- /dev/null +++ b/esign/src/main/java/com/seeyon/apps/esign/service/EsignByTemplateService.java @@ -0,0 +1,57 @@ +package com.seeyon.apps.esign.service; + +import com.seeyon.aicloud.common.JsonUtils; +import com.seeyon.apps.esign.config.EsignConfigProvider; +import com.seeyon.apps.esign.constants.EsignApiUrl; +import com.seeyon.apps.esign.constants.EsignConfigConstants; +import com.seeyon.apps.esign.po.EsignApiHeader; +import com.seeyon.apps.esign.po.EsignBaseResp; +import com.seeyon.apps.esign.utils.HttpClient; +import com.seeyon.apps.esign.utils.JsonCleaner; +import org.apache.commons.logging.Log; +import org.apache.commons.logging.LogFactory; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.stereotype.Component; + + +import java.util.Map; + +@Component +public class EsignByTemplateService { + + @Autowired + private EsignConfigProvider configProvider; + @Autowired + private TokenCacheManager tokenCacheManager; + private static final Log log = LogFactory.getLog(EsignByTemplateService.class); + + public void signByTemplate(Map params) { + + } + + public void startSignFlow(String flowId) throws Exception { + String url = configProvider.getBizConfigByKey(EsignConfigConstants.ESIGN_HOST) + EsignApiUrl.SIGN_START_URL; + url.replace("{signFlowId}", flowId); + String respStr = HttpClient.httpPostRaw(url, "", null, null); + EsignBaseResp esignBaseResp = JsonUtils.parseObject(respStr, EsignBaseResp.class); + if (esignBaseResp.getCode() != 0) { + throw new Exception("签署发起失败"); + } + } + + public String createBySignTemplate(Map params) throws Exception { + EsignApiHeader esignApiHeader = EsignApiHeader.build(); + String jsonBody = JsonCleaner.removeEmptyObjects(JsonUtils.toJSONString(params)); + esignApiHeader.token(tokenCacheManager.getToken()).appId(configProvider.getBizConfigByKey(EsignConfigConstants.APP_ID)); + 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"); + EsignBaseResp esignBaseResp = JsonUtils.parseObject(respStr, EsignBaseResp.class); + Map dataMap = (Map) esignBaseResp.getData(); + if(!"0".equals(esignBaseResp.getCode() + "")) { + throw new RuntimeException("签署发起失败," + esignBaseResp.getMessage()); + } + String flowId = (String) dataMap.get("signFlowId"); + return flowId; + } +} diff --git a/esign/src/main/java/com/seeyon/apps/esign/service/EsignByUploadFileService.java b/esign/src/main/java/com/seeyon/apps/esign/service/EsignByUploadFileService.java new file mode 100644 index 0000000..111189d --- /dev/null +++ b/esign/src/main/java/com/seeyon/apps/esign/service/EsignByUploadFileService.java @@ -0,0 +1,190 @@ +package com.seeyon.apps.esign.service; + +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.ContractFile; +import com.seeyon.apps.esign.po.EsignApiHeader; +import com.seeyon.apps.esign.po.EsignBaseResp; +import com.seeyon.apps.esign.po.EsignFileUploadParams; +import com.seeyon.apps.esign.po.EsignHttpResponse; +import com.seeyon.apps.esign.po.GetUploadUrlResp; +import com.seeyon.apps.esign.po.SignFlowConfig; +import com.seeyon.apps.esign.po.Signer; +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 org.apache.commons.codec.binary.Base64; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.stereotype.Component; +import org.springframework.web.multipart.MultipartFile; + +import java.io.File; +import java.io.FileInputStream; +import java.io.FileNotFoundException; +import java.io.IOException; +import java.io.InputStream; +import java.security.MessageDigest; +import java.security.NoSuchAlgorithmException; +import java.util.ArrayList; +import java.util.HashMap; +import java.util.List; +import java.util.Map; + +@Component +public class EsignByUploadFileService { + + @Autowired + private EsignConfigProvider configProvider; + @Autowired + protected TokenCacheManager tokenCacheManager; + + + public Map getDownloadFileInfo(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()); + String respStr = HttpClient.httpGet(getDownloadUrl, esignApiHeader.convert2Headers(), null); + EsignBaseResp esignBaseResp = JsonUtils.parseObject(respStr, EsignBaseResp.class); + if(esignBaseResp.getCode() != 0 || esignBaseResp.getData() == null){ + throw new RuntimeException("下载合同文件失败"); + } + Map data = (Map) esignBaseResp.getData(); + Object[] files = (Object[]) data.get("files"); + if(files.length <= 0) { + throw new RuntimeException("下载合同文件失败"); + } + Map fileInfo = (Map) files[0]; + return fileInfo; + } + + public GetUploadUrlResp getUploadFileUrl(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()); + EsignFileUploadParams params = new EsignFileUploadParams(); + params.setFileName(fileName); + params.setContentMd5(fileMd5); + params.setFileSize(fileSize); + params.setConvertToPDF(convert2Pdf); + params.setContentType("application/octet-stream"); + String respStr = HttpClient.httpPostRaw(url, JsonUtils.toJSONString(params),esignApiHeader.convert2Headers(), null); + EsignBaseResp esignBaseResp = JsonUtils.parseObject(respStr, EsignBaseResp.class); + Object data = esignBaseResp.getData(); + if (data != null) { + Map map = (Map) data; + resp.setFileUploadUrl((String) map.get("fileUploadUrl")); + resp.setFileId((String) map.get("fileId")); + } + return resp; + } + + + public List getSignPosition(String fileId) throws Exception { + 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)); + List keywords = new ArrayList<>(); + keywords.add("甲方盖章/签字"); + keywords.add("乙方盖章/签字"); + Map params = new HashMap<>(); + params.put("keywords",keywords); + esignApiHeader.token(tokenCacheManager.getToken()); + String respStr = HttpClient.httpPostRaw(url,JsonUtils.toJSONString(params),esignApiHeader.convert2Headers(),null); + Map map = JsonUtils.parseObject(respStr, Map.class); + Map data = (Map) map.get("data"); + Object[] keywordPositions = (Object[]) data.get("keywordPositions"); + List resList = new ArrayList<>(); + for (Object position : keywordPositions) { + resList.add(position); + } + return resList; + } + + public String uploadFileToEsign(String refId) throws Exception { + String tempDir = System.getProperty("java.io.tmpdir"); + File file = null; + FileUtil fileUtil = new FileUtil(); + try { + List paths = fileUtil.fieldFileDownload(Long.parseLong(refId), tempDir + File.separator + "oafile" + File.separator); + file = new File(paths.get(0)); + String contentMD5 = EsignByUploadFileService.getFileContentMD5(paths.get(0)); + GetUploadUrlResp uploadResp = getUploadFileUrl(file.getName(), contentMD5, file.length(),true); + uploadFile(uploadResp.getFileUploadUrl(), contentMD5, file.getName(), paths.get(0)); + return uploadResp.getFileId(); + }finally { + if(file != null) { + file.delete(); + } + } + } + + public static String getFileContentMD5(String filePath) throws Exception { + // 获取文件MD5的二进制数组(128位) + byte[] bytes = getFileMD5Bytes128(filePath); + // 对文件MD5的二进制数组进行base64编码 + return new String(Base64.encodeBase64String(bytes)); + } + + /*** + * 获取文件MD5-二进制数组(128位) + * + * @return + * @throws IOException + */ + public static byte[] getFileMD5Bytes128(String filePath) throws Exception { + byte[] md5Bytes = null; + File file = new File(filePath); + try (FileInputStream fis = new FileInputStream(file)) { + MessageDigest md5 = MessageDigest.getInstance("MD5"); + byte[] buffer = new byte[1024]; + int length = -1; + while ((length = fis.read(buffer, 0, 1024)) != -1) { + md5.update(buffer, 0, length); + } + md5Bytes = md5.digest(); + } + return md5Bytes; + } + + + public String uploadFile(String uploadUrl,String contentMD5,String fileName,String filePath) throws Exception { +// EsignApiHeader esignApiHeader = EsignApiHeader.build(); +// esignApiHeader.setContentType("application/octet-stream"); +// esignApiHeader.setContentMd5(contentMD5); + EsignHttpResponse esignHttpResponse = EsignHttpHelper.doUploadHttp(uploadUrl, EsignRequestType.PUT, getBytes(filePath), contentMD5, "application/octet-stream", false); +// return HttpClient.uploadBinaryFile(uploadUrl,esignApiHeader.convert2Headers(),new FileInputStream(file),fileName); + return esignHttpResponse.getBody(); + } + + public static byte[] getBytes(String filePath) throws Exception { + File file = new File(filePath); + FileInputStream fis = null; + byte[] buffer = null; + try { + fis = new FileInputStream(file); + buffer = new byte[(int) file.length()]; + fis.read(buffer); + } catch (Exception e) { + Exception ex = new Exception("获取文件字节流失败", e); + ex.initCause(e); + throw ex; + } finally { + if (fis != null) { + try { + fis.close(); + } catch (IOException e) { + Exception ex = new Exception("关闭文件字节流失败", e); + ex.initCause(e); + throw ex; + } + } + } + return buffer; + } + +} + diff --git a/esign/src/main/java/com/seeyon/apps/esign/service/EsignCallbackBizService.java b/esign/src/main/java/com/seeyon/apps/esign/service/EsignCallbackBizService.java new file mode 100644 index 0000000..9d730d8 --- /dev/null +++ b/esign/src/main/java/com/seeyon/apps/esign/service/EsignCallbackBizService.java @@ -0,0 +1,96 @@ +package com.seeyon.apps.esign.service; + +import com.alibaba.fastjson.JSONObject; +import com.seeyon.apps.esign.config.EsignConfigProvider; +import com.seeyon.apps.esign.constants.EsignConfigConstants; +import com.seeyon.apps.esign.form.EnumMapUtils; +import com.seeyon.apps.esign.form.FormDataOperator; +import com.seeyon.apps.esign.form.FormUpdateField; +import com.seeyon.apps.esign.form.FormWhereCondition; +import com.seeyon.apps.esign.utils.FileUtil; +import com.seeyon.apps.esign.utils.ProtUtil; +import com.seeyon.ctp.util.JDBCAgent; +import org.apache.commons.logging.Log; +import org.apache.commons.logging.LogFactory; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.stereotype.Component; + +import java.util.ArrayList; +import java.util.List; +import java.util.Map; + + +@Component +public class EsignCallbackBizService { + + private static final Log log = LogFactory.getLog(EsignCallbackBizService.class); + @Autowired + private ProtUtil protUtil; + @Autowired + private EsignConfigProvider configProvider; + + public void handleSuccessSignCallbackBiz(String tablename,String updatefield,String statusField,String formId,String fileUrl,String fileName) throws Exception { + String[] strings = formId.split("_"); + String oaFlowId = strings[0]; + String tempFormId = strings[1]; + String[] statusParams = statusField.split("_"); + String status = statusParams[0]; + String enumId = statusParams[1]; + String enumItemId = EnumMapUtils.getEnumItemValueByEnumId("已签署",Long.parseLong(enumId)); + //下载文件到本地 + FormDataOperator formDataOperator = new FormDataOperator(); + List conditions = new ArrayList<>(); + String refId = FileUtil.uploadContractToOA(fileUrl, + fileName, getModuleId(tempFormId), + configProvider.getBizConfigByKey(EsignConfigConstants.FORMEDITLOGINNAME), + configProvider.getBizConfigByKey(EsignConfigConstants.updateAccountName)); + List updateFields = new ArrayList<>(); + updateFields.add(FormUpdateField.build().fieldName(updatefield).value(refId)); + updateFields.add(FormUpdateField.build().fieldName(status).value(enumItemId)); + conditions.add(FormWhereCondition.build().value(tempFormId).fieldName("ID")); + formDataOperator.updateMasterForm(updateFields,tablename,conditions); + JSONObject params = new JSONObject(); + params.put("message", "签署完成!!!"); + params.put("returnCode", 1); + protUtil.sendPostNotification(params.toString(), configProvider.getBizConfigByKey(EsignConfigConstants.nodeTokenUrl), oaFlowId); + } + + public void handleFailSignCallbackBiz(String tableName,String statusField,String formId,String failMsg) throws Exception { + String[] strings = formId.split("_"); + String oaFlowId = strings[0]; + String tempFormId = strings[1]; + String[] statusParams = statusField.split("_"); + String status = statusParams[0]; + String enumId = statusParams[1]; + String enumItemId = EnumMapUtils.getEnumItemValueByEnumId("签署失败",Long.parseLong(enumId)); + FormDataOperator formDataOperator = new FormDataOperator(); + List conditions = new ArrayList<>(); + List updateFields = new ArrayList<>(); + updateFields.add(FormUpdateField.build().fieldName(status).value(enumItemId)); + conditions.add(FormWhereCondition.build().value(tempFormId).fieldName("ID")); + formDataOperator.updateMasterForm(updateFields,tableName,conditions); + JSONObject params = new JSONObject(); + params.put("message", "签署失败: " + failMsg); + params.put("returnCode", 2); + protUtil.sendPostNotification(params.toString(), configProvider.getBizConfigByKey(EsignConfigConstants.nodeTokenUrl), oaFlowId); + } + + private String getModuleId(String formId) { + JDBCAgent jdbcAgent = new JDBCAgent(); + try { + String sql = "SELECT MODULE_ID FROM ctp_content_all where CONTENT_DATA_ID = ?"; + List params = new ArrayList<>(); + params.add(formId); + jdbcAgent.execute(sql,params); + List list = jdbcAgent.resultSetToList(); + if(list == null || !(list.size() > 0)) { + throw new RuntimeException("MODULE_ID获取失败"); + } + Map map = (Map) list.get(0); + return map.get("module_id") +""; + }catch (Exception e) { + e.printStackTrace(); + } + return null; + } +} diff --git a/esign/src/main/java/com/seeyon/apps/esign/service/EsignFileTemplateService.java b/esign/src/main/java/com/seeyon/apps/esign/service/EsignFileTemplateService.java new file mode 100644 index 0000000..1dbd0d8 --- /dev/null +++ b/esign/src/main/java/com/seeyon/apps/esign/service/EsignFileTemplateService.java @@ -0,0 +1,144 @@ +package com.seeyon.apps.esign.service; + +import com.seeyon.aicloud.common.JsonUtils; +import com.seeyon.apps.esign.config.EsignConfigProvider; +import com.seeyon.apps.esign.constants.EsignApiUrl; +import com.seeyon.apps.esign.constants.EsignConfigConstants; +import com.seeyon.apps.esign.po.EsignApiHeader; +import com.seeyon.apps.esign.po.EsignBaseResp; +import com.seeyon.apps.esign.po.GetUploadUrlResp; +import com.seeyon.apps.esign.po.SignFile; +import com.seeyon.apps.esign.po.TemplateComponent; +import com.seeyon.apps.esign.po.TemplateInfo; +import com.seeyon.apps.esign.utils.FileUtil; +import com.seeyon.apps.esign.utils.HttpClient; +import com.seeyon.apps.ext.workflow.vo.FormDataVo; +import com.seeyon.ctp.common.exceptions.BusinessException; +import org.apache.commons.logging.Log; +import org.apache.commons.logging.LogFactory; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.stereotype.Component; + + +import java.io.File; +import java.util.ArrayList; +import java.util.HashMap; +import java.util.List; +import java.util.Map; +import java.util.Set; + +@Component +public class EsignFileTemplateService { + + private static final String ORI_TEMPLATE = "原始合同模板文件"; + private static final Log log = LogFactory.getLog(EsignFileTemplateService.class); + @Autowired + private EsignConfigProvider configProvider; + @Autowired + private TokenCacheManager tokenCacheManager; + @Autowired + private EsignByUploadFileService uploadFileService; + private String orgId; + + private void fillOrgId() { + EsignApiHeader esignApiHeader = EsignApiHeader.build(); + try { + esignApiHeader.token(tokenCacheManager.getToken()).appId(configProvider.getBizConfigByKey(EsignConfigConstants.APP_ID)); + } catch (Exception e) { + e.printStackTrace(); + } + //获取orgId + String queryStr = EsignApiUrl.QUERY_ORGINFO + "?orgName=" + configProvider.getBizConfigByKey(EsignConfigConstants.UNITNAME); + String reqUrl = configProvider.getBizConfigByKey(EsignConfigConstants.ESIGN_HOST) + queryStr; + String orgInfoRespStr = HttpClient.httpGet(reqUrl, esignApiHeader.convert2Headers(), "UTF-8"); + EsignBaseResp orgInfoResp = JsonUtils.parseObject(orgInfoRespStr, EsignBaseResp.class); + Map orgData = (Map) orgInfoResp.getData(); + orgId = (String) orgData.get("orgId"); + } + + //填充模板 + public SignFile fillTemplate(String templateId, String fileName, Map params) { + //请求示例 + Map reqParams = new HashMap<>(); + reqParams.put("docTemplateId",templateId); + reqParams.put("fileName",fileName); + List components = new ArrayList<>(); + Set keySets = params.keySet(); + for (String key : keySets) { + TemplateComponent component = new TemplateComponent(); + component.setComponentKey(key); + component.setComponentValue((String) params.get(key)); + components.add(component); + } + reqParams.put("components",components); + String url = ""; + String resp = HttpClient.httpPostRaw(url, JsonUtils.toJSONString(reqParams), null, null); + EsignBaseResp esignBaseResp = JsonUtils.parseObject(resp, EsignBaseResp.class); + if(esignBaseResp.getCode() != 0) {} + Map dataMap = (Map) esignBaseResp.getData(); + SignFile signFile = new SignFile(); + signFile.setFileId((String) dataMap.get("fileId")); + signFile.setFileName(fileName); + return signFile; + } + + //获取模板详细信息 + public Map getTemplateDetail(String signTemplateId,String orgId,Boolean queryComponents) { + String url = configProvider.getBizConfigByKey(EsignConfigConstants.ESIGN_HOST) + "?" + "signTemplateId=" + signTemplateId + "&orgId=" + orgId + (queryComponents != null ? "&queryComponents=" + queryComponents : ""); + String resp = HttpClient.httpGet(url, null, "UTF-8"); + EsignBaseResp esignBaseResp = JsonUtils.parseObject(resp, EsignBaseResp.class); + Map data = (Map) esignBaseResp.getData(); + return data; + } + + //获取模板详细信息 + public Map getTemplateDetail(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)); + String resp = HttpClient.httpGet(url, apiHeader.convert2Headers(), "UTF-8"); + EsignBaseResp esignBaseResp = JsonUtils.parseObject(resp, EsignBaseResp.class); + Map data = (Map) esignBaseResp.getData(); + return data; + } + + public Map queryTemplates(Integer pageNo) throws Exception { + EsignApiHeader esignApiHeader = EsignApiHeader.build().appId(configProvider.getBizConfigByKey(EsignConfigConstants.APP_ID)); + String queryStr = EsignApiUrl.QUERY_TEMPLATES_URL + "?" + "orgId=" + obtainOrgId() + "&pageNum=" + pageNo + "&pageSize=" + 20 + "&status=" + 1; + esignApiHeader.token(tokenCacheManager.getToken()); + String url = configProvider.getBizConfigByKey(EsignConfigConstants.ESIGN_HOST) + queryStr; + String templateListRespStr = HttpClient.httpGet(url, esignApiHeader.convert2Headers(), "UTF-8"); + EsignBaseResp templateListResp = JsonUtils.parseObject(templateListRespStr, EsignBaseResp.class); + Map listData = (Map)templateListResp.getData(); + Integer total = (Integer) listData.get("total"); + Object[] templateArray = (Object[]) listData.get("signTemplates"); + Map pageMap = new HashMap<>(); + pageMap.put("total",total); + pageMap.put("templateList",templateArray); + return pageMap; + } + + public String getCompareDetailUrl(String templateRefId,String contractRefId) throws Exception { + String templateFileId = uploadFileService.uploadFileToEsign(templateRefId); + String contractFileId = uploadFileService.uploadFileToEsign(contractRefId); + String url = configProvider.getBizConfigByKey(EsignConfigConstants.ESIGN_HOST) + EsignApiUrl.CONTRACT_COMPARE_GETURL; + Map params = new HashMap<>(); + params.put("standardFileId",templateFileId); + params.put("comparativeFileId",contractFileId); + String jsonString = JsonUtils.toJSONString(params); + EsignApiHeader esignApiHeader = EsignApiHeader.build().appId(configProvider.getBizConfigByKey(EsignConfigConstants.APP_ID)); + esignApiHeader.token(tokenCacheManager.getToken()); + String respStr = HttpClient.httpPostRaw(url, jsonString, esignApiHeader.convert2Headers(), null); + EsignBaseResp esignBaseResp = JsonUtils.parseObject(respStr, EsignBaseResp.class); + log.info("调用获取合同比对链接接口返回值: " + JsonUtils.toJSONString(esignBaseResp)); + Map data = (Map) esignBaseResp.getData(); + String contractCompareUrl = data.get("contractCompareUrl"); + return contractCompareUrl; + } + + private String obtainOrgId() { + if(orgId == null) { + fillOrgId(); + } + return orgId; + } +} diff --git a/esign/src/main/java/com/seeyon/apps/esign/service/SealService.java b/esign/src/main/java/com/seeyon/apps/esign/service/SealService.java new file mode 100644 index 0000000..a7d6eb7 --- /dev/null +++ b/esign/src/main/java/com/seeyon/apps/esign/service/SealService.java @@ -0,0 +1,75 @@ +package com.seeyon.apps.esign.service; + +import cn.hutool.json.JSONObject; +import com.cedarsoftware.util.io.JsonObject; +import com.seeyon.aicloud.common.JsonUtils; +import com.seeyon.apps.esign.config.EsignConfigProvider; +import com.seeyon.apps.esign.constants.EsignApiUrl; +import com.seeyon.apps.esign.constants.EsignConfigConstants; +import com.seeyon.apps.esign.po.EsignApiHeader; +import com.seeyon.apps.esign.po.EsignBaseResp; +import com.seeyon.apps.esign.utils.HttpClient; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.stereotype.Component; + +import java.util.ArrayList; +import java.util.LinkedList; +import java.util.List; +import java.util.Map; + +@Component +public class SealService { + + @Autowired + private EsignConfigProvider configProvider; + + public void grantSeal(Map params) throws Exception { + JsonObject reqParams = new JsonObject(); + String sealId = getSealId((String) params.get("orgId"), (String) params.get("sealName")); + reqParams.put("sealId",sealId); + List authorizedPsnIds = new ArrayList<>(); + authorizedPsnIds.add((String) params.get("accountId")); + reqParams.put("authorizedPsnIds",authorizedPsnIds); + reqParams.put("sealRole","SEAL_USER"); + reqParams.put("transactorPsnId",params.get("managerId")); + JSONObject sealAuthScope = new JSONObject(); + List templateIds = new ArrayList<>(); + templateIds.add("ALL"); + sealAuthScope.put("templateIds",templateIds); + reqParams.put("sealAuthScope",sealAuthScope); + EsignApiHeader esignApiHeader = EsignApiHeader.build(); + esignApiHeader.appId(configProvider.getBizConfigByKey(EsignConfigConstants.APP_ID)) + .httpMethod("POST") + .heads("") + .pathAndParameters(EsignApiUrl.SEAL_GRANT_URL) + .contentMD5(reqParams.toString()) + .signature(configProvider.getBizConfigByKey(EsignConfigConstants.APP_SECRET)); + String url = configProvider.getBizConfigByKey(EsignConfigConstants.ESIGN_HOST) + EsignApiUrl.SEAL_GRANT_URL; + HttpClient.httpPostRaw(url,reqParams.toString(),esignApiHeader.convert2Headers(),null); + } + + private String getSealId(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)) + .httpMethod("GET") + .heads("") + .pathAndParameters(EsignApiUrl.QUERY_SEAL_URL + "?" + HttpClient.sortQueryString("orgId=" + orgId + "&pageNo=" + pageNo + "&pageSize=" + pageSize)) + .contentMD5("") + .signature(configProvider.getBizConfigByKey(EsignConfigConstants.APP_SECRET)); + String url = host + EsignApiUrl.QUERY_SEAL_URL + "?orgId=" + orgId + "&pageNo=" + pageNo + "&pageSize=" + pageSize; + String respStr = HttpClient.httpGet(url, esignApiHeader.convert2Headers(), "UTF-8"); + EsignBaseResp esignBaseResp = JsonUtils.parseObject(respStr, EsignBaseResp.class); + Map data = (Map) esignBaseResp.getData(); + LinkedList seals = (LinkedList) data.get("seals"); + for (Object seal : seals) { + Map sealMap = (Map) seal; + if(sealMap.get("sealName").equals(sealName)){ + return (String) sealMap.get("sealId"); + } + } + return null; + } +} diff --git a/esign/src/main/java/com/seeyon/apps/esign/service/TokenCacheManager.java b/esign/src/main/java/com/seeyon/apps/esign/service/TokenCacheManager.java new file mode 100644 index 0000000..f3c91f2 --- /dev/null +++ b/esign/src/main/java/com/seeyon/apps/esign/service/TokenCacheManager.java @@ -0,0 +1,101 @@ +package com.seeyon.apps.esign.service; + +import com.seeyon.aicloud.common.JsonUtils; +import com.seeyon.apps.esign.config.EsignConfigProvider; +import com.seeyon.apps.esign.constants.EsignApiUrl; +import com.seeyon.apps.esign.constants.EsignConfigConstants; +import com.seeyon.apps.esign.po.EsignApiHeader; +import com.seeyon.apps.esign.po.EsignBaseResp; +import com.seeyon.apps.esign.po.EsignToken; +import com.seeyon.apps.esign.utils.HttpClient; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.stereotype.Component; + +import java.util.Map; +import java.util.concurrent.Executors; +import java.util.concurrent.ScheduledExecutorService; +import java.util.concurrent.TimeUnit; +import java.util.concurrent.atomic.AtomicReference; + +@Component +public class TokenCacheManager { + + @Autowired + private EsignConfigProvider configProvider; + private final AtomicReference tokenRef = new AtomicReference<>(); + 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) { + EsignApiHeader esignApiHeader = EsignApiHeader.build(); + try { + esignApiHeader.token(token).appId(configProvider.getBizConfigByKey(EsignConfigConstants.APP_ID)); + } catch (Exception e) { + e.printStackTrace(); + } + //获取orgId + String queryStr = EsignApiUrl.QUERY_ORGINFO + "?orgName=" + configProvider.getBizConfigByKey(EsignConfigConstants.UNITNAME); + 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) { + return true; + } + return false; + } + + public String getToken() { + EsignToken current = tokenRef.get(); + if (current != null && !checkExpired(current.getTokenStr())) { + return current.getTokenStr(); + } + return refreshToken(); + } + + private String refreshToken() { + EsignToken newToken = fetchNewToken(); + tokenRef.set(newToken); + return newToken.getTokenStr(); + } + + private void checkTokenExpiry() { + EsignToken current = tokenRef.get(); + if (current != null && isTokenExpired(current)) { + refreshToken(); + } + } + + private boolean isTokenExpired(EsignToken token) { + return System.currentTimeMillis() >= token.getTtl(); + } + + private EsignToken fetchNewToken() { + // 实际获取token的逻辑 + String queryStr = "?appId=" + configProvider.getBizConfigByKey(EsignConfigConstants.APP_ID) + "&secret=" + configProvider.getBizConfigByKey(EsignConfigConstants.APP_SECRET) + "&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) { + throw new RuntimeException("获取e签宝token失败"); + } + Map dataMap = (Map) esignBaseResp.getData(); + String token = (String) dataMap.get("token"); + Long ttl = Long.parseLong((String) dataMap.get("expiresIn")) ; + String refreshToken = (String) dataMap.get("refreshToken"); + EsignToken esignToken = new EsignToken(); + esignToken.setTokenStr(token); + esignToken.setTtl(ttl); + esignToken.setRefreshToken(refreshToken); + return esignToken; + } + + public void shutdown() { + scheduler.shutdown(); + } +} \ No newline at end of file diff --git a/esign/src/main/java/com/seeyon/apps/esign/utils/AttachmentUtils.java b/esign/src/main/java/com/seeyon/apps/esign/utils/AttachmentUtils.java new file mode 100644 index 0000000..b232623 --- /dev/null +++ b/esign/src/main/java/com/seeyon/apps/esign/utils/AttachmentUtils.java @@ -0,0 +1,26 @@ +package com.seeyon.apps.esign.utils; + +import com.seeyon.apps.esign.constants.EsignConfigConstants; +import com.seeyon.apps.esign.form.FormDataOperator; +import com.seeyon.apps.esign.form.FormUpdateField; +import com.seeyon.apps.esign.form.FormWhereCondition; + +import java.util.ArrayList; +import java.util.List; + +public class AttachmentUtils { + + public void fileFillBack(String url,String fileName,String loginName,String unitName,String tableName,String updateField,String formId,String formNo) throws Exception { + String refId = FileUtil.uploadContractToOA(url, fileName, formId, loginName, unitName); + if(formNo != null) { + + }else { + FormDataOperator formDataOperator = new FormDataOperator(); + List updateFields = new ArrayList<>(); + List conditions = new ArrayList<>(); + updateFields.add(FormUpdateField.build().fieldName(updateField).value(refId)); + conditions.add(FormWhereCondition.build().value(formId).fieldName("ID")); + formDataOperator.updateMasterForm(updateFields,tableName,conditions); + } + } +} diff --git a/esign/src/main/java/com/seeyon/apps/esign/utils/EnHancedMap.java b/esign/src/main/java/com/seeyon/apps/esign/utils/EnHancedMap.java new file mode 100644 index 0000000..d0cd7ef --- /dev/null +++ b/esign/src/main/java/com/seeyon/apps/esign/utils/EnHancedMap.java @@ -0,0 +1,17 @@ +package com.seeyon.apps.esign.utils; + +import java.util.Map; + +public class EnHancedMap { + + private Map map; + + public EnHancedMap of(String key, Object value) { + map.put(key, value); + return this; + } + + public Map getMap() { + return map; + } +} diff --git a/esign/src/main/java/com/seeyon/apps/esign/utils/EsignHttpCfgHelper.java b/esign/src/main/java/com/seeyon/apps/esign/utils/EsignHttpCfgHelper.java new file mode 100644 index 0000000..cdd5971 --- /dev/null +++ b/esign/src/main/java/com/seeyon/apps/esign/utils/EsignHttpCfgHelper.java @@ -0,0 +1,471 @@ +package com.seeyon.apps.esign.utils; +import com.seeyon.apps.esign.po.EsignException; +import com.seeyon.apps.esign.po.EsignHttpResponse; +import org.apache.http.*; +import org.apache.http.auth.AuthScope; +import org.apache.http.auth.UsernamePasswordCredentials; +import org.apache.http.client.ClientProtocolException; +import org.apache.http.client.CredentialsProvider; +import org.apache.http.client.HttpRequestRetryHandler; +import org.apache.http.client.config.RequestConfig; +import org.apache.http.client.entity.UrlEncodedFormEntity; +import org.apache.http.client.methods.CloseableHttpResponse; +import org.apache.http.client.methods.HttpRequestBase; +import org.apache.http.client.protocol.HttpClientContext; +import org.apache.http.config.Registry; +import org.apache.http.config.RegistryBuilder; +import org.apache.http.conn.ConnectTimeoutException; +import org.apache.http.conn.socket.ConnectionSocketFactory; +import org.apache.http.conn.socket.LayeredConnectionSocketFactory; +import org.apache.http.conn.socket.PlainConnectionSocketFactory; +import org.apache.http.conn.ssl.NoopHostnameVerifier; +import org.apache.http.conn.ssl.SSLConnectionSocketFactory; +import org.apache.http.entity.ByteArrayEntity; +import org.apache.http.entity.ContentType; +import org.apache.http.entity.StringEntity; +import org.apache.http.impl.client.BasicCredentialsProvider; +import org.apache.http.impl.client.CloseableHttpClient; +import org.apache.http.impl.client.HttpClientBuilder; +import org.apache.http.impl.conn.PoolingHttpClientConnectionManager; +import org.apache.http.protocol.HttpContext; +import org.apache.http.util.EntityUtils; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + +import javax.net.ssl.*; +import java.io.IOException; +import java.io.InterruptedIOException; +import java.net.UnknownHostException; +import java.security.cert.CertificateException; +import java.security.cert.X509Certificate; +import java.text.MessageFormat; +import java.util.Arrays; +import java.util.List; +import java.util.Map; + +/** + * @description Http请求 辅助类 + * @author 澄泓 + * @since JDK1.7 + */ +public class EsignHttpCfgHelper { + + private static Logger LOGGER = LoggerFactory.getLogger(EsignHttpCfgHelper.class); + /** + * 超时时间,默认15000毫秒 + */ + private static int MAX_TIMEOUT = 15000; + /** + * 请求池最大连接数,默认100个 + */ + private static int MAX_TOTAL=100; + /** + * 单域名最大的连接数,默认50个 + */ + private static int ROUTE_MAX_TOTAL=50; + /** + * 请求失败重试次数,默认3次 + */ + private static int MAX_RETRY = 3; + /** + * 是否需要域名校验,默认不需要校验 + */ + private static boolean SSL_VERIFY=false; + + /** + * 正向代理IP + */ + private static String PROXY_IP; + /** + * 正向代理端口,默认8888 + */ + private static int PROXY_PORT=8888; + /** + * 代理协议,默认http + */ + private static String PROXY_AGREEMENT="http"; + + /** + * 是否开启代理,默认false + */ + private static boolean OPEN_PROXY=false; + + /** + * 代理服务器用户名 + */ + private static String PROXY_USERNAME=""; + + /** + * 代理服务器密码 + */ + private static String PROXY_PASSWORD=""; + + + private static PoolingHttpClientConnectionManager connMgr; //连接池 + private static HttpRequestRetryHandler retryHandler; //重试机制 + + private static CloseableHttpClient httpClient=null; + + public static int getMaxTimeout() { + return MAX_TIMEOUT; + } + + public static void setMaxTimeout(int maxTimeout) { + MAX_TIMEOUT = maxTimeout; + } + + public static int getMaxTotal() { + return MAX_TOTAL; + } + + public static void setMaxTotal(int maxTotal) { + MAX_TOTAL = maxTotal; + } + + public static int getRouteMaxTotal() { + return ROUTE_MAX_TOTAL; + } + + public static void setRouteMaxTotal(int routeMaxTotal) { + ROUTE_MAX_TOTAL = routeMaxTotal; + } + + public static int getMaxRetry() { + return MAX_RETRY; + } + + public static void setMaxRetry(int maxRetry) { + MAX_RETRY = maxRetry; + } + + public static boolean isSslVerify() { + return SSL_VERIFY; + } + + public static void setSslVerify(boolean sslVerify) { + SSL_VERIFY = sslVerify; + } + + public static String getProxyIp() { + return PROXY_IP; + } + + public static void setProxyIp(String proxyIp) { + PROXY_IP = proxyIp; + } + + public static int getProxyPort() { + return PROXY_PORT; + } + + public static void setProxyPort(int proxyPort) { + PROXY_PORT = proxyPort; + } + + public static String getProxyAgreement() { + return PROXY_AGREEMENT; + } + + public static void setProxyAgreement(String proxyAgreement) { + PROXY_AGREEMENT = proxyAgreement; + } + + public static boolean getOpenProxy() { + return OPEN_PROXY; + } + + public static void setOpenProxy(boolean openProxy) { + OPEN_PROXY = openProxy; + } + + public static String getProxyUsername() { + return PROXY_USERNAME; + } + + public static void setProxyUserame(String proxyUsername) { + PROXY_USERNAME = proxyUsername; + } + + public static String getProxyPassword() { + return PROXY_PASSWORD; + } + + public static void setProxyPassword(String proxyPassword) { + PROXY_PASSWORD = proxyPassword; + } + + + + + /** + * 不允许外部创建实例 + */ + private EsignHttpCfgHelper() { + } + + //------------------------------公有方法start-------------------------------------------- + + + /** + * @description 发起HTTP / HTTPS 请求 + * + * @param reqType + * {@link EsignRequestType} 请求类型 GET、 POST 、 DELETE 、 PUT + * @param httpUrl + * {@link String} 请求目标地址 + * @param headers + * {@link Map} 请求头 + * @param param + * {@link Object} 参数 + * @return + * @throws EsignException + * @author 澄泓 + */ + public static EsignHttpResponse sendHttp(EsignRequestType reqType, String httpUrl, Map headers, Object param, boolean debug) + throws EsignException { + HttpRequestBase reqBase=null; + if(httpUrl.startsWith("http")){ + reqBase=reqType.getHttpType(httpUrl); + }else{ + throw new EsignException("请求url地址格式错误"); + } + if(debug){ + LOGGER.info("请求头:{}",headers+"\n"); + LOGGER.info("请求参数\n{}", param+"\n"); + LOGGER.info("请求地址\n:{}\n请求方式\n:{}",reqBase.getURI(),reqType+"\n"); + } + //请求方法不是GET或者DELETE时传入body体,否则不传入。 + String[] methods = {"DELETE", "GET"}; + if(param instanceof String&&Arrays.binarySearch(methods, reqType.name())<0){//POST或者PUT请求 + ((HttpEntityEnclosingRequest) reqBase).setEntity( + new StringEntity(String.valueOf(param), ContentType.create("application/json", "UTF-8"))); + } + //参数时字节流数组 + else if(param instanceof byte[]) { + reqBase=reqType.getHttpType(httpUrl); + byte[] paramBytes = (byte[])param; + ((HttpEntityEnclosingRequest) reqBase).setEntity(new ByteArrayEntity(paramBytes)); + } + //参数是form表单时 + else if(param instanceof List){ + ((HttpEntityEnclosingRequest) reqBase).setEntity(new UrlEncodedFormEntity((Iterable) param)); + } + httpClient = getHttpClient(); + config(reqBase); + + //设置请求头 + if(headers != null &&headers.size()>0) { + for(Map.Entry entry :headers.entrySet()) { + reqBase.setHeader(entry.getKey(), entry.getValue()); + } + } + //响应对象 + CloseableHttpResponse res = null; + //响应内容 + String resCtx = null; + int status; + EsignHttpResponse esignHttpResponse = new EsignHttpResponse(); + try { + //执行请求 + res = httpClient.execute(reqBase); + status=res.getStatusLine().getStatusCode(); + + //获取请求响应对象和响应entity + HttpEntity httpEntity = res.getEntity(); + if(httpEntity != null) { + resCtx = EntityUtils.toString(httpEntity,"utf-8"); + } + if(debug) { + LOGGER.info("响应\n{}", resCtx + "\n"); + LOGGER.info("----------------------------end------------------------"); + } + } catch (NoHttpResponseException e) { + throw new EsignException("服务器丢失了",e); + } catch (SSLHandshakeException e){ + String msg = MessageFormat.format("SSL握手异常", e); + EsignException ex = new EsignException(msg, e); + throw ex; + } catch (UnknownHostException e){ + EsignException ex = new EsignException("服务器找不到", e); + ex.initCause(e); + throw ex; + } catch(ConnectTimeoutException e){ + EsignException ex = new EsignException("连接超时", e); + ex.initCause(e); + throw ex; + } catch(SSLException e){ + EsignException ex = new EsignException("SSL异常",e); + ex.initCause(e); + throw ex; + } catch (ClientProtocolException e) { + EsignException ex = new EsignException("请求头异常",e); + ex.initCause(e); + throw ex; + } catch (IOException e) { + EsignException ex = new EsignException("网络请求失败",e); + ex.initCause(e); + throw ex; + } finally { + if(res != null) { + try { + res.close(); + } catch (IOException e) { + EsignException ex = new EsignException("--->>关闭请求响应失败",e); + ex.initCause(e); + throw ex; + } + } + } + esignHttpResponse.setStatus(status); + esignHttpResponse.setBody(resCtx); + return esignHttpResponse; + } + //------------------------------公有方法end---------------------------------------------- + + //------------------------------私有方法start-------------------------------------------- + + /** + * @description 请求头和超时时间配置 + * + * @param httpReqBase + * @author 澄泓 + */ + private static void config(HttpRequestBase httpReqBase) { + // 配置请求的超时设置 + RequestConfig.Builder builder = RequestConfig.custom() + .setConnectionRequestTimeout(MAX_TIMEOUT) + .setConnectTimeout(MAX_TIMEOUT) + .setSocketTimeout(MAX_TIMEOUT); + if(OPEN_PROXY){ + HttpHost proxy=new HttpHost(PROXY_IP,PROXY_PORT,PROXY_AGREEMENT); + builder.setProxy(proxy); + } + RequestConfig requestConfig = builder.build(); + httpReqBase.setConfig(requestConfig); + } + + /** + * @description 连接池配置 + * + * @return + * @author 澄泓 + */ + private static void cfgPoolMgr() throws EsignException { + ConnectionSocketFactory plainsf = PlainConnectionSocketFactory.getSocketFactory(); + LayeredConnectionSocketFactory sslsf = SSLConnectionSocketFactory.getSocketFactory(); + if(!SSL_VERIFY){ + sslsf=sslConnectionSocketFactory(); + } + + Registry registry = RegistryBuilder.create() + .register("http", plainsf) + .register("https", sslsf) + .build(); + + //连接池管理器 + connMgr = new PoolingHttpClientConnectionManager(registry); + //请求池最大连接数 + connMgr.setMaxTotal(MAX_TOTAL); + //但域名最大的连接数 + connMgr.setDefaultMaxPerRoute(ROUTE_MAX_TOTAL); + } + + + + + /** + * @description 设置重试机制 + * + * @author 澄泓 + */ + private static void cfgRetryHandler() { + retryHandler = new HttpRequestRetryHandler() { + + @Override + public boolean retryRequest(IOException e, int excCount, HttpContext ctx) { + //超过最大重试次数,就放弃 + if(excCount > MAX_RETRY) { + return false; + } + //服务器丢掉了链接,就重试 + if(e instanceof NoHttpResponseException) { + return true; + } + //不重试SSL握手异常 + if(e instanceof SSLHandshakeException) { + return false; + } + //中断 + if(e instanceof InterruptedIOException) { + return false; + } + //目标服务器不可达 + if(e instanceof UnknownHostException) { + return false; + } + //连接超时 + //SSL异常 + if(e instanceof SSLException) { + return false; + } + + HttpClientContext clientCtx = HttpClientContext.adapt(ctx); + HttpRequest req = clientCtx.getRequest(); + //如果是幂等请求,就再次尝试 + if(!(req instanceof HttpEntityEnclosingRequest)) { + return true; + } + return false; + } + }; + } + + /** + * 忽略域名校验 + */ + private static SSLConnectionSocketFactory sslConnectionSocketFactory() throws EsignException { + try { + SSLContext ctx = SSLContext.getInstance("TLS"); // 创建一个上下文(此处指定的协议类型似乎不是重点) + X509TrustManager tm = new X509TrustManager() { // 创建一个跳过SSL证书的策略 + public X509Certificate[] getAcceptedIssuers() { + return null; + } + + public void checkClientTrusted(X509Certificate[] arg0, String arg1) throws CertificateException { + } + + public void checkServerTrusted(X509Certificate[] arg0, String arg1) throws CertificateException { + } + }; + ctx.init(null, new TrustManager[] { tm }, null); // 使用上面的策略初始化上下文 + return new SSLConnectionSocketFactory(ctx, new String[] { "SSLv3", "TLSv1", "TLSv1.1", "TLSv1.2" }, null, NoopHostnameVerifier.INSTANCE); + }catch (Exception e){ + EsignException ex = new EsignException("忽略域名校验失败",e); + ex.initCause(e); + throw ex; + } + + } + + /** + * @description 获取单例HttpClient + * + * @return + * @author 澄泓 + */ + private static synchronized CloseableHttpClient getHttpClient() throws EsignException { + if(httpClient==null) { + CredentialsProvider credsProvider = new BasicCredentialsProvider(); + credsProvider.setCredentials(new AuthScope(PROXY_IP,PROXY_PORT),new UsernamePasswordCredentials(PROXY_USERNAME, PROXY_PASSWORD)); + cfgPoolMgr(); + cfgRetryHandler(); + HttpClientBuilder httpClientBuilder = HttpClientBuilder.create(); + httpClient = httpClientBuilder.setDefaultCredentialsProvider(credsProvider).setConnectionManager(connMgr).setRetryHandler(retryHandler).build(); + } + return httpClient; + + } + //------------------------------私有方法end---------------------------------------------- + + +} diff --git a/esign/src/main/java/com/seeyon/apps/esign/utils/EsignHttpHelper.java b/esign/src/main/java/com/seeyon/apps/esign/utils/EsignHttpHelper.java new file mode 100644 index 0000000..1f9e103 --- /dev/null +++ b/esign/src/main/java/com/seeyon/apps/esign/utils/EsignHttpHelper.java @@ -0,0 +1,83 @@ +package com.seeyon.apps.esign.utils; + +import com.seeyon.apps.esign.po.EsignException; +import com.seeyon.apps.esign.po.EsignHttpResponse; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + +import java.util.HashMap; +import java.util.Map; + +/** + * @description Http 请求 辅助类 + * @author 澄泓 + * @since JDK1.7 + */ +public class EsignHttpHelper { + private static final Logger LOGGER = LoggerFactory.getLogger(EsignHttpHelper.class); + + /** + * 不允许外部创建实例 + */ + private EsignHttpHelper() { + + } + + /** + * @description 发送常规HTTP 请求 + * + * @param reqType 请求方式 + * @param url 请求路径 + * @param paramStr 请求参数 + * @return + * @throws EsignException + * @author 澄泓 + */ + public static EsignHttpResponse doCommHttp(String host, String url, EsignRequestType reqType, Object paramStr , Map httpHeader, boolean debug) throws EsignException { + return EsignHttpCfgHelper.sendHttp(reqType, host+url,httpHeader, paramStr, debug); + } + + + /** + * @description 发送文件流上传 HTTP 请求 + * + * @param reqType 请求方式 + * @param uploadUrl 请求路径 + * @param param 请求参数 + * @param fileContentMd5 文件fileContentMd5 + * @param contentType 文件MIME类型 + * @return + * @author 澄泓 + */ + public static EsignHttpResponse doUploadHttp( String uploadUrl,EsignRequestType reqType,byte[] param, String fileContentMd5, + String contentType, boolean debug) throws EsignException { + Map uploadHeader = buildUploadHeader(fileContentMd5, contentType); + if(debug){ + LOGGER.info("----------------------------start------------------------"); + LOGGER.info("fileContentMd5:{}",fileContentMd5); + LOGGER.info("contentType:{}",contentType); + } + return EsignHttpCfgHelper.sendHttp(reqType,uploadUrl, uploadHeader, param,debug); + } + + + + + /** + * @description 创建文件流上传 请求头 + * + * @param fileContentMd5 + * @param contentType + * @return + * @author 澄泓 + */ + public static Map buildUploadHeader(String fileContentMd5, String contentType) { + Map header = new HashMap<>(); + header.put("Content-MD5", fileContentMd5); + header.put("Content-Type", contentType); + + return header; + } + + // ------------------------------私有方法end---------------------------------------------- +} diff --git a/esign/src/main/java/com/seeyon/apps/esign/utils/EsignRequestType.java b/esign/src/main/java/com/seeyon/apps/esign/utils/EsignRequestType.java new file mode 100644 index 0000000..81de093 --- /dev/null +++ b/esign/src/main/java/com/seeyon/apps/esign/utils/EsignRequestType.java @@ -0,0 +1,38 @@ +package com.seeyon.apps.esign.utils; + +import org.apache.http.client.methods.HttpDelete; +import org.apache.http.client.methods.HttpGet; +import org.apache.http.client.methods.HttpPost; +import org.apache.http.client.methods.HttpPut; +import org.apache.http.client.methods.HttpRequestBase; + +public enum EsignRequestType { + + POST{ + @Override + public HttpRequestBase getHttpType(String url) { + return new HttpPost(url); + } + }, + GET{ + @Override + public HttpRequestBase getHttpType(String url) { + return new HttpGet(url); + } + }, + DELETE{ + @Override + public HttpRequestBase getHttpType(String url) { + return new HttpDelete(url); + } + }, + PUT{ + @Override + public HttpRequestBase getHttpType(String url) { + return new HttpPut(url); + } + }, + ; + + public abstract HttpRequestBase getHttpType(String url); +} diff --git a/esign/src/main/java/com/seeyon/apps/esign/utils/FileUtil.java b/esign/src/main/java/com/seeyon/apps/esign/utils/FileUtil.java new file mode 100644 index 0000000..5b87431 --- /dev/null +++ b/esign/src/main/java/com/seeyon/apps/esign/utils/FileUtil.java @@ -0,0 +1,530 @@ +package com.seeyon.apps.esign.utils; + +import com.alibaba.fastjson.JSONArray; +import com.alibaba.fastjson.JSONObject; +import com.seeyon.ctp.common.AppContext; +import com.seeyon.ctp.common.SystemEnvironment; +import com.seeyon.ctp.common.exceptions.BusinessException; +import com.seeyon.ctp.common.filemanager.manager.AttachmentManager; +import com.seeyon.ctp.common.filemanager.manager.FileManager; +import com.seeyon.ctp.common.po.filemanager.Attachment; +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.poi.hssf.usermodel.HSSFWorkbook; +import org.apache.poi.ss.usermodel.Cell; +import org.apache.poi.ss.usermodel.Row; +import org.apache.poi.ss.usermodel.Sheet; +import org.apache.poi.ss.usermodel.Workbook; +import org.apache.poi.xssf.usermodel.XSSFWorkbook; +import www.seeyon.com.utils.StringUtil; +import www.seeyon.com.utils.UUIDUtil; + +import java.io.BufferedOutputStream; +import java.io.File; +import java.io.FileInputStream; +import java.io.FileNotFoundException; +import java.io.FileOutputStream; +import java.io.IOException; +import java.io.InputStream; +import java.io.OutputStream; +import java.text.SimpleDateFormat; +import java.util.ArrayList; +import java.util.Date; +import java.util.HashMap; +import java.util.Iterator; +import java.util.List; +import java.util.Map; +import java.util.UUID; + +public class FileUtil { + + private static final long MAX_FILE_SIZE = 100 * 1024 * 1024; // 100MB + private static final String TEMP_DIR = System.getProperty("java.io.tmpdir") + File.separator + "seeyontempfile"; + private static final String DEFAULT_FILENAME_PREFIX = "没有文件名_"; + private static final String CATEGORY_CODE = "66"; + private FileManager fileManager; + + public void setFileManager(FileManager fileManager) { + this.fileManager = fileManager; + } + + public FileManager getFileManager() { + if (fileManager == null) { + fileManager = (FileManager) AppContext.getBean("fileManager"); + } + return fileManager; + } + + private AttachmentManager attachmentManager; + + public void setAttachmentManager(AttachmentManager attachmentManager) { + this.attachmentManager = attachmentManager; + } + + public AttachmentManager getAttachmentManager() { + if (attachmentManager == null) { + attachmentManager = (AttachmentManager) AppContext.getBean("attachmentManager"); + } + return attachmentManager; + } + + public void isFilePath(String filePath) { + File directory = new File(filePath); + if (!directory.exists()) { + directory.mkdirs(); + } + + } + + + /** + * 上传附件 + * + * @param fileNames + * @throws Exception + * @throws NumberFormatException + */ + public List fileUpload(List fileNames, String summaryId, Long memberId, Long accountId) throws NumberFormatException, Exception { + + SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss"); +// List> lists = dataDao.findAttachAll(id); + FileUploadExporter fileUpload = new FileUploadExporter(); + List attachments = new ArrayList(); + File f = null; + long l = UUIDUtil.getUUIDLong(); + for (int i = 0; i < fileNames.size(); i++) { + String fileName = fileNames.get(i); + if (StringUtils.isNotEmpty(fileName)) { + f = new File(fileName); + if (!f.exists()) { + return null; + } + if (f.length() > 102400000) { + return null; + } + } + String[] strs = new String[]{f.getAbsolutePath()}; + String s = fileUpload.processUpload(strs); + +// if(StringUtils.isNotEmpty(s)) { + Map map = new HashMap(); + String attachName = f.getName(); + String[] suffixNames = attachName.split("\\."); + map.put("type", "0"); + map.put("fileUrl", s); + map.put("mimeType", "application/" + suffixNames[suffixNames.length - 1].toLowerCase()); +// if(suffixNames[suffixNames.length-1].equals("docx")) { +// map.put("mimeType", "application/docx"); +// }else { +// map.put("mimeType", "image/png"); +// } + map.put("size", f.length() + ""); +// System.out.println(beanId); + + map.put("subReference", l + ""); + map.put("category", "66"); + map.put("createdate", sdf.format(new Date())); + map.put("filename", f.getName()); + map.put("reference", summaryId); + Attachment attachment = new Attachment(map); + + attachments.add(attachment); + } + +// } + String str = getAttachmentManager().create(attachments, memberId, accountId); +// attachmentManager.create(attachments); +// System.out.println(str); + return attachments; + } + + + public List fieldFileDownload(Long refId, String path) throws BusinessException { +// 判断路径是否存在 + File file = new File(path); + if (!file.exists()) { + file.mkdirs(); + } + List fileUrls = getAttachmentManager().getBySubReference(refId); + System.out.println(fileUrls.size()); + List filepaths = new ArrayList<>(); + for (Long fileUrl : fileUrls) { + Attachment attachment = getAttachmentManager().getAttachmentByFileURL(fileUrl); + InputStream inputStream = getFileManager().getFileInputStream(attachment.getFileUrl()); + String filepath = path + attachment.getFilename(); + try (OutputStream outputStream = new BufferedOutputStream(new FileOutputStream(filepath))) { + byte[] buffer = new byte[1024]; + int bytesRead; + while ((bytesRead = inputStream.read(buffer)) != -1) { + outputStream.write(buffer, 0, bytesRead); + } + outputStream.flush(); + } catch (FileNotFoundException e) { + e.printStackTrace(); + } catch (IOException e) { + e.printStackTrace(); + } + filepaths.add(filepath); + } + return filepaths; + } + + + public JSONArray getFileContent(String filePath) throws IOException { + JSONArray jsonArray = new JSONArray(); + String houzhui = filePath.substring(filePath.lastIndexOf(".") + 1); + // 创建文件输入流 + FileInputStream file = new FileInputStream(new File(filePath)); + // 创建工作簿对象 + Workbook workbook; + System.out.println("当前文件为"+houzhui+"后缀"); + if ("xlsx".equals(houzhui) || "XLSX".equals(houzhui)) { + workbook = new XSSFWorkbook(file); + } else { + workbook = new HSSFWorkbook(file); + } + // 获取第一个工作表 + Sheet sheet = workbook.getSheetAt(0); + // 迭代行 + Iterator rowIterator = sheet.iterator(); +// 根据行跳过设置 + row : while (rowIterator.hasNext()) { + Row row = rowIterator.next(); + if (row.getRowNum() < 2) { + continue; + } + int num = 0; + int bj = 0; + JSONObject jsonObject = new JSONObject(); + JSONArray SPS = new JSONArray(); + JSONObject SP = new JSONObject(); + boolean isddh = false; + + // 迭代单元格 + Iterator cellIterator = row.cellIterator(); + cell : while (cellIterator.hasNext()) { +// 获取单元格对象 + Cell cell = cellIterator.next(); +// 单元格索引为1的数据(订单号) + if (cell.getColumnIndex() == 1) { + String ddh = ""; + switch (cell.getCellType()) { + case STRING: + ddh = cell.getStringCellValue(); + break; + case NUMERIC: + ddh = cell.getNumericCellValue()+""; + break; + default: + ddh = ""; + } +// 如果当前订单号为空,则跳过当前行数据 +// 查询当前订单号是否已经存在 + for (int i = 0; i < jsonArray.size(); i++) { + JSONObject json = jsonArray.getJSONObject(i); + if (ddh.equals(json.getString("DDH"))) { +// 订单号已经存在 + bj = i; + isddh = true; + jsonObject = json; + SPS = jsonObject.getJSONArray("SPS"); + } else { + num++; + } + } + if (num == jsonArray.size()) { +// switch (cell.getCellType()) { +// case STRING: + jsonObject.put("DDH",ddh); +// break; +// case NUMERIC: +// jsonObject.put("DDH", cell.getNumericCellValue()); +// break; +// default: +// jsonObject.put("DDH", ""); +// } +//// jsonObject.put("DDH", cell.getStringCellValue()); + } + } + switch (cell.getColumnIndex()) { + case 3: + if (!isddh) { + switch (cell.getCellType()) { + case STRING: + jsonObject.put("GMFMC", cell.getStringCellValue()); + break; + case NUMERIC: + jsonObject.put("GMFMC", cell.getNumericCellValue()); + break; + default: + jsonObject.put("GMFMC", ""); + } + } + break; + case 4: + if (!isddh) { + switch (cell.getCellType()) { + case STRING: + jsonObject.put("GMFNSRSBH", cell.getStringCellValue()); + break; + case NUMERIC: + jsonObject.put("GMFNSRSBH", cell.getNumericCellValue()); + break; + default: + jsonObject.put("GMFNSRSBH", ""); + } + } + break; + case 5: + if (!isddh) { + switch (cell.getCellType()) { + case STRING: + jsonObject.put("GMFYX", cell.getStringCellValue()); + break; + case NUMERIC: + jsonObject.put("GMFYX", cell.getNumericCellValue()); + break; + default: + jsonObject.put("GMFYX", ""); + } + } + break; + case 6: + if (!isddh) { + switch (cell.getCellType()) { + case STRING: + jsonObject.put("GMFSJ", cell.getStringCellValue()); + break; + case NUMERIC: + jsonObject.put("GMFSJ", cell.getNumericCellValue()); + break; + default: + jsonObject.put("GMFSJ", ""); + } + } + break; + case 17: + if (!isddh) { + switch (cell.getCellType()) { + case STRING: + jsonObject.put("BZ", cell.getStringCellValue()); + break; + case NUMERIC: + jsonObject.put("BZ", cell.getNumericCellValue()); + break; + default: + jsonObject.put("BZ", ""); + } + } + break; + case 2: + switch (cell.getCellType()) { + case STRING: + SP.put("FXHXZ", cell.getStringCellValue()); + break; + case NUMERIC: + SP.put("FXHXZ", cell.getNumericCellValue()); + break; + default: + SP.put("FXHXZ", ""); + } + break; + case 7: + switch (cell.getCellType()) { + case STRING: + SP.put("XMMC", cell.getStringCellValue()); + break; + case NUMERIC: + SP.put("XMMC", cell.getNumericCellValue()); + break; + default: + SP.put("XMMC", ""); + } + break; + case 8: + switch (cell.getCellType()) { + case STRING: + SP.put("SPBM", cell.getStringCellValue()); + break; + case NUMERIC: + SP.put("SPBM", cell.getNumericCellValue()); + break; + default: + SP.put("SPBM", ""); + } + break; + case 9: + switch (cell.getCellType()) { + case STRING: + SP.put("GGXH", cell.getStringCellValue()); + break; + case NUMERIC: + SP.put("GGXH", cell.getNumericCellValue()); + break; + default: + SP.put("GGXH", ""); + } + break; + case 10: + switch (cell.getCellType()) { + case STRING: + SP.put("DW", cell.getStringCellValue()); + break; + case NUMERIC: + SP.put("DW", cell.getNumericCellValue()); + break; + default: + SP.put("DW", ""); + } + break; + case 11: + switch (cell.getCellType()) { + case STRING: + SP.put("NUM", cell.getStringCellValue()); + break; + case NUMERIC: + SP.put("NUM", cell.getNumericCellValue()); + break; + default: + SP.put("NUM", ""); + } + break; + case 12: + switch (cell.getCellType()) { + case STRING: + SP.put("SPDJ", cell.getStringCellValue()); + break; + case NUMERIC: + SP.put("SPDJ", cell.getNumericCellValue()); + break; + default: + SP.put("SPDJ", ""); + } + break; + case 13: + switch (cell.getCellType()) { + case STRING: + SP.put("JE", cell.getStringCellValue()); + break; + case NUMERIC: + SP.put("JE", cell.getNumericCellValue()); + break; + default: + SP.put("JE", ""); + } + break; + case 14: + switch (cell.getCellType()) { + case STRING: + SP.put("SL", cell.getStringCellValue()); + break; + case NUMERIC: + SP.put("SL", cell.getNumericCellValue()); + break; + default: + SP.put("SL", ""); + } + break; + case 15: + switch (cell.getCellType()) { + case STRING: + SP.put("ZKJE", cell.getStringCellValue()); + break; + case NUMERIC: + SP.put("ZKJE", cell.getNumericCellValue()); + break; + default: + SP.put("ZKJE", ""); + } + break; + case 16: + switch (cell.getCellType()) { + case STRING: + SP.put("YHZCBS", cell.getStringCellValue()); + break; + case NUMERIC: + SP.put("YHZCBS", cell.getNumericCellValue()); + break; + default: + SP.put("YHZCBS", ""); + } + break; + } + } + if(StringUtil.isEmpty(jsonObject.getString("DDH"))){ + continue row; + } + SPS.add(SP); + jsonObject.put("SPS", SPS); + if (num == jsonArray.size()) { + jsonArray.add(jsonObject); + } else { + jsonArray.set(bj, jsonObject); + } + } + // 关闭工作簿 + workbook.close(); + file.close(); + return jsonArray; + } + + public JSONArray getFileContent(long fileId) throws IOException { + System.out.println("获取参数附件ID"+fileId); +// 附件路径 + String path = SystemEnvironment.getApplicationFolder()+"/hxinvoiceFile/"+fileId+"/"; + System.out.println("文件下载路径"+path); + List fileUrls = getAttachmentManager().getBySubReference(fileId); + Attachment attachment = getAttachmentManager().getAttachmentByFileURL(fileUrls.get(0)); + String filePath = path+attachment.getFilename(); + JSONArray jsonArray = getFileContent(filePath); + return jsonArray; + } + + + public static String uploadContractToOA(String url,String fileName, String formId, String loginName, String updateAccountName) throws Exception { + + OrgManager orgManager = (OrgManager) AppContext.getBean("orgManager"); + V3xOrgMember member = orgManager.getMemberByLoginName(loginName); + V3xOrgAccount account = orgManager.getAccountByName(updateAccountName); + + File tempDir = new File(TEMP_DIR); + if (!tempDir.exists()) { + tempDir.mkdirs(); + } + String savePath = TEMP_DIR + File.separator + fileName; + HttpClient.httpDownloadFile(url, null,savePath,"ITF-8"); + SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss"); + + String refId = String.valueOf(Math.abs(UUID.randomUUID().getLeastSignificantBits())); + FileUploadExporter fileUpload = new FileUploadExporter(); + List attachments = new ArrayList<>(); + + File file = new File(savePath); + if (file.exists() && file.length() <= MAX_FILE_SIZE) { + String uploadedPath = fileUpload.processUpload(new String[]{file.getAbsolutePath()}); + Map attachMeta = new HashMap<>(); + attachMeta.put("type", "0"); + attachMeta.put("fileUrl", uploadedPath); + attachMeta.put("size", String.valueOf(file.length())); + attachMeta.put("subReference", refId); + attachMeta.put("category", CATEGORY_CODE); + attachMeta.put("createdate", sdf.format(new Date())); + attachMeta.put("filename", fileName); + attachMeta.put("reference", formId); + attachMeta.put("mimeType", "application/" + "pdf"); + attachments.add(new Attachment(attachMeta)); + } + if (attachments.isEmpty()) return null; + AttachmentManager attachmentManager = (AttachmentManager) AppContext.getBean("attachmentManager"); + attachmentManager.create(attachments, member.getId(), account.getId()); + file.delete(); + return refId; + } + + private static boolean isBlank(String str) { + return str == null || str.trim().isEmpty(); + } +} diff --git a/esign/src/main/java/com/seeyon/apps/esign/utils/HmacSHA256Util.java b/esign/src/main/java/com/seeyon/apps/esign/utils/HmacSHA256Util.java new file mode 100644 index 0000000..fb0b99e --- /dev/null +++ b/esign/src/main/java/com/seeyon/apps/esign/utils/HmacSHA256Util.java @@ -0,0 +1,27 @@ +package com.seeyon.apps.esign.utils; + +import javax.crypto.Mac; +import javax.crypto.spec.SecretKeySpec; +import java.nio.charset.StandardCharsets; +import java.security.InvalidKeyException; +import java.security.NoSuchAlgorithmException; +import java.util.Base64; + +public class HmacSHA256Util { + public static String encrypt(String data, String key) + throws NoSuchAlgorithmException, InvalidKeyException { + Mac sha256_HMAC = Mac.getInstance("HmacSHA256"); + SecretKeySpec secret_key = new SecretKeySpec( + key.getBytes(StandardCharsets.UTF_8), "HmacSHA256"); + sha256_HMAC.init(secret_key); + byte[] hash = sha256_HMAC.doFinal(data.getBytes(StandardCharsets.UTF_8)); + return Base64.getEncoder().encodeToString(hash); + } + + public static void main(String[] args) throws Exception { + String data = "Hello World"; + String key = "secret"; + String result = encrypt(data, key); + System.out.println("HmacSHA256加密结果: " + result); + } +} \ No newline at end of file diff --git a/esign/src/main/java/com/seeyon/apps/esign/utils/HttpClient.java b/esign/src/main/java/com/seeyon/apps/esign/utils/HttpClient.java new file mode 100644 index 0000000..a35fc5a --- /dev/null +++ b/esign/src/main/java/com/seeyon/apps/esign/utils/HttpClient.java @@ -0,0 +1,499 @@ +package com.seeyon.apps.esign.utils; + +import org.apache.http.HttpEntity; +import org.apache.http.HttpEntityEnclosingRequest; +import org.apache.http.HttpStatus; +import org.apache.http.NameValuePair; +import org.apache.http.client.entity.UrlEncodedFormEntity; +import org.apache.http.client.methods.CloseableHttpResponse; +import org.apache.http.client.methods.HttpDelete; +import org.apache.http.client.methods.HttpGet; +import org.apache.http.client.methods.HttpPost; +import org.apache.http.client.methods.HttpPut; +import org.apache.http.client.methods.HttpRequestBase; +import org.apache.http.entity.ByteArrayEntity; +import org.apache.http.entity.ContentType; +import org.apache.http.entity.StringEntity; +import org.apache.http.entity.mime.HttpMultipartMode; +import org.apache.http.entity.mime.MultipartEntityBuilder; +import org.apache.http.impl.client.CloseableHttpClient; +import org.apache.http.impl.client.HttpClientBuilder; +import org.apache.http.impl.client.HttpClients; +import org.apache.http.message.BasicNameValuePair; +import org.apache.http.util.EntityUtils; + +import java.io.File; +import java.io.FileOutputStream; +import java.io.IOException; +import java.io.InputStream; +import java.io.OutputStream; +import java.nio.charset.Charset; +import java.util.ArrayList; +import java.util.List; +import java.util.Map; +import java.util.Set; +import java.util.TreeMap; +import java.util.stream.Collectors; + +/** + * @ClassName: HttpClient + * @Description: HTTP请求工具类 + * @Author: GiikJc + * @Date: 2022/7/12 15:03 + */ + +/** + * 发送Get请求:HttpResponse httpGet(String url,Map headers,String encode) + *发送Post请求,同表单Post提交:HttpResponse httpPostForm(String url,Map params, Map headers,String encode) + *发送Post Raw请求:HttpResponse httpPostRaw(String url,String stringJson,Map headers, String encode) + *发送Put Raw请求:HttpResponse httpPutRaw(String url,String stringJson,Map headers, String encode) + *发送Delete请求:HttpResponse httpDelete(String url,Map headers,String encode) + */ +public class HttpClient { + + /** + * 发送 HTTP GET 请求下载文件 + * @param url 下载文件的 URL + * @param headers 请求头 + * @param savePath 文件保存的路径 + * @param encode 文件内容的编码 + * @return 下载成功返回 true,失败返回 false + */ + public static boolean httpDownloadFile(String url, Map headers, String savePath, String encode) { + if (encode == null) { + encode = "utf-8"; // 默认字符编码 + } + + CloseableHttpClient httpClient = null; + CloseableHttpResponse httpResponse = null; + InputStream inputStream = null; + OutputStream outputStream = null; + + try { + // 创建 HttpClient 实例 + httpClient = HttpClients.createDefault(); + HttpGet httpGet = new HttpGet(url); + + // 设置请求头 + if (headers != null && headers.size() > 0) { + for (Map.Entry entry : headers.entrySet()) { + httpGet.setHeader(entry.getKey(), entry.getValue()); + } + } + + // 执行请求 + httpResponse = httpClient.execute(httpGet); + HttpEntity entity = httpResponse.getEntity(); + + // 检查响应状态码 + if (httpResponse.getStatusLine().getStatusCode() == 200) { + inputStream = entity.getContent(); + + // 创建输出流,将文件保存到本地 + outputStream = new FileOutputStream(savePath); + + // 设置缓冲区 + byte[] buffer = new byte[4096]; + int bytesRead; + while ((bytesRead = inputStream.read(buffer)) != -1) { + outputStream.write(buffer, 0, bytesRead); + } + + // 文件下载成功 + return true; + } else { + System.out.println("Download failed, HTTP error code: " + httpResponse.getStatusLine().getStatusCode()); + return false; + } + } catch (Exception e) { + e.printStackTrace(); + return false; + } finally { + try { + if (inputStream != null) { + inputStream.close(); + } + if (outputStream != null) { + outputStream.close(); + } + if (httpResponse != null) { + httpResponse.close(); + } + if (httpClient != null) { + httpClient.close(); + } + } catch (IOException e) { + e.printStackTrace(); + } + } + } + + /** + * 对queryString参数按key进行字典序升序排序 + * @param queryString 原始参数字符串,如"b=2&a=1&c=3" + * @return 排序后的字符串,如"a=1&b=2&c=3" + */ + public static String sortQueryString(String queryString) { + if (queryString == null || queryString.isEmpty()) { + return queryString; + } + + String[] pairs = queryString.split("&"); + Map params = new TreeMap<>(); + + for (String pair : pairs) { + String[] kv = pair.split("="); + if (kv.length == 2) { + params.put(kv[0], kv[1]); + } else if (kv.length == 1) { + params.put(kv[0], ""); + } + } + + return params.entrySet().stream() + .map(entry -> entry.getKey() + "=" + entry.getValue()) + .collect(Collectors.joining("&")); + } + /** + * 发送http get请求 + */ + public static String httpGet(String url,Map headers,String encode){ + + if(encode == null){ + encode = "utf-8"; + } + CloseableHttpResponse httpResponse = null; + CloseableHttpClient closeableHttpClient = null; + String content = null; + //since 4.3 不再使用 DefaultHttpClient + try { + closeableHttpClient = HttpClientBuilder.create().build(); + HttpGet httpGet = new HttpGet(url); + //设置header + if (headers != null && headers.size() > 0) { + for (Map.Entry entry : headers.entrySet()) { + httpGet.setHeader(entry.getKey(),entry.getValue()); + } + } + + httpResponse = closeableHttpClient.execute(httpGet); + HttpEntity entity = httpResponse.getEntity(); + content = EntityUtils.toString(entity, encode); + } catch (Exception e) { + e.printStackTrace(); + }finally{ + try { + httpResponse.close(); + } catch (IOException e) { + e.printStackTrace(); + } + } + try { //关闭连接、释放资源 + closeableHttpClient.close(); + } catch (IOException e) { + e.printStackTrace(); + } + return content; + } + /** + * 发送 http post 请求,参数以form表单键值对的形式提交。 + */ + public static String httpPostForm(String url,Map params, Map headers,String encode){ + + if(encode == null){ + encode = "utf-8"; + } + + String content = null; + CloseableHttpResponse httpResponse = null; + CloseableHttpClient closeableHttpClient = null; + try { + + closeableHttpClient = HttpClients.createDefault(); + HttpPost httpost = new HttpPost(url); + + //设置header + if (headers != null && headers.size() > 0) { + for (Map.Entry entry : headers.entrySet()) { + httpost.setHeader(entry.getKey(),entry.getValue()); + } + } + //组织请求参数 + List paramList = new ArrayList (); + if(params != null && params.size() > 0){ + Set keySet = params.keySet(); + for(String key : keySet) { + paramList.add(new BasicNameValuePair(key, params.get(key))); + } + } + httpost.setEntity(new UrlEncodedFormEntity(paramList, encode)); + + + httpResponse = closeableHttpClient.execute(httpost); + HttpEntity entity = httpResponse.getEntity(); + content = EntityUtils.toString(entity, encode); + } catch (Exception e) { + e.printStackTrace(); + }finally{ + try { + httpResponse.close(); + } catch (IOException e) { + e.printStackTrace(); + } + } + try { //关闭连接、释放资源 + closeableHttpClient.close(); + } catch (IOException e) { + e.printStackTrace(); + } + return content; + } + + /** + * 发送 http post 请求,参数以原生字符串进行提交 + * @param url + * @param encode + * @return + */ + public static String httpPostRaw(String url,String stringJson,Map headers, String encode){ + if(encode == null){ + encode = "utf-8"; + } + String content = null; + CloseableHttpResponse httpResponse = null; + CloseableHttpClient closeableHttpClient = null; + try { + + //HttpClients.createDefault()等价于 HttpClientBuilder.create().build(); + closeableHttpClient = HttpClients.createDefault(); + HttpPost httpost = new HttpPost(url); + + //设置header + httpost.setHeader("Content-type", "application/json"); + if (headers != null && headers.size() > 0) { + for (Map.Entry entry : headers.entrySet()) { + httpost.setHeader(entry.getKey(),entry.getValue()); + } + } + //组织请求参数 + StringEntity stringEntity = new StringEntity(stringJson, encode); + httpost.setEntity(stringEntity); + + + //响应信息 + httpResponse = closeableHttpClient.execute(httpost); + HttpEntity entity = httpResponse.getEntity(); + content = EntityUtils.toString(entity, encode); + } catch (Exception e) { + e.printStackTrace(); + }finally{ + try { + httpResponse.close(); + } catch (IOException e) { + e.printStackTrace(); + } + } + try { //关闭连接、释放资源 + closeableHttpClient.close(); + } catch (IOException e) { + e.printStackTrace(); + } + return content; + } + + /** + * 发送 http put 请求,参数以原生字符串进行提交 + * @param url + * @param encode + * @return + */ + public static String httpPutRaw(String url,String stringJson,Map headers, String encode){ + if(encode == null){ + encode = "utf-8"; + } + CloseableHttpResponse httpResponse = null; + CloseableHttpClient closeableHttpClient = null; + String content = null; + //since 4.3 不再使用 DefaultHttpClient + try { + + //HttpClients.createDefault()等价于 HttpClientBuilder.create().build(); + closeableHttpClient = HttpClients.createDefault(); + HttpPut httpput = new HttpPut(url); + + //设置header + httpput.setHeader("Content-type", "application/json"); + if (headers != null && headers.size() > 0) { + for (Map.Entry entry : headers.entrySet()) { + httpput.setHeader(entry.getKey(),entry.getValue()); + } + } + //组织请求参数 + StringEntity stringEntity = new StringEntity(stringJson, encode); + httpput.setEntity(stringEntity); + //响应信息 + httpResponse = closeableHttpClient.execute(httpput); + HttpEntity entity = httpResponse.getEntity(); + content = EntityUtils.toString(entity, encode); + } catch (Exception e) { + e.printStackTrace(); + }finally{ + try { + httpResponse.close(); + } catch (IOException e) { + e.printStackTrace(); + } + } + try { + closeableHttpClient.close(); //关闭连接、释放资源 + } catch (IOException e) { + e.printStackTrace(); + } + return content; + } + /** + * 发送http delete请求 + */ + public static String httpDelete(String url,Map headers,String encode){ + if(encode == null){ + encode = "utf-8"; + } + String content = null; + CloseableHttpResponse httpResponse = null; + CloseableHttpClient closeableHttpClient = null; + try { + //since 4.3 不再使用 DefaultHttpClient + closeableHttpClient = HttpClientBuilder.create().build(); + HttpDelete httpdelete = new HttpDelete(url); + //设置header + if (headers != null && headers.size() > 0) { + for (Map.Entry entry : headers.entrySet()) { + httpdelete.setHeader(entry.getKey(),entry.getValue()); + } + } + + httpResponse = closeableHttpClient.execute(httpdelete); + HttpEntity entity = httpResponse.getEntity(); + content = EntityUtils.toString(entity, encode); + } catch (Exception e) { + e.printStackTrace(); + }finally{ + try { + httpResponse.close(); + } catch (IOException e) { + e.printStackTrace(); + } + } + try { //关闭连接、释放资源 + closeableHttpClient.close(); + } catch (IOException e) { + e.printStackTrace(); + } + return content; + } + + /** + * 发送 http post 请求,支持文件上传 + */ + public static String httpPostFormMultipart(String url,Map params, List files,Map headers,String encode){ + if(encode == null){ + encode = "utf-8"; + } + CloseableHttpResponse httpResponse = null; + CloseableHttpClient closeableHttpClient = null; + String content = null; + //since 4.3 不再使用 DefaultHttpClient + try { + + closeableHttpClient = HttpClients.createDefault(); + HttpPost httpost = new HttpPost(url); + + //设置header + if (headers != null && headers.size() > 0) { + for (Map.Entry entry : headers.entrySet()) { + httpost.setHeader(entry.getKey(),entry.getValue()); + } + } + MultipartEntityBuilder mEntityBuilder = MultipartEntityBuilder.create(); + mEntityBuilder.setMode(HttpMultipartMode.BROWSER_COMPATIBLE); + mEntityBuilder.setCharset(Charset.forName(encode)); + + // 普通参数 + ContentType contentType = ContentType.create("text/plain",Charset.forName(encode));//解决中文乱码 + if (params != null && params.size() > 0) { + Set keySet = params.keySet(); + for (String key : keySet) { + mEntityBuilder.addTextBody(key, params.get(key),contentType); + } + } + //二进制参数 + if (files != null && files.size() > 0) { + for (File file : files) { + mEntityBuilder.addBinaryBody("file", file); + } + } + httpost.setEntity(mEntityBuilder.build()); + httpResponse = closeableHttpClient.execute(httpost); + HttpEntity entity = httpResponse.getEntity(); + content = EntityUtils.toString(entity, encode); + } catch (Exception e) { + e.printStackTrace(); + }finally{ + try { + httpResponse.close(); + } catch (IOException e) { + e.printStackTrace(); + } + } + try { //关闭连接、释放资源 + closeableHttpClient.close(); + } catch (IOException e) { + e.printStackTrace(); + } + return content; + } + + + public static String uploadBinaryFile(String url, Map headers, + InputStream io, String fileName) throws IOException { + + CloseableHttpClient client = HttpClients.createDefault(); + HttpPut put = new HttpPut(url); + String responseBody = null; + + try { + // 设置请求头 + for (String key : headers.keySet()) { + put.addHeader(key, headers.get(key)); + } + + // 构建多部分实体 + MultipartEntityBuilder builder = MultipartEntityBuilder.create() + .setMode(HttpMultipartMode.BROWSER_COMPATIBLE) + .setCharset(Charset.forName("UTF-8")); + builder.addBinaryBody("file", io, ContentType.MULTIPART_FORM_DATA, fileName); + + put.setEntity(builder.build()); + + // 执行请求 + CloseableHttpResponse response = null; + try { + response = client.execute(put); + HttpEntity resEntity = response.getEntity(); + responseBody = EntityUtils.toString(resEntity, "UTF-8"); + + // 无论状态码如何,都返回响应体 + return responseBody; + + } finally { + if(response != null) { + response.close(); + } + } + } finally { + client.close(); + io.close(); + } + } + +} \ No newline at end of file diff --git a/esign/src/main/java/com/seeyon/apps/esign/utils/JsonCleaner.java b/esign/src/main/java/com/seeyon/apps/esign/utils/JsonCleaner.java new file mode 100644 index 0000000..4c3d09c --- /dev/null +++ b/esign/src/main/java/com/seeyon/apps/esign/utils/JsonCleaner.java @@ -0,0 +1,28 @@ +package com.seeyon.apps.esign.utils; + +import com.fasterxml.jackson.databind.JsonNode; +import com.fasterxml.jackson.databind.ObjectMapper; +import com.fasterxml.jackson.databind.node.ObjectNode; + +import java.util.Iterator; +import java.util.Map; + +public class JsonCleaner { + + public static String removeEmptyObjects(String jsonStr) throws Exception { + ObjectMapper mapper = new ObjectMapper(); + ObjectNode node = (ObjectNode) mapper.readTree(jsonStr); + + Iterator> fields = node.fields(); + while (fields.hasNext()) { + Map.Entry entry = fields.next(); + if (entry.getValue().isObject() && entry.getValue().isEmpty()) { + fields.remove(); + } + } + + return mapper.writeValueAsString(node); + } + + +} \ No newline at end of file diff --git a/esign/src/main/java/com/seeyon/apps/esign/utils/ProtUtil.java b/esign/src/main/java/com/seeyon/apps/esign/utils/ProtUtil.java new file mode 100644 index 0000000..5773dcb --- /dev/null +++ b/esign/src/main/java/com/seeyon/apps/esign/utils/ProtUtil.java @@ -0,0 +1,89 @@ +package com.seeyon.apps.esign.utils; + +import com.alibaba.fastjson.JSONObject; +import com.seeyon.aicloud.common.JsonUtils; +import com.seeyon.apps.common.plugin.vo.ConfigVo; +import com.seeyon.apps.esign.config.EsignConfigProvider; +import com.seeyon.apps.esign.constants.EsignConfigConstants; +import org.apache.commons.httpclient.HttpStatus; +import org.apache.commons.logging.Log; +import org.apache.commons.logging.LogFactory; +import org.apache.http.HttpResponse; +import org.apache.http.client.methods.HttpGet; +import org.apache.http.impl.client.DefaultHttpClient; +import org.apache.http.message.BasicHeader; +import org.apache.http.util.EntityUtils; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.stereotype.Component; +import www.seeyon.com.utils.StringUtil; + +import java.io.FileNotFoundException; +import java.io.IOException; +import java.util.Map; + +@Component +public class ProtUtil { + + private static final Log log = LogFactory.getLog(ProtUtil.class); + @Autowired + private EsignConfigProvider configProvider; + + public String getPluginId() {return EsignConfigConstants.getPluginId();} + /** + * 获取一个token + * + * @return + * @throws IOException + * @throws FileNotFoundException + */ + private String getToken(String oatokenurl,String restName,String restPassword,String loginName) throws FileNotFoundException, IOException { + String address = oatokenurl + restName + "/" + restPassword; + if(StringUtil.isNotEmpty(loginName)){ + address = address +"?loginName="+loginName; + } + DefaultHttpClient client = new DefaultHttpClient(); + String result = ""; + HttpGet get = new HttpGet(address); + // 添加 Headers 信息 + get.addHeader(new BasicHeader("Accept", "application/json")); + try { + HttpResponse res = client.execute(get); + if (res.getStatusLine().getStatusCode() == HttpStatus.SC_OK) { + result = EntityUtils.toString(res.getEntity()); + } + } catch (Exception e) { + throw new RuntimeException(e); + } + String token = ""; + if(result.contains("{")) { + JSONObject jsObj = JSONObject.parseObject(result); + token = jsObj.get("id").toString(); + }else { + token = result; + } + return token; + } + + + /** + * 调用post接口 + * @return + */ + public String sendPostNotification(String params, String urlParam, String token) throws IOException { + String host = configProvider.getBizConfigByKey(EsignConfigConstants.OA_HOST); + String tokenGetUrl = configProvider.getBizConfigByKey(EsignConfigConstants.getTokenUrl); + String restName = configProvider.getBizConfigByKey(EsignConfigConstants.restName); + String restPwd = configProvider.getBizConfigByKey(EsignConfigConstants.restPwd); + String oatoken = getToken(host + tokenGetUrl,restName,restPwd,null); + String url = host + urlParam+ token+"?token="+oatoken; + log.info("调用恢复超级节点接口请求地址为: " + url); + String respStr = HttpClient.httpPostRaw(url, params, null, null); + log.info("调用恢复超级节点接口响应结果: " + respStr); + Map map = JsonUtils.parseObject(respStr, Map.class); + if(!"0".equals(map.get("code")) || map.get("code") == null) { + throw new RuntimeException("恢复阻塞的超级节点失败: " + map.get("message")); + } + return respStr; + } + +} diff --git a/esign/src/main/java/com/seeyon/ctp/rest/resources/EsignTemplateResource.java b/esign/src/main/java/com/seeyon/ctp/rest/resources/EsignTemplateResource.java new file mode 100644 index 0000000..95382e3 --- /dev/null +++ b/esign/src/main/java/com/seeyon/ctp/rest/resources/EsignTemplateResource.java @@ -0,0 +1,49 @@ +package com.seeyon.ctp.rest.resources; + +import cn.hutool.log.Log; +import com.seeyon.apps.esign.service.EsignFileTemplateService; +import com.seeyon.ctp.common.AppContext; + +import javax.ws.rs.Consumes; +import javax.ws.rs.GET; +import javax.ws.rs.POST; +import javax.ws.rs.Path; +import javax.ws.rs.Produces; +import javax.ws.rs.QueryParam; +import javax.ws.rs.core.Response; +import java.util.Map; + +@Path("cap4/etemplate") +public class EsignTemplateResource extends BaseResource { + + private static final Log log = Log.get(EsignTemplateResource.class); + private EsignFileTemplateService esignFileTemplateService = (EsignFileTemplateService) AppContext.getBean("esignFileTemplateService"); + + @GET + @Produces({"application/json"}) + @Consumes({"application/json"}) + @Path("/querypage") + public Response queryTemplates(@QueryParam("pageNum") Integer pageNum) { + try { + Map map = esignFileTemplateService.queryTemplates(pageNum); + return success(map); + }catch (Exception e) { + log.error(e.getMessage(),e); + } + return fail("失败"); + } + + @POST + @Produces({"application/json"}) + @Consumes({"application/json"}) + @Path("/compareurl") + public Response compare(@QueryParam("templateRefId") String templateRefId,@QueryParam("contractRefId") String contractRefId) { + try { + String compareDetailUrl = esignFileTemplateService.getCompareDetailUrl(templateRefId, contractRefId); + return success(compareDetailUrl); + }catch (Exception e) { + log.error(e.getMessage(),e); + } + return fail("失败"); + } +} diff --git a/esign/src/main/resources/needless_check_login.xml b/esign/src/main/resources/needless_check_login.xml new file mode 100644 index 0000000..f52b410 --- /dev/null +++ b/esign/src/main/resources/needless_check_login.xml @@ -0,0 +1,328 @@ + + + + /esigncallback.do + + callback + + + + /qrCodeForm.do + + index + newMain + + + + /sc.do + + qr + + + + /elearning.do + + error + m3Redirect + message + pcRedirect + + + + /phoneLogin/phoneLogin.do + + getMessageCode + validateMessageCode + + + + /wechat/miniprogram.do + + a8home + bind + bindMemberPhone + login + unbind + + + + /portal/spaceController.do + + showThemSpace + + + + /identification.do + + getSessionId + + + + /fileUpload.do + + showRTE + + + + /fileDownload.do + + showRTE + + + + /form/formUpgrade.do + + toUpgrade + upgrade + viewUpgrade + + + + formtalkFormMapperController.do + + importFormtalkData + + + + /thirdpartyController.do + + access + index + logoutNotify + show + mailAuth + + + + /main.do + + changeLocale + hangup + headerjs + index + login + login4Ucpc + login4Ucpc3 + login4Vjoin + logout + logout4Session + logout4Vjoin + logout4ZX + main + login4QrCode + qrCodeHelp + updateLoginSeed + + + + /trustdo/A8/XRD.do + + getLoginAccount + getLoginAcctoken + webLogin + + + + /share.do + + index + + + + /genericController.do + + index + + + + /edoc/edocUpgradeControllor.do + + upgrade + download + + + + /uploadService.do + + processUploadService + + + + /autoinstall.do + + ieSetDown + regInstallDown + regInstallDown64 + downloadAssistant + + + + /personalBind.do + + getBindTypeByLoginName + isCanUse + retrievePassword + sendVerificationCodeToBindEmail + sendVerificationCodeToBindNum + validateVerificationCode + + + + + + + + + + + /commonimage.do + + showImage + + + + /individualManager.do + + resetPassword + + + + /wechat/dingding.do + + binding + index + main + newIndex + newMain + viewh5Message + + + + /uc/rest.do + + commonPierce + downloadImage + getBgTimeStamp + getLoginsecurityMsg + sendsms + smsrequired + testIp + isQrLogin + getDigitalCodeInfo + + + + portalManager + + sendSMSLoginCode + smsLoginEnabled + + + + loginUserManager + + getLockTime + + + + qrCodeLoginManager + + isLogin + + + + meetingAjaxManager + + meetingPanelData + meetingPanelDisplay + + + + /m3/loginController.do + + transLogin + transLogout + getProfile + + + + /m3/mClientBindController.do + + bindApply + + + + m3ProductManager + + productInfo + productStatus + + + + /m3/homeSkinController.do + + downloadImage + getSkinImageUrl + + + + /m3/transModeController.do + + getTransModeForMobile + + + + /media/media.do + + mediaShow + + + + /ocipEdoc.do + + index + + + + /colView.do + + index + + + + /caAccountManagerController.do + + findKeyNumByLoginName + + + + /fddCallbackController.do + + asynch + synch + + + + /seeyonReport/seeyonReportController.do + + redirectSeeyonReport + + + + /imc.do + + index + logout + + + + + /cloudbuild.do + + download + getDownloadPageInfo + getLatestVersionInfo + getDownloadQrUrl + + + \ No newline at end of file diff --git a/esign/src/main/resources/needless_check_login_recheck.xml b/esign/src/main/resources/needless_check_login_recheck.xml new file mode 100644 index 0000000..2f8dd25 --- /dev/null +++ b/esign/src/main/resources/needless_check_login_recheck.xml @@ -0,0 +1,433 @@ + + + + + + /esigncallback.do + com.seeyon.apps.esign.controller.EsignCallBackController + + callback + + + + /qrCodeForm.do + com.seeyon.apps.qrCodeForm.controller.QrCodeFormController + + index + newMain + + + + + /sc.do + com.seeyon.cap4.form.modules.smartCode.controller.SmartCodeController + + qr + + + + /media/media.do + com.seeyon.ctp.common.media.controller.MediaController + + mediaShow + + + + /phoneLogin/phoneLogin.do + com.seeyon.ctp.login.controller.PhoneLoginController + + getMessageCode + validateMessageCode + + + + portalManager + com.seeyon.ctp.portal.manager.PortalManagerImpl + + sendSMSLoginCode + smsLoginEnabled + + + + /fileDownload.do + com.seeyon.ctp.common.fileupload.FileUploadController + + showRTE + + + + loginUserManager + com.seeyon.ctp.login.LoginUserManagerImpl + + getLockTime + + + + /main.do + com.seeyon.ctp.login.controller.MainController + + changeLocale + hangup + headerjs + index + login + login4Ucpc + login4Ucpc3 + login4Vjoin + logout + logout4Session + logout4Vjoin + logout4ZX + main + login4QrCode + qrCodeHelp + updateLoginSeed + + + + /trustdo/A8/XRD.do + com.seeyon.apps.trustdo.controller.XRDController + + getLoginAccount + getLoginAcctoken + webLogin + + + + /share.do + com.seeyon.v3x.system.share.controller.ShareController + + index + + + + /edoc/edocUpgradeControllor.do + com.seeyon.v3x.edoc.controller.EdocUpgradeControllor + + upgrade + download + + + + /m3/mClientBindController.do + com.seeyon.apps.m3.bind.controller.M3ClientBindController + + bindApply + + + + /uploadService.do + com.seeyon.ctp.services.FileUploadService + + processUploadService + + + + /uc/rest.do + com.seeyon.apps.zx.controller.ZxRestController + + commonPierce + downloadImage + getBgTimeStamp + getLoginsecurityMsg + sendsms + smsrequired + testIp + isQrLogin + getDigitalCodeInfo + + + + /m3/homeSkinController.do + com.seeyon.apps.m3.skin.controller.M3HomeSkinController + + downloadImage + getSkinImageUrl + + + + /colView.do + com.seeyon.apps.ocip.exchange.collaboration.controller.CollViewController + + index + + + + /autoinstall.do + com.seeyon.apps.autoinstall.controller.AutoInstallController + + ieSetDown + regInstallDown + regInstallDown64 + downloadAssistant + + + + + + + + + + + + /caAccountManagerController.do + com.seeyon.v3x.ca.caaccount.controller.CAAccountManagerController + + findKeyNumByLoginName + + + + /elearning.do + com.seeyon.apps.elearning.controller.ElearningController + + error + m3Redirect + message + pcRedirect + + + + /wechat/miniprogram.do + com.seeyon.apps.weixin.controller.MiniProgramController + + a8home + bind + bindMemberPhone + login + unbind + + + + /portal/spaceController.do + com.seeyon.ctp.portal.space.controller.SpaceController + + showThemSpace + + + + /identification.do + com.seeyon.v3x.identification.controller.IdentificationController + + getSessionId + + + + /fddCallbackController.do + com.seeyon.apps.econtract.fdd.controller.FddCallbackController + + asynch + synch + + + + m3ProductManager + com.seeyon.apps.m3.product.manager.impl.M3ProductManagerImpl + + productInfo + productStatus + + + + /ocipEdoc.do + com.seeyon.apps.ocip.exchange.edoc.OCIPEdocController + + index + + + + /m3/loginController.do + + transLogin + transLogout + getProfile + + + + /fileUpload.do + com.seeyon.ctp.common.fileupload.FileUploadController + + showRTE + processUpload + + + + qrCodeLoginManager + com.seeyon.ctp.login.manager.QrCodeLoginManagerImpl + + isLogin + + + + /form/formUpgrade.do + com.seeyon.ctp.form.service.FormUpgradeController + + toUpgrade + upgrade + viewUpgrade + + + + /seeyonReport/seeyonReportController.do + com.seeyon.apps.seeyonreport.controller.SeeyonReportController + + redirectSeeyonReport + + + + formtalkFormMapperController.do + com.seeyon.apps.formtalk.controller.FormtalkImportController + + importFormtalkData + + + + /thirdpartyController.do + com.seeyon.ctp.portal.sso.thirdpartyintegration.controller.ThirdpartyController + + access + index + logoutNotify + show + mailAuth + + + + /m3/transModeController.do + com.seeyon.apps.m3.transmissionmode.controller.M3TransModeController + + getTransModeForMobile + + + + /genericController.do + com.seeyon.v3x.common.controller.GenericController + + index + + + + /personalBind.do + com.seeyon.v3x.personalaffair.controller.PersonalBindController + + getBindTypeByLoginName + isCanUse + retrievePassword + sendVerificationCodeToBindEmail + sendVerificationCodeToBindNum + validateVerificationCode + + + + /commonimage.do + com.seeyon.apps.common.image.controller.ImageController + + showImage + + + + /individualManager.do + com.seeyon.v3x.personalaffair.controller.IndividualManagerController + + resetPassword + + + + meetingAjaxManager + com.seeyon.apps.meeting.manager.MeetingAjaxManagerImpl + + meetingPanelData + meetingPanelDisplay + + + + /wechat/dingding.do + com.seeyon.apps.weixin.controller.DingDingController + + binding + index + main + newIndex + newMain + viewh5Message + + + + /imc.do + com.seeyon.apps.imc.controller.ImcLoginController + + index + logout + + + + /wechat/feishu.do + com.seeyon.apps.weixin.controller.FeishuController + + newMain + viewh5Message + + + + + + + + + + + + + + + /wechat/pcapp.do + com.seeyon.apps.weixin.controller.PcAppController + + transferPageFromWxCoreServer + gotoPcApp + checkCodeTurnToRightPage + transfer + transferMsg + + + + /wechat/feishu/approvalData.do + com.seeyon.apps.zhifei.feishu.approval.controller.ApprovalDataController + + index + + + + /zhifei/feishu.do + com.seeyon.apps.zhifei.controller.FeishuController + + newMain + viewh5Message + + + + /zhifei/pcapp.do + com.seeyon.apps.zhifei.controller.ZhifeiPcAppController + + transferPageFromWxCoreServer + gotoPcApp + + + + /zhifei/feishu/approvalData.do + com.seeyon.apps.zhifei.feishu.approval.controller.ApprovalDataController + + index + + + + /cloudbuild.do + com.seeyon.apps.cloudbuild.controller.CloudBuildController + + download + getDownloadPageInfo + getLatestVersionInfo + getDownloadQrUrl + + + diff --git a/esign/src/test/java/TestOne.java b/esign/src/test/java/TestOne.java new file mode 100644 index 0000000..bd5cb6f --- /dev/null +++ b/esign/src/test/java/TestOne.java @@ -0,0 +1,7 @@ +import com.seeyon.apps.esign.GtlyEsignPluginApi; + +public class TestOne { + public static void main(String[] args) { + new GtlyEsignPluginApi(); + } +} diff --git a/seeyon/WEB-INF/cfgHome/component/src_esign/pluginCfg.xml b/seeyon/WEB-INF/cfgHome/component/src_esign/pluginCfg.xml new file mode 100644 index 0000000..02bdf41 --- /dev/null +++ b/seeyon/WEB-INF/cfgHome/component/src_esign/pluginCfg.xml @@ -0,0 +1,6 @@ + + + src_esign + 国通领驾E签宝集成 + 20250624 + diff --git a/seeyon/WEB-INF/cfgHome/component/src_esign/spring/spring-bean.xml b/seeyon/WEB-INF/cfgHome/component/src_esign/spring/spring-bean.xml new file mode 100644 index 0000000..4cf1673 --- /dev/null +++ b/seeyon/WEB-INF/cfgHome/component/src_esign/spring/spring-bean.xml @@ -0,0 +1,26 @@ + + + + + + + + + + + + esignCallBackController + + + + + + + \ No newline at end of file diff --git a/seeyon/WEB-INF/cfgHome/component/src_esign/spring/spring-controller.xml b/seeyon/WEB-INF/cfgHome/component/src_esign/spring/spring-controller.xml new file mode 100644 index 0000000..990676f --- /dev/null +++ b/seeyon/WEB-INF/cfgHome/component/src_esign/spring/spring-controller.xml @@ -0,0 +1,6 @@ + + + + + + diff --git a/seeyon/apps_res/cap/customerCtrlResources/esignContractCompareBtnResources/css/contractCompareBtn.css b/seeyon/apps_res/cap/customerCtrlResources/esignContractCompareBtnResources/css/contractCompareBtn.css new file mode 100644 index 0000000..e5c4ae0 --- /dev/null +++ b/seeyon/apps_res/cap/customerCtrlResources/esignContractCompareBtnResources/css/contractCompareBtn.css @@ -0,0 +1,36 @@ +.customButton_class_box { + width: 35%; + line-height: 24px; + height:24px; + color: #1f85ec; + cursor: pointer; + font-family: "Microsoft YaHei"!important; + overflow: hidden; + text-overflow: ellipsis; + white-space: nowrap; + word-break:keep-all; + box-sizing: border-box; + -webkit-box-sizing : border-box; + -moz-box-sizing : border-box; + text-align: center; + outline: none; + border: 1px solid #1f85ec; + background-color: #fff; + border-radius: 15px; + -webkit-border-radius: 15px; + -moz-border-radius: 15px; +} +.customInputArea{ + width: 65%; + height:auto; + color: #1f85ec; + font-family: "Microsoft YaHei"!important; + overflow: hidden; + text-overflow: ellipsis; + white-space: nowrap; + word-break:keep-all; +} +.customButton_box_content{ + width: 100%; + height: auto; +} diff --git a/seeyon/apps_res/cap/customerCtrlResources/esignContractCompareBtnResources/css/img/icon16.png b/seeyon/apps_res/cap/customerCtrlResources/esignContractCompareBtnResources/css/img/icon16.png new file mode 100644 index 0000000..e43def3 Binary files /dev/null and b/seeyon/apps_res/cap/customerCtrlResources/esignContractCompareBtnResources/css/img/icon16.png differ diff --git a/seeyon/apps_res/cap/customerCtrlResources/esignContractCompareBtnResources/html/contractCompare.html b/seeyon/apps_res/cap/customerCtrlResources/esignContractCompareBtnResources/html/contractCompare.html new file mode 100644 index 0000000..63cd5dc --- /dev/null +++ b/seeyon/apps_res/cap/customerCtrlResources/esignContractCompareBtnResources/html/contractCompare.html @@ -0,0 +1,104 @@ + + + + + e签宝合同比对 + + + + + +
+
+ +
+ + + + + + \ No newline at end of file diff --git a/seeyon/apps_res/cap/customerCtrlResources/esignContractCompareBtnResources/js/compareBiz.js b/seeyon/apps_res/cap/customerCtrlResources/esignContractCompareBtnResources/js/compareBiz.js new file mode 100644 index 0000000..d65faaa --- /dev/null +++ b/seeyon/apps_res/cap/customerCtrlResources/esignContractCompareBtnResources/js/compareBiz.js @@ -0,0 +1,99 @@ +$(document).ready(async function() { + const apiBaseUrl = window.location.origin; + let currentFilePage = 1; + let totalFilePages = 1; + let searchKeyword; + const filePageSize = 10; + + const dataList = await pageQueryTemplates(); + renderTemplates(dataList); + + + function renderTemplates(list) { + const container = $('#file-list'); + container.empty(); + list.forEach(file => { + const fileItem = $(` +
+ ${file.signTemplateName} +
+ `); + container.append(fileItem); + }); + filePagination() + } + + async function pageQueryTemplates() { + const pageIndex = currentFilePage; + const response = await fetch( + `${apiBaseUrl}/seeyon/rest/cap4/etemplate/querypage?pageNum=${pageIndex}`, {} + ); + const res = await response.json(); + // 校验返回值 + + console.log(res) + let respData = res.data; + totalFilePages = Math.ceil(respData.total / filePageSize); + return res.data.templateList; + } + + async function getContractCompareUrl(templateId,templateFileId) { + const response = await fetch( + `${apiBaseUrl}/seeyon/rest/cap4/etemplate/compareurl?templateId=${templateId}&templateFileId=${templateFileId}`, {} + ); + const res = await response.json(); + // 校验返回值 + } + + function filePagination() { + // 分页逻辑 + const pagination = $('#file-pagination'); + pagination.empty(); + + const firstBtn = $(''); + const prevBtn = $(''); + const nextBtn = $(''); + const pageInfo = $(`第 ${currentFilePage} 页`); + + // 判断是否禁用按钮 + prevBtn.prop('disabled', currentFilePage === 1); + + // 首页按钮点击事件 + firstBtn.click(async () => { + currentFilePage = 1; // 跳转到第一页 + await loadTemplates(); // 加载文件 + }); + + // 上一页按钮点击事件 + prevBtn.click(async () => { + if (currentFilePage <= 1) return; // 防止重复请求 + currentFilePage--; // 页码减一 + await loadTemplates(); // 加载文件 + }); + + // 下一页按钮点击事件 + nextBtn.click(async () => { + currentFilePage++; // 页码加一 + await loadTemplates(); // 加载文件 + }); + + // 加载文件的逻辑 + async function loadTemplates() { + let tempTemplateList; + + tempTemplateList = await pageQueryTemplates(); + + renderTemplates(tempFileList); // 渲染文件列表 + pageInfo.text(`第 ${currentFilePage} 页`); // 更新页数信息 + } + + // 添加按钮到分页容器 + pagination.append(firstBtn, prevBtn, pageInfo, nextBtn); + } + + function getCookie(name) { + const value = `; ${document.cookie}`; + const parts = value.split(`; ${name}=`); + if (parts.length === 2) return parts.pop().split(';').shift(); + } +}) \ No newline at end of file diff --git a/seeyon/apps_res/cap/customerCtrlResources/esignContractCompareBtnResources/js/compareinit.js b/seeyon/apps_res/cap/customerCtrlResources/esignContractCompareBtnResources/js/compareinit.js new file mode 100644 index 0000000..388ffea --- /dev/null +++ b/seeyon/apps_res/cap/customerCtrlResources/esignContractCompareBtnResources/js/compareinit.js @@ -0,0 +1,207 @@ +(function(factory) { + var nameSpace = 'field_8899554679928334458'; + if (!window[nameSpace]) { + console.log("开始实例化控件") + var Builder = factory(); + window[nameSpace] = { + instance: {} + }; + window[nameSpace].init = function(options) { + window[nameSpace].instance[options.privateId] = new Builder(options); + }; + } +})(function() { + function App(options) { + var self = this; + self.initParams(options); + //初始化dom + self.initDom(); + //事件 + self.events(); + } + + App.prototype = { + initParams: function(options) { + console.log("开始初始化参数") + var self = this; + self.adaptation = options.adaptation; + self.privateId = options.privateId; + self.preUrl = options.url_prefix; + self.adaptation.formMessage = options.formMessage; + self.messageObj = options.getData; + console.log(self.messageObj) + }, + initDom: function() { + var self = this; + console.log("开始渲染dom") + dynamicLoading.css(self.preUrl + '/css/contractCompareBtn.css'); + self.appendChildDom(); + }, + events: function() { + var self = this; + // 监听是否数据刷新 + console.log("设置事件监听") + self.adaptation.ObserverEvent.listen('Event' + self.privateId, function() { + self.messageObj = self.adaptation.childrenGetData(self.privateId); + self.appendChildDom(); + }); + }, + openCompareUrl: function(privateId, messageObj, adaptation) { + // 实际的业务代码方法 + messageObj = adaptation.childrenGetData(privateId); + const targetObj = messageObj.formdata.formmains[adaptation.formMessage.tableName] + //backFill(ids, messageObj.id, messageObj.display, privateId,messageObj, adaptation); + //dialog.close() + console.log(targetObj) + if (targetObj) { + let contractRefId; + let templateRefId; + for (const key in targetObj) { + if (targetObj.hasOwnProperty(key) && !/^auxiliary/.test(key)) { + if (targetObj[key].display === "合同审批附件") { + console.log(targetObj[key]) + contractRefId = targetObj[key].showValue; + console.log("合同附件refId: " + contractRefId) + + + } + if (targetObj[key].display === "原始合同模板文件") { + console.log(targetObj[key]) + templateRefId = targetObj[key].showValue; + console.log("模板文件refId: " + templateRefId) + } + } + } + + $.ajax({ + type: "POST", + url: '/seeyon/rest/cap4/etemplate/compareurl?templateRefId=' + + templateRefId + '&contractRefId=' + + contractRefId, + data: {}, + dataType: "json", + contentType: 'application/json;charset=UTF-8', + success: function(res) { + // 后台解析数据后 将数据填写到表单中 + if (res.code == 0) { + window.open(res.data, "_blank"); + } else { + // 报错 + $.alert(res.message); + } + }, + complete: function() {}, + error: function(e) { + top.$.error(e.responseText); + } + }); + } + }, + appendChildDom: function() { + var self = this; + const params = new URLSearchParams(window.location.search); + console.log(params) + const openFrom = params.get('openFrom'); // 返回"2025" + const type = params.get('type'); + var edit = !((openFrom != null && (openFrom == 'listPending' || openFrom == 'listDone' || + openFrom == 'listSent')) || (type != null && type == 'browse')); + console.log(edit) + var domStructure = '
' + + '
' + + '' + + '
' + + '
'; + document.querySelector('#' + self.privateId).innerHTML = domStructure; + var compare = function() { + self.openCompareUrl(self.privateId, self.messageObj, self.adaptation) + } + + var content = self.messageObj.formdata.content; + const picker = document.querySelector('.customButton_class_box' + '.' + self.privateId); + if (picker) { + document.querySelector('.customButton_class_box' + '.' + self.privateId) + .removeEventListener( + 'click', compare); + document.querySelector('.customButton_class_box' + '.' + self.privateId).addEventListener( + 'click', compare); + } + const goNewPages = document.querySelectorAll('.goToNewPage'); + if (goNewPages.length > 0) { + goNewPages.forEach(element => { + element.addEventListener('click', function(e) { + window.open(e.currentTarget.dataset.href, '_blank'); // + }); + }); + } + //渲染隐藏权限 + if (self.messageObj.auth === 'hide') { + document.querySelector('#' + self.privateId).innerHTML = + '
***
'; + } + } + + }; + + function backFill(ids, fieldName, fieldDisplay, privateId, messageObj, adaptation) { + var param = new Object(); + param.masterId = messageObj.formdata.content.contentDataId; + param.ids = ids; + param.formId = messageObj.formdata.content.contentTemplateId; + param.fieldName = fieldName; + param.fieldDisplay = fieldDisplay; + param.masterId = messageObj.formdata.content.contentDataId; + $.ajax({ + type: "POST", + url: '/seeyon/rest/cap4/hywp/fileref', + data: JSON.stringify(param), + dataType: "json", + contentType: 'application/json;charset=UTF-8', + success: function(res) { + // 后台解析数据后 将数据填写到表单中 + if (res.code == 0) { + var backfill = {}; + backfill.tableName = adaptation.formMessage.tableName; + // 回填主表 + backfill.tableCategory = 'formmain'; + // 后台组装的data数据 + console.log(res.data) + backfill.updateData = res.data; + adaptation.backfillFormControlData(backfill, privateId); + } else { + // 报错 + $.alert(res.message); + } + }, + complete: function() {}, + error: function(e) { + top.$.error(e.responseText); + } + }); + } + var dynamicLoading = { + css: function(path) { + if (!path || path.length === 0) { + throw new Error('argument "path" is required !'); + } + var head = document.getElementsByTagName('head')[0]; + var link = document.createElement('link'); + link.href = path; + link.rel = 'stylesheet'; + link.type = 'text/css'; + head.appendChild(link); + }, + js: function(path) { + if (!path || path.length === 0) { + throw new Error('argument "path" is required !'); + } + var head = document.getElementsByTagName('head')[0]; + var script = document.createElement('script'); + script.src = path; + script.type = 'text/javascript'; + head.appendChild(script); + } + } + return App; +}); \ No newline at end of file