Browse Source

接口平台初始化脚本

dev-V1.10.1
vincent 3 weeks ago
parent
commit
9b39491fb0
  1. 153
      zdxt-modules/zdxt-enforcement-code/src/main/java/com/zdxt/enforcementcode/controller/externalInterface/ApiSignDemo.java
  2. 1
      zdxt-modules/zdxt-enforcement-code/src/main/java/com/zdxt/enforcementcode/controller/externalInterface/LongGangInterfaceController.java
  3. 16
      zdxt-web-server/zdxt-admin-web-server/src/main/resources/application-dev.yml

153
zdxt-modules/zdxt-enforcement-code/src/main/java/com/zdxt/enforcementcode/controller/externalInterface/ApiSignDemo.java

@ -0,0 +1,153 @@
package com.zdxt.enforcementcode.controller.externalInterface;
import cn.hutool.core.util.IdUtil;
import cn.hutool.crypto.SecureUtil;
import cn.hutool.crypto.asymmetric.KeyType;
import cn.hutool.http.HttpRequest;
import cn.hutool.http.HttpResponse;
import com.alibaba.fastjson2.JSONObject;
import com.zdxt.enforcementcode.common.util.ApiSignUtil;
import java.nio.charset.StandardCharsets;
import java.util.HashMap;
import java.util.Map;
public class ApiSignDemo {
private static final String APP_KEY = "XXX";
private static final String APP_SECRET = "XXX";
private static final String BASE_URL = "http://localhost:8080";
// 平台公钥:加密请求体
private static final String PLATFORM_PUBLIC_KEY = "XXXXXX";
// 调用方私钥:解密响应体
private static final String CALLER_PRIVATE_KEY = "XXXXXX";
public static void main(String[] args) throws Exception {
System.out.println("========================================");
System.out.println(" 模拟第三方请求 - 加签 + 加解密");
System.out.println("========================================\n");
// =====================================================================
// ① 加签:生成 HMAC-SHA256 签名
// =====================================================================
// timestamp: 毫秒级时间戳(13位),服务端校验与服务器时间差不超过配置阈值
// nonce: 随机字符串,防止重放攻击
// 签名原文: 将 appKey、timestamp、nonce 按 key 字母排序后拼接为 key=value&key=value 格式
// 签名值: 使用 HmacSHA256 算法 + appSecret 对签名原文计算摘要,结果 Base64 编码
String timestamp = String.valueOf(System.currentTimeMillis());
String nonce = IdUtil.fastSimpleUUID();
Map<String, String> signParams = new HashMap<>();
signParams.put("appKey", APP_KEY);
signParams.put("timestamp", timestamp);
signParams.put("nonce", nonce);
// buildSignContent: TreeMap 排序 → 过滤空值 → 拼接 "appKey=xxx&nonce=xxx&timestamp=xxx"
String signContent = ApiSignUtil.buildSignContent(signParams);
// hmacSign: HmacSHA256(签名原文, appSecret) → Base64 编码
String sign = ApiSignUtil.hmacSign(signContent, APP_SECRET);
System.out.println("【签名参数】");
System.out.println(" App-Key: " + APP_KEY);
System.out.println(" Timestamp: " + timestamp);
System.out.println(" Nonce: " + nonce);
System.out.println(" 签名原文: " + signContent);
System.out.println(" Sign: " + sign);
System.out.println();
// =====================================================================
// ② 构建业务请求体(JSON 格式,与 Controller 的 @RequestBody Bo 类字段对应)
// =====================================================================
String rawBody = """
{
"planType": 1,
"planDate": "2026-09-03",
"planTime": 1,
"enforceContent": "日常环保执法检查0904",
"enterpriseName": "深新粤云(深圳)信息技术有限公司圳市XX科技有限公司",
"enterpriseNumber": "91440300769156389U",
"contactPerson": "张三",
"contactPhone": "13800138000",
"enforceUserNames": "测试1,测试2",
"enforceUserIds": "17608417058,17608416858",
"deptId": "20210922212955057-A601-27251E588",
"deptName": "深圳市司法局",
"createBy": "17608417058",
"remark": "测试数据",
"outSerialNo": "LG20260903001"
}""";
System.out.println("【原始请求体】");
System.out.println(" " + rawBody);
System.out.println();
// =====================================================================
// ③ 加密请求体:RSA 公钥加密(使用平台公钥,服务端用平台私钥解密)
// =====================================================================
// 加密后的密文是 Base64 编码的字符串,不再是可读的 JSON
// 服务端 ApiCryptoFilter 会用 platformPrivateKey 解密还原为原始 JSON
String requestBody = ApiSignUtil.rsaEncrypt(rawBody, PLATFORM_PUBLIC_KEY);
System.out.println("【加密后请求体】");
System.out.println(" " + requestBody.substring(0, Math.min(80, requestBody.length())) + "...");
System.out.println();
// =====================================================================
// ④ 发起 HTTP POST 请求
// =====================================================================
// 请求头说明:
// App-Key: 应用标识,服务端通过它查 sys_api_platform_config 获取密钥和渠道信息
// Timestamp: 毫秒级时间戳,服务端校验请求是否过期
// Nonce: 随机串,防重放
// Sign: HMAC-SHA256 签名值,服务端用 appSecret 验签
// Encrypted: 标记请求体已加密,触发服务端 ApiCryptoFilter 解密逻辑
// Content-Type: 固定为 application/json
//
// 服务端处理链路:
// ApiCryptoFilter(解密请求体) → ApiSignInterceptor(验签) → Controller(业务处理)
String url = BASE_URL + "/external/api/lg/plan/saveOrUpdatePlan";
System.out.println("【发送请求】");
System.out.println(" URL: " + url);
HttpResponse response = HttpRequest.post(url)
.header("App-Key", APP_KEY)
.header("Timestamp", timestamp)
.header("Nonce", nonce)
.header("Sign", sign)
.header("Encrypted", "true")
.header("Content-Type", "application/json;charset=UTF-8")
.body(requestBody)
.timeout(10000)
.execute();
System.out.println(" 状态码: " + response.getStatus());
System.out.println(" Encrypted: " + response.header("Encrypted"));
System.out.println();
// =====================================================================
// ⑤ 解密响应体:RSA 私钥解密(服务端用调用方公钥加密,调用方用自己的私钥解密)
// =====================================================================
// 服务端 ApiCryptoFilter 处理完业务后,用 callerPublicKey 加密响应体
// 调用方收到密文后,用 callerPrivateKey 解密还原为原始 JSON 响应
String responseBody = response.body();
System.out.println("【加密响应】");
System.out.println(" " + (responseBody.length() > 200 ? responseBody.substring(0, 200) + "..." : responseBody));
System.out.println();
// SecureUtil.rsa(privateKey, null): 用调用方私钥构造 RSA 解密器
// decryptStr: Base64 解码密文 → RSA 私钥解密 → UTF-8 字符串
String decryptedResponse = SecureUtil.rsa(CALLER_PRIVATE_KEY, null)
.decryptStr(responseBody, KeyType.PrivateKey, StandardCharsets.UTF_8);
System.out.println("【解密后响应】");
JSONObject json = JSONObject.parseObject(decryptedResponse);
System.out.println(" " + json.toString());
response.close();
System.out.println();
System.out.println("========================================");
System.out.println(" 请求完成");
System.out.println("========================================");
}
}

1
zdxt-modules/zdxt-enforcement-code/src/main/java/com/zdxt/enforcementcode/controller/externalInterface/LongGangInterfaceController.java

@ -15,6 +15,7 @@ import com.zdxt.enforcementcode.domain.vo.SrzDeptVo;
import com.zdxt.enforcementcode.domain.vo.externalInterface.LongGangCaseSyncVo; import com.zdxt.enforcementcode.domain.vo.externalInterface.LongGangCaseSyncVo;
import com.zdxt.enforcementcode.domain.vo.externalInterface.LongGangCreatePlanVo; import com.zdxt.enforcementcode.domain.vo.externalInterface.LongGangCreatePlanVo;
import com.zdxt.enforcementcode.service.*; import com.zdxt.enforcementcode.service.*;
import io.swagger.v3.oas.annotations.tags.Tag;
import lombok.RequiredArgsConstructor; import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j; import lombok.extern.slf4j.Slf4j;
import org.dromara.common.core.domain.R; import org.dromara.common.core.domain.R;

16
zdxt-web-server/zdxt-admin-web-server/src/main/resources/application-dev.yml

@ -58,12 +58,12 @@ spring:
# 主库数据源 # 主库数据源
master: master:
driverClassName: com.mysql.cj.jdbc.Driver driverClassName: com.mysql.cj.jdbc.Driver
# url: jdbc:mysql://146.56.223.227:3306/zfjd2.0?useUnicode=true&characterEncoding=utf8&zeroDateTimeBehavior=convertToNull&useSSL=true&serverTimezone=GMT%2B8 url: jdbc:mysql://146.56.223.227:3306/zfjd2.0?useUnicode=true&characterEncoding=utf8&zeroDateTimeBehavior=convertToNull&useSSL=true&serverTimezone=GMT%2B8
# username: zfjd username: zfjd
# password: zdxt@1234 password: zdxt@1234
url: jdbc:mysql://172.16.20.72:3306/zfjd_ef20_1_2026_07_13?useUnicode=true&characterEncoding=utf8&zeroDateTimeBehavior=convertToNull&useSSL=true&serverTimezone=GMT%2B8 # url: jdbc:mysql://172.16.20.72:3306/zfjd_ef20_1_2026_07_13?useUnicode=true&characterEncoding=utf8&zeroDateTimeBehavior=convertToNull&useSSL=true&serverTimezone=GMT%2B8
username: root # username: root
password: zdxt@8888 # password: zdxt@8888
# jdbc 所有参数配置参考 https://lionli.blog.csdn.net/article/details/122018562 # jdbc 所有参数配置参考 https://lionli.blog.csdn.net/article/details/122018562
# rewriteBatchedStatements=true 批处理优化 大幅提升批量插入更新删除性能(对数据库有性能损耗 使用批量操作应考虑性能问题) # rewriteBatchedStatements=true 批处理优化 大幅提升批量插入更新删除性能(对数据库有性能损耗 使用批量操作应考虑性能问题)
@ -376,9 +376,9 @@ business-data-sync:
springdoc: springdoc:
api-docs: api-docs:
enabled: false enabled: true
swagger-ui: swagger-ui:
enabled: false enabled: true
info: info:
# 标题 # 标题
title: '执法监督码接口文档' title: '执法监督码接口文档'

Loading…
Cancel
Save