From 773d886aa603ca4bd5e51d251f3f38a2126e5d44 Mon Sep 17 00:00:00 2001
From: Jack <46790855@qq.com>
Date: Tue, 11 Mar 2025 17:01:31 +0800
Subject: [PATCH] =?UTF-8?q?e=E7=AD=BE=E5=AE=9D=E5=8F=91=E8=B5=B7=E7=AD=BE?=
=?UTF-8?q?=E7=BD=B2=E6=B5=81=E7=A8=8B=EF=BC=8C=E5=A4=9A=E4=B8=AA=E6=96=B9?=
=?UTF-8?q?=E6=B3=95=E8=B0=83=E6=95=B4?=
MIME-Version: 1.0
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: 8bit
---
.../mall/common/constant/CommonConstant.java | 4 +
.../common/modules/esign/EsignContract.java | 27 +-
.../esign/EsignContractFillingFile.java | 6 +
.../mall/shop/components/TaskService.java | 51 ++++
.../EsignContractFillingFileService.java | 21 ++
.../esign/service/EsignContractService.java | 20 ++
.../EsignContractFillingFileServiceImpl.java | 152 +++++++++--
.../impl/EsignContractServiceImpl.java | 246 +++++++++++++++++-
.../impl/EsignPlatformInfoServiceImpl.java | 2 +
.../mobile/ShopMerchEntryController.java | 2 +
.../impl/ShopMerchEntryServiceImpl.java | 27 +-
.../src/main/resources/bootstrap-dev.yml | 19 ++
.../src/main/resources/bootstrap-local.yml | 3 +
.../src/main/resources/bootstrap-prod.yml | 5 +-
.../src/main/resources/bootstrap-test.yml | 21 +-
.../src/main/resources/bootstrap-uat.yml | 21 +-
16 files changed, 595 insertions(+), 32 deletions(-)
create mode 100644 mall-shop/src/main/java/com/suisung/mall/shop/components/TaskService.java
diff --git a/mall-common/src/main/java/com/suisung/mall/common/constant/CommonConstant.java b/mall-common/src/main/java/com/suisung/mall/common/constant/CommonConstant.java
index a9aedeb8..2baae62b 100644
--- a/mall-common/src/main/java/com/suisung/mall/common/constant/CommonConstant.java
+++ b/mall-common/src/main/java/com/suisung/mall/common/constant/CommonConstant.java
@@ -50,4 +50,8 @@ public class CommonConstant {
public static final Integer MCH_APPR_STA_NOPASS = 2;
public static final Integer MCH_APPR_STA_PADDING = 3;
public static final Integer MCH_APPR_STA_NONE = 4;
+
+ // 入驻商家主体类型,企业或个人:1-企业;2-个人;
+ public static final Integer MCH_ENTITY_TYPE_QY = 1;
+ public static final Integer MCH_ENTITY_TYPE_GR = 2;
}
diff --git a/mall-common/src/main/java/com/suisung/mall/common/modules/esign/EsignContract.java b/mall-common/src/main/java/com/suisung/mall/common/modules/esign/EsignContract.java
index b4f7e357..741fdf42 100644
--- a/mall-common/src/main/java/com/suisung/mall/common/modules/esign/EsignContract.java
+++ b/mall-common/src/main/java/com/suisung/mall/common/modules/esign/EsignContract.java
@@ -32,9 +32,6 @@ public class EsignContract implements Serializable {
@ApiModelProperty(value = "自增ID")
private Long id;
- @ApiModelProperty(value = "店铺编号")
- private String store_id;
-
@ApiModelProperty(value = "合同编号,自定义生成")
private String contract_number;
@@ -44,6 +41,21 @@ public class EsignContract implements Serializable {
@ApiModelProperty(value = "合同模版Id")
private String doc_template_id;
+ @ApiModelProperty(value = "合同文件Id")
+ private String contract_file_id;
+
+ @ApiModelProperty(value = "签署合同请求参数")
+ private String req_params;
+
+ @ApiModelProperty(value = "商家注册手机号")
+ private String mch_mobile;
+
+ @ApiModelProperty(value = "商家营业执照编号,如果是个人,可空")
+ private String mch_biz_license;
+
+ @ApiModelProperty(value = "商家公司名称")
+ private String mch_company;
+
@ApiModelProperty(value = "生成的未签署合同地址(30天有效期)")
private String unsigned_contract_url;
@@ -53,6 +65,15 @@ public class EsignContract implements Serializable {
@ApiModelProperty(value = "未签署合同地址本地下载地址")
private String local_contract_url;
+ @ApiModelProperty(value = "合作方签署状态:1-等待签署;2 - 已完成(所有签署方完成签署)3 - 已撤销(发起方撤销签署任务)5 - 已过期(签署截止日到期后触发)7 - 已拒签(签署方拒绝签署)")
+ private Integer sign_flow_status;
+
+ @ApiModelProperty(value = "店铺编号")
+ private String store_id;
+
+ @ApiModelProperty(value = "签署流程ID")
+ private String sign_flow_id;
+
@ApiModelProperty(value = "记录状态:1-有效;2-无效;")
private Integer status;
diff --git a/mall-common/src/main/java/com/suisung/mall/common/modules/esign/EsignContractFillingFile.java b/mall-common/src/main/java/com/suisung/mall/common/modules/esign/EsignContractFillingFile.java
index 045b1f12..7e2491be 100644
--- a/mall-common/src/main/java/com/suisung/mall/common/modules/esign/EsignContractFillingFile.java
+++ b/mall-common/src/main/java/com/suisung/mall/common/modules/esign/EsignContractFillingFile.java
@@ -56,6 +56,12 @@ public class EsignContractFillingFile implements Serializable {
@ApiModelProperty(value = "未签署合同地址本地下载地址")
private String unsigned_contract_local_url;
+ @ApiModelProperty(value = "甲方签署印章XY位置")
+ private String mch_sign_position;
+
+ @ApiModelProperty(value = "乙方(平台方)签署印章XY位置")
+ private String plat_sign_position;
+
@ApiModelProperty(value = "合同排序")
private Integer seq;
diff --git a/mall-shop/src/main/java/com/suisung/mall/shop/components/TaskService.java b/mall-shop/src/main/java/com/suisung/mall/shop/components/TaskService.java
new file mode 100644
index 00000000..7bccc8c9
--- /dev/null
+++ b/mall-shop/src/main/java/com/suisung/mall/shop/components/TaskService.java
@@ -0,0 +1,51 @@
+/*
+ * Copyright (c) 2025. Lorem ipsum dolor sit amet, consectetur adipiscing elit.
+ * Morbi non lorem porttitor neque feugiat blandit. Ut vitae ipsum eget quam lacinia accumsan.
+ * Etiam sed turpis ac ipsum condimentum fringilla. Maecenas magna.
+ * Proin dapibus sapien vel ante. Aliquam erat volutpat. Pellentesque sagittis ligula eget metus.
+ * Vestibulum commodo. Ut rhoncus gravida arcu.
+ */
+
+package com.suisung.mall.shop.components;
+
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.stereotype.Service;
+
+import java.util.concurrent.ThreadPoolExecutor;
+
+/**
+ * 使用方法:
+ *
+ * @Autowired private TaskService taskService;
+ *
+ * public void run(String... args) throws Exception {
+ * // 定义一个任务
+ * Runnable task = () -> {
+ * System.out.println("任务正在执行,线程: " + Thread.currentThread().getName());
+ * try {
+ * Thread.sleep(2000);
+ * } catch (InterruptedException e) {
+ * e.printStackTrace();
+ * }
+ * System.out.println("任务执行完成,线程: " + Thread.currentThread().getName());
+ * };
+ *
+ * // 使用线程池执行任务
+ * taskService.executeTask(task);
+ *
+ * System.out.println("主线程继续执行其他任务");
+ * }
+ */
+@Service
+public class TaskService {
+ private final ThreadPoolExecutor threadPoolExecutor;
+
+ @Autowired
+ public TaskService(ThreadPoolExecutor threadPoolExecutor) {
+ this.threadPoolExecutor = threadPoolExecutor;
+ }
+
+ public void executeTask(Runnable task) {
+ threadPoolExecutor.execute(task);
+ }
+}
diff --git a/mall-shop/src/main/java/com/suisung/mall/shop/esign/service/EsignContractFillingFileService.java b/mall-shop/src/main/java/com/suisung/mall/shop/esign/service/EsignContractFillingFileService.java
index 0a10b95e..b74357c8 100644
--- a/mall-shop/src/main/java/com/suisung/mall/shop/esign/service/EsignContractFillingFileService.java
+++ b/mall-shop/src/main/java/com/suisung/mall/shop/esign/service/EsignContractFillingFileService.java
@@ -8,7 +8,9 @@
package com.suisung.mall.shop.esign.service;
+import cn.hutool.json.JSONArray;
import com.suisung.mall.common.modules.esign.EsignContractFillingFile;
+import org.springframework.data.util.Pair;
public interface EsignContractFillingFileService {
@@ -21,6 +23,15 @@ public interface EsignContractFillingFileService {
*/
Boolean fillDocTemplate(String mchLicenseNumber, String platLicenseNumber);
+ /**
+ * 获取模版的甲方与乙方印章XY位置数据
+ *
+ * @param docTemplateId
+ * @param fileId
+ * @return
+ */
+ Pair getSignPosition(String docTemplateId, String fileId);
+
/**
* 根据注册手机号禁用合同
*
@@ -44,4 +55,14 @@ public interface EsignContractFillingFileService {
* @return
*/
Boolean trySaveRecord(EsignContractFillingFile esignContractFillingFile);
+
+
+ /**
+ * 根据商家手机号和模版ID获取合同填充文件
+ *
+ * @param mchMobile
+ * @param templateId
+ * @return
+ */
+ EsignContractFillingFile getEsignContractFillingFile(String mchMobile, String templateId);
}
diff --git a/mall-shop/src/main/java/com/suisung/mall/shop/esign/service/EsignContractService.java b/mall-shop/src/main/java/com/suisung/mall/shop/esign/service/EsignContractService.java
index 9bcfeb9d..13966ccf 100644
--- a/mall-shop/src/main/java/com/suisung/mall/shop/esign/service/EsignContractService.java
+++ b/mall-shop/src/main/java/com/suisung/mall/shop/esign/service/EsignContractService.java
@@ -11,4 +11,24 @@ package com.suisung.mall.shop.esign.service;
public interface EsignContractService {
Object signFlowCreateByFile();
+
+ /**
+ * 更新合同流程ID和文件地址
+ *
+ * @param mchMobile
+ * @param contractFileId
+ * @param signFlowId
+ * @param fileUrl
+ * @return
+ */
+ Boolean updateContractFlowIdAndFileUrl(String mchMobile, String contractFileId, String signFlowId, String fileUrl);
+
+ /**
+ * 商家入驻审核通过,模版就绪之后,预创建签署流程。
+ *
+ * @param mchMobile
+ * @param templateId
+ * @return
+ */
+ Boolean preCreateSignFlow(String mchMobile, String templateId);
}
diff --git a/mall-shop/src/main/java/com/suisung/mall/shop/esign/service/impl/EsignContractFillingFileServiceImpl.java b/mall-shop/src/main/java/com/suisung/mall/shop/esign/service/impl/EsignContractFillingFileServiceImpl.java
index 15196a91..1e9cf72f 100644
--- a/mall-shop/src/main/java/com/suisung/mall/shop/esign/service/impl/EsignContractFillingFileServiceImpl.java
+++ b/mall-shop/src/main/java/com/suisung/mall/shop/esign/service/impl/EsignContractFillingFileServiceImpl.java
@@ -24,6 +24,7 @@ import com.suisung.mall.common.utils.StringUtils;
import com.suisung.mall.core.web.service.impl.BaseServiceImpl;
import com.suisung.mall.shop.esign.mapper.EsignContractFillingFileMapper;
import com.suisung.mall.shop.esign.service.EsignContractFillingFileService;
+import com.suisung.mall.shop.esign.service.EsignContractService;
import com.suisung.mall.shop.esign.service.EsignPlatformInfoService;
import com.suisung.mall.shop.esign.utils.comm.EsignHttpHelper;
import com.suisung.mall.shop.esign.utils.comm.EsignHttpResponse;
@@ -33,6 +34,8 @@ import com.suisung.mall.shop.page.service.OssService;
import com.suisung.mall.shop.store.service.ShopMerchEntryService;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Value;
+import org.springframework.context.annotation.Lazy;
+import org.springframework.data.util.Pair;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.util.ObjectUtils;
@@ -57,6 +60,9 @@ public class EsignContractFillingFileServiceImpl extends BaseServiceImpl
+ * 后台管理员审核商家通过之后,触发调用这个方法,生成未签署合同文件,预备签署
*
* @param mchLicenseNumber 入驻商家(甲方)的营业执照号
* @param platLicenseNumber 平台方(代理商方)(乙方)营业执照号
@@ -81,17 +94,15 @@ public class EsignContractFillingFileServiceImpl extends BaseServiceImpl() {{
put("componentKey", "plat_contracts");
- put("componentValue", "《平台商户入驻服务框架协议》和《小发同城服务费结算》");
+ put("componentValue", "平台商户入驻服务框架协议和小发同城服务费结算");
}});
// 签署时间
@@ -245,9 +255,9 @@ public class EsignContractFillingFileServiceImpl extends BaseServiceImpl header = null;
try {
- header = EsignHttpHelper.signAndBuildSignAndJsonHeader(appId, appSecret, jsonParma, requestType.name(), apiaddr, true);
+ header = EsignHttpHelper.signAndBuildSignAndJsonHeader(appId, appSecret, jsonParma, requestType.name(), apiaddr, debug);
//发起接口请求
- EsignHttpResponse createByDocTemplate = EsignHttpHelper.doCommHttp(serverUrl, apiaddr, requestType, jsonParma, header, true);
+ EsignHttpResponse createByDocTemplate = EsignHttpHelper.doCommHttp(serverUrl, apiaddr, requestType, jsonParma, header, debug);
log.info("合同生成数据:{}", createByDocTemplate);
if (createByDocTemplate.getStatus() != 200) {
return false;
@@ -257,6 +267,7 @@ public class EsignContractFillingFileServiceImpl extends BaseServiceImpl signPositionPair = getSignPosition(templateId, fileId);
+ if (signPositionPair != null) {
+ esignContractFillingFile.setMch_sign_position(signPositionPair.getFirst().toString());
+ esignContractFillingFile.setPlat_sign_position(signPositionPair.getSecond().toString());
+ }
+
if (esignContractFillingFileService.trySaveRecord(esignContractFillingFile)) {
successCnt += 1;
+
+ // 预新增一个签署合同记录(要不要异步执行?)
+ esignContractService.preCreateSignFlow(esignContractFillingFile.getMobile(), esignContractFillingFile.getDoc_template_id());
}
} catch (EsignDemoException e) {
@@ -288,6 +309,78 @@ public class EsignContractFillingFileServiceImpl extends BaseServiceImpl 0;
}
+ /**
+ * 获取模版的甲方与乙方印章XY位置数据
+ *
+ * @param docTemplateId
+ * @param fileId
+ * @return
+ */
+ @Override
+ public Pair getSignPosition(String docTemplateId, String fileId) {
+ String apiaddr = "/v3/doc-templates/" + docTemplateId;
+
+ //请求参数body体,json格式。get或者delete请求时jsonString传空json:"{}"或者null
+ String jsonParm = null;
+ try {
+ //请求方法
+ EsignRequestType requestType = EsignRequestType.GET;
+ //生成签名鉴权方式的的header
+ Map header = EsignHttpHelper.signAndBuildSignAndJsonHeader(appId, appSecret, jsonParm, requestType.name(), apiaddr, debug);
+ //发起接口请求
+ EsignHttpResponse resp = EsignHttpHelper.doCommHttp(serverUrl, apiaddr, requestType, jsonParm, header, debug);
+ if (resp.getStatus() != 200 || StrUtil.isEmpty(resp.getBody())) {
+ return null;
+ }
+
+ JSONArray components = JSONUtil.parseObj(resp.getBody()).getJSONObject("data").getJSONArray("components");
+ if (CollectionUtil.isEmpty(components)) {
+ return null;
+ }
+
+ // 处理符合的数据
+// Pair pair = new Pair<>();
+ JSONArray retMchArr = new JSONArray();
+ JSONArray retPlatArr = new JSONArray();
+ for (JSONObject component : components.jsonIter()) {
+ String componentName = component.getStr("componentName");
+ String customBizNum = StringUtils.genLklOrderNo(4);
+ if (componentName.equals("甲方签署区")) {
+ JSONObject signFields = new JSONObject();
+ signFields.put("customBizNum", customBizNum);
+ signFields.put("fileId", fileId);
+ signFields.put("normalSignFieldConfig", component.getJSONArray("signFields"));
+ signFields.putByPath("normalSignFieldConfig.signFieldStyle", 1); //签章区样式 1 - 单页签章,2 - 骑缝签章(点击了解 骑缝盖章)
+
+ JSONObject signFieldPosition = new JSONObject();
+ signFieldPosition.put("positionPage", component.getByPath("componentPosition.componentPageNum"));
+ signFieldPosition.put("positionX", component.getByPath("componentPosition.componentPositionX"));
+ signFieldPosition.put("positionY", component.getByPath("componentPosition.componentPositionY"));
+ signFields.putByPath("normalSignFieldConfig.signFieldPosition", signFieldPosition);
+ retMchArr.add(signFields);
+ } else if (componentName.equals("乙方签署区")) {
+ JSONObject signFields = new JSONObject();
+ signFields.put("customBizNum", customBizNum);
+ signFields.put("fileId", fileId);
+ signFields.put("normalSignFieldConfig", component.getJSONArray("signFields"));
+ signFields.putByPath("normalSignFieldConfig.signFieldStyle", 1); //签章区样式 1 - 单页签章,2 - 骑缝签章(点击了解 骑缝盖章)
+
+ JSONObject signFieldPosition = new JSONObject();
+ signFieldPosition.put("positionPage", component.getByPath("componentPosition.componentPageNum"));
+ signFieldPosition.put("positionX", component.getByPath("componentPosition.componentPositionX"));
+ signFieldPosition.put("positionY", component.getByPath("componentPosition.componentPositionY"));
+ signFields.putByPath("normalSignFieldConfig.signFieldPosition", signFieldPosition);
+ retPlatArr.add(signFields);
+ }
+ }
+
+ return Pair.of(retMchArr, retPlatArr);
+ } catch (EsignDemoException e) {
+ log.error("获取模版的印章XY位置数据失败", e);
+ return null;
+ }
+ }
+
/**
* 更加双方营业执照号码填充合同模版,生成合同文件地址
*
@@ -494,9 +587,9 @@ public class EsignContractFillingFileServiceImpl extends BaseServiceImpl header = null;
try {
- header = EsignHttpHelper.signAndBuildSignAndJsonHeader(appId, appSecret, jsonParma, requestType.name(), apiaddr, true);
+ header = EsignHttpHelper.signAndBuildSignAndJsonHeader(appId, appSecret, jsonParma, requestType.name(), apiaddr, debug);
//发起接口请求
- EsignHttpResponse createByDocTemplate = EsignHttpHelper.doCommHttp(serverUrl, apiaddr, requestType, jsonParma, header, true);
+ EsignHttpResponse createByDocTemplate = EsignHttpHelper.doCommHttp(serverUrl, apiaddr, requestType, jsonParma, header, debug);
log.info("合同生成数据:{}", createByDocTemplate);
if (createByDocTemplate.getStatus() != 200) {
return false;
@@ -584,4 +677,23 @@ public class EsignContractFillingFileServiceImpl extends BaseServiceImpl queryWrapper = new QueryWrapper();
+ queryWrapper.eq("mobile", mchMobile).eq("doc_template_id", templateId).eq("status", CommonConstant.Enable);
+ List list = list(queryWrapper);
+ if (CollectionUtil.isEmpty(list)) {
+ return null;
+ }
+
+ return list.get(0);
+ }
}
diff --git a/mall-shop/src/main/java/com/suisung/mall/shop/esign/service/impl/EsignContractServiceImpl.java b/mall-shop/src/main/java/com/suisung/mall/shop/esign/service/impl/EsignContractServiceImpl.java
index eb0fe9c6..55eaacd7 100644
--- a/mall-shop/src/main/java/com/suisung/mall/shop/esign/service/impl/EsignContractServiceImpl.java
+++ b/mall-shop/src/main/java/com/suisung/mall/shop/esign/service/impl/EsignContractServiceImpl.java
@@ -8,16 +8,32 @@
package com.suisung.mall.shop.esign.service.impl;
+import cn.hutool.core.util.StrUtil;
+import cn.hutool.json.JSONArray;
+import cn.hutool.json.JSONObject;
+import cn.hutool.json.JSONUtil;
+import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
+import com.baomidou.mybatisplus.core.conditions.update.UpdateWrapper;
+import com.suisung.mall.common.constant.CommonConstant;
import com.suisung.mall.common.modules.esign.EsignContract;
+import com.suisung.mall.common.modules.esign.EsignContractFillingFile;
+import com.suisung.mall.common.modules.esign.EsignPlatformInfo;
+import com.suisung.mall.common.modules.merch.ShopMerchEntry;
import com.suisung.mall.core.web.service.impl.BaseServiceImpl;
import com.suisung.mall.shop.esign.mapper.EsignContractMapper;
+import com.suisung.mall.shop.esign.service.EsignContractFillingFileService;
import com.suisung.mall.shop.esign.service.EsignContractService;
+import com.suisung.mall.shop.esign.service.EsignPlatformInfoService;
import com.suisung.mall.shop.esign.utils.comm.EsignHttpHelper;
import com.suisung.mall.shop.esign.utils.enums.EsignRequestType;
import com.suisung.mall.shop.esign.utils.exception.EsignDemoException;
+import com.suisung.mall.shop.page.service.OssService;
+import com.suisung.mall.shop.store.service.ShopMerchEntryService;
import org.springframework.beans.factory.annotation.Value;
+import org.springframework.context.annotation.Lazy;
import org.springframework.stereotype.Service;
+import javax.annotation.Resource;
import java.util.Map;
@Service
@@ -32,20 +48,240 @@ public class EsignContractServiceImpl extends BaseServiceImpl header = EsignHttpHelper.signAndBuildSignAndJsonHeader(appId, appSecret, jsonParm, requestType.name(), apiaddr, true);
//发起接口请求
- return EsignHttpHelper.doCommHttp(serverUrl, apiaddr, requestType, jsonParm, header, true);
+ return EsignHttpHelper.doCommHttp(serverUrl, apiaddr, requestType, jsonParm, header, debug);
} catch (EsignDemoException e) {
throw new RuntimeException(e);
}
}
+
+ /**
+ * 更新合同流程ID和正式盖章合同文件地址,并上传到 oss 服务器
+ *
+ * 发起合同签署流程后,根据返回的流程Id 更改记录;收到完成签署异步通知之后,更改正式签署合同的地址
+ *
+ * @param mchMobile 商家注册手机号
+ * @param contractFileId 未签署合同文件Id
+ * @param signFlowId 合同签署流程ID(signFlowId和fileUrl 起码一个是必填的)
+ * @param fileUrl E签宝的正式签署合同文件地址(可空)
+ * @return
+ */
+ @Override
+ public Boolean updateContractFlowIdAndFileUrl(String mchMobile, String contractFileId, String signFlowId, String fileUrl) {
+ if (StrUtil.isBlank(mchMobile) || StrUtil.isBlank(contractFileId) || (StrUtil.isBlank(signFlowId) && StrUtil.isBlank(fileUrl))) {
+ return false;
+ }
+
+ UpdateWrapper queryWrapper = new UpdateWrapper<>();
+ queryWrapper.eq("mch_mobile", mchMobile);
+ queryWrapper.eq("contract_file_id", contractFileId);
+ queryWrapper.eq("status", CommonConstant.Enable);
+
+ if (StrUtil.isNotBlank(signFlowId)) {
+ queryWrapper.set("sign_flow_id", signFlowId);
+ }
+
+ if (StrUtil.isNotBlank(fileUrl)) {
+ queryWrapper.set("signed_contract_url", fileUrl);
+
+ // REMARK 把合同文件 url 上传到cos服务器
+ String cosFileName = TENGXUN_DEFAULT_DIR.concat("/").concat("contract")
+ .concat("/")
+ .concat("signed").concat("/")
+ .concat(contractFileId).concat(".pdf");
+ // 上传到cos服务器
+ String localFileUrl = ossService.uploadObject4OSS(fileUrl, cosFileName);
+ queryWrapper.set("local_contract_url", localFileUrl);
+ }
+
+ return this.update(queryWrapper);
+ }
+
+ /**
+ * 商家入驻审核通过,模版就绪之后,预创建签署流程。
+ *
+ * @param mchMobile
+ * @param templateId
+ * @return
+ */
+ @Override
+ public Boolean preCreateSignFlow(String mchMobile, String templateId) {
+ if (StrUtil.isBlank(mchMobile) || StrUtil.isBlank(templateId)) {
+ return false;
+ }
+
+ EsignContractFillingFile esignContractFillingFile = esignContractFillingFileService.getEsignContractFillingFile(mchMobile, templateId);
+ if (esignContractFillingFile == null || !esignContractFillingFile.getStatus().equals(CommonConstant.Enable)) {
+ return false;
+ }
+
+ // 获取商家审核通过的入驻信息
+ ShopMerchEntry shopMerchEntry = shopMerchEntryService.getShopMerchEntryByLicenseNumber(esignContractFillingFile.getMobile(), "", CommonConstant.MCH_APPR_STA_PASS);
+ if (shopMerchEntry == null) {
+ return false;
+ }
+
+ // 获取乙方平台方信息
+ EsignPlatformInfo esignPlatformInfo = esignPlatformInfoService.getEsignPlatformInfo(0, "");
+ if (esignPlatformInfo == null) {
+ return false;
+ }
+
+ // 未签合同文件ID
+ String fileId = esignContractFillingFile.getFile_id();
+
+ // 组织生成签署合同的请求参数。
+ String reqParams = buildSignReqParams(shopMerchEntry, esignPlatformInfo, esignContractFillingFile);
+
+ // 保存签署合同记录
+ EsignContract esignContract = new EsignContract();
+ esignContract.setContract_number(esignContractFillingFile.getContract_number());
+ esignContract.setDoc_template_id(esignContractFillingFile.getDoc_template_id());
+ esignContract.setContract_name(esignContractFillingFile.getContract_name());
+ esignContract.setContract_file_id(fileId);
+ esignContract.setMch_mobile(esignContractFillingFile.getMobile());
+ esignContract.setMch_company(shopMerchEntry.getBiz_license_company());
+ esignContract.setMch_biz_license(shopMerchEntry.getBiz_license_number());
+ esignContract.setReq_params(reqParams);
+ esignContract.setUnsigned_contract_url(esignContractFillingFile.getUnsigned_contract_local_url());
+ esignContract.setStore_id(esignContractFillingFile.getStore_id());
+ esignContract.setSign_flow_status(-1);//合作方签署状态:-1:预备数据阶段;1-等待签署;2 - 已完成(所有签署方完成签署)3 - 已撤销(发起方撤销签署任务)5 - 已过期(签署截止日到期后触发)7 - 已拒签(签署方拒绝签署)
+
+ return saveOrUpdateByMchMobile(esignContract);
+ }
+
+ /**
+ * 根据商家的注册手机号,新增或更新签署合同记录。
+ *
+ * @param esignContract
+ * @return
+ */
+ public Boolean saveOrUpdateByMchMobile(EsignContract esignContract) {
+ if (esignContract == null || esignContract.getMch_mobile() == null) {
+ return false;
+ }
+
+ QueryWrapper queryWrapper = new QueryWrapper<>();
+ queryWrapper.eq("mch_mobile", esignContract.getMch_mobile());
+
+ return saveOrUpdate(esignContract, queryWrapper);
+ }
+
+ /**
+ * 组织生成签署合同的请求参数。
+ *
+ * @param shopMerchEntry
+ * @param esignPlatformInfo
+ * @param esignContractFillingFile
+ * @return
+ */
+ protected String buildSignReqParams(ShopMerchEntry shopMerchEntry, EsignPlatformInfo esignPlatformInfo, EsignContractFillingFile esignContractFillingFile) {
+ if (shopMerchEntry == null || esignPlatformInfo == null || esignContractFillingFile == null) {
+ return "";
+ }
+
+ String fileId = esignContractFillingFile.getFile_id();
+ JSONObject reqParams = new JSONObject();
+
+ String contractName = esignContractFillingFile.getContract_name();
+
+ JSONArray docs = new JSONArray();
+ docs.add(new JSONObject().put("fileId", fileId).put("fileName", contractName + ".pdf"));
+ reqParams.put("docs", docs);
+
+
+ JSONObject signFlowConfig = new JSONObject();
+ signFlowConfig.put("signFlowTitle", contractName);
+ signFlowConfig.put("signFlowExpireTime", System.currentTimeMillis() + 90L * 24 * 60 * 60 * 1000); // 90天
+ signFlowConfig.put("autoFinish", true);
+ signFlowConfig.put("notifyUrl", main_domain + "/admin/shop/esign/asyn/notify");
+ signFlowConfig.putByPath("signFlowConfig.redirectUrl", "wechat://back");
+ reqParams.put("signFlowConfig", signFlowConfig);
+
+ // 签署双方信息
+ JSONArray signers = new JSONArray();
+
+ // 甲方商户信息
+ JSONObject mchSigner = new JSONObject();
+ mchSigner.putByPath("signConfig.signOrder", 1);
+ mchSigner.putByPath("noticeConfig.noticeTypes", "1");// 短信
+ mchSigner.putByPath("signFields", JSONUtil.parseArray(esignContractFillingFile.getMch_sign_position()));
+ if (shopMerchEntry.getEntity_type().equals(CommonConstant.MCH_ENTITY_TYPE_QY)) {
+ // 企业
+ mchSigner.put("signerType", 1);
+ mchSigner.putByPath("orgSignerInfo.orgName", shopMerchEntry.getBiz_license_company());
+ mchSigner.putByPath("orgSignerInfo.orgInfo.orgIDCardNum", shopMerchEntry.getBiz_license_number());
+ mchSigner.putByPath("orgSignerInfo.orgInfo.orgIDCardType", "CRED_ORG_USCC");
+ mchSigner.putByPath("orgSignerInfo.transactorInfo.psnAccount", shopMerchEntry.getLogin_mobile());
+ mchSigner.putByPath("orgSignerInfo.transactorInfo.psnInfo.psnName", shopMerchEntry.getLegal_person_name());
+ } else {
+ // 个人
+ mchSigner.put("signerType", 0);
+ mchSigner.putByPath("psnSignerInfo.psnAccount", shopMerchEntry.getLogin_mobile());
+ mchSigner.putByPath("psnSignerInfo.psnInfo.psnName", shopMerchEntry.getContact_name());
+ }
+ // 加入甲方信息
+ signers.add(mchSigner);
+
+ // 乙方平台方信息
+ JSONObject platSigner = new JSONObject();
+ platSigner.putByPath("signConfig.signOrder", 1);
+ platSigner.putByPath("noticeConfig.noticeTypes", "1,2"); // 短信和邮件
+ platSigner.putByPath("signFields", JSONUtil.parseArray(esignContractFillingFile.getPlat_sign_position()));
+ if (shopMerchEntry.getEntity_type().equals(CommonConstant.MCH_ENTITY_TYPE_QY)) {
+ // 企业
+ platSigner.put("signerType", 1);
+ platSigner.putByPath("orgSignerInfo.orgName", esignPlatformInfo.getLicense_company());
+ platSigner.putByPath("orgSignerInfo.orgInfo.orgIDCardNum", esignPlatformInfo.getLicense_number());
+ platSigner.putByPath("orgSignerInfo.orgInfo.orgIDCardType", "CRED_ORG_USCC");
+ platSigner.putByPath("orgSignerInfo.transactorInfo.psnAccount", esignPlatformInfo.getLegal_person_mobile());
+ platSigner.putByPath("orgSignerInfo.transactorInfo.psnInfo.psnName", esignPlatformInfo.getLegal_person_name());
+ } else {
+ // 个人
+ platSigner.put("signerType", 0);
+ platSigner.putByPath("psnSignerInfo.psnAccount", esignPlatformInfo.getLegal_person_mobile());
+ platSigner.putByPath("psnSignerInfo.psnInfo.psnName", shopMerchEntry.getLegal_person_name());
+ }
+ // 加入乙方平台方信息
+ signers.add(platSigner);
+
+ reqParams.put("signers", signers);
+
+ return reqParams.toString();
+ }
}
diff --git a/mall-shop/src/main/java/com/suisung/mall/shop/esign/service/impl/EsignPlatformInfoServiceImpl.java b/mall-shop/src/main/java/com/suisung/mall/shop/esign/service/impl/EsignPlatformInfoServiceImpl.java
index d37503ef..93963837 100644
--- a/mall-shop/src/main/java/com/suisung/mall/shop/esign/service/impl/EsignPlatformInfoServiceImpl.java
+++ b/mall-shop/src/main/java/com/suisung/mall/shop/esign/service/impl/EsignPlatformInfoServiceImpl.java
@@ -38,6 +38,8 @@ public class EsignPlatformInfoServiceImpl extends BaseServiceImpl result = new HashMap<>();
if (record == null || record.getApproval_status() == null) {
+ // 配合前端的要求,没有申请过入驻商城平台的时候,返回未申请状态
result.put("id", 0L);
result.put("approval_status", 4);
result.put("approval_remark", "");
diff --git a/mall-shop/src/main/java/com/suisung/mall/shop/store/service/impl/ShopMerchEntryServiceImpl.java b/mall-shop/src/main/java/com/suisung/mall/shop/store/service/impl/ShopMerchEntryServiceImpl.java
index f6019da3..1b17c1b4 100644
--- a/mall-shop/src/main/java/com/suisung/mall/shop/store/service/impl/ShopMerchEntryServiceImpl.java
+++ b/mall-shop/src/main/java/com/suisung/mall/shop/store/service/impl/ShopMerchEntryServiceImpl.java
@@ -24,6 +24,8 @@ import com.suisung.mall.common.utils.StringUtils;
import com.suisung.mall.common.utils.phone.PhoneNumberUtils;
import com.suisung.mall.core.web.service.impl.BaseServiceImpl;
import com.suisung.mall.shop.base.service.AccountBaseConfigService;
+import com.suisung.mall.shop.components.TaskService;
+import com.suisung.mall.shop.esign.service.EsignContractFillingFileService;
import com.suisung.mall.shop.esign.service.EsignPlatformInfoService;
import com.suisung.mall.shop.message.service.ShopMessageTemplateService;
import com.suisung.mall.shop.store.mapper.ShopMerchEntryMapper;
@@ -51,6 +53,13 @@ public class ShopMerchEntryServiceImpl extends BaseServiceImpl {
+ // 生成电子合同模版和填充模版数据,并生该商家和平台方签署的未盖章合同文件
+ Boolean genSuccess = esignContractFillingFileService.fillDocTemplate(record.getBiz_license_number(), "");
+ if (!genSuccess) {
+ log.error("###商家入驻电子合同生成失败###");
+ }
+ });
+
+
} else if (approvalStatus.equals(CommonConstant.Disable2) && StrUtil.isBlank(approvalRemark)) {
approvalRemark = "审核未通过,请继续完善入驻资料信息。";
}
diff --git a/mall-shop/src/main/resources/bootstrap-dev.yml b/mall-shop/src/main/resources/bootstrap-dev.yml
index 8ce5a8c4..24364d7b 100644
--- a/mall-shop/src/main/resources/bootstrap-dev.yml
+++ b/mall-shop/src/main/resources/bootstrap-dev.yml
@@ -116,6 +116,8 @@ logging:
io: error
reactor: error
springfox: error
+# 项目主域名
+main_domain: @project.domain@
# 个推
getui:
# Url前缀
@@ -137,3 +139,20 @@ sf-express:
appkey: cd57608baa9c00fe1cda5f652b14240d
dev_id: 1711573316
enable: 2
+#拉卡拉进件配置
+lakala:
+ tk:
+ #服务地址
+ server_url: https://test.wsmsd.cn/sit/htkauth
+ client_id: lsycs
+ client_secret: XPa1HB5d55Ig0qV8
+ api_pub_key_path: payKey/lakala/dev/tk_api_public_key.txt
+ api_pri_key_path: payKey/lakala/dev/tk_api_private_key.txt
+#e签宝配置
+esign:
+ server_url: https://smlopenapi.esign.cn
+ #正式地址 https://openapi.esign.cn
+ app_id: 7439053575
+ app_secret: 8da2e1eeeaf88e09bcf432a2fdd3e4d7
+ app_rsa: MIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEAiC+fUc0+O9m45VEcGciJQ5QQNXs3NkHoHM2qDAdrXOnTwku0Be1IPeWUZ4s7w8xqubyirAAJDc3LpRkwCK84NicA2VwraD4on8MNtX8MLALZjLc1jZTmRAPKVfTKAcainR7ET78Y+QKJgezNvI7u45FO4Db+dWCC7pbedxBo+kHKA8im+/G0hpQaklxw1wjIMNv+x+YBnm8FOXRPWJZ+eItF5qJOT2C16QCY7hdeHknom+NMpZD8E/WAMtf03BcgigsoavTVnPI0xnN8BCrgykDWgO5bUXeIgNEF1LJS6r8s6BaMl+ZWbuODtbsrQ941GbFOe6x8tnhPIeehIa1AWQIDAQAB
+ debug: true
diff --git a/mall-shop/src/main/resources/bootstrap-local.yml b/mall-shop/src/main/resources/bootstrap-local.yml
index bbd357d4..3a19a2d7 100644
--- a/mall-shop/src/main/resources/bootstrap-local.yml
+++ b/mall-shop/src/main/resources/bootstrap-local.yml
@@ -116,6 +116,8 @@ logging:
io: error
reactor: error
springfox: error
+# 项目主域名
+main_domain: @project.domain@
# 个推
getui:
# Url前缀
@@ -153,3 +155,4 @@ esign:
app_id: 7439053575
app_secret: 8da2e1eeeaf88e09bcf432a2fdd3e4d7
app_rsa: MIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEAiC+fUc0+O9m45VEcGciJQ5QQNXs3NkHoHM2qDAdrXOnTwku0Be1IPeWUZ4s7w8xqubyirAAJDc3LpRkwCK84NicA2VwraD4on8MNtX8MLALZjLc1jZTmRAPKVfTKAcainR7ET78Y+QKJgezNvI7u45FO4Db+dWCC7pbedxBo+kHKA8im+/G0hpQaklxw1wjIMNv+x+YBnm8FOXRPWJZ+eItF5qJOT2C16QCY7hdeHknom+NMpZD8E/WAMtf03BcgigsoavTVnPI0xnN8BCrgykDWgO5bUXeIgNEF1LJS6r8s6BaMl+ZWbuODtbsrQ941GbFOe6x8tnhPIeehIa1AWQIDAQAB
+ debug: true
\ No newline at end of file
diff --git a/mall-shop/src/main/resources/bootstrap-prod.yml b/mall-shop/src/main/resources/bootstrap-prod.yml
index 824d9aa1..890b72d7 100644
--- a/mall-shop/src/main/resources/bootstrap-prod.yml
+++ b/mall-shop/src/main/resources/bootstrap-prod.yml
@@ -122,6 +122,8 @@ logging:
io: error
reactor: error
springfox: error
+# 项目主域名
+main_domain: @project.domain@
# 个推
getui:
# Url前缀
@@ -161,4 +163,5 @@ esign:
#正式地址 https://openapi.esign.cn
app_id: 7439053575
app_secret: 8da2e1eeeaf88e09bcf432a2fdd3e4d7
- app_rsa: MIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEAiC
\ No newline at end of file
+ app_rsa: MIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEAiC
+ debug: false
\ No newline at end of file
diff --git a/mall-shop/src/main/resources/bootstrap-test.yml b/mall-shop/src/main/resources/bootstrap-test.yml
index 3409fbac..5b3c59a3 100644
--- a/mall-shop/src/main/resources/bootstrap-test.yml
+++ b/mall-shop/src/main/resources/bootstrap-test.yml
@@ -120,6 +120,8 @@ logging:
io: error
reactor: error
springfox: error
+# 项目主域名
+main_domain: @project.domain@
# 个推
getui:
# Url前缀
@@ -140,4 +142,21 @@ sf-express:
appid: 1711573316
appkey: cd57608baa9c00fe1cda5f652b14240d
dev_id: 1711573316
- enable: 2
\ No newline at end of file
+ enable: 2
+#拉卡拉进件配置
+lakala:
+ tk:
+ #服务地址
+ server_url: https://test.wsmsd.cn/sit/htkauth
+ client_id: lsycs
+ client_secret: XPa1HB5d55Ig0qV8
+ api_pub_key_path: payKey/lakala/dev/tk_api_public_key.txt
+ api_pri_key_path: payKey/lakala/dev/tk_api_private_key.txt
+#e签宝配置
+esign:
+ server_url: https://smlopenapi.esign.cn
+ #正式地址 https://openapi.esign.cn
+ app_id: 7439053575
+ app_secret: 8da2e1eeeaf88e09bcf432a2fdd3e4d7
+ app_rsa: MIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEAiC+fUc0+O9m45VEcGciJQ5QQNXs3NkHoHM2qDAdrXOnTwku0Be1IPeWUZ4s7w8xqubyirAAJDc3LpRkwCK84NicA2VwraD4on8MNtX8MLALZjLc1jZTmRAPKVfTKAcainR7ET78Y+QKJgezNvI7u45FO4Db+dWCC7pbedxBo+kHKA8im+/G0hpQaklxw1wjIMNv+x+YBnm8FOXRPWJZ+eItF5qJOT2C16QCY7hdeHknom+NMpZD8E/WAMtf03BcgigsoavTVnPI0xnN8BCrgykDWgO5bUXeIgNEF1LJS6r8s6BaMl+ZWbuODtbsrQ941GbFOe6x8tnhPIeehIa1AWQIDAQAB
+ debug: true
\ No newline at end of file
diff --git a/mall-shop/src/main/resources/bootstrap-uat.yml b/mall-shop/src/main/resources/bootstrap-uat.yml
index 3409fbac..5b3c59a3 100644
--- a/mall-shop/src/main/resources/bootstrap-uat.yml
+++ b/mall-shop/src/main/resources/bootstrap-uat.yml
@@ -120,6 +120,8 @@ logging:
io: error
reactor: error
springfox: error
+# 项目主域名
+main_domain: @project.domain@
# 个推
getui:
# Url前缀
@@ -140,4 +142,21 @@ sf-express:
appid: 1711573316
appkey: cd57608baa9c00fe1cda5f652b14240d
dev_id: 1711573316
- enable: 2
\ No newline at end of file
+ enable: 2
+#拉卡拉进件配置
+lakala:
+ tk:
+ #服务地址
+ server_url: https://test.wsmsd.cn/sit/htkauth
+ client_id: lsycs
+ client_secret: XPa1HB5d55Ig0qV8
+ api_pub_key_path: payKey/lakala/dev/tk_api_public_key.txt
+ api_pri_key_path: payKey/lakala/dev/tk_api_private_key.txt
+#e签宝配置
+esign:
+ server_url: https://smlopenapi.esign.cn
+ #正式地址 https://openapi.esign.cn
+ app_id: 7439053575
+ app_secret: 8da2e1eeeaf88e09bcf432a2fdd3e4d7
+ app_rsa: MIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEAiC+fUc0+O9m45VEcGciJQ5QQNXs3NkHoHM2qDAdrXOnTwku0Be1IPeWUZ4s7w8xqubyirAAJDc3LpRkwCK84NicA2VwraD4on8MNtX8MLALZjLc1jZTmRAPKVfTKAcainR7ET78Y+QKJgezNvI7u45FO4Db+dWCC7pbedxBo+kHKA8im+/G0hpQaklxw1wjIMNv+x+YBnm8FOXRPWJZ+eItF5qJOT2C16QCY7hdeHknom+NMpZD8E/WAMtf03BcgigsoavTVnPI0xnN8BCrgykDWgO5bUXeIgNEF1LJS6r8s6BaMl+ZWbuODtbsrQ941GbFOe6x8tnhPIeehIa1AWQIDAQAB
+ debug: true
\ No newline at end of file