From 34981c30a78e8bbd7791131059a9210f9928b62c Mon Sep 17 00:00:00 2001
From: 刘光辉 <347230014@qq.com>
Date: 星期四, 17 九月 2026 09:24:09 +0800
Subject: [PATCH] Merge remote-tracking branch 'origin/master' into master

---
 jnpf-biz-common/jnpf-biz-common-audit/src/main/java/jnpf/bizcommon/audit/service/DataInterfaceSignAuditService.java |  127 ++++++++++++++++++++++++++++++++++++++++++
 1 files changed, 127 insertions(+), 0 deletions(-)

diff --git a/jnpf-biz-common/jnpf-biz-common-audit/src/main/java/jnpf/bizcommon/audit/service/DataInterfaceSignAuditService.java b/jnpf-biz-common/jnpf-biz-common-audit/src/main/java/jnpf/bizcommon/audit/service/DataInterfaceSignAuditService.java
new file mode 100644
index 0000000..eb7bb78
--- /dev/null
+++ b/jnpf-biz-common/jnpf-biz-common-audit/src/main/java/jnpf/bizcommon/audit/service/DataInterfaceSignAuditService.java
@@ -0,0 +1,127 @@
+package jnpf.bizcommon.audit.service;
+
+import jnpf.audit.AuditConsts;
+import jnpf.audit.model.AuditEventDTO;
+import jnpf.bizcommon.audit.service.sign.AuditSignEvidence;
+import jnpf.bizcommon.audit.service.sign.AuditSignEvidenceReader;
+import jnpf.bizcommon.audit.service.sign.AuditSignMetaData;
+import jnpf.util.JsonUtil;
+import lombok.RequiredArgsConstructor;
+import lombok.extern.slf4j.Slf4j;
+import org.springframework.stereotype.Service;
+
+import java.nio.charset.StandardCharsets;
+import java.security.MessageDigest;
+import java.util.Collections;
+import java.util.LinkedHashMap;
+import java.util.Map;
+
+/** 涓烘暟鎹帴鍙f搷浣滀簨瀹炶ˉ鍏呰姹傛墍鎼哄甫鐨勭數瀛愮鍚嶄簨瀹炪�� */
+@Slf4j
+@Service
+@RequiredArgsConstructor
+public class DataInterfaceSignAuditService {
+
+    private static final String SIGN_ACTION = "SIGN";
+    private static final String REQUEST_SIGN_FIELD = "__request_biz_sign__";
+
+    private final AuditSignEvidenceReader signEvidenceReader;
+    private final AuditEventService auditEventService;
+
+    /**
+     * 鍙鐞嗘樉寮忔惡甯� relatedSignId 鐨勬暟鎹帴鍙d簨浠躲�傚紓甯稿悜涓婁氦缁欏璁℃姇閫掑櫒杩涘叆 spool 閲嶈瘯锛�
+     * 璋冪敤鍙戠敓鍦ㄥ璁℃湇鍔″唴閮紝涓嶄細褰卞搷鍘熷涓氬姟璇锋眰銆�
+     */
+    public void recordRelatedSign(AuditEventDTO businessEvent) {
+        if (businessEvent == null || isBlank(businessEvent.getRelatedSignId())
+                || !AuditConsts.TYPE_DATA_CHANGE.equals(businessEvent.getEventType())
+                || !"DATA_INTERFACE".equals(businessEvent.getBizType())) {
+            return;
+        }
+
+        String signId = businessEvent.getRelatedSignId().trim();
+        Map<String, AuditSignEvidence> evidences = signEvidenceReader.read(
+                Collections.singletonList(signId), businessEvent.getTenantId());
+        AuditSignEvidence evidence = evidences.get(signId);
+        if (evidence == null) {
+            log.warn("[DATA-INTERFACE-AUDIT] 鏈煡璇㈠埌鍚岀鎴风鍚嶈褰曪紝璺宠繃绛惧悕浜嬩欢 clientEventId={}",
+                    businessEvent.getClientEventId());
+            return;
+        }
+        if (isBlank(evidence.operatorId())
+                || !evidence.operatorId().equals(businessEvent.getOperatorId())) {
+            log.warn("[DATA-INTERFACE-AUDIT] 绛惧悕褰掑睘涓庡綋鍓嶆搷浣滀汉涓嶄竴鑷达紝璺宠繃绛惧悕浜嬩欢 clientEventId={}",
+                    businessEvent.getClientEventId());
+            return;
+        }
+
+        AuditSignMetaData metaData = AuditSignMetaData.parse(evidence.metaData());
+        String signatureRole = metaData.isReviewButton() ? "REVIEW" : "PRIMARY";
+        Map<String, Object> extra = new LinkedHashMap<>();
+        extra.put("signField", REQUEST_SIGN_FIELD);
+        extra.put("signatureRole", signatureRole);
+        extra.put("auditSource", "DATA_INTERFACE");
+        if (!isBlank(evidence.accountName())) {
+            extra.put("accountName", evidence.accountName());
+        }
+        if (!isBlank(evidence.opType())) {
+            extra.put("opType", evidence.opType());
+        }
+
+        AuditEventDTO signEvent = AuditEventDTO.builder()
+                .clientEventId(signClientEventId(businessEvent.getOperationId(), signId))
+                .operationId(businessEvent.getOperationId())
+                .eventTime(evidence.signedAt() == null
+                        ? businessEvent.getEventTime() : evidence.signedAt())
+                .tenantId(businessEvent.getTenantId())
+                .operatorId(evidence.operatorId())
+                .operatorName(businessEvent.getOperatorName())
+                .operatorOrgId(businessEvent.getOperatorOrgId())
+                .appName(businessEvent.getAppName())
+                .bizModule(businessEvent.getBizModule())
+                .ip(businessEvent.getIp())
+                .ipRegion(businessEvent.getIpRegion())
+                .browser(businessEvent.getBrowser())
+                .os(businessEvent.getOs())
+                .requestUri(businessEvent.getRequestUri())
+                .eventType(AuditConsts.TYPE_E_SIGNATURE)
+                .actionCode(SIGN_ACTION)
+                .actionLabel(metaData.isReviewButton() ? "澶嶅绛惧悕" : "鐢靛瓙绛惧悕")
+                .sourceLayer(3)
+                .targetTable(AuditSignEvidenceReader.SIGN_TABLE)
+                .targetId(signId)
+                .bizType(businessEvent.getBizType())
+                .bizCode(businessEvent.getBizCode())
+                .reason(evidence.note())
+                .extra(JsonUtil.getObjectToString(extra))
+                .recordTitle(businessEvent.getRecordTitle())
+                .entryType(businessEvent.getEntryType())
+                .entryId(businessEvent.getEntryId())
+                .entryName(businessEvent.getEntryName())
+                .build();
+        auditEventService.saveIdempotent(signEvent);
+    }
+
+    private static String signClientEventId(String operationId, String signId) {
+        String source = value(operationId) + "\n" + value(signId);
+        try {
+            byte[] digest = MessageDigest.getInstance("SHA-256")
+                    .digest(source.getBytes(StandardCharsets.UTF_8));
+            StringBuilder hex = new StringBuilder("DIS-");
+            for (byte item : digest) {
+                hex.append(String.format("%02x", item & 0xff));
+            }
+            return hex.toString();
+        } catch (Exception e) {
+            throw new IllegalStateException("鐢熸垚鏁版嵁鎺ュ彛绛惧悕浜嬩欢骞傜瓑閿け璐�", e);
+        }
+    }
+
+    private static String value(String text) {
+        return text == null ? "" : text;
+    }
+
+    private static boolean isBlank(String text) {
+        return text == null || text.trim().isEmpty();
+    }
+}

--
Gitblit v1.8.0