日志完善

This commit is contained in:
2026-06-17 10:01:57 +08:00
parent 8b80288947
commit 02eab7ca01
7 changed files with 300 additions and 8 deletions
@@ -46,6 +46,9 @@ public interface ContractLaunchMapper {
/** 根据 contractSysId 查询合同(法务回调时用于定位) */ /** 根据 contractSysId 查询合同(法务回调时用于定位) */
ContractLaunchDto selectContractByContractSysId(@Param("contractSysId") String contractSysId); ContractLaunchDto selectContractByContractSysId(@Param("contractSysId") String contractSysId);
/** 根据 sealContractId 查询合同(签章平台回调时用于定位) */
ContractLaunchDto selectContractBySealContractId(@Param("sealContractId") String sealContractId);
/** 新增合同 */ /** 新增合同 */
int insertContract(ContractLaunchDto contract); int insertContract(ContractLaunchDto contract);
@@ -451,12 +451,21 @@ public class ContractLaunchServiceImpl implements ContractLaunchService {
contract.setUpdateTime(completedTime); contract.setUpdateTime(completedTime);
contractLaunchMapper.updateContract(contract); contractLaunchMapper.updateContract(contract);
saveSignedFile(id, sealDto, currentUser.getUsername()); saveSignedFile(id, sealDto, currentUser.getUsername());
// 区分在线签署完成和线下签署上传两种场景记录日志
boolean isOfflineUpload = sealDto.getSignedOfflineReason() != null && !sealDto.getSignedOfflineReason().isBlank();
if (isOfflineUpload) {
// 线下签署:先记录上传行为,再记录签署完成
insertLog(id, ContractLaunchConstants.ACTION_SEAL_UPLOAD,
"上传已签署版本", ContractLaunchConstants.ACTION_STATUS_SUCCESS,
"线下签署原因: " + sealDto.getSignedOfflineReason(), sealDto, currentUser);
}
insertLog( insertLog(
id, id,
ContractLaunchConstants.ACTION_SEAL_FINISH, ContractLaunchConstants.ACTION_SEAL_FINISH,
singleAgreement ? "盖章完成" : "签署完成", singleAgreement ? "盖章完成" : (isOfflineUpload ? "线下签署完成" : "在线签署完成"),
ContractLaunchConstants.ACTION_STATUS_SUCCESS, ContractLaunchConstants.ACTION_STATUS_SUCCESS,
singleAgreement ? "单方协议已盖章生效,流程完成" : "合同签署已完成,待采集", singleAgreement ? "单方协议已盖章生效,流程完成"
: (isOfflineUpload ? "线下签署文件已上传,待采集" : "合同在线签署已完成,待采集"),
sealDto, sealDto,
currentUser currentUser
); );
@@ -46,6 +46,24 @@ public final class ContractLaunchConstants {
public static final String ACTION_TERMINATE = "terminate"; public static final String ACTION_TERMINATE = "terminate";
public static final String ACTION_CHANGE = "change"; public static final String ACTION_CHANGE = "change";
// ==================== 签章平台操作日志 ====================
/** 创建签署流程(签章平台合同创建) */
public static final String ACTION_SEAL_CREATE = "seal_create";
/** 签章平台签署确认(托管签署) */
public static final String ACTION_SEAL_SIGN = "seal_sign";
/** 签章平台签署完成(完结签署流程) */
public static final String ACTION_SEAL_COMPLETE = "seal_complete";
/** 签章平台取消签署 */
public static final String ACTION_SEAL_CANCEL = "seal_cancel";
/** 签章平台时间戳签章 */
public static final String ACTION_SEAL_TIMESTAMP = "seal_timestamp";
/** 签章平台批注签章 */
public static final String ACTION_SEAL_COMMENT = "seal_comment";
/** 签章平台回调通知 */
public static final String ACTION_SEAL_CALLBACK = "seal_callback";
/** 线下签署文件上传 */
public static final String ACTION_SEAL_UPLOAD = "seal_upload";
public static final String ACTION_STATUS_SUCCESS = "success"; public static final String ACTION_STATUS_SUCCESS = "success";
public static final String ACTION_STATUS_FAILED = "failed"; public static final String ACTION_STATUS_FAILED = "failed";
public static final String ACTION_STATUS_PENDING = "pending"; public static final String ACTION_STATUS_PENDING = "pending";
@@ -2,7 +2,9 @@ package com.nbport.zgwl.seal.controller;
import com.alibaba.fastjson2.JSON; import com.alibaba.fastjson2.JSON;
import com.nbport.zgwl.common.R; import com.nbport.zgwl.common.R;
import com.nbport.zgwl.contractlaunch.utils.ContractLaunchConstants;
import com.nbport.zgwl.seal.handler.SealWebSocketHandler; import com.nbport.zgwl.seal.handler.SealWebSocketHandler;
import com.nbport.zgwl.seal.service.SealLogService;
import org.slf4j.Logger; import org.slf4j.Logger;
import org.slf4j.LoggerFactory; import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired; import org.springframework.beans.factory.annotation.Autowired;
@@ -18,6 +20,9 @@ import java.util.Map;
/** /**
* 签章平台回调接口控制器 * 签章平台回调接口控制器
* *
* 接收签章平台推送的回调通知,将关键回调写入合同操作日志表,
* 实现签署过程全程留痕。
*
* @author xiaofengzhou * @author xiaofengzhou
*/ */
@RestController @RestController
@@ -29,6 +34,9 @@ public class SealCallbackController {
@Autowired @Autowired
private SealWebSocketHandler webSocketHandler; private SealWebSocketHandler webSocketHandler;
@Autowired
private SealLogService sealLogService;
@PostMapping("/login") @PostMapping("/login")
public R<String> loginCallback(@RequestBody Map<String, Object> params) { public R<String> loginCallback(@RequestBody Map<String, Object> params) {
log.info("收到身份认证回调: {}", JSON.toJSONString(params)); log.info("收到身份认证回调: {}", JSON.toJSONString(params));
@@ -36,9 +44,15 @@ public class SealCallbackController {
try { try {
String requestId = (String) params.get("requestId"); String requestId = (String) params.get("requestId");
webSocketHandler.sendCallbackMessage(requestId, "login", params); webSocketHandler.sendCallbackMessage(requestId, "login", params);
// 身份认证回调记录日志(不关联具体合同)
sealLogService.logSealAction(null, ContractLaunchConstants.ACTION_SEAL_CALLBACK,
"身份认证回调", "身份认证回调已接收,requestId: " + requestId, params);
return R.success("回调接收成功"); return R.success("回调接收成功");
} catch (Exception e) { } catch (Exception e) {
log.error("处理身份认证回调失败", e); log.error("处理身份认证回调失败", e);
sealLogService.logSealAction(null, ContractLaunchConstants.ACTION_SEAL_CALLBACK,
"身份认证回调", ContractLaunchConstants.ACTION_STATUS_FAILED,
"处理身份认证回调失败: " + e.getMessage(), params);
return R.error("回调处理失败: " + e.getMessage()); return R.error("回调处理失败: " + e.getMessage());
} }
} }
@@ -52,9 +66,18 @@ public class SealCallbackController {
String requestId = (String) params.get("requestId"); String requestId = (String) params.get("requestId");
webSocketHandler.sendCallbackMessage(requestId, "sign", params); webSocketHandler.sendCallbackMessage(requestId, "sign", params);
webSocketHandler.sendCallbackMessage(contractId, "contract_status", params); webSocketHandler.sendCallbackMessage(contractId, "contract_status", params);
// 签署回调记录日志(关联到本系统合同)
Long internalContractId = sealLogService.findContractIdBySealContractId(contractId);
sealLogService.logSealAction(internalContractId, ContractLaunchConstants.ACTION_SEAL_CALLBACK,
"签署回调", "收到签章平台签署回调,签章平台合同ID: " + contractId, params);
return R.success("回调接收成功"); return R.success("回调接收成功");
} catch (Exception e) { } catch (Exception e) {
log.error("处理签署回调失败", e); log.error("处理签署回调失败", e);
String contractId = (String) params.get("contractId");
Long internalContractId = sealLogService.findContractIdBySealContractId(contractId);
sealLogService.logSealAction(internalContractId, ContractLaunchConstants.ACTION_SEAL_CALLBACK,
"签署回调", ContractLaunchConstants.ACTION_STATUS_FAILED,
"处理签署回调失败: " + e.getMessage(), params);
return R.error("回调处理失败: " + e.getMessage()); return R.error("回调处理失败: " + e.getMessage());
} }
} }
@@ -68,9 +91,18 @@ public class SealCallbackController {
String requestId = (String) params.get("requestId"); String requestId = (String) params.get("requestId");
webSocketHandler.sendCallbackMessage(requestId, "presign", params); webSocketHandler.sendCallbackMessage(requestId, "presign", params);
webSocketHandler.sendCallbackMessage(contractId, "contract_status", params); webSocketHandler.sendCallbackMessage(contractId, "contract_status", params);
// 预盖章回调记录日志(关联到本系统合同)
Long internalContractId = sealLogService.findContractIdBySealContractId(contractId);
sealLogService.logSealAction(internalContractId, ContractLaunchConstants.ACTION_SEAL_CALLBACK,
"预盖章回调", "收到签章平台预盖章回调,签章平台合同ID: " + contractId, params);
return R.success("回调接收成功"); return R.success("回调接收成功");
} catch (Exception e) { } catch (Exception e) {
log.error("处理预盖章回调失败", e); log.error("处理预盖章回调失败", e);
String contractId = (String) params.get("contractId");
Long internalContractId = sealLogService.findContractIdBySealContractId(contractId);
sealLogService.logSealAction(internalContractId, ContractLaunchConstants.ACTION_SEAL_CALLBACK,
"预盖章回调", ContractLaunchConstants.ACTION_STATUS_FAILED,
"处理预盖章回调失败: " + e.getMessage(), params);
return R.error("回调处理失败: " + e.getMessage()); return R.error("回调处理失败: " + e.getMessage());
} }
} }
@@ -82,9 +114,15 @@ public class SealCallbackController {
try { try {
String requestId = (String) params.get("requestId"); String requestId = (String) params.get("requestId");
webSocketHandler.sendCallbackMessage(requestId, "trusteeship", params); webSocketHandler.sendCallbackMessage(requestId, "trusteeship", params);
// 托管章回调记录日志
sealLogService.logSealAction(null, ContractLaunchConstants.ACTION_SEAL_CALLBACK,
"托管章回调", "收到签章平台托管章回调,requestId: " + requestId, params);
return R.success("回调接收成功"); return R.success("回调接收成功");
} catch (Exception e) { } catch (Exception e) {
log.error("处理托管章回调失败", e); log.error("处理托管章回调失败", e);
sealLogService.logSealAction(null, ContractLaunchConstants.ACTION_SEAL_CALLBACK,
"托管章回调", ContractLaunchConstants.ACTION_STATUS_FAILED,
"处理托管章回调失败: " + e.getMessage(), params);
return R.error("回调处理失败: " + e.getMessage()); return R.error("回调处理失败: " + e.getMessage());
} }
} }
@@ -96,9 +134,15 @@ public class SealCallbackController {
try { try {
String requestId = (String) params.get("requestId"); String requestId = (String) params.get("requestId");
webSocketHandler.sendCallbackMessage(requestId, "signQrCode", params); webSocketHandler.sendCallbackMessage(requestId, "signQrCode", params);
// 签名二维码回调记录日志
sealLogService.logSealAction(null, ContractLaunchConstants.ACTION_SEAL_CALLBACK,
"签名二维码回调", "收到签章平台签名二维码回调,requestId: " + requestId, params);
return R.success("回调接收成功"); return R.success("回调接收成功");
} catch (Exception e) { } catch (Exception e) {
log.error("处理签名二维码回调失败", e); log.error("处理签名二维码回调失败", e);
sealLogService.logSealAction(null, ContractLaunchConstants.ACTION_SEAL_CALLBACK,
"签名二维码回调", ContractLaunchConstants.ACTION_STATUS_FAILED,
"处理签名二维码回调失败: " + e.getMessage(), params);
return R.error("回调处理失败: " + e.getMessage()); return R.error("回调处理失败: " + e.getMessage());
} }
} }
@@ -3,7 +3,9 @@ package com.nbport.zgwl.seal.controller;
import com.alibaba.fastjson2.JSON; import com.alibaba.fastjson2.JSON;
import com.alibaba.fastjson2.JSONObject; import com.alibaba.fastjson2.JSONObject;
import com.nbport.zgwl.common.R; import com.nbport.zgwl.common.R;
import com.nbport.zgwl.contractlaunch.utils.ContractLaunchConstants;
import com.nbport.zgwl.seal.config.SealConfig; import com.nbport.zgwl.seal.config.SealConfig;
import com.nbport.zgwl.seal.service.SealLogService;
import com.nbport.zgwl.seal.service.SealTokenService; import com.nbport.zgwl.seal.service.SealTokenService;
import com.nbport.zgwl.seal.utils.SealHttpClient; import com.nbport.zgwl.seal.utils.SealHttpClient;
import org.slf4j.Logger; import org.slf4j.Logger;
@@ -37,6 +39,9 @@ public class SealProxyController {
@Autowired @Autowired
private SealTokenService sealTokenService; private SealTokenService sealTokenService;
@Autowired
private SealLogService sealLogService;
private String proxyPost(String apiPath, String requestBody) { private String proxyPost(String apiPath, String requestBody) {
String accessToken = sealTokenService.getAccessToken(); String accessToken = sealTokenService.getAccessToken();
String url = sealConfig.getBaseUrl() + apiPath; String url = sealConfig.getBaseUrl() + apiPath;
@@ -62,6 +67,14 @@ public class SealProxyController {
} }
} }
/**
* 从请求参数中提取 contractId(签章平台的合同ID)。
*/
private String extractContractId(Map<String, ?> params) {
Object value = params.get("contractId");
return value == null ? null : String.valueOf(value).trim();
}
@PostMapping("/token/getAccessToken") @PostMapping("/token/getAccessToken")
public R<Object> getAccessToken() { public R<Object> getAccessToken() {
try { try {
@@ -104,9 +117,28 @@ public class SealProxyController {
String accessToken = sealTokenService.getAccessToken(); String accessToken = sealTokenService.getAccessToken();
String url = sealConfig.getBaseUrl() + "/saas/api/contract/start"; String url = sealConfig.getBaseUrl() + "/saas/api/contract/start";
String response = SealHttpClient.postMultipart(url, file, contractName, description, accessToken); String response = SealHttpClient.postMultipart(url, file, contractName, description, accessToken);
return parseSealResponse(response); R<Object> result = parseSealResponse(response);
// 记录创建签署流程日志
Map<String, Object> logPayload = new HashMap<>();
logPayload.put("contractName", contractName);
logPayload.put("description", description);
logPayload.put("response", response);
sealLogService.logSealAction(null, ContractLaunchConstants.ACTION_SEAL_CREATE,
"创建签署流程",
result.getCode() != null && "0000".equals(String.valueOf(result.getCode()))
? ContractLaunchConstants.ACTION_STATUS_SUCCESS
: ContractLaunchConstants.ACTION_STATUS_FAILED,
"在签章平台创建签署流程,合同名称: " + contractName,
logPayload);
return result;
} catch (Exception e) { } catch (Exception e) {
log.error("创建签署流程失败", e); log.error("创建签署流程失败", e);
Map<String, Object> logPayload = new HashMap<>();
logPayload.put("contractName", contractName);
logPayload.put("error", e.getMessage());
sealLogService.logSealAction(null, ContractLaunchConstants.ACTION_SEAL_CREATE,
"创建签署流程", ContractLaunchConstants.ACTION_STATUS_FAILED,
"创建签署流程失败: " + e.getMessage(), logPayload);
return R.error("创建签署流程失败: " + e.getMessage()); return R.error("创建签署流程失败: " + e.getMessage());
} }
} }
@@ -153,9 +185,27 @@ public class SealProxyController {
try { try {
JSONObject body = new JSONObject(params); JSONObject body = new JSONObject(params);
String response = proxyPost("/saas/api/contract/confirmSign", body.toJSONString()); String response = proxyPost("/saas/api/contract/confirmSign", body.toJSONString());
return parseSealResponse(response); R<Object> result = parseSealResponse(response);
// 记录托管签署日志
String sealContractId = extractContractId(params);
Long contractId = sealLogService.findContractIdBySealContractId(sealContractId);
sealLogService.logSealAction(contractId, ContractLaunchConstants.ACTION_SEAL_SIGN,
"托管签署",
result.getCode() != null && "0000".equals(String.valueOf(result.getCode()))
? ContractLaunchConstants.ACTION_STATUS_SUCCESS
: ContractLaunchConstants.ACTION_STATUS_FAILED,
"执行托管签署,签章平台合同ID: " + sealContractId,
params);
return result;
} catch (Exception e) { } catch (Exception e) {
log.error("托管签署失败", e); log.error("托管签署失败", e);
String sealContractId = extractContractId(params);
Long contractId = sealLogService.findContractIdBySealContractId(sealContractId);
Map<String, Object> logPayload = new HashMap<>(params);
logPayload.put("error", e.getMessage());
sealLogService.logSealAction(contractId, ContractLaunchConstants.ACTION_SEAL_SIGN,
"托管签署", ContractLaunchConstants.ACTION_STATUS_FAILED,
"托管签署失败: " + e.getMessage(), logPayload);
return R.error("托管签署失败: " + e.getMessage()); return R.error("托管签署失败: " + e.getMessage());
} }
} }
@@ -178,9 +228,27 @@ public class SealProxyController {
try { try {
JSONObject body = new JSONObject(params); JSONObject body = new JSONObject(params);
String response = proxyPost("/saas/api/contract/signTimestamp", body.toJSONString()); String response = proxyPost("/saas/api/contract/signTimestamp", body.toJSONString());
return parseSealResponse(response); R<Object> result = parseSealResponse(response);
// 记录时间戳签章日志
String sealContractId = extractContractId(params);
Long contractId = sealLogService.findContractIdBySealContractId(sealContractId);
sealLogService.logSealAction(contractId, ContractLaunchConstants.ACTION_SEAL_TIMESTAMP,
"时间戳签章",
result.getCode() != null && "0000".equals(String.valueOf(result.getCode()))
? ContractLaunchConstants.ACTION_STATUS_SUCCESS
: ContractLaunchConstants.ACTION_STATUS_FAILED,
"执行时间戳签章,签章平台合同ID: " + sealContractId,
params);
return result;
} catch (Exception e) { } catch (Exception e) {
log.error("签署时间签章失败", e); log.error("签署时间签章失败", e);
String sealContractId = extractContractId(params);
Long contractId = sealLogService.findContractIdBySealContractId(sealContractId);
Map<String, Object> logPayload = new HashMap<>(params);
logPayload.put("error", e.getMessage());
sealLogService.logSealAction(contractId, ContractLaunchConstants.ACTION_SEAL_TIMESTAMP,
"时间戳签章", ContractLaunchConstants.ACTION_STATUS_FAILED,
"时间戳签章失败: " + e.getMessage(), logPayload);
return R.error("签署时间签章失败: " + e.getMessage()); return R.error("签署时间签章失败: " + e.getMessage());
} }
} }
@@ -204,9 +272,27 @@ public class SealProxyController {
try { try {
JSONObject body = new JSONObject(params); JSONObject body = new JSONObject(params);
String response = proxyPost("/saas/api/contract/signCommentSeal", body.toJSONString()); String response = proxyPost("/saas/api/contract/signCommentSeal", body.toJSONString());
return parseSealResponse(response); R<Object> result = parseSealResponse(response);
// 记录批注签章日志
String sealContractId = extractContractId(params);
Long contractId = sealLogService.findContractIdBySealContractId(sealContractId);
sealLogService.logSealAction(contractId, ContractLaunchConstants.ACTION_SEAL_COMMENT,
"批注签章",
result.getCode() != null && "0000".equals(String.valueOf(result.getCode()))
? ContractLaunchConstants.ACTION_STATUS_SUCCESS
: ContractLaunchConstants.ACTION_STATUS_FAILED,
"执行批注签章,签章平台合同ID: " + sealContractId,
params);
return result;
} catch (Exception e) { } catch (Exception e) {
log.error("签署批注签章失败", e); log.error("签署批注签章失败", e);
String sealContractId = extractContractId(params);
Long contractId = sealLogService.findContractIdBySealContractId(sealContractId);
Map<String, Object> logPayload = new HashMap<>(params);
logPayload.put("error", e.getMessage());
sealLogService.logSealAction(contractId, ContractLaunchConstants.ACTION_SEAL_COMMENT,
"批注签章", ContractLaunchConstants.ACTION_STATUS_FAILED,
"批注签章失败: " + e.getMessage(), logPayload);
return R.error("签署批注签章失败: " + e.getMessage()); return R.error("签署批注签章失败: " + e.getMessage());
} }
} }
@@ -217,9 +303,27 @@ public class SealProxyController {
JSONObject body = new JSONObject(); JSONObject body = new JSONObject();
body.put("contractId", params.get("contractId")); body.put("contractId", params.get("contractId"));
String response = proxyPost("/saas/api/contract/complete", body.toJSONString()); String response = proxyPost("/saas/api/contract/complete", body.toJSONString());
return parseSealResponse(response); R<Object> result = parseSealResponse(response);
// 记录完成签署流程日志
String sealContractId = params.get("contractId");
Long contractId = sealLogService.findContractIdBySealContractId(sealContractId);
sealLogService.logSealAction(contractId, ContractLaunchConstants.ACTION_SEAL_COMPLETE,
"完成签署流程",
result.getCode() != null && "0000".equals(String.valueOf(result.getCode()))
? ContractLaunchConstants.ACTION_STATUS_SUCCESS
: ContractLaunchConstants.ACTION_STATUS_FAILED,
"在签章平台完结签署流程,签章平台合同ID: " + sealContractId,
params);
return result;
} catch (Exception e) { } catch (Exception e) {
log.error("完成签署流程失败", e); log.error("完成签署流程失败", e);
String sealContractId = params.get("contractId");
Long contractId = sealLogService.findContractIdBySealContractId(sealContractId);
Map<String, Object> logPayload = new HashMap<>(params);
logPayload.put("error", e.getMessage());
sealLogService.logSealAction(contractId, ContractLaunchConstants.ACTION_SEAL_COMPLETE,
"完成签署流程", ContractLaunchConstants.ACTION_STATUS_FAILED,
"完成签署流程失败: " + e.getMessage(), logPayload);
return R.error("完成签署流程失败: " + e.getMessage()); return R.error("完成签署流程失败: " + e.getMessage());
} }
} }
@@ -230,9 +334,27 @@ public class SealProxyController {
JSONObject body = new JSONObject(); JSONObject body = new JSONObject();
body.put("contractId", params.get("contractId")); body.put("contractId", params.get("contractId"));
String response = proxyPost("/saas/api/contract/cancel", body.toJSONString()); String response = proxyPost("/saas/api/contract/cancel", body.toJSONString());
return parseSealResponse(response); R<Object> result = parseSealResponse(response);
// 记录取消签署流程日志
String sealContractId = params.get("contractId");
Long contractId = sealLogService.findContractIdBySealContractId(sealContractId);
sealLogService.logSealAction(contractId, ContractLaunchConstants.ACTION_SEAL_CANCEL,
"取消签署流程",
result.getCode() != null && "0000".equals(String.valueOf(result.getCode()))
? ContractLaunchConstants.ACTION_STATUS_SUCCESS
: ContractLaunchConstants.ACTION_STATUS_FAILED,
"在签章平台取消签署流程,签章平台合同ID: " + sealContractId,
params);
return result;
} catch (Exception e) { } catch (Exception e) {
log.error("取消签署流程失败", e); log.error("取消签署流程失败", e);
String sealContractId = params.get("contractId");
Long contractId = sealLogService.findContractIdBySealContractId(sealContractId);
Map<String, Object> logPayload = new HashMap<>(params);
logPayload.put("error", e.getMessage());
sealLogService.logSealAction(contractId, ContractLaunchConstants.ACTION_SEAL_CANCEL,
"取消签署流程", ContractLaunchConstants.ACTION_STATUS_FAILED,
"取消签署流程失败: " + e.getMessage(), logPayload);
return R.error("取消签署流程失败: " + e.getMessage()); return R.error("取消签署流程失败: " + e.getMessage());
} }
} }
@@ -0,0 +1,90 @@
package com.nbport.zgwl.seal.service;
import com.alibaba.fastjson2.JSON;
import com.nbport.zgwl.contractlaunch.dto.ContractLaunchDto;
import com.nbport.zgwl.contractlaunch.dto.ContractLaunchLogDto;
import com.nbport.zgwl.contractlaunch.mapper.ContractLaunchMapper;
import com.nbport.zgwl.contractlaunch.utils.ContractLaunchConstants;
import com.nbport.zgwl.entity.SysUserEntity;
import com.nbport.zgwl.utils.AdminSecurityManage;
import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.springframework.stereotype.Service;
import java.time.LocalDateTime;
/**
* 签章操作日志服务
*
* 供 seal 包下的 Controller 使用,将签章平台的关键操作和回调
* 统一写入合同操作日志表(SEAL_CONTRACT_LAUNCH_LOG),
* 实现合同全生命周期的全程留痕。
*/
@Slf4j
@Service
@RequiredArgsConstructor
public class SealLogService {
private final ContractLaunchMapper contractLaunchMapper;
private final AdminSecurityManage adminSecurityManage;
/**
* 根据签章平台的 contractId 查找本系统的合同ID。
*
* 签章平台的 contractId 对应本系统合同的 sealContractId 字段。
* 如果找不到对应的合同记录,返回 null。
*/
public Long findContractIdBySealContractId(String sealContractId) {
if (sealContractId == null || sealContractId.isBlank()) {
return null;
}
try {
ContractLaunchDto contract = contractLaunchMapper.selectContractBySealContractId(sealContractId);
return contract == null ? null : contract.getId();
} catch (Exception e) {
log.warn("根据 sealContractId 查询合同失败: {}", sealContractId, e);
return null;
}
}
/**
* 记录签章操作日志。
*
* @param contractId 本系统合同ID(可为 null,表示未关联到具体合同)
* @param actionType 操作类型(见 ContractLaunchConstants.ACTION_SEAL_*
* @param actionName 操作名称
* @param actionStatus 操作状态(success/failed/pending
* @param actionContent 操作内容描述
* @param payload 原始报文(会被 JSON 序列化存储)
*/
public void logSealAction(Long contractId, String actionType, String actionName,
String actionStatus, String actionContent, Object payload) {
try {
SysUserEntity currentUser = adminSecurityManage.getUser();
ContractLaunchLogDto logDto = new ContractLaunchLogDto();
logDto.setId(contractLaunchMapper.selectLogSeqNextVal());
logDto.setContractId(contractId);
logDto.setActionType(actionType);
logDto.setActionName(actionName);
logDto.setActionStatus(actionStatus);
logDto.setOperatorName(currentUser == null ? "system" : currentUser.getUsername());
logDto.setOperatorPhone(currentUser == null ? null : currentUser.getMobilePhone());
logDto.setActionTime(LocalDateTime.now());
logDto.setActionContent(actionContent);
logDto.setCallbackPayload(payload == null ? null : JSON.toJSONString(payload));
contractLaunchMapper.insertLog(logDto);
} catch (Exception e) {
// 日志记录失败不影响主流程
log.error("写入签章操作日志失败 contractId={}, actionType={}", contractId, actionType, e);
}
}
/**
* 记录签章操作日志(简化版,自动使用 success 状态)。
*/
public void logSealAction(Long contractId, String actionType, String actionName,
String actionContent, Object payload) {
logSealAction(contractId, actionType, actionName,
ContractLaunchConstants.ACTION_STATUS_SUCCESS, actionContent, payload);
}
}
@@ -275,6 +275,12 @@
and IS_DELETED = 'N' and IS_DELETED = 'N'
</select> </select>
<select id="selectContractBySealContractId" resultMap="ContractLaunchResult">
<include refid="mainColumns"/>
where SEAL_CONTRACT_ID = #{sealContractId}
and IS_DELETED = 'N'
</select>
<insert id="insertContract" parameterType="com.nbport.zgwl.contractlaunch.dto.ContractLaunchDto"> <insert id="insertContract" parameterType="com.nbport.zgwl.contractlaunch.dto.ContractLaunchDto">
insert into SEAL_CONTRACT_LAUNCH_MAIN ( insert into SEAL_CONTRACT_LAUNCH_MAIN (
ID, CONTRACT_SYS_ID, CONTRACT_CODE, LAW_CONTRACT_CODE, LAW_CONTRACT_ID, ID, CONTRACT_SYS_ID, CONTRACT_CODE, LAW_CONTRACT_CODE, LAW_CONTRACT_ID,