|
@@ -8,10 +8,7 @@ import lombok.extern.log4j.Log4j2;
|
|
|
import org.apache.shiro.SecurityUtils;
|
|
|
import org.jeecg.common.exception.JeecgBootException;
|
|
|
import org.jeecg.common.system.vo.LoginUser;
|
|
|
-import org.jeecg.modules.app.dto.DocTemplateDTO;
|
|
|
-import org.jeecg.modules.app.dto.ExternalAuthRequestDTO;
|
|
|
-import org.jeecg.modules.app.dto.GetPsnAuthUrlDTO;
|
|
|
-import org.jeecg.modules.app.dto.SealInfoDTO;
|
|
|
+import org.jeecg.modules.app.dto.*;
|
|
|
import org.jeecg.modules.app.esign.comm.EsignHttpResponse;
|
|
|
import org.jeecg.modules.app.esign.exception.EsignDemoException;
|
|
|
import org.jeecg.modules.app.esign.fileAndTemplate.FileDemo;
|
|
@@ -160,39 +157,39 @@ public class ESignServiceImpl implements IESignService {
|
|
|
@Override
|
|
|
@Transactional(rollbackFor = Exception.class)
|
|
|
public List<String> createSign(String orderCode){
|
|
|
- List<String> signFlowIds = new ArrayList<>();
|
|
|
- AppOrder appOrder = orderMapper.selectOne(Wrappers.<AppOrder>lambdaQuery()
|
|
|
- .eq(AppOrder::getOrderCode, orderCode));
|
|
|
-
|
|
|
- List<String> familyIds = Arrays.asList(appOrder.getFamilyIds().split(","));
|
|
|
- AppContractInfo contractInfo = appAccountMapper.selectById(appOrder.getContractNo());
|
|
|
- SysDepart sysDepart = sysDepartMapper.selectOne(Wrappers.<SysDepart>lambdaQuery()
|
|
|
- .eq(SysDepart::getOrgCode, appOrder.getOrgCode()));
|
|
|
-
|
|
|
- // 预加载家庭成员信息
|
|
|
- Map<String, FamilyMembers> familyMemberMap = familyIds.stream()
|
|
|
- .map(familyMembersMapper::selectById)
|
|
|
- .collect(Collectors.toMap(FamilyMembers::getId, fm -> fm));
|
|
|
-
|
|
|
- // 构建签署流程
|
|
|
- familyIds.forEach(familyId -> {
|
|
|
- try {
|
|
|
- FamilyMembers familyMembers = familyMemberMap.get(familyId);
|
|
|
- JsonObject dto = buildSignFlowDto(contractInfo, sysDepart, familyMembers);
|
|
|
-
|
|
|
- EsignHttpResponse response = createByFile(dto.toString());
|
|
|
- String signFlowId = extractSignFlowId(response);
|
|
|
-
|
|
|
- log.info("生成签署流程ID: {}", signFlowId);
|
|
|
- signFlowIds.add(signFlowId);
|
|
|
- saveSignFlowRecord(signFlowId, appOrder, familyId);
|
|
|
- } catch (EsignDemoException e) {
|
|
|
- log.error("签署流程创建失败,订单号: {}", orderCode, e);
|
|
|
- throw new JeecgBootException(e.getMessage());
|
|
|
- }
|
|
|
+ List<String> signFlowIds = new ArrayList<>();
|
|
|
+ AppOrder appOrder = orderMapper.selectOne(Wrappers.<AppOrder>lambdaQuery()
|
|
|
+ .eq(AppOrder::getOrderCode, orderCode));
|
|
|
+
|
|
|
+ List<String> familyIds = Arrays.asList(appOrder.getFamilyIds().split(","));
|
|
|
+ AppContractInfo contractInfo = appAccountMapper.selectById(appOrder.getContractNo());
|
|
|
+ SysDepart sysDepart = sysDepartMapper.selectOne(Wrappers.<SysDepart>lambdaQuery()
|
|
|
+ .eq(SysDepart::getOrgCode, appOrder.getOrgCode()));
|
|
|
+
|
|
|
+ // 预加载家庭成员信息
|
|
|
+ Map<String, FamilyMembers> familyMemberMap = familyIds.stream()
|
|
|
+ .map(familyMembersMapper::selectById)
|
|
|
+ .collect(Collectors.toMap(FamilyMembers::getId, fm -> fm));
|
|
|
+
|
|
|
+ // 构建签署流程
|
|
|
+ familyIds.forEach(familyId -> {
|
|
|
+ try {
|
|
|
+ FamilyMembers familyMembers = familyMemberMap.get(familyId);
|
|
|
+ JsonObject dto = buildSignFlowDto(contractInfo, sysDepart, familyMembers);
|
|
|
+
|
|
|
+ EsignHttpResponse response = createByFile(dto.toString());
|
|
|
+ String signFlowId = extractSignFlowId(response);
|
|
|
+
|
|
|
+ log.info("生成签署流程ID: {}", signFlowId);
|
|
|
+ signFlowIds.add(signFlowId);
|
|
|
+ saveSignFlowRecord(signFlowId, appOrder, familyId);
|
|
|
+ } catch (EsignDemoException e) {
|
|
|
+ log.error("签署流程创建失败,订单号: {}", orderCode, e);
|
|
|
+ throw new JeecgBootException(e.getMessage());
|
|
|
+ }
|
|
|
});
|
|
|
|
|
|
- return signFlowIds;
|
|
|
+ return signFlowIds;
|
|
|
}
|
|
|
/**
|
|
|
* 构建签署流程请求体
|
|
@@ -262,76 +259,55 @@ public class ESignServiceImpl implements IESignService {
|
|
|
return dto;
|
|
|
}
|
|
|
|
|
|
- /**
|
|
|
- * 构建签署人信息
|
|
|
- */
|
|
|
- private JsonArray buildSigners(AppContractInfo contractInfo, FamilyMembers familyMembers,String orgId) throws EsignDemoException {
|
|
|
- JsonArray signers = new JsonArray();
|
|
|
-
|
|
|
- // 获取模板组件信息
|
|
|
- EsignHttpResponse getComponentsInfo = getComponentsInfo(contractInfo.getDocTemplateId());
|
|
|
- JsonObject getComponentsInfoObject = gson.fromJson(getComponentsInfo.getBody(), JsonObject.class);
|
|
|
+ private SignPositionGroup groupComponentPositions(JsonObject getComponentsInfoObject) {
|
|
|
+ SignPositionGroup group = new SignPositionGroup();
|
|
|
+ List<SignPositionGroup.ComponentPosition> merchant = new ArrayList<>();
|
|
|
+ List<SignPositionGroup.ComponentPosition> customer = new ArrayList<>();
|
|
|
|
|
|
- if (!getComponentsInfoObject.has("data") || !getComponentsInfoObject.getAsJsonObject("data").has("components")) {
|
|
|
- throw new EsignDemoException("模板组件信息缺失");
|
|
|
- }
|
|
|
-
|
|
|
- JsonArray components = getComponentsInfoObject.getAsJsonObject("data").getAsJsonArray("components");
|
|
|
+ JsonArray components = getComponentsInfoObject
|
|
|
+ .getAsJsonObject("data")
|
|
|
+ .getAsJsonArray("components");
|
|
|
|
|
|
- // 构建签署人结构
|
|
|
- JsonObject signer1 = new JsonObject();
|
|
|
- JsonObject signer2 = new JsonObject();
|
|
|
- JsonArray personalSignFields = new JsonArray();
|
|
|
- JsonArray enterpriseSignFields = new JsonArray();
|
|
|
-
|
|
|
- // 设置签署人基础信息
|
|
|
- setupSignerBaseInfo(signer1, familyMembers, 0); // 个人签署人
|
|
|
- if (orgId != null) {
|
|
|
- setupEnterpriseSigner(signer2, orgId); // 企业签署人
|
|
|
- }
|
|
|
-
|
|
|
- // 遍历组件并分配签署区域
|
|
|
for (JsonElement element : components) {
|
|
|
JsonObject component = element.getAsJsonObject();
|
|
|
- JsonObject specialAttribute = component.getAsJsonObject("componentSpecialAttribute");
|
|
|
+ String role = component
|
|
|
+ .getAsJsonObject("componentSpecialAttribute")
|
|
|
+ .get("signerRole").getAsString();
|
|
|
|
|
|
- if (specialAttribute != null && specialAttribute.has("signerRole")) {
|
|
|
- String signerRole = specialAttribute.get("signerRole").getAsString();
|
|
|
- JsonObject position = component.getAsJsonObject("componentPosition");
|
|
|
- JsonObject size = component.getAsJsonObject("componentSize");
|
|
|
+ JsonObject position = component
|
|
|
+ .getAsJsonObject("componentPosition");
|
|
|
|
|
|
- int x = position.get("componentPositionX").getAsInt();
|
|
|
- int y = position.get("componentPositionY").getAsInt();
|
|
|
- int width = size.get("componentWidth").getAsInt();
|
|
|
- int height = size.get("componentHeight").getAsInt();
|
|
|
+ int x = position.get("componentPositionX").getAsInt();
|
|
|
+ int y = position.get("componentPositionY").getAsInt();
|
|
|
|
|
|
- JsonObject signField = buildSignFieldFromComponent(contractInfo.getFileId(), x, y, width, height, "商户".equals(signerRole));
|
|
|
+ SignPositionGroup.ComponentPosition cp = new SignPositionGroup.ComponentPosition(x, y);
|
|
|
|
|
|
- if ("用户".equals(signerRole)) {
|
|
|
- personalSignFields.add(signField);
|
|
|
- } else if ("商户".equals(signerRole)) {
|
|
|
- enterpriseSignFields.add(signField);
|
|
|
- }
|
|
|
+ if ("商户".equals(role)) {
|
|
|
+ merchant.add(cp);
|
|
|
+ } else if ("用户".equals(role)) {
|
|
|
+ customer.add(cp);
|
|
|
}
|
|
|
}
|
|
|
-
|
|
|
- // 添加签署区域
|
|
|
- if (!personalSignFields.isEmpty()) {
|
|
|
- signer1.add("signFields", personalSignFields);
|
|
|
- signers.add(signer1);
|
|
|
- }
|
|
|
-
|
|
|
- if (!enterpriseSignFields.isEmpty()) {
|
|
|
- signer2.add("signFields", enterpriseSignFields);
|
|
|
- signers.add(signer2);
|
|
|
- }
|
|
|
-
|
|
|
- return signers;
|
|
|
+ group.setMerchant(merchant);
|
|
|
+ group.setCustomer(customer);
|
|
|
+ return group;
|
|
|
}
|
|
|
|
|
|
-
|
|
|
- private void setupSignerBaseInfo(JsonObject signer, FamilyMembers familyMembers, int signerType) {
|
|
|
- signer.addProperty("signerType", signerType);
|
|
|
+ /**
|
|
|
+ * 构建签署人信息
|
|
|
+ */
|
|
|
+ private JsonArray buildSigners(AppContractInfo contractInfo, FamilyMembers familyMembers,String orgId) throws EsignDemoException {
|
|
|
+ JsonArray signers = new JsonArray();
|
|
|
+ EsignHttpResponse getComponentsInfo = getComponentsInfo(contractInfo.getDocTemplateId());
|
|
|
+ JsonObject getComponentsInfoObject = gson.fromJson(getComponentsInfo.getBody(), JsonObject.class);
|
|
|
+ System.err.println("查询模板详情返回:"+getComponentsInfoObject);
|
|
|
+ SignPositionGroup positionGroup = groupComponentPositions(getComponentsInfoObject);
|
|
|
+ // 个人签署人
|
|
|
+ JsonObject signer1 = new JsonObject();
|
|
|
+ signer1.add("signConfig", buildSignConfig(1, 10));
|
|
|
+ signer1.add("noticeConfig", buildNoticeConfig(""));
|
|
|
+ signer1.addProperty("signerType", 0);
|
|
|
+ // 签署人信息
|
|
|
JsonObject psnSignerInfo = new JsonObject();
|
|
|
psnSignerInfo.addProperty("psnAccount", familyMembers.getPhone());
|
|
|
|
|
@@ -340,18 +316,29 @@ public class ESignServiceImpl implements IESignService {
|
|
|
psnInfo.addProperty("psnIDCardNum", familyMembers.getIdentityCard());
|
|
|
psnInfo.addProperty("psnIDCardType", "CRED_PSN_CH_IDCARD");
|
|
|
psnSignerInfo.add("psnInfo", psnInfo);
|
|
|
- signer.add("psnSignerInfo", psnSignerInfo);
|
|
|
-
|
|
|
- // 添加签署配置和通知配置
|
|
|
- signer.add("signConfig", buildSignConfig(1, 10));
|
|
|
- signer.add("noticeConfig", buildNoticeConfig(""));
|
|
|
- }
|
|
|
|
|
|
- private void setupEnterpriseSigner(JsonObject signer, String orgId) {
|
|
|
- signer.addProperty("signerType", 1);
|
|
|
+ signer1.add("psnSignerInfo", psnSignerInfo);
|
|
|
+ positionGroup.getCustomer().forEach(position -> {
|
|
|
+ signer1.add("signFields", buildSignFields(contractInfo.getFileId(), position.getX(), position.getY(), 100, 0, 0,false,""));
|
|
|
+ });
|
|
|
+// signer1.add("signFields", buildSignFields(contractInfo.getFileId(), 100, 200, 96, 100, 100,false,""));
|
|
|
+ // 企业签署人
|
|
|
+ JsonObject signer2 = new JsonObject();
|
|
|
+ signer2.addProperty("signerType", 1);
|
|
|
JsonObject orgSignerInfo = new JsonObject();
|
|
|
orgSignerInfo.addProperty("orgId", orgId);
|
|
|
- signer.add("orgSignerInfo", orgSignerInfo);
|
|
|
+ positionGroup.getMerchant().forEach(position -> {
|
|
|
+ try {
|
|
|
+ signer2.add("signFields", buildSignFields(contractInfo.getFileId(), position.getX(), position.getY(), 100, 0, 0,true,orgAuthorizedSeal(orgId)));
|
|
|
+ } catch (EsignDemoException e) {
|
|
|
+ throw new RuntimeException(e);
|
|
|
+ }
|
|
|
+ });
|
|
|
+// signer2.add("signFields", buildSignFields(contractInfo.getFileId(), 300, 200, 159, 300, 100,true,orgAuthorizedSeal(orgId)));
|
|
|
+
|
|
|
+ signers.add(signer1);
|
|
|
+ signers.add(signer2);
|
|
|
+ return signers;
|
|
|
}
|
|
|
|
|
|
/**
|
|
@@ -373,9 +360,16 @@ public class ESignServiceImpl implements IESignService {
|
|
|
return noticeConfig;
|
|
|
}
|
|
|
|
|
|
-
|
|
|
- private JsonObject buildSignFieldFromComponent(String fileId, int x, int y, int width, int height, boolean autoSign) {
|
|
|
+ /**
|
|
|
+ * 构建签署区域
|
|
|
+ */
|
|
|
+ private JsonArray buildSignFields(String fileId,
|
|
|
+ int x, int y,
|
|
|
+ int size,
|
|
|
+ int dateX, int dateY,boolean autoSign,String signature) {
|
|
|
+ JsonArray signFields = new JsonArray();
|
|
|
JsonObject field = new JsonObject();
|
|
|
+
|
|
|
field.addProperty("fileId", fileId);
|
|
|
field.addProperty("customBizNum", "自定义编码0001");
|
|
|
field.addProperty("signFieldType", 0);
|
|
@@ -386,8 +380,9 @@ public class ESignServiceImpl implements IESignService {
|
|
|
normalConfig.addProperty("freeMode", false);
|
|
|
normalConfig.addProperty("movableSignField", false);
|
|
|
normalConfig.addProperty("psnSealStyles", "0,1");
|
|
|
- normalConfig.addProperty("signFieldSize", String.valueOf(width)); // 使用组件宽度作为尺寸
|
|
|
+ normalConfig.addProperty("signFieldSize", String.valueOf(size));
|
|
|
normalConfig.addProperty("signFieldStyle", 1);
|
|
|
+ normalConfig.addProperty("assignedSealId", signature);
|
|
|
|
|
|
// 位置配置
|
|
|
JsonObject position = new JsonObject();
|
|
@@ -396,18 +391,19 @@ public class ESignServiceImpl implements IESignService {
|
|
|
position.addProperty("positionY", y);
|
|
|
normalConfig.add("signFieldPosition", position);
|
|
|
|
|
|
- // 日期配置(可选)
|
|
|
+ // 日期配置
|
|
|
JsonObject dateConfig = new JsonObject();
|
|
|
dateConfig.addProperty("dateFormat", "yyyy-MM-dd");
|
|
|
dateConfig.addProperty("showSignDate", 1);
|
|
|
- dateConfig.addProperty("signDatePositionX", x + width + 10); // 日期默认在签名右侧
|
|
|
- dateConfig.addProperty("signDatePositionY", y);
|
|
|
+ dateConfig.addProperty("signDatePositionX", dateX);
|
|
|
+ dateConfig.addProperty("signDatePositionY", dateY);
|
|
|
|
|
|
field.add("normalSignFieldConfig", normalConfig);
|
|
|
field.add("signDateConfig", dateConfig);
|
|
|
- return field;
|
|
|
- }
|
|
|
|
|
|
+ signFields.add(field);
|
|
|
+ return signFields;
|
|
|
+ }
|
|
|
|
|
|
/**
|
|
|
* 提取签署流程ID
|
|
@@ -518,10 +514,11 @@ public class ESignServiceImpl implements IESignService {
|
|
|
}
|
|
|
|
|
|
@Override
|
|
|
- public List<SealInfoDTO> orgOwnSeal(String orgId) {
|
|
|
+ public List<SealInfoDTO> orgOwnSeal(String orgCode) {
|
|
|
+ AppSite appSite = appSiteMapper.selectOne(Wrappers.<AppSite>lambdaQuery().eq(AppSite::getOrgCode, orgCode));
|
|
|
try {
|
|
|
// 调用API获取响应
|
|
|
- EsignHttpResponse response = orgOwnSealList(orgId);
|
|
|
+ EsignHttpResponse response = orgOwnSealList(appSite.getEsignOrgId());
|
|
|
|
|
|
// 解析JSON响应
|
|
|
JsonObject result = gson.fromJson(response.getBody(), JsonObject.class);
|
|
@@ -536,10 +533,62 @@ public class ESignServiceImpl implements IESignService {
|
|
|
if (!data.has("seals")) {
|
|
|
throw new JeecgBootException("响应数据中缺少'seals'字段");
|
|
|
}
|
|
|
-
|
|
|
- // 转换数据
|
|
|
- return gson.fromJson(data.getAsJsonArray("seals"),
|
|
|
- new TypeToken<List<SealInfoDTO>>(){}.getType());
|
|
|
+ // 原始数据
|
|
|
+ JsonArray seals = data.getAsJsonArray("seals");
|
|
|
+
|
|
|
+ JsonArray filteredSeals = new JsonArray();
|
|
|
+ for (JsonElement element : seals) {
|
|
|
+ JsonObject seal = element.getAsJsonObject();
|
|
|
+ if ("PUBLIC".equals(seal.get("sealBizType").getAsString())) {
|
|
|
+ filteredSeals.add(seal);
|
|
|
+ }
|
|
|
+ }
|
|
|
+ List<SealInfoDTO> sealInfoDTOList = gson.fromJson(filteredSeals, new TypeToken<List<SealInfoDTO>>(){}.getType());
|
|
|
+ sealInfoDTOList.forEach(a ->{
|
|
|
+ a.setOrgCode(orgCode);
|
|
|
+ try {
|
|
|
+ // 调用接口获取授权信息
|
|
|
+ EsignHttpResponse response1 = orgSealsExternalAuth(appSite.getEsignOrgId(), a.getSealId());
|
|
|
+ JsonObject result1 = gson.fromJson(response1.getBody(), JsonObject.class);
|
|
|
+
|
|
|
+ // 检查 data 字段
|
|
|
+ if (!result1.has("data")) {
|
|
|
+ log.warn("授权信息中缺少 data 字段");
|
|
|
+ a.setIsStatus(false);
|
|
|
+ return;
|
|
|
+ }
|
|
|
+
|
|
|
+ JsonObject data1 = result1.getAsJsonObject("data");
|
|
|
+ if (!data1.has("sealAuthorizedInfos")) {
|
|
|
+ log.warn("授权信息中缺少 sealAuthorizedInfos 字段");
|
|
|
+ a.setIsStatus(false);
|
|
|
+ return;
|
|
|
+ }
|
|
|
+
|
|
|
+ // 遍历授权信息列表
|
|
|
+ JsonArray sealAuthorizedInfos = data1.getAsJsonArray("sealAuthorizedInfos");
|
|
|
+ boolean isValid = false;
|
|
|
+
|
|
|
+ for (JsonElement element : sealAuthorizedInfos) {
|
|
|
+ JsonObject info = element.getAsJsonObject();
|
|
|
+ String expireReason = info.get("expireReasonDescription").getAsString();
|
|
|
+ String status = info.get("statusDescription").getAsString();
|
|
|
+
|
|
|
+ if ("未失效".equals(expireReason) && "正常".equals(status)) {
|
|
|
+ isValid = true;
|
|
|
+ break;
|
|
|
+ }
|
|
|
+ }
|
|
|
+
|
|
|
+ // 设置 isStatus 字段
|
|
|
+ a.setIsStatus(isValid);
|
|
|
+
|
|
|
+ } catch (EsignDemoException | JsonSyntaxException e) {
|
|
|
+ log.error("处理印章授权状态失败,sealId: {}", a.getSealId(), e);
|
|
|
+ a.setIsStatus(false);
|
|
|
+ }
|
|
|
+ });
|
|
|
+ return sealInfoDTOList;
|
|
|
|
|
|
} catch (JsonSyntaxException e) {
|
|
|
throw new JeecgBootException("JSON解析失败: " + e.getMessage(), e);
|