mirror of
https://gitee.com/huangge1199_admin/vue-pro.git
synced 2024-11-22 15:21:53 +08:00
Merge branch 'master-jdk17' into feature/db
# Conflicts: # sql/tools/README.md
This commit is contained in:
commit
27e2996c5d
@ -67,8 +67,8 @@ exit
|
|||||||
|
|
||||||
① 下载人大金仓 Docker 镜像:
|
① 下载人大金仓 Docker 镜像:
|
||||||
|
|
||||||
> x86_64版本: https://kingbase.oss-cn-beijing.aliyuncs.com/KESV8R3/V009R001C001B0025-安装包-docker/x86_64/kdb_x86_64_V009R001C001B0025.tar
|
> x86_64 版本: https://kingbase.oss-cn-beijing.aliyuncs.com/KESV8R3/V009R001C001B0025-安装包-docker/x86_64/kdb_x86_64_V009R001C001B0025.tar
|
||||||
> aarch64版本:https://kingbase.oss-cn-beijing.aliyuncs.com/KESV8R3/V009R001C001B0025-安装包-docker/aarch64/kdb_aarch64_V009R001C001B0025.tar
|
> aarch64 版本:https://kingbase.oss-cn-beijing.aliyuncs.com/KESV8R3/V009R001C001B0025-安装包-docker/aarch64/kdb_aarch64_V009R001C001B0025.tar
|
||||||
|
|
||||||
② 加载镜像文件,在镜像 tar 文件所在目录运行:
|
② 加载镜像文件,在镜像 tar 文件所在目录运行:
|
||||||
|
|
||||||
@ -80,11 +80,11 @@ docker load -i x86_64/kdb_x86_64_V009R001C001B0025.tar
|
|||||||
|
|
||||||
```Bash
|
```Bash
|
||||||
docker compose up -d kingbase
|
docker compose up -d kingbase
|
||||||
# 注意:启动完 dm 后,需要手动再执行如下命令,因为 dm 不支持初始化脚本
|
# 注意:启动完 kingbase 后,需要手动再执行如下命令,因为 dm 不支持初始化脚本
|
||||||
docker compose exec kingbase bash -c 'ksql -U $DB_USER -d test -f /tmp/schema.sql'
|
docker compose exec kingbase bash -c "exec ksql -Uroot -d test -f /tmp/schema.sql"
|
||||||
```
|
```
|
||||||
|
|
||||||
**注意**: MyBatis, MyBatis Plus 目前不兼容人大金仓,推荐直接使用PostgreSQL JDBC 驱动,已经 url 配置方式连接数据库。
|
**注意**: MyBatis、MyBatis Plus 目前不兼容人大金仓,推荐直接使用 PostgreSQL JDBC 驱动,已经 url 配置方式连接数据库。
|
||||||
|
|
||||||
### 1.7 华为 OpenGauss
|
### 1.7 华为 OpenGauss
|
||||||
|
|
||||||
|
@ -247,15 +247,15 @@ id,name,type,parentId
|
|||||||
246,英属印度洋领地,1,0
|
246,英属印度洋领地,1,0
|
||||||
247,东萨摩亚,1,0
|
247,东萨摩亚,1,0
|
||||||
248,诺福克岛,1,0
|
248,诺福克岛,1,0
|
||||||
110000,北京,2,1
|
110000,北京市,2,1
|
||||||
120000,天津,2,1
|
120000,天津市,2,1
|
||||||
130000,河北省,2,1
|
130000,河北省,2,1
|
||||||
140000,山西省,2,1
|
140000,山西省,2,1
|
||||||
150000,内蒙古自治区,2,1
|
150000,内蒙古自治区,2,1
|
||||||
210000,辽宁省,2,1
|
210000,辽宁省,2,1
|
||||||
220000,吉林省,2,1
|
220000,吉林省,2,1
|
||||||
230000,黑龙江省,2,1
|
230000,黑龙江省,2,1
|
||||||
310000,上海,2,1
|
310000,上海市,2,1
|
||||||
320000,江苏省,2,1
|
320000,江苏省,2,1
|
||||||
330000,浙江省,2,1
|
330000,浙江省,2,1
|
||||||
340000,安徽省,2,1
|
340000,安徽省,2,1
|
||||||
@ -268,7 +268,7 @@ id,name,type,parentId
|
|||||||
440000,广东省,2,1
|
440000,广东省,2,1
|
||||||
450000,广西壮族自治区,2,1
|
450000,广西壮族自治区,2,1
|
||||||
460000,海南省,2,1
|
460000,海南省,2,1
|
||||||
500000,重庆,2,1
|
500000,重庆市,2,1
|
||||||
510000,四川省,2,1
|
510000,四川省,2,1
|
||||||
520000,贵州省,2,1
|
520000,贵州省,2,1
|
||||||
530000,云南省,2,1
|
530000,云南省,2,1
|
||||||
|
|
@ -34,20 +34,24 @@ public class CronUtils {
|
|||||||
* @return 满足条件的执行时间
|
* @return 满足条件的执行时间
|
||||||
*/
|
*/
|
||||||
public static List<LocalDateTime> getNextTimes(String cronExpression, int n) {
|
public static List<LocalDateTime> getNextTimes(String cronExpression, int n) {
|
||||||
// 获得 CronExpression 对象
|
// 1. 获得 CronExpression 对象
|
||||||
CronExpression cron;
|
CronExpression cron;
|
||||||
try {
|
try {
|
||||||
cron = new CronExpression(cronExpression);
|
cron = new CronExpression(cronExpression);
|
||||||
} catch (ParseException e) {
|
} catch (ParseException e) {
|
||||||
throw new IllegalArgumentException(e.getMessage());
|
throw new IllegalArgumentException(e.getMessage());
|
||||||
}
|
}
|
||||||
// 从当前开始计算,n 个满足条件的
|
// 2. 从当前开始计算,n 个满足条件的
|
||||||
Date now = new Date();
|
Date now = new Date();
|
||||||
List<LocalDateTime> nextTimes = new ArrayList<>(n);
|
List<LocalDateTime> nextTimes = new ArrayList<>(n);
|
||||||
for (int i = 0; i < n; i++) {
|
for (int i = 0; i < n; i++) {
|
||||||
Date nextTime = cron.getNextValidTimeAfter(now);
|
Date nextTime = cron.getNextValidTimeAfter(now);
|
||||||
|
// 2.1 如果 nextTime 为 null,说明没有更多的有效时间,退出循环
|
||||||
|
if (nextTime == null) {
|
||||||
|
break;
|
||||||
|
}
|
||||||
nextTimes.add(LocalDateTimeUtil.of(nextTime));
|
nextTimes.add(LocalDateTimeUtil.of(nextTime));
|
||||||
// 切换现在,为下一个触发时间;
|
// 2.2 切换现在,为下一个触发时间;
|
||||||
now = nextTime;
|
now = nextTime;
|
||||||
}
|
}
|
||||||
return nextTimes;
|
return nextTimes;
|
||||||
|
@ -12,7 +12,7 @@
|
|||||||
<packaging>jar</packaging>
|
<packaging>jar</packaging>
|
||||||
|
|
||||||
<name>${project.artifactId}</name>
|
<name>${project.artifactId}</name>
|
||||||
<description>服务保证,提供分布式锁、幂等、限流、熔断等等功能</description>
|
<description>服务保证,提供分布式锁、幂等、限流、熔断、API 签名等等功能</description>
|
||||||
<url>https://github.com/YunaiV/ruoyi-vue-pro</url>
|
<url>https://github.com/YunaiV/ruoyi-vue-pro</url>
|
||||||
|
|
||||||
<dependencies>
|
<dependencies>
|
||||||
@ -35,6 +35,13 @@
|
|||||||
<artifactId>lock4j-redisson-spring-boot-starter</artifactId>
|
<artifactId>lock4j-redisson-spring-boot-starter</artifactId>
|
||||||
<optional>true</optional>
|
<optional>true</optional>
|
||||||
</dependency>
|
</dependency>
|
||||||
|
|
||||||
|
<!-- Test 测试相关 -->
|
||||||
|
<dependency>
|
||||||
|
<groupId>cn.iocoder.boot</groupId>
|
||||||
|
<artifactId>yudao-spring-boot-starter-test</artifactId>
|
||||||
|
<scope>test</scope>
|
||||||
|
</dependency>
|
||||||
</dependencies>
|
</dependencies>
|
||||||
|
|
||||||
</project>
|
</project>
|
||||||
|
@ -0,0 +1,28 @@
|
|||||||
|
package cn.iocoder.yudao.framework.signature.config;
|
||||||
|
|
||||||
|
import cn.iocoder.yudao.framework.redis.config.YudaoRedisAutoConfiguration;
|
||||||
|
import cn.iocoder.yudao.framework.signature.core.aop.ApiSignatureAspect;
|
||||||
|
import cn.iocoder.yudao.framework.signature.core.redis.ApiSignatureRedisDAO;
|
||||||
|
import org.springframework.boot.autoconfigure.AutoConfiguration;
|
||||||
|
import org.springframework.context.annotation.Bean;
|
||||||
|
import org.springframework.data.redis.core.StringRedisTemplate;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* HTTP API 签名的自动配置类
|
||||||
|
*
|
||||||
|
* @author Zhougang
|
||||||
|
*/
|
||||||
|
@AutoConfiguration(after = YudaoRedisAutoConfiguration.class)
|
||||||
|
public class YudaoApiSignatureAutoConfiguration {
|
||||||
|
|
||||||
|
@Bean
|
||||||
|
public ApiSignatureAspect signatureAspect(ApiSignatureRedisDAO signatureRedisDAO) {
|
||||||
|
return new ApiSignatureAspect(signatureRedisDAO);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Bean
|
||||||
|
public ApiSignatureRedisDAO signatureRedisDAO(StringRedisTemplate stringRedisTemplate) {
|
||||||
|
return new ApiSignatureRedisDAO(stringRedisTemplate);
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
@ -0,0 +1,59 @@
|
|||||||
|
package cn.iocoder.yudao.framework.signature.core.annotation;
|
||||||
|
|
||||||
|
import cn.iocoder.yudao.framework.common.exception.enums.GlobalErrorCodeConstants;
|
||||||
|
|
||||||
|
import java.lang.annotation.*;
|
||||||
|
import java.util.concurrent.TimeUnit;
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* HTTP API 签名注解
|
||||||
|
*
|
||||||
|
* @author Zhougang
|
||||||
|
*/
|
||||||
|
@Inherited
|
||||||
|
@Documented
|
||||||
|
@Target({ElementType.METHOD, ElementType.TYPE})
|
||||||
|
@Retention(RetentionPolicy.RUNTIME)
|
||||||
|
public @interface ApiSignature {
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 同一个请求多长时间内有效 默认 60 秒
|
||||||
|
*/
|
||||||
|
int timeout() default 60;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 时间单位,默认为 SECONDS 秒
|
||||||
|
*/
|
||||||
|
TimeUnit timeUnit() default TimeUnit.SECONDS;
|
||||||
|
|
||||||
|
// ========================== 签名参数 ==========================
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 提示信息,签名失败的提示
|
||||||
|
*
|
||||||
|
* @see GlobalErrorCodeConstants#BAD_REQUEST
|
||||||
|
*/
|
||||||
|
String message() default "签名不正确"; // 为空时,使用 BAD_REQUEST 错误提示
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 签名字段:appId 应用ID
|
||||||
|
*/
|
||||||
|
String appId() default "appId";
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 签名字段:timestamp 时间戳
|
||||||
|
*/
|
||||||
|
String timestamp() default "timestamp";
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 签名字段:nonce 随机数,10 位以上
|
||||||
|
*/
|
||||||
|
String nonce() default "nonce";
|
||||||
|
|
||||||
|
/**
|
||||||
|
* sign 客户端签名
|
||||||
|
*/
|
||||||
|
String sign() default "sign";
|
||||||
|
|
||||||
|
}
|
@ -0,0 +1,169 @@
|
|||||||
|
package cn.iocoder.yudao.framework.signature.core.aop;
|
||||||
|
|
||||||
|
import cn.hutool.core.lang.Assert;
|
||||||
|
import cn.hutool.core.map.MapUtil;
|
||||||
|
import cn.hutool.core.util.ObjUtil;
|
||||||
|
import cn.hutool.core.util.StrUtil;
|
||||||
|
import cn.hutool.crypto.digest.DigestUtil;
|
||||||
|
import cn.iocoder.yudao.framework.common.exception.ServiceException;
|
||||||
|
import cn.iocoder.yudao.framework.common.util.servlet.ServletUtils;
|
||||||
|
import cn.iocoder.yudao.framework.signature.core.annotation.ApiSignature;
|
||||||
|
import cn.iocoder.yudao.framework.signature.core.redis.ApiSignatureRedisDAO;
|
||||||
|
import jakarta.servlet.http.HttpServletRequest;
|
||||||
|
import lombok.AllArgsConstructor;
|
||||||
|
import lombok.extern.slf4j.Slf4j;
|
||||||
|
import org.aspectj.lang.JoinPoint;
|
||||||
|
import org.aspectj.lang.annotation.Aspect;
|
||||||
|
import org.aspectj.lang.annotation.Before;
|
||||||
|
|
||||||
|
import java.util.Map;
|
||||||
|
import java.util.Objects;
|
||||||
|
import java.util.SortedMap;
|
||||||
|
import java.util.TreeMap;
|
||||||
|
|
||||||
|
import static cn.iocoder.yudao.framework.common.exception.enums.GlobalErrorCodeConstants.BAD_REQUEST;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 拦截声明了 {@link ApiSignature} 注解的方法,实现签名
|
||||||
|
*
|
||||||
|
* @author Zhougang
|
||||||
|
*/
|
||||||
|
@Aspect
|
||||||
|
@Slf4j
|
||||||
|
@AllArgsConstructor
|
||||||
|
public class ApiSignatureAspect {
|
||||||
|
|
||||||
|
private final ApiSignatureRedisDAO signatureRedisDAO;
|
||||||
|
|
||||||
|
@Before("@annotation(signature)")
|
||||||
|
public void beforePointCut(JoinPoint joinPoint, ApiSignature signature) {
|
||||||
|
// 1. 验证通过,直接结束
|
||||||
|
if (verifySignature(signature, Objects.requireNonNull(ServletUtils.getRequest()))) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
// 2. 验证不通过,抛出异常
|
||||||
|
log.error("[beforePointCut][方法{} 参数({}) 签名失败]", joinPoint.getSignature().toString(),
|
||||||
|
joinPoint.getArgs());
|
||||||
|
throw new ServiceException(BAD_REQUEST.getCode(),
|
||||||
|
StrUtil.blankToDefault(signature.message(), BAD_REQUEST.getMsg()));
|
||||||
|
}
|
||||||
|
|
||||||
|
public boolean verifySignature(ApiSignature signature, HttpServletRequest request) {
|
||||||
|
// 1.1 校验 Header
|
||||||
|
if (!verifyHeaders(signature, request)) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
// 1.2 校验 appId 是否能获取到对应的 appSecret
|
||||||
|
String appId = request.getHeader(signature.appId());
|
||||||
|
String appSecret = signatureRedisDAO.getAppSecret(appId);
|
||||||
|
Assert.notNull(appSecret, "[appId({})] 找不到对应的 appSecret", appId);
|
||||||
|
|
||||||
|
// 2. 校验签名【重要!】
|
||||||
|
String clientSignature = request.getHeader(signature.sign()); // 客户端签名
|
||||||
|
String serverSignatureString = buildSignatureString(signature, request, appSecret); // 服务端签名字符串
|
||||||
|
String serverSignature = DigestUtil.sha256Hex(serverSignatureString); // 服务端签名
|
||||||
|
if (ObjUtil.notEqual(clientSignature, serverSignature)) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
// 3. 将 nonce 记入缓存,防止重复使用(重点二:此处需要将 ttl 设定为允许 timestamp 时间差的值 x 2 )
|
||||||
|
String nonce = request.getHeader(signature.nonce());
|
||||||
|
signatureRedisDAO.setNonce(nonce, signature.timeout() * 2, signature.timeUnit());
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 校验请求头加签参数
|
||||||
|
*
|
||||||
|
* 1. appId 是否为空
|
||||||
|
* 2. timestamp 是否为空,请求是否已经超时,默认 10 分钟
|
||||||
|
* 3. nonce 是否为空,随机数是否 10 位以上,是否在规定时间内已经访问过了
|
||||||
|
* 4. sign 是否为空
|
||||||
|
*
|
||||||
|
* @param signature signature
|
||||||
|
* @param request request
|
||||||
|
* @return 是否校验 Header 通过
|
||||||
|
*/
|
||||||
|
private boolean verifyHeaders(ApiSignature signature, HttpServletRequest request) {
|
||||||
|
// 1. 非空校验
|
||||||
|
String appId = request.getHeader(signature.appId());
|
||||||
|
if (StrUtil.isBlank(appId)) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
String timestamp = request.getHeader(signature.timestamp());
|
||||||
|
if (StrUtil.isBlank(timestamp)) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
String nonce = request.getHeader(signature.nonce());
|
||||||
|
if (StrUtil.length(nonce) < 10) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
String sign = request.getHeader(signature.sign());
|
||||||
|
if (StrUtil.isBlank(sign)) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
// 2. 检查 timestamp 是否超出允许的范围 (重点一:此处需要取绝对值)
|
||||||
|
long expireTime = signature.timeUnit().toMillis(signature.timeout());
|
||||||
|
long requestTimestamp = Long.parseLong(timestamp);
|
||||||
|
long timestampDisparity = Math.abs(System.currentTimeMillis() - requestTimestamp);
|
||||||
|
if (timestampDisparity > expireTime) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
// 3. 检查 nonce 是否存在,有且仅能使用一次
|
||||||
|
return signatureRedisDAO.getNonce(nonce) == null;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 构建签名字符串
|
||||||
|
*
|
||||||
|
* 格式为 = 请求参数 + 请求体 + 请求头 + 密钥
|
||||||
|
*
|
||||||
|
* @param signature signature
|
||||||
|
* @param request request
|
||||||
|
* @param appSecret appSecret
|
||||||
|
* @return 签名字符串
|
||||||
|
*/
|
||||||
|
private String buildSignatureString(ApiSignature signature, HttpServletRequest request, String appSecret) {
|
||||||
|
SortedMap<String, String> parameterMap = getRequestParameterMap(request); // 请求头
|
||||||
|
SortedMap<String, String> headerMap = getRequestHeaderMap(signature, request); // 请求参数
|
||||||
|
String requestBody = StrUtil.nullToDefault(ServletUtils.getBody(request), ""); // 请求体
|
||||||
|
return MapUtil.join(parameterMap, "&", "=")
|
||||||
|
+ requestBody
|
||||||
|
+ MapUtil.join(headerMap, "&", "=")
|
||||||
|
+ appSecret;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 获取请求头加签参数 Map
|
||||||
|
*
|
||||||
|
* @param request 请求
|
||||||
|
* @param signature 签名注解
|
||||||
|
* @return signature params
|
||||||
|
*/
|
||||||
|
private static SortedMap<String, String> getRequestHeaderMap(ApiSignature signature, HttpServletRequest request) {
|
||||||
|
SortedMap<String, String> sortedMap = new TreeMap<>();
|
||||||
|
sortedMap.put(signature.appId(), request.getHeader(signature.appId()));
|
||||||
|
sortedMap.put(signature.timestamp(), request.getHeader(signature.timestamp()));
|
||||||
|
sortedMap.put(signature.nonce(), request.getHeader(signature.nonce()));
|
||||||
|
return sortedMap;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 获取请求参数 Map
|
||||||
|
*
|
||||||
|
* @param request 请求
|
||||||
|
* @return queryParams
|
||||||
|
*/
|
||||||
|
private static SortedMap<String, String> getRequestParameterMap(HttpServletRequest request) {
|
||||||
|
SortedMap<String, String> sortedMap = new TreeMap<>();
|
||||||
|
for (Map.Entry<String, String[]> entry : request.getParameterMap().entrySet()) {
|
||||||
|
sortedMap.put(entry.getKey(), entry.getValue()[0]);
|
||||||
|
}
|
||||||
|
return sortedMap;
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
@ -0,0 +1,57 @@
|
|||||||
|
package cn.iocoder.yudao.framework.signature.core.redis;
|
||||||
|
|
||||||
|
import lombok.AllArgsConstructor;
|
||||||
|
import org.springframework.data.redis.core.StringRedisTemplate;
|
||||||
|
|
||||||
|
import java.util.concurrent.TimeUnit;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* HTTP API 签名 Redis DAO
|
||||||
|
*
|
||||||
|
* @author Zhougang
|
||||||
|
*/
|
||||||
|
@AllArgsConstructor
|
||||||
|
public class ApiSignatureRedisDAO {
|
||||||
|
|
||||||
|
private final StringRedisTemplate stringRedisTemplate;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 验签随机数
|
||||||
|
*
|
||||||
|
* KEY 格式:signature_nonce:%s // 参数为 随机数
|
||||||
|
* VALUE 格式:String
|
||||||
|
* 过期时间:不固定
|
||||||
|
*/
|
||||||
|
private static final String SIGNATURE_NONCE = "api_signature_nonce:%s";
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 签名密钥
|
||||||
|
*
|
||||||
|
* HASH 结构
|
||||||
|
* KEY 格式:%s // 参数为 appid
|
||||||
|
* VALUE 格式:String
|
||||||
|
* 过期时间:永不过期(预加载到 Redis)
|
||||||
|
*/
|
||||||
|
private static final String SIGNATURE_APPID = "api_signature_app";
|
||||||
|
|
||||||
|
// ========== 验签随机数 ==========
|
||||||
|
|
||||||
|
public String getNonce(String nonce) {
|
||||||
|
return stringRedisTemplate.opsForValue().get(formatNonceKey(nonce));
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setNonce(String nonce, int time, TimeUnit timeUnit) {
|
||||||
|
stringRedisTemplate.opsForValue().set(formatNonceKey(nonce), "", time, timeUnit);
|
||||||
|
}
|
||||||
|
|
||||||
|
private static String formatNonceKey(String key) {
|
||||||
|
return String.format(SIGNATURE_NONCE, key);
|
||||||
|
}
|
||||||
|
|
||||||
|
// ========== 签名密钥 ==========
|
||||||
|
|
||||||
|
public String getAppSecret(String appId) {
|
||||||
|
return (String) stringRedisTemplate.opsForHash().get(SIGNATURE_APPID, appId);
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
@ -0,0 +1,6 @@
|
|||||||
|
/**
|
||||||
|
* HTTP API 签名,校验安全性
|
||||||
|
*
|
||||||
|
* @see <a href="https://pay.weixin.qq.com/wiki/doc/api/jsapi.php?chapter=4_3>微信支付 —— 安全规范</a>
|
||||||
|
*/
|
||||||
|
package cn.iocoder.yudao.framework.signature;
|
@ -1,3 +1,4 @@
|
|||||||
cn.iocoder.yudao.framework.idempotent.config.YudaoIdempotentConfiguration
|
cn.iocoder.yudao.framework.idempotent.config.YudaoIdempotentConfiguration
|
||||||
cn.iocoder.yudao.framework.lock4j.config.YudaoLock4jConfiguration
|
cn.iocoder.yudao.framework.lock4j.config.YudaoLock4jConfiguration
|
||||||
cn.iocoder.yudao.framework.ratelimiter.config.YudaoRateLimiterConfiguration
|
cn.iocoder.yudao.framework.ratelimiter.config.YudaoRateLimiterConfiguration
|
||||||
|
cn.iocoder.yudao.framework.signature.config.YudaoApiSignatureAutoConfiguration
|
@ -0,0 +1,75 @@
|
|||||||
|
package cn.iocoder.yudao.framework.signature.core;
|
||||||
|
|
||||||
|
import cn.hutool.core.map.MapUtil;
|
||||||
|
import cn.hutool.core.util.IdUtil;
|
||||||
|
import cn.hutool.crypto.digest.DigestUtil;
|
||||||
|
import cn.iocoder.yudao.framework.signature.core.annotation.ApiSignature;
|
||||||
|
import cn.iocoder.yudao.framework.signature.core.aop.ApiSignatureAspect;
|
||||||
|
import cn.iocoder.yudao.framework.signature.core.redis.ApiSignatureRedisDAO;
|
||||||
|
import jakarta.servlet.http.HttpServletRequest;
|
||||||
|
import org.junit.jupiter.api.Test;
|
||||||
|
import org.junit.jupiter.api.extension.ExtendWith;
|
||||||
|
import org.mockito.InjectMocks;
|
||||||
|
import org.mockito.Mock;
|
||||||
|
import org.mockito.junit.jupiter.MockitoExtension;
|
||||||
|
|
||||||
|
import java.io.BufferedReader;
|
||||||
|
import java.io.IOException;
|
||||||
|
import java.io.StringReader;
|
||||||
|
import java.util.concurrent.TimeUnit;
|
||||||
|
|
||||||
|
import static org.junit.jupiter.api.Assertions.assertTrue;
|
||||||
|
import static org.mockito.ArgumentMatchers.eq;
|
||||||
|
import static org.mockito.Mockito.*;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* {@link ApiSignatureTest} 的单元测试
|
||||||
|
*/
|
||||||
|
@ExtendWith(MockitoExtension.class)
|
||||||
|
public class ApiSignatureTest {
|
||||||
|
|
||||||
|
@InjectMocks
|
||||||
|
private ApiSignatureAspect apiSignatureAspect;
|
||||||
|
|
||||||
|
@Mock
|
||||||
|
private ApiSignatureRedisDAO signatureRedisDAO;
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void testSignatureGet() throws IOException {
|
||||||
|
// 搞一个签名
|
||||||
|
Long timestamp = System.currentTimeMillis();
|
||||||
|
String nonce = IdUtil.randomUUID();
|
||||||
|
String appId = "xxxxxx";
|
||||||
|
String appSecret = "yyyyyy";
|
||||||
|
String signString = "k1=v1&v1=k1testappId=xxxxxx&nonce=" + nonce + "×tamp=" + timestamp + "yyyyyy";
|
||||||
|
String sign = DigestUtil.sha256Hex(signString);
|
||||||
|
|
||||||
|
// 准备参数
|
||||||
|
ApiSignature apiSignature = mock(ApiSignature.class);
|
||||||
|
when(apiSignature.appId()).thenReturn("appId");
|
||||||
|
when(apiSignature.timestamp()).thenReturn("timestamp");
|
||||||
|
when(apiSignature.nonce()).thenReturn("nonce");
|
||||||
|
when(apiSignature.sign()).thenReturn("sign");
|
||||||
|
when(apiSignature.timeout()).thenReturn(60);
|
||||||
|
when(apiSignature.timeUnit()).thenReturn(TimeUnit.SECONDS);
|
||||||
|
HttpServletRequest request = mock(HttpServletRequest.class);
|
||||||
|
when(request.getHeader(eq("appId"))).thenReturn(appId);
|
||||||
|
when(request.getHeader(eq("timestamp"))).thenReturn(String.valueOf(timestamp));
|
||||||
|
when(request.getHeader(eq("nonce"))).thenReturn(nonce);
|
||||||
|
when(request.getHeader(eq("sign"))).thenReturn(sign);
|
||||||
|
when(request.getParameterMap()).thenReturn(MapUtil.<String, String[]>builder()
|
||||||
|
.put("v1", new String[]{"k1"}).put("k1", new String[]{"v1"}).build());
|
||||||
|
when(request.getContentType()).thenReturn("application/json");
|
||||||
|
when(request.getReader()).thenReturn(new BufferedReader(new StringReader("test")));
|
||||||
|
// mock 方法
|
||||||
|
when(signatureRedisDAO.getAppSecret(eq(appId))).thenReturn(appSecret);
|
||||||
|
|
||||||
|
// 调用
|
||||||
|
boolean result = apiSignatureAspect.verifySignature(apiSignature, request);
|
||||||
|
// 断言结果
|
||||||
|
assertTrue(result);
|
||||||
|
// 断言调用
|
||||||
|
verify(signatureRedisDAO).setNonce(eq(nonce), eq(120), eq(TimeUnit.SECONDS));
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
@ -1,5 +1,6 @@
|
|||||||
package cn.iocoder.yudao.module.crm.dal.dataobject.business;
|
package cn.iocoder.yudao.module.crm.dal.dataobject.business;
|
||||||
|
|
||||||
|
import cn.iocoder.yudao.framework.mybatis.core.dataobject.BaseDO;
|
||||||
import com.baomidou.mybatisplus.annotation.KeySequence;
|
import com.baomidou.mybatisplus.annotation.KeySequence;
|
||||||
import com.baomidou.mybatisplus.annotation.TableId;
|
import com.baomidou.mybatisplus.annotation.TableId;
|
||||||
import com.baomidou.mybatisplus.annotation.TableName;
|
import com.baomidou.mybatisplus.annotation.TableName;
|
||||||
@ -19,7 +20,7 @@ import lombok.*;
|
|||||||
@Builder
|
@Builder
|
||||||
@NoArgsConstructor
|
@NoArgsConstructor
|
||||||
@AllArgsConstructor
|
@AllArgsConstructor
|
||||||
public class CrmBusinessStatusDO {
|
public class CrmBusinessStatusDO extends BaseDO {
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 主键
|
* 主键
|
||||||
|
@ -28,8 +28,8 @@ public class FileContentDO extends BaseDO {
|
|||||||
/**
|
/**
|
||||||
* 编号,数据库自增
|
* 编号,数据库自增
|
||||||
*/
|
*/
|
||||||
@TableId(type = IdType.INPUT)
|
@TableId
|
||||||
private String id;
|
private Long id;
|
||||||
/**
|
/**
|
||||||
* 配置编号
|
* 配置编号
|
||||||
*
|
*
|
||||||
|
@ -25,7 +25,6 @@ import java.time.LocalDateTime;
|
|||||||
@KeySequence(value = "infra_api_error_log_seq")
|
@KeySequence(value = "infra_api_error_log_seq")
|
||||||
public class ApiErrorLogDO extends BaseDO {
|
public class ApiErrorLogDO extends BaseDO {
|
||||||
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* {@link #requestParams} 的最大长度
|
* {@link #requestParams} 的最大长度
|
||||||
*/
|
*/
|
||||||
|
@ -342,7 +342,8 @@ public class CodegenEngine {
|
|||||||
|
|
||||||
// className 相关
|
// className 相关
|
||||||
// 去掉指定前缀,将 TestDictType 转换成 DictType. 因为在 create 等方法后,不需要带上 Test 前缀
|
// 去掉指定前缀,将 TestDictType 转换成 DictType. 因为在 create 等方法后,不需要带上 Test 前缀
|
||||||
String simpleClassName = removePrefix(table.getClassName(), upperFirst(table.getModuleName()));
|
String simpleClassName = equalsAnyIgnoreCase(table.getClassName(), table.getModuleName()) ? table.getClassName()
|
||||||
|
: removePrefix(table.getClassName(), upperFirst(table.getModuleName()));
|
||||||
bindingMap.put("simpleClassName", simpleClassName);
|
bindingMap.put("simpleClassName", simpleClassName);
|
||||||
bindingMap.put("simpleClassName_underlineCase", toUnderlineCase(simpleClassName)); // 将 DictType 转换成 dict_type
|
bindingMap.put("simpleClassName_underlineCase", toUnderlineCase(simpleClassName)); // 将 DictType 转换成 dict_type
|
||||||
bindingMap.put("classNameVar", lowerFirst(simpleClassName)); // 将 DictType 转换成 dictType,用于变量
|
bindingMap.put("classNameVar", lowerFirst(simpleClassName)); // 将 DictType 转换成 dictType,用于变量
|
||||||
|
@ -1,33 +1,49 @@
|
|||||||
package cn.iocoder.yudao.module.trade.service.order;
|
package cn.iocoder.yudao.module.trade.service.order;
|
||||||
|
|
||||||
|
import cn.hutool.core.util.IdUtil;
|
||||||
|
import cn.iocoder.yudao.framework.common.enums.CommonStatusEnum;
|
||||||
import cn.iocoder.yudao.framework.test.core.ut.BaseDbUnitTest;
|
import cn.iocoder.yudao.framework.test.core.ut.BaseDbUnitTest;
|
||||||
import cn.iocoder.yudao.module.member.api.address.MemberAddressApi;
|
import cn.iocoder.yudao.module.member.api.address.MemberAddressApi;
|
||||||
import cn.iocoder.yudao.module.member.api.user.MemberUserApi;
|
import cn.iocoder.yudao.module.member.api.user.MemberUserApi;
|
||||||
import cn.iocoder.yudao.module.pay.api.order.PayOrderApi;
|
import cn.iocoder.yudao.module.pay.api.order.PayOrderApi;
|
||||||
import cn.iocoder.yudao.module.pay.api.order.dto.PayOrderRespDTO;
|
import cn.iocoder.yudao.module.pay.api.order.dto.PayOrderRespDTO;
|
||||||
import cn.iocoder.yudao.module.pay.enums.order.PayOrderStatusEnum;
|
import cn.iocoder.yudao.module.pay.enums.order.PayOrderStatusEnum;
|
||||||
|
import cn.iocoder.yudao.module.product.api.comment.ProductCommentApi;
|
||||||
import cn.iocoder.yudao.module.product.api.sku.ProductSkuApi;
|
import cn.iocoder.yudao.module.product.api.sku.ProductSkuApi;
|
||||||
import cn.iocoder.yudao.module.product.api.spu.ProductSpuApi;
|
import cn.iocoder.yudao.module.product.api.spu.ProductSpuApi;
|
||||||
import cn.iocoder.yudao.module.promotion.api.coupon.CouponApi;
|
import cn.iocoder.yudao.module.promotion.api.coupon.CouponApi;
|
||||||
|
import cn.iocoder.yudao.module.system.api.notify.NotifyMessageSendApi;
|
||||||
|
import cn.iocoder.yudao.module.trade.controller.admin.delivery.vo.express.DeliveryExpressCreateReqVO;
|
||||||
import cn.iocoder.yudao.module.trade.controller.admin.order.vo.TradeOrderDeliveryReqVO;
|
import cn.iocoder.yudao.module.trade.controller.admin.order.vo.TradeOrderDeliveryReqVO;
|
||||||
import cn.iocoder.yudao.module.trade.dal.dataobject.order.TradeOrderDO;
|
import cn.iocoder.yudao.module.trade.dal.dataobject.order.TradeOrderDO;
|
||||||
import cn.iocoder.yudao.module.trade.dal.mysql.order.TradeOrderItemMapper;
|
import cn.iocoder.yudao.module.trade.dal.mysql.order.TradeOrderItemMapper;
|
||||||
import cn.iocoder.yudao.module.trade.dal.mysql.order.TradeOrderMapper;
|
import cn.iocoder.yudao.module.trade.dal.mysql.order.TradeOrderMapper;
|
||||||
|
import cn.iocoder.yudao.module.trade.dal.redis.no.TradeNoRedisDAO;
|
||||||
|
import cn.iocoder.yudao.module.trade.enums.delivery.DeliveryTypeEnum;
|
||||||
|
import cn.iocoder.yudao.module.trade.enums.order.TradeOrderRefundStatusEnum;
|
||||||
import cn.iocoder.yudao.module.trade.enums.order.TradeOrderStatusEnum;
|
import cn.iocoder.yudao.module.trade.enums.order.TradeOrderStatusEnum;
|
||||||
import cn.iocoder.yudao.module.trade.framework.order.config.TradeOrderConfig;
|
import cn.iocoder.yudao.module.trade.framework.order.config.TradeOrderConfig;
|
||||||
import cn.iocoder.yudao.module.trade.framework.order.config.TradeOrderProperties;
|
import cn.iocoder.yudao.module.trade.framework.order.config.TradeOrderProperties;
|
||||||
|
import cn.iocoder.yudao.module.trade.service.cart.CartServiceImpl;
|
||||||
|
import cn.iocoder.yudao.module.trade.service.delivery.DeliveryExpressService;
|
||||||
|
import cn.iocoder.yudao.module.trade.service.delivery.DeliveryExpressServiceImpl;
|
||||||
|
import cn.iocoder.yudao.module.trade.service.message.TradeMessageServiceImpl;
|
||||||
|
import cn.iocoder.yudao.module.trade.service.order.handler.TradeOrderHandler;
|
||||||
|
import cn.iocoder.yudao.module.trade.service.price.TradePriceServiceImpl;
|
||||||
|
import cn.iocoder.yudao.module.trade.service.price.calculator.TradePriceCalculator;
|
||||||
|
import jakarta.annotation.Resource;
|
||||||
import org.junit.jupiter.api.BeforeEach;
|
import org.junit.jupiter.api.BeforeEach;
|
||||||
import org.junit.jupiter.api.Disabled;
|
import org.junit.jupiter.api.Disabled;
|
||||||
import org.junit.jupiter.api.Test;
|
import org.junit.jupiter.api.Test;
|
||||||
import org.springframework.boot.test.mock.mockito.MockBean;
|
import org.springframework.boot.test.mock.mockito.MockBean;
|
||||||
import org.springframework.context.annotation.Import;
|
import org.springframework.context.annotation.Import;
|
||||||
|
|
||||||
import jakarta.annotation.Resource;
|
|
||||||
import java.time.Duration;
|
import java.time.Duration;
|
||||||
|
|
||||||
import static cn.iocoder.yudao.framework.test.core.util.AssertUtils.assertPojoEquals;
|
import static cn.iocoder.yudao.framework.test.core.util.AssertUtils.assertPojoEquals;
|
||||||
import static cn.iocoder.yudao.framework.test.core.util.RandomUtils.randomPojo;
|
import static cn.iocoder.yudao.framework.test.core.util.RandomUtils.randomPojo;
|
||||||
import static org.junit.jupiter.api.Assertions.*;
|
import static org.junit.jupiter.api.Assertions.*;
|
||||||
|
import static org.mockito.ArgumentMatchers.anyString;
|
||||||
import static org.mockito.ArgumentMatchers.eq;
|
import static org.mockito.ArgumentMatchers.eq;
|
||||||
import static org.mockito.Mockito.when;
|
import static org.mockito.Mockito.when;
|
||||||
|
|
||||||
@ -38,7 +54,9 @@ import static org.mockito.Mockito.when;
|
|||||||
* @since 2022-09-07
|
* @since 2022-09-07
|
||||||
*/
|
*/
|
||||||
@Disabled // TODO 芋艿:后续 fix 补充的单测
|
@Disabled // TODO 芋艿:后续 fix 补充的单测
|
||||||
@Import({TradeOrderUpdateServiceImpl.class, TradeOrderConfig.class})
|
@Import({TradeOrderUpdateServiceImpl.class, TradeOrderConfig.class, CartServiceImpl.class, TradePriceServiceImpl.class,
|
||||||
|
DeliveryExpressServiceImpl.class, TradeMessageServiceImpl.class
|
||||||
|
})
|
||||||
public class TradeOrderUpdateServiceTest extends BaseDbUnitTest {
|
public class TradeOrderUpdateServiceTest extends BaseDbUnitTest {
|
||||||
|
|
||||||
@Resource
|
@Resource
|
||||||
@ -55,7 +73,9 @@ public class TradeOrderUpdateServiceTest extends BaseDbUnitTest {
|
|||||||
private ProductSpuApi productSpuApi;
|
private ProductSpuApi productSpuApi;
|
||||||
@MockBean
|
@MockBean
|
||||||
private ProductSkuApi productSkuApi;
|
private ProductSkuApi productSkuApi;
|
||||||
// @MockBean
|
@MockBean
|
||||||
|
private ProductCommentApi productCommentApi;
|
||||||
|
// @MockBean
|
||||||
// private PriceApi priceApi;
|
// private PriceApi priceApi;
|
||||||
@MockBean
|
@MockBean
|
||||||
private PayOrderApi payOrderApi;
|
private PayOrderApi payOrderApi;
|
||||||
@ -66,11 +86,22 @@ public class TradeOrderUpdateServiceTest extends BaseDbUnitTest {
|
|||||||
|
|
||||||
@MockBean
|
@MockBean
|
||||||
private TradeOrderProperties tradeOrderProperties;
|
private TradeOrderProperties tradeOrderProperties;
|
||||||
|
@MockBean
|
||||||
|
private TradeNoRedisDAO tradeNoRedisDAO;
|
||||||
|
@MockBean
|
||||||
|
private TradeOrderHandler tradeOrderHandler;
|
||||||
|
@MockBean
|
||||||
|
private TradePriceCalculator tradePriceCalculator;
|
||||||
|
@MockBean
|
||||||
|
private NotifyMessageSendApi notifyMessageSendApi;
|
||||||
|
@MockBean
|
||||||
|
private DeliveryExpressService deliveryExpressService;
|
||||||
|
|
||||||
@BeforeEach
|
@BeforeEach
|
||||||
public void setUp() {
|
public void setUp() {
|
||||||
when(tradeOrderProperties.getAppId()).thenReturn(888L);
|
when(tradeOrderProperties.getAppId()).thenReturn(888L);
|
||||||
when(tradeOrderProperties.getPayExpireTime()).thenReturn(Duration.ofDays(1));
|
when(tradeOrderProperties.getPayExpireTime()).thenReturn(Duration.ofDays(1));
|
||||||
|
when(tradeNoRedisDAO.generate(anyString())).thenReturn(IdUtil.randomUUID());
|
||||||
}
|
}
|
||||||
|
|
||||||
// @Test
|
// @Test
|
||||||
@ -259,11 +290,18 @@ public class TradeOrderUpdateServiceTest extends BaseDbUnitTest {
|
|||||||
TradeOrderDO order = randomPojo(TradeOrderDO.class, o -> {
|
TradeOrderDO order = randomPojo(TradeOrderDO.class, o -> {
|
||||||
o.setId(1L).setStatus(TradeOrderStatusEnum.UNDELIVERED.getStatus());
|
o.setId(1L).setStatus(TradeOrderStatusEnum.UNDELIVERED.getStatus());
|
||||||
o.setLogisticsId(null).setLogisticsNo(null).setDeliveryTime(null);
|
o.setLogisticsId(null).setLogisticsNo(null).setDeliveryTime(null);
|
||||||
|
o.setRefundStatus(TradeOrderRefundStatusEnum.NONE.getStatus());
|
||||||
|
o.setDeliveryType(DeliveryTypeEnum.EXPRESS.getType());
|
||||||
});
|
});
|
||||||
tradeOrderMapper.insert(order);
|
tradeOrderMapper.insert(order);
|
||||||
|
|
||||||
|
DeliveryExpressCreateReqVO expressCreateReqVO = new DeliveryExpressCreateReqVO();
|
||||||
|
expressCreateReqVO.setCode("code").setName("Name").setLogo("logo").setSort(0).setStatus(CommonStatusEnum.ENABLE.getStatus());
|
||||||
|
Long deliveryExpressId = deliveryExpressService.createDeliveryExpress(expressCreateReqVO);
|
||||||
// 准备参数
|
// 准备参数
|
||||||
TradeOrderDeliveryReqVO deliveryReqVO = new TradeOrderDeliveryReqVO().setId(1L)
|
TradeOrderDeliveryReqVO deliveryReqVO = new TradeOrderDeliveryReqVO().setId(1L)
|
||||||
.setLogisticsId(10L).setLogisticsNo("100");
|
.setLogisticsId(deliveryExpressId).setLogisticsNo("100");
|
||||||
|
|
||||||
// mock 方法(支付单)
|
// mock 方法(支付单)
|
||||||
|
|
||||||
// 调用
|
// 调用
|
||||||
|
@ -1,128 +1,155 @@
|
|||||||
CREATE TABLE IF NOT EXISTS "trade_order" (
|
CREATE TABLE IF NOT EXISTS "trade_order"
|
||||||
"id" bigint NOT NULL GENERATED BY DEFAULT AS IDENTITY,
|
(
|
||||||
"no" varchar NOT NULL,
|
"id" bigint NOT NULL GENERATED BY DEFAULT AS IDENTITY,
|
||||||
"type" int NOT NULL,
|
"no" varchar NOT NULL,
|
||||||
"terminal" int NOT NULL,
|
"type" int NOT NULL,
|
||||||
"user_id" bigint NOT NULL,
|
"terminal" int NOT NULL,
|
||||||
"user_ip" varchar NOT NULL,
|
"user_id" bigint NOT NULL,
|
||||||
"user_remark" varchar,
|
"user_ip" varchar NOT NULL,
|
||||||
"status" int NOT NULL,
|
"user_remark" varchar,
|
||||||
"product_count" int NOT NULL,
|
"status" int NOT NULL,
|
||||||
"cancel_type" int,
|
"product_count" int NOT NULL,
|
||||||
"remark" varchar,
|
"cancel_type" int,
|
||||||
"pay_status" bit NOT NULL,
|
"remark" varchar,
|
||||||
"pay_time" datetime,
|
"comment_status" boolean,
|
||||||
"finish_time" datetime,
|
"brokerage_user_id" bigint,
|
||||||
"cancel_time" datetime,
|
"pay_status" bit NOT NULL,
|
||||||
"original_price" int NOT NULL,
|
"pay_time" datetime,
|
||||||
"order_price" int NOT NULL,
|
"finish_time" datetime,
|
||||||
"discount_price" int NOT NULL,
|
"cancel_time" datetime,
|
||||||
"delivery_price" int NOT NULL,
|
"total_price" int NULL,
|
||||||
"adjust_price" int NOT NULL,
|
"order_price" int NULL,
|
||||||
"pay_price" int NOT NULL,
|
"discount_price" int NOT NULL,
|
||||||
"pay_order_id" bigint,
|
"delivery_price" int NOT NULL,
|
||||||
"pay_channel_code" varchar,
|
"adjust_price" int NOT NULL,
|
||||||
"delivery_template_id" bigint,
|
"pay_price" int NOT NULL,
|
||||||
"logistics_id" bigint,
|
"delivery_type" int NOT NULL,
|
||||||
"logistics_no" varchar,
|
"pay_order_id" bigint,
|
||||||
"delivery_time" datetime,
|
"pay_channel_code" varchar,
|
||||||
"receive_time" datetime,
|
"delivery_template_id" bigint,
|
||||||
"receiver_name" varchar NOT NULL,
|
"logistics_id" bigint,
|
||||||
"receiver_mobile" varchar NOT NULL,
|
"logistics_no" varchar,
|
||||||
"receiver_area_id" int NOT NULL,
|
"delivery_time" datetime,
|
||||||
"receiver_post_code" int,
|
"receive_time" datetime,
|
||||||
"receiver_detail_address" varchar NOT NULL,
|
"receiver_name" varchar NOT NULL,
|
||||||
"after_sale_status" int NOT NULL,
|
"receiver_mobile" varchar NOT NULL,
|
||||||
"refund_price" int NOT NULL,
|
"receiver_area_id" int NOT NULL,
|
||||||
"coupon_id" bigint NOT NULL,
|
"receiver_post_code" int,
|
||||||
"coupon_price" int NOT NULL,
|
"receiver_detail_address" varchar NOT NULL,
|
||||||
"point_price" int NOT NULL,
|
"pick_up_store_id" long NULL,
|
||||||
"creator" varchar DEFAULT '',
|
"pick_up_verify_code" varchar NULL,
|
||||||
"create_time" datetime NOT NULL DEFAULT CURRENT_TIMESTAMP,
|
"refund_status" int NULL,
|
||||||
"updater" varchar DEFAULT '',
|
"refund_price" int NULL,
|
||||||
"update_time" datetime NOT NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP,
|
"after_sale_status" int NULL,
|
||||||
"deleted" bit NOT NULL DEFAULT FALSE,
|
"coupon_id" bigint NOT NULL,
|
||||||
PRIMARY KEY ("id")
|
"coupon_price" int NOT NULL,
|
||||||
|
"use_point" int NULL,
|
||||||
|
"point_price" int NOT NULL,
|
||||||
|
"give_point" int NULL,
|
||||||
|
"refund_point" int NULL,
|
||||||
|
"vip_price" int NULL,
|
||||||
|
"seckill_activity_id" long NULL,
|
||||||
|
"bargain_activity_id" long NULL,
|
||||||
|
"bargain_record_id" long NULL,
|
||||||
|
"combination_activity_id" long NULL,
|
||||||
|
"combination_head_id" long NULL,
|
||||||
|
"combination_record_id" long NULL,
|
||||||
|
"creator" varchar DEFAULT '',
|
||||||
|
"create_time" datetime NOT NULL DEFAULT CURRENT_TIMESTAMP,
|
||||||
|
"updater" varchar DEFAULT '',
|
||||||
|
"update_time" datetime NOT NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP,
|
||||||
|
"deleted" bit NOT NULL DEFAULT FALSE,
|
||||||
|
PRIMARY KEY ("id")
|
||||||
) COMMENT '交易订单表';
|
) COMMENT '交易订单表';
|
||||||
|
|
||||||
CREATE TABLE IF NOT EXISTS "trade_order_item" (
|
CREATE TABLE IF NOT EXISTS "trade_order_item"
|
||||||
"id" bigint NOT NULL GENERATED BY DEFAULT AS IDENTITY,
|
(
|
||||||
"user_id" bigint NOT NULL,
|
"id" bigint NOT NULL GENERATED BY DEFAULT AS IDENTITY,
|
||||||
"order_id" bigint NOT NULL,
|
"user_id" bigint NOT NULL,
|
||||||
"spu_id" bigint NOT NULL,
|
"order_id" bigint NOT NULL,
|
||||||
"spu_name" varchar NOT NULL,
|
"cart_id" int NULL,
|
||||||
"sku_id" bigint NOT NULL,
|
"spu_id" bigint NOT NULL,
|
||||||
"properties" varchar,
|
"spu_name" varchar NOT NULL,
|
||||||
"pic_url" varchar,
|
"sku_id" bigint NOT NULL,
|
||||||
"count" int NOT NULL,
|
"properties" varchar,
|
||||||
"original_price" int NOT NULL,
|
"pic_url" varchar,
|
||||||
"original_unit_price" int NOT NULL,
|
"count" int NOT NULL,
|
||||||
"discount_price" int NOT NULL,
|
"comment_status" boolean NULL,
|
||||||
"pay_price" int NOT NULL,
|
"price" int NOT NULL,
|
||||||
"order_part_price" int NOT NULL,
|
"discount_price" int NOT NULL,
|
||||||
"order_divide_price" int NOT NULL,
|
"delivery_price" int NULL,
|
||||||
"after_sale_status" int NOT NULL,
|
"adjust_price" int NULL,
|
||||||
"creator" varchar DEFAULT '',
|
"pay_price" int NOT NULL,
|
||||||
"create_time" datetime NOT NULL DEFAULT CURRENT_TIMESTAMP,
|
"coupon_price" int NULL,
|
||||||
"updater" varchar DEFAULT '',
|
"point_price" int NULL,
|
||||||
"update_time" datetime NOT NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP,
|
"use_point" int NULL,
|
||||||
"deleted" bit NOT NULL DEFAULT FALSE,
|
"give_point" int NULL,
|
||||||
PRIMARY KEY ("id")
|
"vip_price" int NULL,
|
||||||
|
"after_sale_id" long NULL,
|
||||||
|
"after_sale_status" int NOT NULL,
|
||||||
|
"creator" varchar DEFAULT '',
|
||||||
|
"create_time" datetime NOT NULL DEFAULT CURRENT_TIMESTAMP,
|
||||||
|
"updater" varchar DEFAULT '',
|
||||||
|
"update_time" datetime NOT NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP,
|
||||||
|
"deleted" bit NOT NULL DEFAULT FALSE,
|
||||||
|
PRIMARY KEY ("id")
|
||||||
) COMMENT '交易订单明细表';
|
) COMMENT '交易订单明细表';
|
||||||
|
|
||||||
CREATE TABLE IF NOT EXISTS "trade_after_sale" (
|
CREATE TABLE IF NOT EXISTS "trade_after_sale"
|
||||||
"id" bigint NOT NULL GENERATED BY DEFAULT AS IDENTITY,
|
(
|
||||||
"no" varchar NOT NULL,
|
"id" bigint NOT NULL GENERATED BY DEFAULT AS IDENTITY,
|
||||||
"status" int NOT NULL,
|
"no" varchar NOT NULL,
|
||||||
"type" int NOT NULL,
|
"status" int NOT NULL,
|
||||||
"way" int NOT NULL,
|
"type" int NOT NULL,
|
||||||
"user_id" bigint NOT NULL,
|
"way" int NOT NULL,
|
||||||
"apply_reason" varchar NOT NULL,
|
"user_id" bigint NOT NULL,
|
||||||
|
"apply_reason" varchar NOT NULL,
|
||||||
"apply_description" varchar,
|
"apply_description" varchar,
|
||||||
"apply_pic_urls" varchar,
|
"apply_pic_urls" varchar,
|
||||||
"order_id" bigint NOT NULL,
|
"order_id" bigint NOT NULL,
|
||||||
"order_no" varchar NOT NULL,
|
"order_no" varchar NOT NULL,
|
||||||
"order_item_id" bigint NOT NULL,
|
"order_item_id" bigint NOT NULL,
|
||||||
"spu_id" bigint NOT NULL,
|
"spu_id" bigint NOT NULL,
|
||||||
"spu_name" varchar NOT NULL,
|
"spu_name" varchar NOT NULL,
|
||||||
"sku_id" bigint NOT NULL,
|
"sku_id" bigint NOT NULL,
|
||||||
"properties" varchar,
|
"properties" varchar,
|
||||||
"pic_url" varchar,
|
"pic_url" varchar,
|
||||||
"count" int NOT NULL,
|
"count" int NOT NULL,
|
||||||
"audit_time" varchar,
|
"audit_time" varchar,
|
||||||
"audit_user_id" bigint,
|
"audit_user_id" bigint,
|
||||||
"audit_reason" varchar,
|
"audit_reason" varchar,
|
||||||
"refund_price" int NOT NULL,
|
"refund_price" int NOT NULL,
|
||||||
"pay_refund_id" bigint,
|
"pay_refund_id" bigint,
|
||||||
"refund_time" varchar,
|
"refund_time" varchar,
|
||||||
"logistics_id" bigint,
|
"logistics_id" bigint,
|
||||||
"logistics_no" varchar,
|
"logistics_no" varchar,
|
||||||
"delivery_time" varchar,
|
"delivery_time" varchar,
|
||||||
"receive_time" varchar,
|
"receive_time" varchar,
|
||||||
"receive_reason" varchar,
|
"receive_reason" varchar,
|
||||||
"creator" varchar DEFAULT '',
|
"creator" varchar DEFAULT '',
|
||||||
"create_time" datetime NOT NULL DEFAULT CURRENT_TIMESTAMP,
|
"create_time" datetime NOT NULL DEFAULT CURRENT_TIMESTAMP,
|
||||||
"updater" varchar DEFAULT '',
|
"updater" varchar DEFAULT '',
|
||||||
"update_time" datetime NOT NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP,
|
"update_time" datetime NOT NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP,
|
||||||
"deleted" bit NOT NULL DEFAULT FALSE,
|
"deleted" bit NOT NULL DEFAULT FALSE,
|
||||||
PRIMARY KEY ("id")
|
PRIMARY KEY ("id")
|
||||||
) COMMENT '交易售后表';
|
) COMMENT '交易售后表';
|
||||||
|
|
||||||
CREATE TABLE IF NOT EXISTS "trade_after_sale_log" (
|
CREATE TABLE IF NOT EXISTS "trade_after_sale_log"
|
||||||
"id" bigint NOT NULL GENERATED BY DEFAULT AS IDENTITY,
|
(
|
||||||
"user_id" bigint NOT NULL,
|
"id" bigint NOT NULL GENERATED BY DEFAULT AS IDENTITY,
|
||||||
"user_type" int NOT NULL,
|
"user_id" bigint NOT NULL,
|
||||||
"after_sale_id" bigint NOT NULL,
|
"user_type" int NOT NULL,
|
||||||
"order_id" bigint NOT NULL,
|
"after_sale_id" bigint NOT NULL,
|
||||||
"order_item_id" bigint NOT NULL,
|
"order_id" bigint NOT NULL,
|
||||||
|
"order_item_id" bigint NOT NULL,
|
||||||
"before_status" int,
|
"before_status" int,
|
||||||
"after_status" int NOT NULL,
|
"after_status" int NOT NULL,
|
||||||
"content" varchar NOT NULL,
|
"content" varchar NOT NULL,
|
||||||
"creator" varchar DEFAULT '',
|
"creator" varchar DEFAULT '',
|
||||||
"create_time" datetime NOT NULL DEFAULT CURRENT_TIMESTAMP,
|
"create_time" datetime NOT NULL DEFAULT CURRENT_TIMESTAMP,
|
||||||
"updater" varchar DEFAULT '',
|
"updater" varchar DEFAULT '',
|
||||||
"update_time" datetime NOT NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP,
|
"update_time" datetime NOT NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP,
|
||||||
"deleted" bit NOT NULL DEFAULT FALSE,
|
"deleted" bit NOT NULL DEFAULT FALSE,
|
||||||
PRIMARY KEY ("id")
|
PRIMARY KEY ("id")
|
||||||
) COMMENT '交易售后日志';
|
) COMMENT '交易售后日志';
|
||||||
|
|
||||||
@ -161,7 +188,7 @@ CREATE TABLE IF NOT EXISTS "trade_brokerage_record"
|
|||||||
"updater" varchar DEFAULT '',
|
"updater" varchar DEFAULT '',
|
||||||
"update_time" datetime NOT NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP,
|
"update_time" datetime NOT NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP,
|
||||||
"deleted" bit NOT NULL DEFAULT FALSE,
|
"deleted" bit NOT NULL DEFAULT FALSE,
|
||||||
"tenant_id" bigint not null default '0',
|
"tenant_id" bigint not null default '0',
|
||||||
PRIMARY KEY ("id")
|
PRIMARY KEY ("id")
|
||||||
) COMMENT '佣金记录';
|
) COMMENT '佣金记录';
|
||||||
CREATE TABLE IF NOT EXISTS "trade_brokerage_withdraw"
|
CREATE TABLE IF NOT EXISTS "trade_brokerage_withdraw"
|
||||||
@ -186,6 +213,22 @@ CREATE TABLE IF NOT EXISTS "trade_brokerage_withdraw"
|
|||||||
"updater" varchar DEFAULT '',
|
"updater" varchar DEFAULT '',
|
||||||
"update_time" datetime NOT NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP,
|
"update_time" datetime NOT NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP,
|
||||||
"deleted" bit NOT NULL DEFAULT FALSE,
|
"deleted" bit NOT NULL DEFAULT FALSE,
|
||||||
"tenant_id" bigint not null default '0',
|
"tenant_id" bigint not null default '0',
|
||||||
|
PRIMARY KEY ("id")
|
||||||
|
) COMMENT '佣金提现';
|
||||||
|
|
||||||
|
CREATE TABLE IF NOT EXISTS "trade_delivery_express"
|
||||||
|
(
|
||||||
|
"id" int NOT NULL GENERATED BY DEFAULT AS IDENTITY,
|
||||||
|
"code" varchar NULL,
|
||||||
|
"name" varchar,
|
||||||
|
"logo" varchar NULL,
|
||||||
|
"sort" int NOT NULL,
|
||||||
|
"status" int NOT NULL,
|
||||||
|
"creator" varchar DEFAULT '',
|
||||||
|
"create_time" datetime NOT NULL DEFAULT CURRENT_TIMESTAMP,
|
||||||
|
"updater" varchar DEFAULT '',
|
||||||
|
"update_time" datetime NOT NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP,
|
||||||
|
"deleted" bit NOT NULL DEFAULT FALSE,
|
||||||
PRIMARY KEY ("id")
|
PRIMARY KEY ("id")
|
||||||
) COMMENT '佣金提现';
|
) COMMENT '佣金提现';
|
@ -11,6 +11,7 @@ import lombok.Getter;
|
|||||||
@Getter
|
@Getter
|
||||||
@AllArgsConstructor
|
@AllArgsConstructor
|
||||||
public enum SexEnum {
|
public enum SexEnum {
|
||||||
|
|
||||||
/** 男 */
|
/** 男 */
|
||||||
MALE(1),
|
MALE(1),
|
||||||
/** 女 */
|
/** 女 */
|
||||||
|
Loading…
Reference in New Issue
Block a user