2 Commity 3d56772cb1 ... d4e60fdfcd

Autor SHA1 Wiadomość Data
  zhangchenm d4e60fdfcd Merge remote-tracking branch 'origin/v1.1-dev' into v1.1-dev 2 tygodni temu
  zhangchenm 67050b6580 e签宝逻辑优化 2 tygodni temu

+ 1 - 1
trade-service/src/main/java/com/trade/service/contract/service/SignPlatformService.java

@@ -18,5 +18,5 @@ public interface SignPlatformService {
     // 处理回调
     void handleCallback(ContractSignCallBack callback);
 
-    Map<String, String> getAccountMap(List<ContractSignInfo> signInfoList);
+     Map<String, String> getAccountMap(List<ContractSignInfo> signInfoList);
 }

+ 43 - 85
trade-service/src/main/java/com/trade/service/contract/service/impl/ESignContractServiceImpl.java

@@ -10,6 +10,7 @@ import java.util.stream.Collectors;
 import javax.annotation.Resource;
 
 import com.trade.service.contract.config.ContractConfigProperties;
+import com.trade.service.contract.util.SignPubUtil;
 import com.trade.service.contract.util.esign.bizprocess.BizProcessorFactory;
 import com.trade.service.contract.util.esign.bizprocess.SignedBizProcessor;
 import org.jsoup.helper.StringUtil;
@@ -50,7 +51,7 @@ import lombok.extern.slf4j.Slf4j;
  */
 @Slf4j
 @Service(ContractConstant.CONTRACT_PLATFORM_SERVICE_NAME_ESIGN)
-public class ESignContractServiceImpl implements SignPlatformService {
+public class ESignContractServiceImpl implements SignPlatformService, SignAccountCreator {
 
     @Resource
     private TFileStorageService fileStorageService;
@@ -77,10 +78,12 @@ public class ESignContractServiceImpl implements SignPlatformService {
     public ContractSignOutput signContract(ContractSignInput signInput) {
         log.info("进入E签宝合同签署流程,业务场景:{},签署失效时长:{}hour", signInput.getBizScene(), signInput.getSignValidTime());
         ContractSignOutput output = new ContractSignOutput();
+        // 获取e签宝账号信息: 先统一创建账号,有任意创建失败则fail fast
+        Map<String, String> accountMap = getAccountMap(signInput.getSigneInfoList());
         // 创建签署流程
         String flowId = creatESignFlow(signInput);
         // 上传签署文件
-        output.setItems(uploadSignFileAndSetPositions(flowId, signInput));
+        output.setItems(uploadSignFileAndSetPositions(flowId, signInput, accountMap));
         // 发起签署流程
         startSignProcess(flowId);
         output.setFlowId(flowId);
@@ -112,8 +115,7 @@ public class ESignContractServiceImpl implements SignPlatformService {
 
     @Override
     public Map<String, String> getAccountMap(List<ContractSignInfo> signInfoList) {
-        // 将e签宝在中间步骤创建的逻辑提过来
-        return null;
+        return SignPubUtil.getAccountMapFromSignInfo(signInfoList, this);
     }
 
     /**
@@ -233,46 +235,6 @@ public class ESignContractServiceImpl implements SignPlatformService {
         log.info("e签宝签署完成文件下载完成,flowId:{}", eSignFlow.getFlowId());
     }
 
-    /**
-     * 获取本次签署所需创建的所有e签宝账号
-     * </p>
-     * ContractSignInfo 传值规则: </br>
-     * 当多个签署文件只需要单方签署时,ContractSignInfo中只需设置singleSigner,sealInfoList中的signer可为空。</br>
-     * 当多个签署文件需要多方签署时,ContractSignInfo中设置singleSigner可为空,设置sealInfoList的signer。</br>
-     * 即:ContractSignInfo中的singleSigner为sealInfoList的signer的备选项。两者不可同时为空。</br>
-     * sealInfoList数组中的ContractSeal对象中的sealIdType为企业证件类型时才需创建企业账号,否则为个人账号。</br>
-     * 创建个人账号时只依赖ContractSigner信息,与ContractSeal无关。即需要加盖个人章时,只需设置ContractSigner信息即可。</br>
-     *
-     * @param signInfo 签署信息
-     * @return <K 签署人证件号, V 签署人e签宝账号id>
-     */
-    private Map<String, String> creatESignAccount(ContractSignInfo signInfo) {
-        // TODO check参数合法性
-        Map<String, String> resultMap = new HashMap<>();
-        // 单方签署
-        ContractSigner signer = signInfo.getSingleSigner();
-        if (null != signer) {
-            resultMap.put(signer.getSignerIdNo(), creatPersonalAccount(signer));
-        }
-        signInfo.getSealInfoList().forEach(sealInfo -> {
-            if (null == sealInfo.getSigner()) {// 签章信息中的签署人为空,则使用签署信息中的签署人
-                if (null == signer) {
-                    throw new ServiceException("签署信息中的签署人和签章信息中的签署人不能同时为空", HttpStatus.BAD_REQUEST);
-                }
-                sealInfo.setSigner(signer);
-            } else {// 签署信息中的签署人不为空,则使用签署信息中的签署人creat个人账号
-                resultMap.computeIfAbsent(sealInfo.getSigner().getSignerIdNo(),
-                        o -> creatPersonalAccount(sealInfo.getSigner()));
-            }
-            // 若存在企业签章,则需创建企业账号
-            if (ESignConstant.CRED_ORG_USCC.equals(sealInfo.getSealIdType())
-                    || ESignConstant.CRED_ORG_UNKNOWN.equals(sealInfo.getSealIdType())) {
-                resultMap.computeIfAbsent(sealInfo.getSealIdNo(), o -> createOrgAccount(sealInfo));
-            }
-        });
-        return resultMap;
-    }
-
     private String creatESignFlow(ContractSignInput signInput) {
         if (StringUtils.isEmpty(signInput.getBizScene())) {
             throw new ServiceException("签署任务-业务场景不能为空", HttpStatus.BAD_REQUEST);
@@ -302,7 +264,8 @@ public class ESignContractServiceImpl implements SignPlatformService {
         return flowId;
     }
 
-    private List<ContractSignOutputItem> uploadSignFileAndSetPositions(String flowId, ContractSignInput signInput) {
+    private List<ContractSignOutputItem> uploadSignFileAndSetPositions(String flowId, ContractSignInput signInput,
+            Map<String, String> accountMap) {
         List<ContractSignInfo> signInfos = signInput.getSigneInfoList();
         if (CollectionUtils.isEmpty(signInfos)) {
             throw new ServiceException("签署任务-待签署信息列表不能为空", HttpStatus.BAD_REQUEST);
@@ -319,7 +282,7 @@ public class ESignContractServiceImpl implements SignPlatformService {
             // 上传签署文件
             String eSignFileId = uploadSignFile(flowId, signInfo);
             // 设置签署位置
-            addSignField(signFieldList, flowId, signInfo, eSignFileId, willTypes);
+            addSignField(signFieldList, flowId, signInfo, eSignFileId, willTypes, accountMap);
             outputItems.add(new ContractSignOutputItem(signInfo.getFileType(), signInfo.getFileId(), eSignFileId));
         }
         ESignRequest.addSignerHandSignArea(flowId, signFieldList);
@@ -328,51 +291,50 @@ public class ESignContractServiceImpl implements SignPlatformService {
 
     /**
      * 添加签署位置
-     *
+     * 
      * @param signFieldList 签署文档列表
      * @param signInfo 签章信息
      * @param eSignFileId e签宝文件id
+     * @param accountMap
      */
     private void addSignField(List<ESignDoc> signFieldList, String flowId, ContractSignInfo signInfo,
-            String eSignFileId, List<String> willTypes) {
+            String eSignFileId, List<String> willTypes, Map<String, String> accountMap) {
         List<ContractSeal> sealInfoList = signInfo.getSealInfoList();
         if (CollectionUtils.isEmpty(sealInfoList)) {
             throw new ServiceException("签署任务-签章信息列表不能为空", HttpStatus.BAD_REQUEST);
         }
-        // 先统一创建账号,有任意创建失败则直接失败,不再进行后续操作
-        Map<String, String> accountMap = creatESignAccount(signInfo);
-        for (ContractSeal salInfo : sealInfoList) {
+        for (ContractSeal sealInfo : sealInfoList) {
             // 签章里的签署人信息未传,则使用签署信息中的签署人信息
-            ContractSigner signer = null == salInfo.getSigner() ? signInfo.getSingleSigner() : salInfo.getSigner();
-            ESignDocPosition posBean = ESignRequest.searchWordsPosition(flowId, eSignFileId, salInfo.getKeyword());
-            if (Boolean.TRUE.equals(salInfo.getWithTime())) {
+            ContractSigner signer = null == sealInfo.getSigner() ? signInfo.getSingleSigner() : sealInfo.getSigner();
+            ESignDocPosition posBean = ESignRequest.searchWordsPosition(flowId, eSignFileId, sealInfo.getKeyword());
+            if (Boolean.TRUE.equals(sealInfo.getWithTime())) {
                 posBean.setAddSignTime(true);
                 posBean.setSignTimeFormat(ESignConstant.SIGN_DATE_FORMAT);
             }
             ESignDoc signField = null;
             // 企业
-            if (ESignConstant.CRED_ORG_USCC.equals(salInfo.getSealIdType())
-                    || ESignConstant.CRED_ORG_UNKNOWN.equals(salInfo.getSealIdType())) {
+            if (ESignConstant.isOrgSealType(sealInfo.getSealIdType())) {
                 // 机构签约类别,当签约主体为机构时必传
-                String actorIdentityType = "2";// 企业
-                if (Boolean.TRUE.equals(salInfo.getSignLegal())) {
-                    actorIdentityType = "3";// 企业法人章
-                }
-                signField = new ESignDoc(eSignFileId, accountMap.get(signer.getSignerIdNo()), actorIdentityType,
-                        accountMap.get(salInfo.getSealIdNo()), null, 1, posBean, null, null, null);
-                if (handleAutoSign(flowId, salInfo, signField))
+                String actorIdentityType = Boolean.TRUE.equals(sealInfo.getSignLegal()) ? "3" : "2";// 2企业 3法人
+                if (Boolean.TRUE.equals(sealInfo.getAutoSign())) {
+                    signField = new ESignDoc(eSignFileId, accountMap.get(sealInfo.getSealIdNo()), null, posBean, null,
+                            null);
+                    handleAutoSign(flowId, sealInfo, signField);
                     continue;
-            } else if (ESignConstant.CRED_PSN_CH_IDCARD.equals(signer.getSignerIdType())
-                    || ESignConstant.CRED_PSN_PASSPORT.equals(signer.getSignerIdType())) {
-                        if (Boolean.TRUE.equals(salInfo.getAutoSign())) {
-                            throw new ServiceException("签署任务-个人签章暂不支持自动签章", HttpStatus.BAD_REQUEST);
-                        }
-                        signField = new ESignDoc(eSignFileId, accountMap.get(signer.getSignerIdNo()), null, null, null,
-                                1, posBean, "1", null, null);
-                    }
+                } else {
+                    signField = new ESignDoc(eSignFileId, accountMap.get(signer.getSignerIdNo()), actorIdentityType,
+                            accountMap.get(sealInfo.getSealIdNo()), null, 1, posBean, null, null, null);
+                }
+            } else if (ESignConstant.isIndividualSealType(signer.getSignerIdType())) {
+                if (Boolean.TRUE.equals(sealInfo.getAutoSign())) {
+                    throw new ServiceException("签署任务-个人签章暂不支持自动签章", HttpStatus.BAD_REQUEST);
+                }
+                signField = new ESignDoc(eSignFileId, accountMap.get(signer.getSignerIdNo()), null, null, null, 1,
+                        posBean, "1", null, null);
+            }
             if (null == signField) {
                 log.error("签署任务-获取签章位置出错fileId:{},sealIdType:{},keyword:{}", signInfo.getFileId(),
-                        salInfo.getSealIdType(), salInfo.getKeyword());
+                        sealInfo.getSealIdType(), sealInfo.getKeyword());
                 throw new ServiceException("签署任务-获取签章位置出错,请检查签章传参是否正确", HttpStatus.ERROR);
             }
             signField.setWillTypes(willTypes);
@@ -390,18 +352,14 @@ public class ESignContractServiceImpl implements SignPlatformService {
      * @param signField e签宝签署任务对象
      * @return 是否自动签章
      */
-    private boolean handleAutoSign(String flowId, ContractSeal sealInfo, ESignDoc signField) {
-        if (Boolean.TRUE.equals(sealInfo.getAutoSign())) {
-            String sealId = contractConfigProperties.getESignSealIdByIdNo(sealInfo.getSealIdNo());
-            if (null == sealId) {
-                throw new ServiceException("签署任务-签章信息-企业签章-自动签章-未配置签章ID", HttpStatus.BAD_REQUEST);
-            }
-            signField.setSealId(sealId);
-            // 调用自动签署方法
-            ESignRequest.addPlatformAutoSignArea(flowId, Collections.singletonList(signField));
-            return true;
+    private void handleAutoSign(String flowId, ContractSeal sealInfo, ESignDoc signField) {
+        String sealId = contractConfigProperties.getESignSealIdByIdNo(sealInfo.getSealIdNo());
+        if (null == sealId) {
+            throw new ServiceException("签署任务-签章信息-企业签章-自动签章-未配置签章ID", HttpStatus.BAD_REQUEST);
         }
-        return false;
+        signField.setSealId(sealId);
+        // 调用自动签署方法
+        ESignRequest.addPlatformAutoSignArea(flowId, Collections.singletonList(signField));
     }
 
     private void saveSignFlowSigner(String flowId, Map<String, String> accountMap) {
@@ -448,7 +406,7 @@ public class ESignContractServiceImpl implements SignPlatformService {
      * @param signer 个人信息
      * @return 个人账号ID
      */
-    private String creatPersonalAccount(ContractSigner signer) {
+    public String creatPersonalAccount(ContractSigner signer) {
         if (null == signer || StrUtil.isBlank(signer.getSigner()) || StrUtil.isBlank(signer.getSignerIdType())
                 || StrUtil.isBlank(signer.getSignerIdNo())
                 || (StrUtil.isBlank(signer.getMobile()) && StringUtil.isBlank(signer.getEmail()))) {
@@ -513,7 +471,7 @@ public class ESignContractServiceImpl implements SignPlatformService {
      * @param sealInfo 签章信息
      * @return 企业账号ID
      */
-    private String createOrgAccount(ContractSeal sealInfo) {
+    public String createOrgAccount(ContractSeal sealInfo) {
         if (null == sealInfo || StrUtil.isBlank(sealInfo.getSealName()) || StrUtil.isBlank(sealInfo.getSealIdNo())) {
             log.error(JSON.toJSONString(sealInfo));
             throw new ServiceException("机构帐号信息不全!", HttpStatus.BAD_REQUEST);

+ 12 - 6
trade-service/src/main/java/com/trade/service/contract/util/SignPubUtil.java

@@ -15,11 +15,18 @@ import java.util.Map;
 public class SignPubUtil {
 
     /**
-     * 根据签署入参,获取签署账号信息
-     * 
+     * 获取本次签署需要创建的账号信息
+     * </p>
+     * ContractSignInfo 传值规则: </br>
+     * 当多个签署文件只需要单方签署时,ContractSignInfo中只需设置singleSigner,sealInfoList中的signer可为空。</br>
+     * 当多个签署文件需要多方签署时,ContractSignInfo中设置singleSigner可为空,设置sealInfoList的signer。</br>
+     * 即:ContractSignInfo中的singleSigner为sealInfoList的signer的备选项。两者不可同时为空。</br>
+     * sealInfoList数组中的ContractSeal对象中的sealIdType为企业证件类型时才需创建企业账号,否则为个人账号。</br>
+     * 创建个人账号时只依赖ContractSigner信息,与ContractSeal无关。即需要加盖个人章时,只需设置ContractSigner信息即可。</br>
+     *
      * @param signInfoList 签署信息列表
      * @param accountCreator 账号创建器
-     * @return 签署账号信息Map
+     * @return <K 签署人证件号, V 签署人第三方账号id>
      */
     public static Map<String, String> getAccountMapFromSignInfo(List<ContractSignInfo> signInfoList,
             SignAccountCreator accountCreator) {
@@ -32,7 +39,7 @@ public class SignPubUtil {
             }
             signInfo.getSealInfoList().forEach(sealInfo -> {
                 if (null == sealInfo.getSigner()) {
-                    if (null == signer) {
+                    if (null == signer && !Boolean.TRUE.equals(sealInfo.getAutoSign())) {
                         throw new ServiceException("签署信息中的签署人和签章信息中的签署人不能同时为空", HttpStatus.BAD_REQUEST);
                     }
                     sealInfo.setSigner(signer);
@@ -41,8 +48,7 @@ public class SignPubUtil {
                             v -> accountCreator.creatPersonalAccount(sealInfo.getSigner()));
                 }
                 // 若存在企业签章,则需创建企业账号
-                if (ESignConstant.CRED_ORG_USCC.equals(sealInfo.getSealIdType())
-                        || ESignConstant.CRED_ORG_UNKNOWN.equals(sealInfo.getSealIdType())) {
+                if (ESignConstant.isOrgSealType(sealInfo.getSealIdType())) {
                     resultMap.computeIfAbsent(sealInfo.getSealIdNo(), v -> accountCreator.createOrgAccount(sealInfo));
                 }
             });

+ 9 - 8
trade-service/src/main/java/com/trade/service/contract/util/esign/ESignConstant.java

@@ -12,18 +12,12 @@ public class ESignConstant {
     public static final String ACTION_TYPE_FLOW_UPDATE = "SIGN_FLOW_UPDATE";
     // 签署人签署完成
     public static final String ACTION_TYPE_FLOW_FINISH = "SIGN_FLOW_FINISH";
-
-
     // 签署人签署完成
     public static final int SIGN_FLOW_STATUS_FINISH = 2;
     // 超时未签署
     public static final int SIGN_FLOW_STATUS_OVERTIME = 5;
     // 拒签
     public static final int SIGN_FLOW_STATUS_REFUSE = 7;
-
-
-
-
     public static final String ESign_PREFIX = "inkasso_";
     /** 《池保理业务合同》 3.0及其之前版本使用 **/
     public static final String FACTORING_CONTRACT = "factoring_contract";
@@ -173,10 +167,17 @@ public class ESignConstant {
         // signKeywordToB.put(PERSONAL_GUARANTEE, "keyword2");
         // signKeywordToB.put(REPAYMENT_COMMITMENT_AUTH_LETTER, "keyword2");
     }
-    
-    
+
     public static boolean isFlowTerminate(int status) {
         return status == SIGN_FLOW_STATUS_FINISH || status == SIGN_FLOW_STATUS_OVERTIME
                 || status == SIGN_FLOW_STATUS_REFUSE;
     }
+
+    public static boolean isOrgSealType(String sealIdType) {
+        return CRED_ORG_USCC.equals(sealIdType) || CRED_ORG_UNKNOWN.equals(sealIdType);
+    }
+
+    public static boolean isIndividualSealType(String sealIdType) {
+        return CRED_PSN_CH_IDCARD.equals(sealIdType) || CRED_PSN_PASSPORT.equals(sealIdType);
+    }
 }