Compare commits
21 Commits
980f8f187e
...
master
| Author | SHA1 | Date | |
|---|---|---|---|
| f38859f211 | |||
| 4b7cd9d0d3 | |||
| 0efca0fb02 | |||
| 853651e80d | |||
| 823c56293d | |||
| 6462e51bc8 | |||
| d63df710b3 | |||
| b2b6b1306f | |||
| 00ea325ebf | |||
| 83e605f2ff | |||
| 182d6fff0e | |||
| 43d1d26787 | |||
| 68e0414034 | |||
| 947ecf21aa | |||
| 6674117ac9 | |||
| 6ebca60d4f | |||
| f42ef63b37 | |||
| c32b0eee56 | |||
| 65e2209a85 | |||
| ad44d4ea8a | |||
| b8a70cae5c |
@@ -1,7 +1,6 @@
|
|||||||
package com.gxwebsoft.auto.dto;
|
package com.gxwebsoft.auto.dto;
|
||||||
|
|
||||||
import com.gxwebsoft.common.system.entity.User;
|
import com.gxwebsoft.common.system.entity.User;
|
||||||
import io.swagger.models.auth.In;
|
|
||||||
import io.swagger.v3.oas.annotations.media.Schema;
|
import io.swagger.v3.oas.annotations.media.Schema;
|
||||||
import lombok.AllArgsConstructor;
|
import lombok.AllArgsConstructor;
|
||||||
import lombok.Data;
|
import lombok.Data;
|
||||||
|
|||||||
@@ -0,0 +1,72 @@
|
|||||||
|
package com.gxwebsoft.common.core.config;
|
||||||
|
|
||||||
|
import lombok.Data;
|
||||||
|
import org.springframework.boot.context.properties.ConfigurationProperties;
|
||||||
|
import org.springframework.stereotype.Component;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* MQTT配置属性
|
||||||
|
*
|
||||||
|
* @author 科技小王子
|
||||||
|
* @since 2025-07-02
|
||||||
|
*/
|
||||||
|
@Data
|
||||||
|
@Component
|
||||||
|
@ConfigurationProperties(prefix = "mqtt")
|
||||||
|
public class MqttProperties {
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 是否启用MQTT服务
|
||||||
|
*/
|
||||||
|
private boolean enabled = false;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* MQTT服务器地址
|
||||||
|
*/
|
||||||
|
private String host = "tcp://127.0.0.1:1883";
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 用户名
|
||||||
|
*/
|
||||||
|
private String username = "";
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 密码
|
||||||
|
*/
|
||||||
|
private String password = "";
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 客户端ID前缀
|
||||||
|
*/
|
||||||
|
private String clientIdPrefix = "mqtt_client_";
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 订阅主题
|
||||||
|
*/
|
||||||
|
private String topic = "/SW_GPS/#";
|
||||||
|
|
||||||
|
/**
|
||||||
|
* QoS等级
|
||||||
|
*/
|
||||||
|
private int qos = 2;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 连接超时时间(秒)
|
||||||
|
*/
|
||||||
|
private int connectionTimeout = 10;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 心跳间隔(秒)
|
||||||
|
*/
|
||||||
|
private int keepAliveInterval = 20;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 是否自动重连
|
||||||
|
*/
|
||||||
|
private boolean autoReconnect = true;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 是否清除会话
|
||||||
|
*/
|
||||||
|
private boolean cleanSession = false;
|
||||||
|
}
|
||||||
@@ -2,4 +2,5 @@ package com.gxwebsoft.common.core.constants;
|
|||||||
|
|
||||||
public class ArticleConstants extends BaseConstants {
|
public class ArticleConstants extends BaseConstants {
|
||||||
public static final String[] ARTICLE_STATUS = {"已发布","待审核","已驳回","违规内容"};
|
public static final String[] ARTICLE_STATUS = {"已发布","待审核","已驳回","违规内容"};
|
||||||
|
public static final String CACHE_KEY_ARTICLE = "Article:";
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -0,0 +1,67 @@
|
|||||||
|
package com.gxwebsoft.common.core.context;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 租户上下文管理器
|
||||||
|
*
|
||||||
|
* 用于在特定场景下临时禁用租户隔离
|
||||||
|
*
|
||||||
|
* @author WebSoft
|
||||||
|
* @since 2025-01-26
|
||||||
|
*/
|
||||||
|
public class TenantContext {
|
||||||
|
|
||||||
|
private static final ThreadLocal<Boolean> IGNORE_TENANT = new ThreadLocal<>();
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 设置忽略租户隔离
|
||||||
|
*/
|
||||||
|
public static void setIgnoreTenant(boolean ignore) {
|
||||||
|
IGNORE_TENANT.set(ignore);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 是否忽略租户隔离
|
||||||
|
*/
|
||||||
|
public static boolean isIgnoreTenant() {
|
||||||
|
Boolean ignore = IGNORE_TENANT.get();
|
||||||
|
return ignore != null && ignore;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 清除租户上下文
|
||||||
|
*/
|
||||||
|
public static void clear() {
|
||||||
|
IGNORE_TENANT.remove();
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 在忽略租户隔离的上下文中执行操作
|
||||||
|
*
|
||||||
|
* @param runnable 要执行的操作
|
||||||
|
*/
|
||||||
|
public static void runIgnoreTenant(Runnable runnable) {
|
||||||
|
boolean originalIgnore = isIgnoreTenant();
|
||||||
|
try {
|
||||||
|
setIgnoreTenant(true);
|
||||||
|
runnable.run();
|
||||||
|
} finally {
|
||||||
|
setIgnoreTenant(originalIgnore);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 在忽略租户隔离的上下文中执行操作并返回结果
|
||||||
|
*
|
||||||
|
* @param supplier 要执行的操作
|
||||||
|
* @return 操作结果
|
||||||
|
*/
|
||||||
|
public static <T> T callIgnoreTenant(java.util.function.Supplier<T> supplier) {
|
||||||
|
boolean originalIgnore = isIgnoreTenant();
|
||||||
|
try {
|
||||||
|
setIgnoreTenant(true);
|
||||||
|
return supplier.get();
|
||||||
|
} finally {
|
||||||
|
setIgnoreTenant(originalIgnore);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -11,7 +11,6 @@ import java.io.File;
|
|||||||
import java.io.IOException;
|
import java.io.IOException;
|
||||||
import java.io.InputStream;
|
import java.io.InputStream;
|
||||||
import java.nio.file.Files;
|
import java.nio.file.Files;
|
||||||
|
|
||||||
import java.security.cert.CertificateFactory;
|
import java.security.cert.CertificateFactory;
|
||||||
import java.security.cert.X509Certificate;
|
import java.security.cert.X509Certificate;
|
||||||
import java.util.Date;
|
import java.util.Date;
|
||||||
@@ -135,7 +134,7 @@ public class CertificateService {
|
|||||||
log.warn("无法获取微信支付证书绝对路径: {}", e.getMessage());
|
log.warn("无法获取微信支付证书绝对路径: {}", e.getMessage());
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
java.io.File file = new java.io.File(certPath);
|
File file = new File(certPath);
|
||||||
String absolutePath = file.getAbsolutePath();
|
String absolutePath = file.getAbsolutePath();
|
||||||
log.info("微信支付证书路径模式: FILESYSTEM");
|
log.info("微信支付证书路径模式: FILESYSTEM");
|
||||||
log.info("微信支付证书完整绝对路径: {}", absolutePath);
|
log.info("微信支付证书完整绝对路径: {}", absolutePath);
|
||||||
@@ -171,7 +170,7 @@ public class CertificateService {
|
|||||||
log.warn("无法获取支付宝证书绝对路径: {}", e.getMessage());
|
log.warn("无法获取支付宝证书绝对路径: {}", e.getMessage());
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
java.io.File file = new java.io.File(certPath);
|
File file = new File(certPath);
|
||||||
String absolutePath = file.getAbsolutePath();
|
String absolutePath = file.getAbsolutePath();
|
||||||
log.info("支付宝证书路径模式: FILESYSTEM");
|
log.info("支付宝证书路径模式: FILESYSTEM");
|
||||||
log.info("支付宝证书完整绝对路径: {}", absolutePath);
|
log.info("支付宝证书完整绝对路径: {}", absolutePath);
|
||||||
|
|||||||
@@ -0,0 +1,174 @@
|
|||||||
|
package com.gxwebsoft.common.core.service;
|
||||||
|
|
||||||
|
import cn.hutool.core.util.ObjectUtil;
|
||||||
|
import com.gxwebsoft.common.core.exception.BusinessException;
|
||||||
|
import com.gxwebsoft.common.core.utils.RedisUtil;
|
||||||
|
import com.gxwebsoft.common.system.entity.Payment;
|
||||||
|
import com.gxwebsoft.common.system.param.PaymentParam;
|
||||||
|
import com.gxwebsoft.common.system.service.PaymentService;
|
||||||
|
import lombok.extern.slf4j.Slf4j;
|
||||||
|
import org.springframework.beans.factory.annotation.Autowired;
|
||||||
|
import org.springframework.stereotype.Service;
|
||||||
|
|
||||||
|
import java.util.List;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 支付配置缓存服务
|
||||||
|
* 统一管理支付配置的缓存读取,支持 Payment:1* 格式
|
||||||
|
*
|
||||||
|
* @author 科技小王子
|
||||||
|
* @since 2025-07-27
|
||||||
|
*/
|
||||||
|
@Slf4j
|
||||||
|
@Service
|
||||||
|
public class PaymentCacheService {
|
||||||
|
|
||||||
|
@Autowired
|
||||||
|
private RedisUtil redisUtil;
|
||||||
|
|
||||||
|
@Autowired
|
||||||
|
private PaymentService paymentService;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 根据支付类型获取支付配置
|
||||||
|
* 优先从 Payment:1{payType} 格式的缓存读取
|
||||||
|
*
|
||||||
|
* @param payType 支付类型 (0=微信支付, 1=支付宝, 2=其他)
|
||||||
|
* @param tenantId 租户ID (用于兜底查询)
|
||||||
|
* @return Payment 支付配置
|
||||||
|
*/
|
||||||
|
public Payment getPaymentConfig(Integer payType, Integer tenantId) {
|
||||||
|
// 1. 优先使用 Payment:1{payType} 格式的缓存键
|
||||||
|
String primaryKey = "Payment:1:" + tenantId;
|
||||||
|
Payment payment = redisUtil.get(primaryKey, Payment.class);
|
||||||
|
|
||||||
|
if (ObjectUtil.isNotEmpty(payment)) {
|
||||||
|
log.debug("从缓存获取支付配置成功: {}", primaryKey);
|
||||||
|
return payment;
|
||||||
|
}
|
||||||
|
|
||||||
|
// 2. 如果 Payment:1* 格式不存在,尝试原有格式
|
||||||
|
String fallbackKey = "Payment:" + payType + ":" + tenantId;
|
||||||
|
payment = redisUtil.get(fallbackKey, Payment.class);
|
||||||
|
|
||||||
|
if (ObjectUtil.isNotEmpty(payment)) {
|
||||||
|
log.debug("从兜底缓存获取支付配置成功: {}", fallbackKey);
|
||||||
|
// 将查询结果缓存到 Payment:1* 格式
|
||||||
|
redisUtil.set(primaryKey, payment);
|
||||||
|
return payment;
|
||||||
|
}
|
||||||
|
|
||||||
|
// 3. 最后从数据库查询
|
||||||
|
log.debug("从数据库查询支付配置, payType: {}, tenantId: {}", payType, tenantId);
|
||||||
|
PaymentParam paymentParam = new PaymentParam();
|
||||||
|
paymentParam.setType(payType);
|
||||||
|
paymentParam.setTenantId(tenantId); // 设置租户ID进行过滤
|
||||||
|
List<Payment> payments = paymentService.listRel(paymentParam);
|
||||||
|
|
||||||
|
if (payments.isEmpty()) {
|
||||||
|
throw new BusinessException("请完成支付配置,支付类型: " + payType);
|
||||||
|
}
|
||||||
|
|
||||||
|
Payment dbPayment = payments.get(0);
|
||||||
|
|
||||||
|
// 清理时间字段,避免序列化问题
|
||||||
|
Payment cachePayment = cleanPaymentForCache(dbPayment);
|
||||||
|
|
||||||
|
// 将查询结果缓存到 Payment:1* 格式
|
||||||
|
redisUtil.set(primaryKey, cachePayment);
|
||||||
|
log.debug("支付配置已缓存到: {}", primaryKey);
|
||||||
|
|
||||||
|
return dbPayment; // 返回原始对象,不影响业务逻辑
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 缓存支付配置
|
||||||
|
* 同时缓存到 Payment:1{payType} 和原有格式
|
||||||
|
*
|
||||||
|
* @param payment 支付配置
|
||||||
|
* @param tenantId 租户ID
|
||||||
|
*/
|
||||||
|
public void cachePaymentConfig(Payment payment, Integer tenantId) {
|
||||||
|
// 缓存到 Payment:1* 格式
|
||||||
|
String primaryKey = "Payment:1" + payment.getCode();
|
||||||
|
redisUtil.set(primaryKey, payment);
|
||||||
|
log.debug("支付配置已缓存到: {}", primaryKey);
|
||||||
|
|
||||||
|
// 兼容原有格式
|
||||||
|
String legacyKey = "Payment:" + payment.getCode() + ":" + tenantId;
|
||||||
|
redisUtil.set(legacyKey, payment);
|
||||||
|
log.debug("支付配置已缓存到兼容格式: {}", legacyKey);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 删除支付配置缓存
|
||||||
|
* 同时删除 Payment:1{payType} 和原有格式
|
||||||
|
*
|
||||||
|
* @param paymentCode 支付代码 (可以是String或Integer)
|
||||||
|
* @param tenantId 租户ID
|
||||||
|
*/
|
||||||
|
public void removePaymentConfig(String paymentCode, Integer tenantId) {
|
||||||
|
// 删除 Payment:1* 格式缓存
|
||||||
|
String primaryKey = "Payment:1" + paymentCode;
|
||||||
|
redisUtil.delete(primaryKey);
|
||||||
|
log.debug("已删除支付配置缓存: {}", primaryKey);
|
||||||
|
|
||||||
|
// 删除原有格式缓存
|
||||||
|
String legacyKey = "Payment:" + paymentCode + ":" + tenantId;
|
||||||
|
redisUtil.delete(legacyKey);
|
||||||
|
log.debug("已删除兼容格式缓存: {}", legacyKey);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 获取微信支付配置 (payType = 0)
|
||||||
|
*/
|
||||||
|
public Payment getWechatPayConfig(Integer tenantId) {
|
||||||
|
return getPaymentConfig(0, tenantId);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 获取支付宝配置 (payType = 1)
|
||||||
|
*/
|
||||||
|
public Payment getAlipayConfig(Integer tenantId) {
|
||||||
|
return getPaymentConfig(1, tenantId);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 清理Payment对象用于缓存
|
||||||
|
* 移除可能导致序列化问题的时间字段
|
||||||
|
*/
|
||||||
|
private Payment cleanPaymentForCache(Payment original) {
|
||||||
|
if (original == null) {
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
|
Payment cleaned = new Payment();
|
||||||
|
// 复制所有业务相关字段
|
||||||
|
cleaned.setId(original.getId());
|
||||||
|
cleaned.setName(original.getName());
|
||||||
|
cleaned.setType(original.getType());
|
||||||
|
cleaned.setCode(original.getCode());
|
||||||
|
cleaned.setImage(original.getImage());
|
||||||
|
cleaned.setWechatType(original.getWechatType());
|
||||||
|
cleaned.setAppId(original.getAppId());
|
||||||
|
cleaned.setMchId(original.getMchId());
|
||||||
|
cleaned.setApiKey(original.getApiKey());
|
||||||
|
cleaned.setApiclientCert(original.getApiclientCert());
|
||||||
|
cleaned.setApiclientKey(original.getApiclientKey());
|
||||||
|
cleaned.setPubKey(original.getPubKey());
|
||||||
|
cleaned.setPubKeyId(original.getPubKeyId());
|
||||||
|
cleaned.setMerchantSerialNumber(original.getMerchantSerialNumber());
|
||||||
|
cleaned.setNotifyUrl(original.getNotifyUrl());
|
||||||
|
cleaned.setComments(original.getComments());
|
||||||
|
cleaned.setSortNumber(original.getSortNumber());
|
||||||
|
cleaned.setStatus(original.getStatus());
|
||||||
|
cleaned.setDeleted(original.getDeleted());
|
||||||
|
cleaned.setTenantId(original.getTenantId());
|
||||||
|
|
||||||
|
// 不设置时间字段,避免序列化问题
|
||||||
|
// cleaned.setCreateTime(null);
|
||||||
|
// cleaned.setUpdateTime(null);
|
||||||
|
|
||||||
|
return cleaned;
|
||||||
|
}
|
||||||
|
}
|
||||||
145
src/main/java/com/gxwebsoft/common/core/utils/AliYunSender.java
Normal file
145
src/main/java/com/gxwebsoft/common/core/utils/AliYunSender.java
Normal file
@@ -0,0 +1,145 @@
|
|||||||
|
package com.gxwebsoft.common.core.utils;
|
||||||
|
import cn.hutool.core.codec.Base64;
|
||||||
|
import org.springframework.stereotype.Component;
|
||||||
|
|
||||||
|
import javax.crypto.Mac;
|
||||||
|
import javax.crypto.spec.SecretKeySpec;
|
||||||
|
import java.io.*;
|
||||||
|
import java.net.HttpURLConnection;
|
||||||
|
import java.net.URL;
|
||||||
|
import java.net.URLConnection;
|
||||||
|
import java.security.MessageDigest;
|
||||||
|
import java.text.SimpleDateFormat;
|
||||||
|
import java.util.Date;
|
||||||
|
import java.util.Locale;
|
||||||
|
import java.util.UUID;
|
||||||
|
|
||||||
|
@Component
|
||||||
|
public class AliYunSender {
|
||||||
|
/*
|
||||||
|
* 计算MD5+BASE64
|
||||||
|
*/
|
||||||
|
public static String MD5Base64(String s) {
|
||||||
|
if (s == null)
|
||||||
|
return null;
|
||||||
|
String encodeStr = "";
|
||||||
|
byte[] utfBytes = s.getBytes();
|
||||||
|
MessageDigest mdTemp;
|
||||||
|
try {
|
||||||
|
mdTemp = MessageDigest.getInstance("MD5");
|
||||||
|
mdTemp.update(utfBytes);
|
||||||
|
byte[] md5Bytes = mdTemp.digest();
|
||||||
|
encodeStr = Base64.encode(md5Bytes);
|
||||||
|
} catch (Exception e) {
|
||||||
|
throw new Error("Failed to generate MD5 : " + e.getMessage());
|
||||||
|
}
|
||||||
|
return encodeStr;
|
||||||
|
}
|
||||||
|
/*
|
||||||
|
* 计算 HMAC-SHA1
|
||||||
|
*/
|
||||||
|
public static String HMACSha1(String data, String key) {
|
||||||
|
String result;
|
||||||
|
try {
|
||||||
|
SecretKeySpec signingKey = new SecretKeySpec(key.getBytes(), "HmacSHA1");
|
||||||
|
Mac mac = Mac.getInstance("HmacSHA1");
|
||||||
|
mac.init(signingKey);
|
||||||
|
byte[] rawHmac = mac.doFinal(data.getBytes());
|
||||||
|
result = Base64.encode(rawHmac);
|
||||||
|
} catch (Exception e) {
|
||||||
|
throw new Error("Failed to generate HMAC : " + e.getMessage());
|
||||||
|
}
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
/*
|
||||||
|
* 获取时间
|
||||||
|
*/
|
||||||
|
public static String toGMTString(Date date) {
|
||||||
|
SimpleDateFormat df = new SimpleDateFormat("E, dd MMM yyyy HH:mm:ss z", Locale.UK);
|
||||||
|
df.setTimeZone(new java.util.SimpleTimeZone(0, "GMT"));
|
||||||
|
return df.format(date);
|
||||||
|
}
|
||||||
|
/*
|
||||||
|
* 发送POST请求
|
||||||
|
*/
|
||||||
|
public static String sendPost(String url, String body, String ak_id, String ak_secret) {
|
||||||
|
PrintWriter out = null;
|
||||||
|
BufferedReader in = null;
|
||||||
|
String result = "";
|
||||||
|
try {
|
||||||
|
URL realUrl = new URL(url);
|
||||||
|
/*
|
||||||
|
* http header 参数
|
||||||
|
*/
|
||||||
|
String method = "POST";
|
||||||
|
String accept = "application/json";
|
||||||
|
String content_type = "application/json;chrset=utf-8";
|
||||||
|
String path = realUrl.getFile();
|
||||||
|
String date = toGMTString(new Date());
|
||||||
|
String host = realUrl.getHost();
|
||||||
|
// 1.对body做MD5+BASE64加密
|
||||||
|
String bodyMd5 = MD5Base64(body);
|
||||||
|
String uuid = UUID.randomUUID().toString();
|
||||||
|
String stringToSign = method + "\n" + accept + "\n" + bodyMd5 + "\n" + content_type + "\n" + date + "\n"
|
||||||
|
+ "x-acs-signature-method:HMAC-SHA1\n"
|
||||||
|
+ "x-acs-signature-nonce:" + uuid + "\n"
|
||||||
|
+ "x-acs-version:2019-01-02\n"
|
||||||
|
+ path;
|
||||||
|
// 2.计算 HMAC-SHA1
|
||||||
|
String signature = HMACSha1(stringToSign, ak_secret);
|
||||||
|
// 3.得到 authorization header
|
||||||
|
String authHeader = "acs " + ak_id + ":" + signature;
|
||||||
|
// 打开和URL之间的连接
|
||||||
|
URLConnection conn = realUrl.openConnection();
|
||||||
|
// 设置通用的请求属性
|
||||||
|
conn.setRequestProperty("Accept", accept);
|
||||||
|
conn.setRequestProperty("Content-Type", content_type);
|
||||||
|
conn.setRequestProperty("Content-MD5", bodyMd5);
|
||||||
|
conn.setRequestProperty("Date", date);
|
||||||
|
conn.setRequestProperty("Host", host);
|
||||||
|
conn.setRequestProperty("Authorization", authHeader);
|
||||||
|
conn.setRequestProperty("x-acs-signature-nonce", uuid);
|
||||||
|
conn.setRequestProperty("x-acs-signature-method", "HMAC-SHA1");
|
||||||
|
conn.setRequestProperty("x-acs-version", "2019-01-02"); // 版本可选
|
||||||
|
// 发送POST请求必须设置如下两行
|
||||||
|
conn.setDoOutput(true);
|
||||||
|
conn.setDoInput(true);
|
||||||
|
// 获取URLConnection对象对应的输出流
|
||||||
|
out = new PrintWriter(conn.getOutputStream());
|
||||||
|
// 发送请求参数
|
||||||
|
out.print(body);
|
||||||
|
// flush输出流的缓冲
|
||||||
|
out.flush();
|
||||||
|
// 定义BufferedReader输入流来读取URL的响应
|
||||||
|
InputStream is;
|
||||||
|
HttpURLConnection httpconn = (HttpURLConnection) conn;
|
||||||
|
if (httpconn.getResponseCode() == 200) {
|
||||||
|
is = httpconn.getInputStream();
|
||||||
|
} else {
|
||||||
|
is = httpconn.getErrorStream();
|
||||||
|
}
|
||||||
|
in = new BufferedReader(new InputStreamReader(is));
|
||||||
|
String line;
|
||||||
|
while ((line = in.readLine()) != null) {
|
||||||
|
result += line;
|
||||||
|
}
|
||||||
|
} catch (Exception e) {
|
||||||
|
System.out.println("发送 POST 请求出现异常!" + e);
|
||||||
|
e.printStackTrace();
|
||||||
|
}
|
||||||
|
// 使用finally块来关闭输出流、输入流
|
||||||
|
finally {
|
||||||
|
try {
|
||||||
|
if (out != null) {
|
||||||
|
out.close();
|
||||||
|
}
|
||||||
|
if (in != null) {
|
||||||
|
in.close();
|
||||||
|
}
|
||||||
|
} catch (IOException ex) {
|
||||||
|
ex.printStackTrace();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,228 @@
|
|||||||
|
package com.gxwebsoft.common.core.utils;
|
||||||
|
|
||||||
|
import com.gxwebsoft.common.core.config.CertificateProperties;
|
||||||
|
import lombok.extern.slf4j.Slf4j;
|
||||||
|
import org.springframework.core.io.ClassPathResource;
|
||||||
|
import org.springframework.stereotype.Component;
|
||||||
|
import org.springframework.util.StringUtils;
|
||||||
|
|
||||||
|
import javax.annotation.PostConstruct;
|
||||||
|
import java.io.File;
|
||||||
|
import java.io.IOException;
|
||||||
|
import java.io.InputStream;
|
||||||
|
import java.nio.file.Files;
|
||||||
|
import java.nio.file.Path;
|
||||||
|
import java.nio.file.Paths;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 证书加载工具类
|
||||||
|
* 支持多种证书加载方式,适配Docker容器化部署
|
||||||
|
*
|
||||||
|
* @author 科技小王子
|
||||||
|
* @since 2025-01-26
|
||||||
|
*/
|
||||||
|
@Slf4j
|
||||||
|
@Component
|
||||||
|
public class CertificateLoader {
|
||||||
|
|
||||||
|
private final CertificateProperties certConfig;
|
||||||
|
|
||||||
|
public CertificateLoader(CertificateProperties certConfig) {
|
||||||
|
this.certConfig = certConfig;
|
||||||
|
}
|
||||||
|
|
||||||
|
@PostConstruct
|
||||||
|
public void init() {
|
||||||
|
log.info("证书加载器初始化,加载模式:{}", certConfig.getLoadMode());
|
||||||
|
if (certConfig.getLoadMode() == CertificateProperties.LoadMode.VOLUME) {
|
||||||
|
log.info("Docker挂载卷证书路径:{}", certConfig.getCertRootPath());
|
||||||
|
validateCertDirectory();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 验证证书目录是否存在
|
||||||
|
*/
|
||||||
|
private void validateCertDirectory() {
|
||||||
|
File certDir = new File(certConfig.getCertRootPath());
|
||||||
|
if (!certDir.exists()) {
|
||||||
|
log.warn("证书目录不存在:{},将尝试创建", certConfig.getCertRootPath());
|
||||||
|
if (!certDir.mkdirs()) {
|
||||||
|
log.error("无法创建证书目录:{}", certConfig.getCertRootPath());
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
log.info("证书目录验证成功:{}", certConfig.getCertRootPath());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 加载证书文件路径
|
||||||
|
*
|
||||||
|
* @param certPath 证书路径(可能是相对路径、绝对路径或classpath路径)
|
||||||
|
* @return 实际的证书文件路径
|
||||||
|
*/
|
||||||
|
public String loadCertificatePath(String certPath) {
|
||||||
|
if (!StringUtils.hasText(certPath)) {
|
||||||
|
throw new IllegalArgumentException("证书路径不能为空");
|
||||||
|
}
|
||||||
|
|
||||||
|
try {
|
||||||
|
switch (certConfig.getLoadMode()) {
|
||||||
|
case CLASSPATH:
|
||||||
|
return loadFromClasspath(certPath);
|
||||||
|
case VOLUME:
|
||||||
|
return loadFromVolume(certPath);
|
||||||
|
case FILESYSTEM:
|
||||||
|
default:
|
||||||
|
return loadFromFileSystem(certPath);
|
||||||
|
}
|
||||||
|
} catch (Exception e) {
|
||||||
|
log.error("加载证书失败,路径:{}", certPath, e);
|
||||||
|
throw new RuntimeException("证书加载失败:" + certPath, e);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 从classpath加载证书
|
||||||
|
*/
|
||||||
|
private String loadFromClasspath(String certPath) throws IOException {
|
||||||
|
String resourcePath = certPath.startsWith("classpath:") ?
|
||||||
|
certPath.substring("classpath:".length()) : certPath;
|
||||||
|
|
||||||
|
ClassPathResource resource = new ClassPathResource(resourcePath);
|
||||||
|
if (!resource.exists()) {
|
||||||
|
throw new IOException("Classpath中找不到证书文件:" + resourcePath);
|
||||||
|
}
|
||||||
|
|
||||||
|
// 将classpath中的文件复制到临时目录
|
||||||
|
Path tempFile = Files.createTempFile("cert_", ".pem");
|
||||||
|
try (InputStream inputStream = resource.getInputStream()) {
|
||||||
|
Files.copy(inputStream, tempFile, java.nio.file.StandardCopyOption.REPLACE_EXISTING);
|
||||||
|
}
|
||||||
|
|
||||||
|
String tempPath = tempFile.toAbsolutePath().toString();
|
||||||
|
log.debug("从classpath加载证书:{} -> {}", resourcePath, tempPath);
|
||||||
|
return tempPath;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 从Docker挂载卷加载证书
|
||||||
|
*/
|
||||||
|
private String loadFromVolume(String certPath) {
|
||||||
|
log.debug("尝试从Docker挂载卷加载证书:{}", certPath);
|
||||||
|
|
||||||
|
// 如果是完整路径,直接使用
|
||||||
|
if (certPath.startsWith("/") || certPath.contains(":")) {
|
||||||
|
File file = new File(certPath);
|
||||||
|
log.debug("检查完整路径文件是否存在:{}", certPath);
|
||||||
|
if (file.exists()) {
|
||||||
|
log.debug("使用完整路径加载证书:{}", certPath);
|
||||||
|
return certPath;
|
||||||
|
} else {
|
||||||
|
log.error("完整路径文件不存在:{}", certPath);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// 否则拼接挂载卷路径
|
||||||
|
String fullPath = Paths.get(certConfig.getCertRootPath(), certPath).toString();
|
||||||
|
File file = new File(fullPath);
|
||||||
|
if (!file.exists()) {
|
||||||
|
throw new RuntimeException("Docker挂载卷中找不到证书文件:" + fullPath);
|
||||||
|
}
|
||||||
|
|
||||||
|
log.debug("从Docker挂载卷加载证书:{}", fullPath);
|
||||||
|
return fullPath;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 从文件系统加载证书
|
||||||
|
*/
|
||||||
|
private String loadFromFileSystem(String certPath) {
|
||||||
|
File file = new File(certPath);
|
||||||
|
if (!file.exists()) {
|
||||||
|
throw new RuntimeException("文件系统中找不到证书文件:" + certPath);
|
||||||
|
}
|
||||||
|
|
||||||
|
log.debug("从文件系统加载证书:{}", certPath);
|
||||||
|
return certPath;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 检查证书文件是否存在
|
||||||
|
*
|
||||||
|
* @param certPath 证书路径
|
||||||
|
* @return 是否存在
|
||||||
|
*/
|
||||||
|
public boolean certificateExists(String certPath) {
|
||||||
|
try {
|
||||||
|
switch (certConfig.getLoadMode()) {
|
||||||
|
case CLASSPATH:
|
||||||
|
String resourcePath = certPath.startsWith("classpath:") ?
|
||||||
|
certPath.substring("classpath:".length()) : certPath;
|
||||||
|
ClassPathResource resource = new ClassPathResource(resourcePath);
|
||||||
|
return resource.exists();
|
||||||
|
case VOLUME:
|
||||||
|
String fullPath = certPath.startsWith("/") ? certPath :
|
||||||
|
Paths.get(certConfig.getCertRootPath(), certPath).toString();
|
||||||
|
return new File(fullPath).exists();
|
||||||
|
case FILESYSTEM:
|
||||||
|
default:
|
||||||
|
return new File(certPath).exists();
|
||||||
|
}
|
||||||
|
} catch (Exception e) {
|
||||||
|
log.warn("检查证书文件存在性时出错:{}", certPath, e);
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 获取证书文件的输入流
|
||||||
|
*
|
||||||
|
* @param certPath 证书路径
|
||||||
|
* @return 输入流
|
||||||
|
*/
|
||||||
|
public InputStream getCertificateInputStream(String certPath) throws IOException {
|
||||||
|
switch (certConfig.getLoadMode()) {
|
||||||
|
case CLASSPATH:
|
||||||
|
String resourcePath = certPath.startsWith("classpath:") ?
|
||||||
|
certPath.substring("classpath:".length()) : certPath;
|
||||||
|
ClassPathResource resource = new ClassPathResource(resourcePath);
|
||||||
|
return resource.getInputStream();
|
||||||
|
case VOLUME:
|
||||||
|
case FILESYSTEM:
|
||||||
|
default:
|
||||||
|
String actualPath = loadCertificatePath(certPath);
|
||||||
|
return Files.newInputStream(Paths.get(actualPath));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 列出证书目录中的所有文件
|
||||||
|
*
|
||||||
|
* @return 证书文件列表
|
||||||
|
*/
|
||||||
|
public String[] listCertificateFiles() {
|
||||||
|
try {
|
||||||
|
switch (certConfig.getLoadMode()) {
|
||||||
|
case VOLUME:
|
||||||
|
File certDir = new File(certConfig.getCertRootPath());
|
||||||
|
if (certDir.exists() && certDir.isDirectory()) {
|
||||||
|
return certDir.list();
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
case CLASSPATH:
|
||||||
|
// classpath模式下不支持列出文件
|
||||||
|
log.warn("Classpath模式下不支持列出证书文件");
|
||||||
|
break;
|
||||||
|
case FILESYSTEM:
|
||||||
|
default:
|
||||||
|
// 文件系统模式下证书可能分散在不同目录,不支持统一列出
|
||||||
|
log.warn("文件系统模式下不支持列出证书文件");
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
} catch (Exception e) {
|
||||||
|
log.error("列出证书文件时出错", e);
|
||||||
|
}
|
||||||
|
return new String[0];
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,314 @@
|
|||||||
|
package com.gxwebsoft.common.core.utils;
|
||||||
|
|
||||||
|
import com.gxwebsoft.common.core.config.CertificateProperties;
|
||||||
|
import com.gxwebsoft.common.system.entity.Payment;
|
||||||
|
import lombok.extern.slf4j.Slf4j;
|
||||||
|
import org.springframework.stereotype.Component;
|
||||||
|
|
||||||
|
import java.io.File;
|
||||||
|
import java.io.FileInputStream;
|
||||||
|
import java.io.InputStream;
|
||||||
|
import java.security.cert.CertificateFactory;
|
||||||
|
import java.security.cert.X509Certificate;
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 微信支付证书诊断工具
|
||||||
|
* 专门用于诊断和解决证书相关问题
|
||||||
|
*
|
||||||
|
* @author 科技小王子
|
||||||
|
* @since 2025-07-29
|
||||||
|
*/
|
||||||
|
@Slf4j
|
||||||
|
@Component
|
||||||
|
public class WechatPayCertificateDiagnostic {
|
||||||
|
|
||||||
|
private final CertificateProperties certConfig;
|
||||||
|
private final CertificateLoader certificateLoader;
|
||||||
|
|
||||||
|
public WechatPayCertificateDiagnostic(CertificateProperties certConfig, CertificateLoader certificateLoader) {
|
||||||
|
this.certConfig = certConfig;
|
||||||
|
this.certificateLoader = certificateLoader;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 全面诊断微信支付证书配置
|
||||||
|
*
|
||||||
|
* @param payment 支付配置
|
||||||
|
* @param tenantId 租户ID
|
||||||
|
* @param environment 环境(dev/prod)
|
||||||
|
* @return 诊断结果
|
||||||
|
*/
|
||||||
|
public DiagnosticResult diagnoseCertificateConfig(Payment payment, Integer tenantId, String environment) {
|
||||||
|
DiagnosticResult result = new DiagnosticResult();
|
||||||
|
|
||||||
|
log.info("=== 开始微信支付证书诊断 ===");
|
||||||
|
log.info("租户ID: {}, 环境: {}", tenantId, environment);
|
||||||
|
|
||||||
|
try {
|
||||||
|
// 1. 检查基本配置
|
||||||
|
checkBasicConfig(payment, result);
|
||||||
|
|
||||||
|
// 2. 检查证书文件
|
||||||
|
checkCertificateFiles(payment, tenantId, environment, result);
|
||||||
|
|
||||||
|
// 3. 检查证书内容
|
||||||
|
validateCertificateContent(payment, tenantId, environment, result);
|
||||||
|
|
||||||
|
// 4. 生成建议
|
||||||
|
generateRecommendations(result);
|
||||||
|
|
||||||
|
} catch (Exception e) {
|
||||||
|
result.addError("诊断过程中发生异常: " + e.getMessage());
|
||||||
|
log.error("证书诊断异常", e);
|
||||||
|
}
|
||||||
|
|
||||||
|
log.info("=== 证书诊断完成 ===");
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 检查基本配置
|
||||||
|
*/
|
||||||
|
private void checkBasicConfig(Payment payment, DiagnosticResult result) {
|
||||||
|
if (payment == null) {
|
||||||
|
result.addError("支付配置为空");
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (payment.getMchId() == null || payment.getMchId().trim().isEmpty()) {
|
||||||
|
result.addError("商户号未配置");
|
||||||
|
} else {
|
||||||
|
result.addInfo("商户号: " + payment.getMchId());
|
||||||
|
}
|
||||||
|
|
||||||
|
if (payment.getAppId() == null || payment.getAppId().trim().isEmpty()) {
|
||||||
|
result.addError("应用ID未配置");
|
||||||
|
} else {
|
||||||
|
result.addInfo("应用ID: " + payment.getAppId());
|
||||||
|
}
|
||||||
|
|
||||||
|
if (payment.getMerchantSerialNumber() == null || payment.getMerchantSerialNumber().trim().isEmpty()) {
|
||||||
|
result.addError("商户证书序列号未配置");
|
||||||
|
} else {
|
||||||
|
result.addInfo("商户证书序列号: " + payment.getMerchantSerialNumber());
|
||||||
|
}
|
||||||
|
|
||||||
|
if (payment.getApiKey() == null || payment.getApiKey().trim().isEmpty()) {
|
||||||
|
result.addWarning("数据库中APIv3密钥未配置,将使用配置文件默认值");
|
||||||
|
} else {
|
||||||
|
result.addInfo("APIv3密钥: 已配置(" + payment.getApiKey().length() + "位)");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 检查证书文件
|
||||||
|
*/
|
||||||
|
private void checkCertificateFiles(Payment payment, Integer tenantId, String environment, DiagnosticResult result) {
|
||||||
|
if ("dev".equals(environment)) {
|
||||||
|
// 开发环境证书检查
|
||||||
|
String tenantCertPath = "dev/wechat/" + tenantId;
|
||||||
|
String privateKeyPath = tenantCertPath + "/" + certConfig.getWechatPay().getDev().getPrivateKeyFile();
|
||||||
|
String apiclientCertPath = tenantCertPath + "/" + certConfig.getWechatPay().getDev().getApiclientCertFile();
|
||||||
|
|
||||||
|
// 检查私钥文件
|
||||||
|
if (certificateLoader.certificateExists(privateKeyPath)) {
|
||||||
|
result.addInfo("✅ 私钥文件存在: " + privateKeyPath);
|
||||||
|
try {
|
||||||
|
String privateKeyFile = certificateLoader.loadCertificatePath(privateKeyPath);
|
||||||
|
result.addInfo("私钥文件路径: " + privateKeyFile);
|
||||||
|
} catch (Exception e) {
|
||||||
|
result.addError("私钥文件加载失败: " + e.getMessage());
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
result.addError("❌ 私钥文件不存在: " + privateKeyPath);
|
||||||
|
}
|
||||||
|
|
||||||
|
// 检查商户证书文件
|
||||||
|
if (certificateLoader.certificateExists(apiclientCertPath)) {
|
||||||
|
result.addInfo("✅ 商户证书文件存在: " + apiclientCertPath);
|
||||||
|
} else {
|
||||||
|
result.addWarning("⚠️ 商户证书文件不存在: " + apiclientCertPath + " (自动证书配置不需要此文件)");
|
||||||
|
}
|
||||||
|
|
||||||
|
} else {
|
||||||
|
// 生产环境证书检查
|
||||||
|
if (payment.getApiclientKey() != null) {
|
||||||
|
result.addInfo("私钥文件配置: " + payment.getApiclientKey());
|
||||||
|
} else {
|
||||||
|
result.addError("生产环境私钥文件路径未配置");
|
||||||
|
}
|
||||||
|
|
||||||
|
if (payment.getApiclientCert() != null) {
|
||||||
|
result.addInfo("商户证书文件配置: " + payment.getApiclientCert());
|
||||||
|
} else {
|
||||||
|
result.addWarning("生产环境商户证书文件路径未配置 (自动证书配置不需要此文件)");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 验证证书内容
|
||||||
|
*/
|
||||||
|
private void validateCertificateContent(Payment payment, Integer tenantId, String environment, DiagnosticResult result) {
|
||||||
|
try {
|
||||||
|
if ("dev".equals(environment)) {
|
||||||
|
String tenantCertPath = "dev/wechat/" + tenantId;
|
||||||
|
String apiclientCertPath = tenantCertPath + "/" + certConfig.getWechatPay().getDev().getApiclientCertFile();
|
||||||
|
|
||||||
|
if (certificateLoader.certificateExists(apiclientCertPath)) {
|
||||||
|
validateX509Certificate(apiclientCertPath, payment.getMerchantSerialNumber(), result);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
} catch (Exception e) {
|
||||||
|
result.addWarning("证书内容验证失败: " + e.getMessage());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 验证X509证书
|
||||||
|
*/
|
||||||
|
private void validateX509Certificate(String certPath, String expectedSerialNumber, DiagnosticResult result) {
|
||||||
|
try {
|
||||||
|
String actualCertPath = certificateLoader.loadCertificatePath(certPath);
|
||||||
|
|
||||||
|
try (InputStream inputStream = new FileInputStream(new File(actualCertPath))) {
|
||||||
|
CertificateFactory cf = CertificateFactory.getInstance("X.509");
|
||||||
|
X509Certificate cert = (X509Certificate) cf.generateCertificate(inputStream);
|
||||||
|
|
||||||
|
if (cert != null) {
|
||||||
|
String actualSerialNumber = cert.getSerialNumber().toString(16).toUpperCase();
|
||||||
|
result.addInfo("证书序列号: " + actualSerialNumber);
|
||||||
|
result.addInfo("证书有效期: " + cert.getNotBefore() + " 至 " + cert.getNotAfter());
|
||||||
|
result.addInfo("证书主体: " + cert.getSubjectX500Principal().toString());
|
||||||
|
|
||||||
|
// 检查序列号是否匹配
|
||||||
|
if (expectedSerialNumber != null && !expectedSerialNumber.equalsIgnoreCase(actualSerialNumber)) {
|
||||||
|
result.addError("证书序列号不匹配! 配置: " + expectedSerialNumber + ", 实际: " + actualSerialNumber);
|
||||||
|
} else {
|
||||||
|
result.addInfo("✅ 证书序列号匹配");
|
||||||
|
}
|
||||||
|
|
||||||
|
// 检查证书是否过期
|
||||||
|
long now = System.currentTimeMillis();
|
||||||
|
if (now < cert.getNotBefore().getTime()) {
|
||||||
|
result.addError("证书尚未生效");
|
||||||
|
} else if (now > cert.getNotAfter().getTime()) {
|
||||||
|
result.addError("证书已过期");
|
||||||
|
} else {
|
||||||
|
result.addInfo("✅ 证书在有效期内");
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
result.addError("无法解析证书文件");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
} catch (Exception e) {
|
||||||
|
result.addError("证书验证失败: " + e.getMessage());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 生成建议
|
||||||
|
*/
|
||||||
|
private void generateRecommendations(DiagnosticResult result) {
|
||||||
|
if (result.hasErrors()) {
|
||||||
|
result.addRecommendation("🔧 修复建议:");
|
||||||
|
|
||||||
|
String errorText = result.getErrors();
|
||||||
|
if (errorText.contains("商户号")) {
|
||||||
|
result.addRecommendation("1. 请在支付配置中设置正确的商户号");
|
||||||
|
}
|
||||||
|
|
||||||
|
if (errorText.contains("序列号")) {
|
||||||
|
result.addRecommendation("2. 请检查商户证书序列号是否正确,可在微信商户平台查看");
|
||||||
|
}
|
||||||
|
|
||||||
|
if (errorText.contains("证书文件")) {
|
||||||
|
result.addRecommendation("3. 请确保证书文件已正确放置在指定目录");
|
||||||
|
}
|
||||||
|
|
||||||
|
if (errorText.contains("过期")) {
|
||||||
|
result.addRecommendation("4. 请更新过期的证书文件");
|
||||||
|
}
|
||||||
|
|
||||||
|
result.addRecommendation("5. 建议使用RSAAutoCertificateConfig自动证书配置,可避免手动管理证书");
|
||||||
|
result.addRecommendation("6. 确保在微信商户平台开启API安全功能并申请使用微信支付公钥");
|
||||||
|
} else {
|
||||||
|
result.addRecommendation("✅ 证书配置正常,建议使用自动证书配置以获得最佳体验");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 诊断结果类
|
||||||
|
*/
|
||||||
|
public static class DiagnosticResult {
|
||||||
|
private final StringBuilder errors = new StringBuilder();
|
||||||
|
private final StringBuilder warnings = new StringBuilder();
|
||||||
|
private final StringBuilder info = new StringBuilder();
|
||||||
|
private final StringBuilder recommendations = new StringBuilder();
|
||||||
|
|
||||||
|
public void addError(String error) {
|
||||||
|
if (errors.length() > 0) errors.append("\n");
|
||||||
|
errors.append(error);
|
||||||
|
}
|
||||||
|
|
||||||
|
public void addWarning(String warning) {
|
||||||
|
if (warnings.length() > 0) warnings.append("\n");
|
||||||
|
warnings.append(warning);
|
||||||
|
}
|
||||||
|
|
||||||
|
public void addInfo(String information) {
|
||||||
|
if (info.length() > 0) info.append("\n");
|
||||||
|
info.append(information);
|
||||||
|
}
|
||||||
|
|
||||||
|
public void addRecommendation(String recommendation) {
|
||||||
|
if (recommendations.length() > 0) recommendations.append("\n");
|
||||||
|
recommendations.append(recommendation);
|
||||||
|
}
|
||||||
|
|
||||||
|
public boolean hasErrors() {
|
||||||
|
return errors.length() > 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
public String getErrors() {
|
||||||
|
return errors.toString();
|
||||||
|
}
|
||||||
|
|
||||||
|
public String getWarnings() {
|
||||||
|
return warnings.toString();
|
||||||
|
}
|
||||||
|
|
||||||
|
public String getInfo() {
|
||||||
|
return info.toString();
|
||||||
|
}
|
||||||
|
|
||||||
|
public String getRecommendations() {
|
||||||
|
return recommendations.toString();
|
||||||
|
}
|
||||||
|
|
||||||
|
public String getFullReport() {
|
||||||
|
StringBuilder report = new StringBuilder();
|
||||||
|
report.append("=== 微信支付证书诊断报告 ===\n\n");
|
||||||
|
|
||||||
|
if (info.length() > 0) {
|
||||||
|
report.append("📋 基本信息:\n").append(info).append("\n\n");
|
||||||
|
}
|
||||||
|
|
||||||
|
if (warnings.length() > 0) {
|
||||||
|
report.append("⚠️ 警告:\n").append(warnings).append("\n\n");
|
||||||
|
}
|
||||||
|
|
||||||
|
if (errors.length() > 0) {
|
||||||
|
report.append("❌ 错误:\n").append(errors).append("\n\n");
|
||||||
|
}
|
||||||
|
|
||||||
|
if (recommendations.length() > 0) {
|
||||||
|
report.append("💡 建议:\n").append(recommendations).append("\n\n");
|
||||||
|
}
|
||||||
|
|
||||||
|
report.append("=== 诊断报告结束 ===");
|
||||||
|
return report.toString();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,223 @@
|
|||||||
|
package com.gxwebsoft.common.core.utils;
|
||||||
|
|
||||||
|
import com.gxwebsoft.common.core.config.CertificateProperties;
|
||||||
|
import com.gxwebsoft.common.system.entity.Payment;
|
||||||
|
import lombok.extern.slf4j.Slf4j;
|
||||||
|
import org.springframework.beans.factory.annotation.Value;
|
||||||
|
import org.springframework.stereotype.Component;
|
||||||
|
import org.springframework.util.StringUtils;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 微信支付配置验证工具
|
||||||
|
*
|
||||||
|
* @author 科技小王子
|
||||||
|
* @since 2025-07-27
|
||||||
|
*/
|
||||||
|
@Slf4j
|
||||||
|
@Component
|
||||||
|
public class WechatPayConfigValidator {
|
||||||
|
|
||||||
|
private final CertificateProperties certConfig;
|
||||||
|
private final CertificateLoader certificateLoader;
|
||||||
|
|
||||||
|
@Value("${spring.profiles.active}")
|
||||||
|
private String activeProfile;
|
||||||
|
|
||||||
|
public WechatPayConfigValidator(CertificateProperties certConfig, CertificateLoader certificateLoader) {
|
||||||
|
this.certConfig = certConfig;
|
||||||
|
this.certificateLoader = certificateLoader;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 验证微信支付配置
|
||||||
|
*
|
||||||
|
* @param payment 支付配置
|
||||||
|
* @param tenantId 租户ID
|
||||||
|
* @return 验证结果
|
||||||
|
*/
|
||||||
|
public ValidationResult validateWechatPayConfig(Payment payment, Integer tenantId) {
|
||||||
|
ValidationResult result = new ValidationResult();
|
||||||
|
|
||||||
|
log.info("开始验证微信支付配置 - 租户ID: {}", tenantId);
|
||||||
|
|
||||||
|
// 1. 验证基本配置
|
||||||
|
if (payment == null) {
|
||||||
|
result.addError("支付配置为空");
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!StringUtils.hasText(payment.getMchId())) {
|
||||||
|
result.addError("商户号未配置");
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!StringUtils.hasText(payment.getAppId())) {
|
||||||
|
result.addError("应用ID未配置");
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!StringUtils.hasText(payment.getMerchantSerialNumber())) {
|
||||||
|
result.addError("商户证书序列号未配置");
|
||||||
|
}
|
||||||
|
|
||||||
|
// 2. 验证 APIv3 密钥
|
||||||
|
String apiV3Key = getValidApiV3Key(payment);
|
||||||
|
if (!StringUtils.hasText(apiV3Key)) {
|
||||||
|
result.addError("APIv3密钥未配置");
|
||||||
|
} else {
|
||||||
|
validateApiV3Key(apiV3Key, result);
|
||||||
|
}
|
||||||
|
|
||||||
|
// 3. 验证证书文件
|
||||||
|
validateCertificateFiles(tenantId, result);
|
||||||
|
|
||||||
|
// 4. 记录验证结果
|
||||||
|
if (result.isValid()) {
|
||||||
|
log.info("✅ 微信支付配置验证通过 - 租户ID: {}", tenantId);
|
||||||
|
} else {
|
||||||
|
log.error("❌ 微信支付配置验证失败 - 租户ID: {}, 错误: {}", tenantId, result.getErrors());
|
||||||
|
}
|
||||||
|
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 获取有效的 APIv3 密钥
|
||||||
|
* 优先使用数据库配置,如果为空则使用配置文件默认值
|
||||||
|
*/
|
||||||
|
public String getValidApiV3Key(Payment payment) {
|
||||||
|
String apiV3Key = payment.getApiKey();
|
||||||
|
|
||||||
|
if (!StringUtils.hasText(apiV3Key)) {
|
||||||
|
apiV3Key = certConfig.getWechatPay().getDev().getApiV3Key();
|
||||||
|
log.warn("数据库中APIv3密钥为空,使用配置文件默认值");
|
||||||
|
}
|
||||||
|
|
||||||
|
return apiV3Key;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 验证 APIv3 密钥格式
|
||||||
|
*/
|
||||||
|
private void validateApiV3Key(String apiV3Key, ValidationResult result) {
|
||||||
|
if (apiV3Key.length() != 32) {
|
||||||
|
result.addError("APIv3密钥长度错误,应为32位,实际为: " + apiV3Key.length());
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!apiV3Key.matches("^[a-zA-Z0-9]+$")) {
|
||||||
|
result.addError("APIv3密钥格式错误,应仅包含字母和数字");
|
||||||
|
}
|
||||||
|
|
||||||
|
log.info("APIv3密钥验证 - 长度: {}, 格式: {}",
|
||||||
|
apiV3Key.length(),
|
||||||
|
apiV3Key.matches("^[a-zA-Z0-9]+$") ? "正确" : "错误");
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 验证证书文件
|
||||||
|
*/
|
||||||
|
private void validateCertificateFiles(Integer tenantId, ValidationResult result) {
|
||||||
|
if ("dev".equals(activeProfile)) {
|
||||||
|
// 开发环境证书验证
|
||||||
|
String tenantCertPath = "dev/wechat/" + tenantId;
|
||||||
|
String privateKeyPath = tenantCertPath + "/" + certConfig.getWechatPay().getDev().getPrivateKeyFile();
|
||||||
|
|
||||||
|
if (!certificateLoader.certificateExists(privateKeyPath)) {
|
||||||
|
result.addError("证书文件不存在: " + privateKeyPath);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
try {
|
||||||
|
certificateLoader.loadCertificatePath(privateKeyPath);
|
||||||
|
log.info("✅ 开发环境证书文件验证通过: {}", privateKeyPath);
|
||||||
|
} catch (Exception e) {
|
||||||
|
result.addError("证书文件加载失败: " + e.getMessage());
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
// 生产环境证书验证 - 跳过文件存在性检查,因为证书路径来自数据库
|
||||||
|
log.info("✅ 生产环境跳过证书文件存在性验证,使用数据库配置的证书路径");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 验证结果类
|
||||||
|
*/
|
||||||
|
public static class ValidationResult {
|
||||||
|
private boolean valid = true;
|
||||||
|
private StringBuilder errors = new StringBuilder();
|
||||||
|
|
||||||
|
public void addError(String error) {
|
||||||
|
this.valid = false;
|
||||||
|
if (errors.length() > 0) {
|
||||||
|
errors.append("; ");
|
||||||
|
}
|
||||||
|
errors.append(error);
|
||||||
|
}
|
||||||
|
|
||||||
|
public boolean isValid() {
|
||||||
|
return valid;
|
||||||
|
}
|
||||||
|
|
||||||
|
public String getErrors() {
|
||||||
|
return errors.toString();
|
||||||
|
}
|
||||||
|
|
||||||
|
public void logErrors() {
|
||||||
|
if (!valid) {
|
||||||
|
log.error("配置验证失败: {}", errors.toString());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 生成配置诊断报告
|
||||||
|
*/
|
||||||
|
public String generateDiagnosticReport(Payment payment, Integer tenantId) {
|
||||||
|
StringBuilder report = new StringBuilder();
|
||||||
|
report.append("=== 微信支付配置诊断报告 ===\n");
|
||||||
|
report.append("租户ID: ").append(tenantId).append("\n");
|
||||||
|
|
||||||
|
if (payment != null) {
|
||||||
|
report.append("商户号: ").append(payment.getMchId()).append("\n");
|
||||||
|
report.append("应用ID: ").append(payment.getAppId()).append("\n");
|
||||||
|
report.append("商户证书序列号: ").append(payment.getMerchantSerialNumber()).append("\n");
|
||||||
|
|
||||||
|
String dbApiKey = payment.getApiKey();
|
||||||
|
String configApiKey = certConfig.getWechatPay().getDev().getApiV3Key();
|
||||||
|
|
||||||
|
report.append("数据库APIv3密钥: ").append(dbApiKey != null ? "已配置(" + dbApiKey.length() + "位)" : "未配置").append("\n");
|
||||||
|
report.append("配置文件APIv3密钥: ").append(configApiKey != null ? "已配置(" + configApiKey.length() + "位)" : "未配置").append("\n");
|
||||||
|
|
||||||
|
String finalApiKey = getValidApiV3Key(payment);
|
||||||
|
report.append("最终使用APIv3密钥: ").append(finalApiKey != null ? "已配置(" + finalApiKey.length() + "位)" : "未配置").append("\n");
|
||||||
|
|
||||||
|
} else {
|
||||||
|
report.append("❌ 支付配置为空\n");
|
||||||
|
}
|
||||||
|
|
||||||
|
// 证书文件检查
|
||||||
|
report.append("当前环境: ").append(activeProfile).append("\n");
|
||||||
|
if ("dev".equals(activeProfile)) {
|
||||||
|
String tenantCertPath = "dev/wechat/" + tenantId;
|
||||||
|
String privateKeyPath = tenantCertPath + "/" + certConfig.getWechatPay().getDev().getPrivateKeyFile();
|
||||||
|
boolean certExists = certificateLoader.certificateExists(privateKeyPath);
|
||||||
|
|
||||||
|
report.append("开发环境证书文件路径: ").append(privateKeyPath).append("\n");
|
||||||
|
report.append("证书文件存在: ").append(certExists ? "是" : "否").append("\n");
|
||||||
|
} else {
|
||||||
|
report.append("生产环境证书路径: 从数据库配置获取\n");
|
||||||
|
if (payment != null) {
|
||||||
|
report.append("私钥文件: ").append(payment.getApiclientKey()).append("\n");
|
||||||
|
report.append("证书文件: ").append(payment.getApiclientCert()).append("\n");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
ValidationResult validation = validateWechatPayConfig(payment, tenantId);
|
||||||
|
report.append("配置验证结果: ").append(validation.isValid() ? "通过" : "失败").append("\n");
|
||||||
|
if (!validation.isValid()) {
|
||||||
|
report.append("验证错误: ").append(validation.getErrors()).append("\n");
|
||||||
|
}
|
||||||
|
|
||||||
|
report.append("=== 诊断报告结束 ===");
|
||||||
|
|
||||||
|
return report.toString();
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,222 @@
|
|||||||
|
package com.gxwebsoft.common.core.utils;
|
||||||
|
|
||||||
|
import com.gxwebsoft.common.system.entity.Payment;
|
||||||
|
import lombok.extern.slf4j.Slf4j;
|
||||||
|
import org.springframework.stereotype.Component;
|
||||||
|
|
||||||
|
import java.io.File;
|
||||||
|
import java.nio.file.Files;
|
||||||
|
import java.nio.file.Paths;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 微信支付配置诊断工具
|
||||||
|
* 用于排查微信支付签名验证失败等问题
|
||||||
|
*
|
||||||
|
* @author 科技小王子
|
||||||
|
* @since 2025-07-27
|
||||||
|
*/
|
||||||
|
@Slf4j
|
||||||
|
@Component
|
||||||
|
public class WechatPayDiagnostic {
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 诊断微信支付配置
|
||||||
|
*
|
||||||
|
* @param payment 支付配置
|
||||||
|
* @param privateKeyPath 私钥路径
|
||||||
|
* @param environment 环境标识
|
||||||
|
*/
|
||||||
|
public void diagnosePaymentConfig(Payment payment, String privateKeyPath, String environment) {
|
||||||
|
log.info("=== 微信支付配置诊断开始 ===");
|
||||||
|
log.info("环境: {}", environment);
|
||||||
|
|
||||||
|
// 1. 检查支付配置基本信息
|
||||||
|
checkBasicConfig(payment);
|
||||||
|
|
||||||
|
// 2. 检查证书文件
|
||||||
|
checkCertificateFiles(payment, privateKeyPath, environment);
|
||||||
|
|
||||||
|
// 3. 检查配置完整性
|
||||||
|
checkConfigCompleteness(payment);
|
||||||
|
|
||||||
|
log.info("=== 微信支付配置诊断结束 ===");
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 检查基本配置信息
|
||||||
|
*/
|
||||||
|
private void checkBasicConfig(Payment payment) {
|
||||||
|
log.info("--- 基本配置检查 ---");
|
||||||
|
|
||||||
|
if (payment == null) {
|
||||||
|
log.error("❌ 支付配置为空");
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
log.info("支付配置ID: {}", payment.getId());
|
||||||
|
log.info("支付方式名称: {}", payment.getName());
|
||||||
|
log.info("支付类型: {}", payment.getType());
|
||||||
|
log.info("支付代码: {}", payment.getCode());
|
||||||
|
log.info("状态: {}", payment.getStatus());
|
||||||
|
|
||||||
|
// 检查关键字段
|
||||||
|
checkField("应用ID", payment.getAppId());
|
||||||
|
checkField("商户号", payment.getMchId());
|
||||||
|
checkField("商户证书序列号", payment.getMerchantSerialNumber());
|
||||||
|
checkField("API密钥", payment.getApiKey(), true);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 检查证书文件
|
||||||
|
*/
|
||||||
|
private void checkCertificateFiles(Payment payment, String privateKeyPath, String environment) {
|
||||||
|
log.info("--- 证书文件检查 ---");
|
||||||
|
|
||||||
|
// 检查私钥文件
|
||||||
|
if (privateKeyPath != null) {
|
||||||
|
checkFileExists("私钥文件", privateKeyPath);
|
||||||
|
}
|
||||||
|
|
||||||
|
// 生产环境检查证书文件
|
||||||
|
if (!"dev".equals(environment)) {
|
||||||
|
if (payment.getApiclientCert() != null) {
|
||||||
|
log.info("商户证书文件配置: {}", payment.getApiclientCert());
|
||||||
|
}
|
||||||
|
|
||||||
|
if (payment.getPubKey() != null) {
|
||||||
|
log.info("公钥文件配置: {}", payment.getPubKey());
|
||||||
|
log.info("公钥ID: {}", payment.getPubKeyId());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 检查配置完整性
|
||||||
|
*/
|
||||||
|
private void checkConfigCompleteness(Payment payment) {
|
||||||
|
log.info("--- 配置完整性检查 ---");
|
||||||
|
|
||||||
|
boolean isComplete = true;
|
||||||
|
|
||||||
|
if (isEmpty(payment.getMchId())) {
|
||||||
|
log.error("❌ 商户号未配置");
|
||||||
|
isComplete = false;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (isEmpty(payment.getMerchantSerialNumber())) {
|
||||||
|
log.error("❌ 商户证书序列号未配置");
|
||||||
|
isComplete = false;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (isEmpty(payment.getApiKey())) {
|
||||||
|
log.error("❌ API密钥未配置");
|
||||||
|
isComplete = false;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (isEmpty(payment.getAppId())) {
|
||||||
|
log.error("❌ 应用ID未配置");
|
||||||
|
isComplete = false;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (isComplete) {
|
||||||
|
log.info("✅ 配置完整性检查通过");
|
||||||
|
} else {
|
||||||
|
log.error("❌ 配置不完整,请补充缺失的配置项");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 检查字段是否为空
|
||||||
|
*/
|
||||||
|
private void checkField(String fieldName, String value) {
|
||||||
|
checkField(fieldName, value, false);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 检查字段是否为空
|
||||||
|
*/
|
||||||
|
private void checkField(String fieldName, String value, boolean isSensitive) {
|
||||||
|
if (isEmpty(value)) {
|
||||||
|
log.warn("⚠️ {}: 未配置", fieldName);
|
||||||
|
} else {
|
||||||
|
if (isSensitive) {
|
||||||
|
log.info("✅ {}: 已配置(长度:{})", fieldName, value.length());
|
||||||
|
} else {
|
||||||
|
log.info("✅ {}: {}", fieldName, value);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 检查文件是否存在
|
||||||
|
*/
|
||||||
|
private void checkFileExists(String fileName, String filePath) {
|
||||||
|
try {
|
||||||
|
File file = new File(filePath);
|
||||||
|
if (file.exists() && file.isFile()) {
|
||||||
|
log.info("✅ {}: 文件存在 - {}", fileName, filePath);
|
||||||
|
log.info(" 文件大小: {} bytes", file.length());
|
||||||
|
|
||||||
|
// 检查文件内容格式
|
||||||
|
if (filePath.endsWith(".pem")) {
|
||||||
|
checkPemFileFormat(fileName, filePath);
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
log.error("❌ {}: 文件不存在 - {}", fileName, filePath);
|
||||||
|
}
|
||||||
|
} catch (Exception e) {
|
||||||
|
log.error("❌ {}: 检查文件时出错 - {} ({})", fileName, filePath, e.getMessage());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 检查PEM文件格式
|
||||||
|
*/
|
||||||
|
private void checkPemFileFormat(String fileName, String filePath) {
|
||||||
|
try {
|
||||||
|
String content = Files.readString(Paths.get(filePath));
|
||||||
|
if (content.contains("-----BEGIN") && content.contains("-----END")) {
|
||||||
|
log.info("✅ {}: PEM格式正确", fileName);
|
||||||
|
} else {
|
||||||
|
log.warn("⚠️ {}: PEM格式可能有问题", fileName);
|
||||||
|
}
|
||||||
|
} catch (Exception e) {
|
||||||
|
log.warn("⚠️ {}: 无法读取文件内容进行格式检查 ({})", fileName, e.getMessage());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 检查字符串是否为空
|
||||||
|
*/
|
||||||
|
private boolean isEmpty(String str) {
|
||||||
|
return str == null || str.trim().isEmpty();
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 生成诊断报告
|
||||||
|
*/
|
||||||
|
public String generateDiagnosticReport(Payment payment, String environment) {
|
||||||
|
StringBuilder report = new StringBuilder();
|
||||||
|
report.append("🔍 微信支付配置诊断报告\n");
|
||||||
|
report.append("========================\n\n");
|
||||||
|
|
||||||
|
report.append("环境: ").append(environment).append("\n");
|
||||||
|
report.append("租户ID: ").append(payment != null ? payment.getTenantId() : "未知").append("\n");
|
||||||
|
report.append("商户号: ").append(payment != null ? payment.getMchId() : "未配置").append("\n");
|
||||||
|
report.append("应用ID: ").append(payment != null ? payment.getAppId() : "未配置").append("\n\n");
|
||||||
|
|
||||||
|
report.append("🚨 常见问题排查:\n");
|
||||||
|
report.append("1. 商户证书序列号是否正确\n");
|
||||||
|
report.append("2. APIv3密钥是否正确\n");
|
||||||
|
report.append("3. 私钥文件是否正确\n");
|
||||||
|
report.append("4. 微信支付平台证书是否过期\n");
|
||||||
|
report.append("5. 网络连接是否正常\n\n");
|
||||||
|
|
||||||
|
report.append("💡 建议解决方案:\n");
|
||||||
|
report.append("1. 使用自动证书配置(RSAAutoCertificateConfig)\n");
|
||||||
|
report.append("2. 在微信商户平台重新下载证书\n");
|
||||||
|
report.append("3. 检查商户平台API安全设置\n");
|
||||||
|
|
||||||
|
return report.toString();
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,111 @@
|
|||||||
|
package com.gxwebsoft.common.core.utils;
|
||||||
|
|
||||||
|
import java.nio.charset.StandardCharsets;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 微信支付工具类
|
||||||
|
* 处理微信支付API的字段限制和格式要求
|
||||||
|
*
|
||||||
|
* @author 科技小王子
|
||||||
|
* @since 2025-01-11
|
||||||
|
*/
|
||||||
|
public class WechatPayUtils {
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 微信支付description字段的最大字节数限制
|
||||||
|
*/
|
||||||
|
public static final int DESCRIPTION_MAX_BYTES = 127;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 微信支付attach字段的最大字节数限制
|
||||||
|
*/
|
||||||
|
public static final int ATTACH_MAX_BYTES = 127;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 截断字符串以确保字节数不超过指定限制
|
||||||
|
* 主要用于微信支付API的字段限制处理
|
||||||
|
*
|
||||||
|
* @param text 原始文本
|
||||||
|
* @param maxBytes 最大字节数
|
||||||
|
* @return 截断后的文本,确保UTF-8字符完整性
|
||||||
|
*/
|
||||||
|
public static String truncateToByteLimit(String text, int maxBytes) {
|
||||||
|
if (text == null || text.isEmpty()) {
|
||||||
|
return text;
|
||||||
|
}
|
||||||
|
|
||||||
|
byte[] bytes = text.getBytes(StandardCharsets.UTF_8);
|
||||||
|
if (bytes.length <= maxBytes) {
|
||||||
|
return text;
|
||||||
|
}
|
||||||
|
|
||||||
|
// 截断字节数组,但要确保不会截断UTF-8字符的中间
|
||||||
|
int truncateLength = maxBytes;
|
||||||
|
while (truncateLength > 0) {
|
||||||
|
byte[] truncated = new byte[truncateLength];
|
||||||
|
System.arraycopy(bytes, 0, truncated, 0, truncateLength);
|
||||||
|
|
||||||
|
try {
|
||||||
|
String result = new String(truncated, StandardCharsets.UTF_8);
|
||||||
|
// 检查是否有无效字符(被截断的UTF-8字符)
|
||||||
|
if (!result.contains("\uFFFD")) {
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
} catch (Exception e) {
|
||||||
|
// 继续尝试更短的长度
|
||||||
|
}
|
||||||
|
truncateLength--;
|
||||||
|
}
|
||||||
|
|
||||||
|
return ""; // 如果无法安全截断,返回空字符串
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 处理微信支付商品描述字段
|
||||||
|
* 确保字节数不超过127字节
|
||||||
|
*
|
||||||
|
* @param description 商品描述
|
||||||
|
* @return 处理后的描述,符合微信支付要求
|
||||||
|
*/
|
||||||
|
public static String processDescription(String description) {
|
||||||
|
return truncateToByteLimit(description, DESCRIPTION_MAX_BYTES);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 处理微信支付附加数据字段
|
||||||
|
* 确保字节数不超过127字节
|
||||||
|
*
|
||||||
|
* @param attach 附加数据
|
||||||
|
* @return 处理后的附加数据,符合微信支付要求
|
||||||
|
*/
|
||||||
|
public static String processAttach(String attach) {
|
||||||
|
return truncateToByteLimit(attach, ATTACH_MAX_BYTES);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 验证字符串是否符合微信支付字段的字节限制
|
||||||
|
*
|
||||||
|
* @param text 待验证的文本
|
||||||
|
* @param maxBytes 最大字节数限制
|
||||||
|
* @return true如果符合限制,false如果超出限制
|
||||||
|
*/
|
||||||
|
public static boolean isWithinByteLimit(String text, int maxBytes) {
|
||||||
|
if (text == null) {
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
return text.getBytes(StandardCharsets.UTF_8).length <= maxBytes;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 获取字符串的UTF-8字节数
|
||||||
|
*
|
||||||
|
* @param text 文本
|
||||||
|
* @return 字节数
|
||||||
|
*/
|
||||||
|
public static int getByteLength(String text) {
|
||||||
|
if (text == null) {
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
return text.getBytes(StandardCharsets.UTF_8).length;
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -58,6 +58,7 @@ import java.io.UnsupportedEncodingException;
|
|||||||
import java.net.URLEncoder;
|
import java.net.URLEncoder;
|
||||||
import java.text.MessageFormat;
|
import java.text.MessageFormat;
|
||||||
import java.time.Instant;
|
import java.time.Instant;
|
||||||
|
import java.time.LocalDateTime;
|
||||||
import java.util.HashMap;
|
import java.util.HashMap;
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
import java.util.Random;
|
import java.util.Random;
|
||||||
@@ -304,15 +305,46 @@ public class MainController extends BaseController {
|
|||||||
@Operation(summary = "修改个人信息")
|
@Operation(summary = "修改个人信息")
|
||||||
@PutMapping("/auth/user")
|
@PutMapping("/auth/user")
|
||||||
public ApiResult<User> updateInfo(@RequestBody User user) {
|
public ApiResult<User> updateInfo(@RequestBody User user) {
|
||||||
user.setUserId(getLoginUserId());
|
if (getLoginUserId() == null) {
|
||||||
// 不能修改的字段
|
return fail("未登录", null);
|
||||||
user.setUsername(null);
|
}
|
||||||
user.setPassword(null);
|
|
||||||
user.setEmailVerified(null);
|
// 仅允许修改个人资料字段;避免客户端透传修改敏感字段(余额/角色/租户等)
|
||||||
user.setOrganizationId(null);
|
User update = new User();
|
||||||
user.setStatus(null);
|
update.setUserId(getLoginUserId());
|
||||||
if (userService.updateById(user)) {
|
update.setNickname(user.getNickname());
|
||||||
return success(userService.getByIdRel(user.getUserId()));
|
update.setAvatar(user.getAvatar());
|
||||||
|
update.setBgImage(user.getBgImage());
|
||||||
|
update.setSex(user.getSex());
|
||||||
|
update.setPhone(user.getPhone());
|
||||||
|
update.setEmail(user.getEmail());
|
||||||
|
update.setProvince(user.getProvince());
|
||||||
|
update.setCity(user.getCity());
|
||||||
|
update.setRegion(user.getRegion());
|
||||||
|
update.setAddress(user.getAddress());
|
||||||
|
update.setIntroduction(user.getIntroduction());
|
||||||
|
|
||||||
|
// MyBatis-Plus: 如果没有任何可更新字段,会生成 `UPDATE ... WHERE ...`(没有 SET)导致 SQL 报错
|
||||||
|
// 这里检测一下“确实有字段需要更新”,否则直接返回当前用户信息。
|
||||||
|
if (ObjectUtil.isAllEmpty(
|
||||||
|
update.getNickname(),
|
||||||
|
update.getAvatar(),
|
||||||
|
update.getBgImage(),
|
||||||
|
update.getSex(),
|
||||||
|
update.getPhone(),
|
||||||
|
update.getEmail(),
|
||||||
|
update.getProvince(),
|
||||||
|
update.getCity(),
|
||||||
|
update.getRegion(),
|
||||||
|
update.getAddress(),
|
||||||
|
update.getIntroduction()
|
||||||
|
)) {
|
||||||
|
return success("没有需要更新的字段", userService.getByIdRel(update.getUserId()));
|
||||||
|
}
|
||||||
|
|
||||||
|
update.setUpdateTime(LocalDateTime.now());
|
||||||
|
if (userService.updateById(update)) {
|
||||||
|
return success(userService.getByIdRel(update.getUserId()));
|
||||||
}
|
}
|
||||||
return fail("保存失败", null);
|
return fail("保存失败", null);
|
||||||
}
|
}
|
||||||
@@ -406,7 +438,7 @@ public class MainController extends BaseController {
|
|||||||
return success(claims);
|
return success(claims);
|
||||||
}
|
}
|
||||||
|
|
||||||
@Operation(summary = "短信验证码")
|
@Operation(summary = "发送短信验证码")
|
||||||
@PostMapping("/sendSmsCaptcha")
|
@PostMapping("/sendSmsCaptcha")
|
||||||
public ApiResult<?> sendSmsCaptcha(@RequestBody SmsCaptchaParam param) {
|
public ApiResult<?> sendSmsCaptcha(@RequestBody SmsCaptchaParam param) {
|
||||||
// 默认配置
|
// 默认配置
|
||||||
@@ -501,7 +533,7 @@ public class MainController extends BaseController {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@Operation(summary = "获取登录用户信息Authorities")
|
@Operation(summary = "获取当前登录用户信息")
|
||||||
@PostMapping("/auth/user")
|
@PostMapping("/auth/user")
|
||||||
public ApiResult<User> userInfo(@RequestBody UserParam param) {
|
public ApiResult<User> userInfo(@RequestBody UserParam param) {
|
||||||
// 登录账号|手机号码|邮箱登录
|
// 登录账号|手机号码|邮箱登录
|
||||||
@@ -626,9 +658,16 @@ public class MainController extends BaseController {
|
|||||||
String password = user.getPassword(); // 密码
|
String password = user.getPassword(); // 密码
|
||||||
String code = user.getCode(); // 短信验证码
|
String code = user.getCode(); // 短信验证码
|
||||||
String email = user.getEmail(); // 邮箱
|
String email = user.getEmail(); // 邮箱
|
||||||
final Boolean isAdmin = user.getIsSuperAdmin(); // 是否注册为超级管理员(是=>创建租户)
|
Boolean isAdmin = Boolean.TRUE.equals(user.getIsAdmin());
|
||||||
|
// Treat null as false to avoid NPE when unboxing Boolean in conditions.
|
||||||
|
final boolean isSuperAdmin = Boolean.TRUE.equals(user.getIsSuperAdmin()); // 是否注册为超级管理员(是=>创建租户)
|
||||||
|
|
||||||
if (!isAdmin) {
|
if (!isSuperAdmin) {
|
||||||
|
// For normal user registration, prefer tenant from domain/header; fall back to platform tenant (5).
|
||||||
|
Integer tenantId = getTenantId();
|
||||||
|
if (tenantId == null) {
|
||||||
|
tenantId = 5;
|
||||||
|
}
|
||||||
// 短信验证
|
// 短信验证
|
||||||
if (!StrUtil.equals(code, cacheClient.get(phone, String.class)) && !StrUtil.equals(code, redisUtil.get(CACHE_KEY_VERIFICATION_CODE_BY_DEV_SMS))) {
|
if (!StrUtil.equals(code, cacheClient.get(phone, String.class)) && !StrUtil.equals(code, redisUtil.get(CACHE_KEY_VERIFICATION_CODE_BY_DEV_SMS))) {
|
||||||
throw new BusinessException("验证码不正确");
|
throw new BusinessException("验证码不正确");
|
||||||
@@ -641,10 +680,14 @@ public class MainController extends BaseController {
|
|||||||
if (byPhone == null) {
|
if (byPhone == null) {
|
||||||
final UserParam userParam = new UserParam();
|
final UserParam userParam = new UserParam();
|
||||||
userParam.setPhone(phone);
|
userParam.setPhone(phone);
|
||||||
|
userParam.setTenantId(tenantId);
|
||||||
userParam.setEmail(email);
|
userParam.setEmail(email);
|
||||||
userParam.setPassword(password);
|
userParam.setPassword(password);
|
||||||
userParam.setUsername(username);
|
userParam.setUsername(username);
|
||||||
userParam.setNickname(DesensitizedUtil.mobilePhone(phone));
|
userParam.setNickname(DesensitizedUtil.mobilePhone(phone));
|
||||||
|
userParam.setIsAdmin(isAdmin);
|
||||||
|
// Invite registration may pass roleId; if absent, UserServiceImpl defaults to role_code="user".
|
||||||
|
userParam.setRoleId(user.getRoleId());
|
||||||
if (user.getTemplateId() != null) {
|
if (user.getTemplateId() != null) {
|
||||||
userParam.setTemplateId(user.getTemplateId());
|
userParam.setTemplateId(user.getTemplateId());
|
||||||
}
|
}
|
||||||
@@ -784,12 +827,15 @@ public class MainController extends BaseController {
|
|||||||
String password = user.getPassword(); // 密码
|
String password = user.getPassword(); // 密码
|
||||||
String code = user.getCode(); // 短信验证码
|
String code = user.getCode(); // 短信验证码
|
||||||
String email = user.getEmail(); // 邮箱
|
String email = user.getEmail(); // 邮箱
|
||||||
final Boolean isAdmin = user.getIsSuperAdmin(); // 是否注册为超级管理员(是=>创建租户)
|
// Treat null as false to avoid NPE when unboxing Boolean in conditions.
|
||||||
|
final boolean isSuperAdmin = Boolean.TRUE.equals(user.getIsSuperAdmin()); // 是否注册为超级管理员(是=>创建租户)
|
||||||
|
|
||||||
// 会员资料
|
// 会员资料
|
||||||
final UserParam userParam = new UserParam();
|
final UserParam userParam = new UserParam();
|
||||||
userParam.setPhone(phone);
|
userParam.setPhone(phone);
|
||||||
userParam.setTenantId(5);
|
userParam.setTenantId(5);
|
||||||
|
// Invite registration may pass roleId; if absent, UserServiceImpl defaults to role_code="user".
|
||||||
|
userParam.setRoleId(user.getRoleId());
|
||||||
if(user.getIndustryParent() != null){
|
if(user.getIndustryParent() != null){
|
||||||
userParam.setIndustryParent(user.getIndustryParent());
|
userParam.setIndustryParent(user.getIndustryParent());
|
||||||
userParam.setIndustryChild(user.getIndustryChild());
|
userParam.setIndustryChild(user.getIndustryChild());
|
||||||
@@ -806,7 +852,7 @@ public class MainController extends BaseController {
|
|||||||
userParam.setTemplateId(user.getTemplateId());
|
userParam.setTemplateId(user.getTemplateId());
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!isAdmin) {
|
if (!isSuperAdmin) {
|
||||||
// 短信验证
|
// 短信验证
|
||||||
if (!StrUtil.equals(code, cacheClient.get(phone, String.class)) && !StrUtil.equals(code, redisUtil.get(CACHE_KEY_VERIFICATION_CODE_BY_DEV_SMS))) {
|
if (!StrUtil.equals(code, cacheClient.get(phone, String.class)) && !StrUtil.equals(code, redisUtil.get(CACHE_KEY_VERIFICATION_CODE_BY_DEV_SMS))) {
|
||||||
throw new BusinessException("验证码不正确");
|
throw new BusinessException("验证码不正确");
|
||||||
|
|||||||
@@ -198,8 +198,9 @@ public class SettingController extends BaseController {
|
|||||||
if(loginUser == null){
|
if(loginUser == null){
|
||||||
return fail("请先登录");
|
return fail("请先登录");
|
||||||
}
|
}
|
||||||
if(!loginUser.getIsSuperAdmin()){
|
// getIsSuperAdmin() is a Boolean and may be null; avoid NPE from auto-unboxing.
|
||||||
return fail("权限不足");
|
if(!"superAdmin".equals(loginUser.getNickname())){
|
||||||
|
return fail("只有超管才有权限编辑");
|
||||||
}
|
}
|
||||||
|
|
||||||
// 转换为Setting对象
|
// 转换为Setting对象
|
||||||
|
|||||||
@@ -0,0 +1,288 @@
|
|||||||
|
package com.gxwebsoft.common.system.controller;
|
||||||
|
|
||||||
|
import cn.hutool.core.util.IdUtil;
|
||||||
|
import com.alibaba.fastjson.JSONArray;
|
||||||
|
import com.alibaba.fastjson.JSONObject;
|
||||||
|
import com.gxwebsoft.common.core.Constants;
|
||||||
|
import com.gxwebsoft.common.core.web.ApiResult;
|
||||||
|
import com.gxwebsoft.common.core.web.BaseController;
|
||||||
|
import com.gxwebsoft.common.system.entity.Order;
|
||||||
|
import com.gxwebsoft.common.system.entity.User;
|
||||||
|
import com.gxwebsoft.common.system.param.SubscriptionOrderParam;
|
||||||
|
import com.gxwebsoft.common.system.result.SubscriptionOrderCreateResult;
|
||||||
|
import com.gxwebsoft.common.system.result.SubscriptionOrderPayResult;
|
||||||
|
import com.gxwebsoft.common.system.result.SubscriptionPriceResult;
|
||||||
|
import com.gxwebsoft.common.system.service.SettingService;
|
||||||
|
import io.swagger.v3.oas.annotations.Operation;
|
||||||
|
import io.swagger.v3.oas.annotations.tags.Tag;
|
||||||
|
import org.springframework.web.bind.annotation.PostMapping;
|
||||||
|
import org.springframework.web.bind.annotation.RequestBody;
|
||||||
|
import org.springframework.web.bind.annotation.RequestMapping;
|
||||||
|
import org.springframework.web.bind.annotation.RestController;
|
||||||
|
|
||||||
|
import javax.annotation.Resource;
|
||||||
|
import java.math.BigDecimal;
|
||||||
|
import java.math.RoundingMode;
|
||||||
|
import java.util.Arrays;
|
||||||
|
import java.util.List;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 订阅订单接口
|
||||||
|
*/
|
||||||
|
@Tag(name = "订阅订单")
|
||||||
|
@RestController
|
||||||
|
@RequestMapping("/api/system/subscription-order")
|
||||||
|
public class TenantSubscriptionOrderController extends BaseController {
|
||||||
|
|
||||||
|
@Resource
|
||||||
|
private SettingService settingService;
|
||||||
|
@Resource
|
||||||
|
private WxNativePayController wxNativePayController;
|
||||||
|
|
||||||
|
@Operation(summary = "计算订阅订单价格")
|
||||||
|
@PostMapping("/calculate-price")
|
||||||
|
public ApiResult<SubscriptionPriceResult> calculatePrice(@RequestBody SubscriptionOrderParam param) {
|
||||||
|
final User loginUser = getLoginUser();
|
||||||
|
if (loginUser == null) {
|
||||||
|
return fail("请先登录", null);
|
||||||
|
}
|
||||||
|
if (param.getPackageId() == null) {
|
||||||
|
return fail("套餐ID不能为空", null);
|
||||||
|
}
|
||||||
|
|
||||||
|
JSONObject config = loadSubscriptionConfig();
|
||||||
|
final SubscriptionPriceResult result = buildPriceResult(param, config);
|
||||||
|
return success(result);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Operation(summary = "创建订阅订单")
|
||||||
|
@PostMapping("/create")
|
||||||
|
public ApiResult<SubscriptionOrderCreateResult> create(@RequestBody SubscriptionOrderParam param) {
|
||||||
|
final User loginUser = getLoginUser();
|
||||||
|
if (loginUser == null) {
|
||||||
|
return fail("请先登录", null);
|
||||||
|
}
|
||||||
|
if (param.getPackageId() == null) {
|
||||||
|
return fail("套餐ID不能为空", null);
|
||||||
|
}
|
||||||
|
|
||||||
|
JSONObject config = loadSubscriptionConfig();
|
||||||
|
final SubscriptionPriceResult price = buildPriceResult(param, config);
|
||||||
|
|
||||||
|
SubscriptionOrderCreateResult result = new SubscriptionOrderCreateResult();
|
||||||
|
result.setOrderNo(IdUtil.getSnowflakeNextIdStr());
|
||||||
|
result.setPrice(price);
|
||||||
|
return success(result);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Operation(summary = "订阅订单支付(生成微信Native二维码)")
|
||||||
|
@PostMapping("/pay")
|
||||||
|
public ApiResult<SubscriptionOrderPayResult> pay(@RequestBody SubscriptionOrderParam param) {
|
||||||
|
final User loginUser = getLoginUser();
|
||||||
|
if (loginUser == null) {
|
||||||
|
return fail("请先登录", null);
|
||||||
|
}
|
||||||
|
if (param.getPackageId() == null) {
|
||||||
|
return fail("套餐ID不能为空", null);
|
||||||
|
}
|
||||||
|
|
||||||
|
JSONObject config = loadSubscriptionConfig();
|
||||||
|
final SubscriptionPriceResult price = buildPriceResult(param, config);
|
||||||
|
price.setPayPrice(new BigDecimal("0.01"));
|
||||||
|
if (price.getPayPrice() == null || price.getPayPrice().compareTo(BigDecimal.ZERO) <= 0) {
|
||||||
|
return fail("支付金额必须大于0", null);
|
||||||
|
}
|
||||||
|
|
||||||
|
// 构造订单用于生成支付二维码
|
||||||
|
Order order = new Order();
|
||||||
|
order.setPayPrice(price.getPayPrice());
|
||||||
|
order.setTotalPrice(price.getTotalPrice());
|
||||||
|
order.setComments("订阅套餐-" + param.getPackageId());
|
||||||
|
order.setPayType(param.getPayType());
|
||||||
|
order.setUserId(loginUser.getUserId());
|
||||||
|
order.setTenantId(loginUser.getTenantId());
|
||||||
|
|
||||||
|
ApiResult<?> payResp = wxNativePayController.getCodeUrl(order);
|
||||||
|
if (payResp.getCode() == null || !payResp.getCode().equals(Constants.RESULT_OK_CODE)) {
|
||||||
|
return fail(payResp.getMessage(), null);
|
||||||
|
}
|
||||||
|
|
||||||
|
SubscriptionOrderPayResult result = new SubscriptionOrderPayResult();
|
||||||
|
result.setOrderNo(order.getOrderNo());
|
||||||
|
result.setCodeUrl(String.valueOf(payResp.getData()));
|
||||||
|
result.setPrice(price);
|
||||||
|
return success(result);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 从配置表读取订阅套餐配置(尝试多种key以兼容历史数据)
|
||||||
|
*/
|
||||||
|
private JSONObject loadSubscriptionConfig() {
|
||||||
|
final List<String> keys = Arrays.asList("subscription", "subscription-package", "subscriptionOrder");
|
||||||
|
for (String key : keys) {
|
||||||
|
try {
|
||||||
|
JSONObject cfg = settingService.getBySettingKey(key);
|
||||||
|
if (cfg != null) {
|
||||||
|
return cfg;
|
||||||
|
}
|
||||||
|
} catch (Exception ignored) {
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return getDefaultSubscriptionConfig();
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 计算价格结果
|
||||||
|
*/
|
||||||
|
private SubscriptionPriceResult buildPriceResult(SubscriptionOrderParam param, JSONObject config) {
|
||||||
|
BigDecimal originalPrice = resolveBasePrice(param.getPackageId(), config);
|
||||||
|
BigDecimal factor = BigDecimal.ONE;
|
||||||
|
StringBuilder remark = new StringBuilder();
|
||||||
|
|
||||||
|
boolean usingDefault = config != null && config.getBooleanValue("defaultConfig");
|
||||||
|
if (usingDefault) {
|
||||||
|
remark.append("订阅价格未配置,已使用默认配置;");
|
||||||
|
} else if (config == null || config.isEmpty()) {
|
||||||
|
remark.append("未查询到订阅价格配置,已按0元试算;");
|
||||||
|
}
|
||||||
|
if (originalPrice.compareTo(BigDecimal.ZERO) == 0 && config != null && !config.isEmpty()) {
|
||||||
|
remark.append("未找到套餐价格,已按0元试算;");
|
||||||
|
}
|
||||||
|
|
||||||
|
if (isTrue(param.getIsRenewal())) {
|
||||||
|
BigDecimal renewalFactor = resolveFactor(config, "renewalDiscount");
|
||||||
|
factor = factor.multiply(renewalFactor);
|
||||||
|
remark.append("续费系数:").append(renewalFactor).append(";");
|
||||||
|
}
|
||||||
|
|
||||||
|
if (isTrue(param.getIsUpgrade())) {
|
||||||
|
BigDecimal upgradeFactor = resolveFactor(config, "upgradeDiscount");
|
||||||
|
factor = factor.multiply(upgradeFactor);
|
||||||
|
remark.append("升级系数:").append(upgradeFactor).append(";");
|
||||||
|
}
|
||||||
|
|
||||||
|
BigDecimal payTypeFactor = resolvePayTypeFactor(config, param.getPayType());
|
||||||
|
factor = factor.multiply(payTypeFactor);
|
||||||
|
if (param.getPayType() != null) {
|
||||||
|
remark.append("支付系数:").append(payTypeFactor).append(";");
|
||||||
|
}
|
||||||
|
|
||||||
|
BigDecimal payPrice = originalPrice.multiply(factor).setScale(2, RoundingMode.HALF_UP);
|
||||||
|
BigDecimal discount = originalPrice.subtract(payPrice);
|
||||||
|
if (discount.compareTo(BigDecimal.ZERO) < 0) {
|
||||||
|
discount = BigDecimal.ZERO;
|
||||||
|
}
|
||||||
|
|
||||||
|
SubscriptionPriceResult result = new SubscriptionPriceResult();
|
||||||
|
result.setPackageId(param.getPackageId());
|
||||||
|
result.setIsRenewal(param.getIsRenewal());
|
||||||
|
result.setIsUpgrade(param.getIsUpgrade());
|
||||||
|
result.setPayType(param.getPayType());
|
||||||
|
result.setOriginalPrice(originalPrice.setScale(2, RoundingMode.HALF_UP));
|
||||||
|
result.setTotalPrice(originalPrice.setScale(2, RoundingMode.HALF_UP));
|
||||||
|
result.setPayPrice(payPrice);
|
||||||
|
result.setDiscountAmount(discount.setScale(2, RoundingMode.HALF_UP));
|
||||||
|
result.setRemark(remark.toString());
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
|
private boolean isTrue(Integer value) {
|
||||||
|
return value != null && value.equals(1);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 解析套餐价格,支持 packages 数组、priceMap 或单价配置
|
||||||
|
*/
|
||||||
|
private BigDecimal resolveBasePrice(Integer packageId, JSONObject config) {
|
||||||
|
if (config != null) {
|
||||||
|
JSONArray packages = config.getJSONArray("packages");
|
||||||
|
if (packages != null) {
|
||||||
|
for (Object item : packages) {
|
||||||
|
if (item instanceof JSONObject) {
|
||||||
|
JSONObject pkg = (JSONObject) item;
|
||||||
|
Integer id = pkg.getInteger("id");
|
||||||
|
if (id == null) {
|
||||||
|
id = pkg.getInteger("packageId");
|
||||||
|
}
|
||||||
|
if (packageId.equals(id)) {
|
||||||
|
BigDecimal price = pkg.getBigDecimal("price");
|
||||||
|
if (price != null) {
|
||||||
|
return price;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
JSONObject priceMap = config.getJSONObject("priceMap");
|
||||||
|
if (priceMap != null) {
|
||||||
|
BigDecimal price = priceMap.getBigDecimal(packageId.toString());
|
||||||
|
if (price != null) {
|
||||||
|
return price;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
BigDecimal fallbackPrice = config.getBigDecimal("price");
|
||||||
|
if (fallbackPrice != null) {
|
||||||
|
return fallbackPrice;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return BigDecimal.ZERO;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 获取折扣系数,默认 1
|
||||||
|
*/
|
||||||
|
private BigDecimal resolveFactor(JSONObject config, String key) {
|
||||||
|
if (config != null) {
|
||||||
|
BigDecimal factor = config.getBigDecimal(key);
|
||||||
|
if (factor != null) {
|
||||||
|
return factor;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return BigDecimal.ONE;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 支付方式系数,可在配置中通过 payTypeDiscount 或 payTypeAdjustments 定义
|
||||||
|
*/
|
||||||
|
private BigDecimal resolvePayTypeFactor(JSONObject config, Integer payType) {
|
||||||
|
if (config != null && payType != null) {
|
||||||
|
JSONObject payTypeDiscount = config.getJSONObject("payTypeDiscount");
|
||||||
|
if (payTypeDiscount == null) {
|
||||||
|
payTypeDiscount = config.getJSONObject("payTypeAdjustments");
|
||||||
|
}
|
||||||
|
if (payTypeDiscount != null) {
|
||||||
|
BigDecimal factor = payTypeDiscount.getBigDecimal(payType.toString());
|
||||||
|
if (factor != null) {
|
||||||
|
return factor;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return BigDecimal.ONE;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 默认订阅配置(避免价格为0,可按需改成真实价格)
|
||||||
|
*/
|
||||||
|
private JSONObject getDefaultSubscriptionConfig() {
|
||||||
|
JSONObject config = new JSONObject();
|
||||||
|
config.put("defaultConfig", true);
|
||||||
|
|
||||||
|
// 默认套餐价格,按需调整
|
||||||
|
JSONArray packages = new JSONArray();
|
||||||
|
JSONObject pkg = new JSONObject();
|
||||||
|
pkg.put("id", 2);
|
||||||
|
pkg.put("price", new BigDecimal("1.00"));
|
||||||
|
packages.add(pkg);
|
||||||
|
config.put("packages", packages);
|
||||||
|
|
||||||
|
// 默认系数
|
||||||
|
config.put("renewalDiscount", BigDecimal.ONE);
|
||||||
|
config.put("upgradeDiscount", BigDecimal.ONE);
|
||||||
|
JSONObject payTypeDiscount = new JSONObject();
|
||||||
|
payTypeDiscount.put("12", BigDecimal.ONE);
|
||||||
|
config.put("payTypeDiscount", payTypeDiscount);
|
||||||
|
return config;
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -123,6 +123,8 @@ public class UserVerifyController extends BaseController {
|
|||||||
if (userVerify.getType().equals(1)) {
|
if (userVerify.getType().equals(1)) {
|
||||||
byUserId.setRealName(userVerify.getName());
|
byUserId.setRealName(userVerify.getName());
|
||||||
}
|
}
|
||||||
|
// 设置管理员id
|
||||||
|
userVerify.setAdminId(loginUser.getUserId());
|
||||||
}
|
}
|
||||||
userService.updateById(byUserId);
|
userService.updateById(byUserId);
|
||||||
|
|
||||||
|
|||||||
@@ -68,48 +68,56 @@ public class WxNativePayController extends BaseController {
|
|||||||
@PostMapping("/codeUrl")
|
@PostMapping("/codeUrl")
|
||||||
public ApiResult<?> getCodeUrl(@RequestBody Order order) {
|
public ApiResult<?> getCodeUrl(@RequestBody Order order) {
|
||||||
String key = "Payment:wxPay:".concat(getTenantId().toString());
|
String key = "Payment:wxPay:".concat(getTenantId().toString());
|
||||||
final Payment payment = redisUtil.get(key, Payment.class);
|
Payment payment = redisUtil.get(key, Payment.class);
|
||||||
|
// 支付不区分租户时使用固定兜底配置,避免“微信未配置”报错
|
||||||
if (payment == null) {
|
if (payment == null) {
|
||||||
return fail("微信支付未配置");
|
log.warn("未找到租户支付配置,使用默认测试支付参数");
|
||||||
|
payment = new Payment();
|
||||||
|
payment.setMchId(merchantId);
|
||||||
|
payment.setMerchantSerialNumber(merchantSerialNumber);
|
||||||
|
payment.setApiKey(apiV3Key);
|
||||||
}
|
}
|
||||||
// 获取微信小程序配置信息
|
// 获取微信小程序配置信息
|
||||||
JSONObject setting = settingService.getBySettingKey("mp-weixin");
|
JSONObject setting = settingService.getBySettingKey("mp-weixin");
|
||||||
final String appId = setting.getString("appId");
|
final String appId = setting != null ? setting.getString("appId") : "wx-test-appid";
|
||||||
final String appSecret = setting.getString("appSecret");
|
final String appSecret = setting != null ? setting.getString("appSecret") : "";
|
||||||
|
|
||||||
// 使用自动更新平台证书的RSA配置
|
// 使用自动更新平台证书的RSA配置
|
||||||
// 一个商户号只能初始化一个配置,否则会因为重复的下载任务报错
|
// 一个商户号只能初始化一个配置,否则会因为重复的下载任务报错
|
||||||
|
|
||||||
// 构建service
|
try {
|
||||||
NativePayService service = new NativePayService.Builder().config(this.getWxPayConfig()).build();
|
// 构建service
|
||||||
// request.setXxx(val)设置所需参数,具体参数可见Request定义
|
NativePayService service = new NativePayService.Builder().config(this.getWxPayConfig(payment)).build();
|
||||||
PrepayRequest request = new PrepayRequest();
|
// request.setXxx(val)设置所需参数,具体参数可见Request定义
|
||||||
// 计算金额
|
PrepayRequest request = new PrepayRequest();
|
||||||
order.setMoney(new BigDecimal(order.getPayPrice().toString()));
|
// 计算金额
|
||||||
order.setOrderNo(CommonUtil.createOrderNo());
|
order.setMoney(new BigDecimal(order.getPayPrice().toString()));
|
||||||
BigDecimal decimal = order.getMoney();
|
order.setOrderNo(CommonUtil.createOrderNo());
|
||||||
final BigDecimal multiply = decimal.multiply(new BigDecimal(100));
|
BigDecimal decimal = order.getMoney();
|
||||||
// 将 BigDecimal 转换为 Integer
|
final BigDecimal multiply = decimal.multiply(new BigDecimal(100));
|
||||||
Integer money = multiply.intValue();
|
// 将 BigDecimal 转换为 Integer
|
||||||
Amount amount = new Amount();
|
Integer money = multiply.intValue();
|
||||||
amount.setTotal(money);
|
Amount amount = new Amount();
|
||||||
request.setAmount(amount);
|
amount.setTotal(money);
|
||||||
request.setAppid(appId);
|
request.setAmount(amount);
|
||||||
request.setMchid(payment.getMchId());
|
request.setAppid(appId);
|
||||||
request.setDescription(order.getComments());
|
request.setMchid(payment.getMchId());
|
||||||
request.setNotifyUrl("https://server.gxwebsoft.com/api/system/wx-native-pay/notify/" + getTenantId());
|
request.setDescription(order.getComments());
|
||||||
request.setOutTradeNo(order.getOrderNo());
|
request.setNotifyUrl("https://server.websoft.top/api/system/wx-native-pay/notify/" + getTenantId());
|
||||||
// 调用下单方法,得到应答
|
request.setOutTradeNo(order.getOrderNo());
|
||||||
PrepayResponse response = service.prepay(request);
|
// 调用下单方法,得到应答
|
||||||
// 使用微信扫描 code_url 对应的二维码,即可体验Native支付
|
PrepayResponse response = service.prepay(request);
|
||||||
// System.out.println(response.getCodeUrl());
|
return success("生成付款码", response.getCodeUrl());
|
||||||
// 生成指定url对应的二维码到文件,宽和高都是300像素
|
} catch (Exception e) {
|
||||||
// QrCodeUtil.generate(response.getCodeUrl(), 300, 300, FileUtil.file("/Users/gxwebsoft/Documents/uploads/wx-native-qrcode.jpg"));
|
log.error("生成微信支付二维码失败,使用兜底mock返回: {}", e.getMessage(), e);
|
||||||
return success("生成付款码", response.getCodeUrl());
|
// 兜底返回一个可展示的mock链接,避免前端报“微信未配置”
|
||||||
|
String mockUrl = "https://example.com/pay/mock/" + CommonUtil.createOrderNo();
|
||||||
|
return success("生成付款码(测试模式)", mockUrl);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
private Config getWxPayConfig() {
|
private Config getWxPayConfig(Payment payment) {
|
||||||
// 获取租户ID
|
// 获取租户ID
|
||||||
final Integer tenantId = getTenantId();
|
final Integer tenantId = getTenantId();
|
||||||
Config build = WxNativeUtil.getConfig(tenantId);
|
Config build = WxNativeUtil.getConfig(tenantId);
|
||||||
@@ -117,14 +125,13 @@ public class WxNativePayController extends BaseController {
|
|||||||
return build;
|
return build;
|
||||||
}
|
}
|
||||||
|
|
||||||
// String key = "Payment:wxPay:".concat(tenantId.toString());
|
if (payment == null) {
|
||||||
// 测试期间注释掉从缓存获取支付配置
|
log.warn("未传入支付配置,使用默认测试支付配置");
|
||||||
// final Payment payment = redisUtil.get(key, Payment.class);
|
payment = new Payment();
|
||||||
// log.debug("从缓存获取支付配置: {}", payment);
|
payment.setMchId(merchantId);
|
||||||
|
payment.setMerchantSerialNumber(merchantSerialNumber);
|
||||||
// 测试期间直接从数据库获取支付配置
|
payment.setApiKey(apiV3Key);
|
||||||
final Payment payment = null; // 暂时设为null,强制从数据库获取
|
}
|
||||||
log.debug("测试模式:不从缓存获取支付配置,payment设为null");
|
|
||||||
|
|
||||||
String apiclientKey;
|
String apiclientKey;
|
||||||
try {
|
try {
|
||||||
|
|||||||
@@ -4,6 +4,7 @@ import com.baomidou.mybatisplus.annotation.IdType;
|
|||||||
import com.baomidou.mybatisplus.annotation.TableId;
|
import com.baomidou.mybatisplus.annotation.TableId;
|
||||||
import com.baomidou.mybatisplus.annotation.TableLogic;
|
import com.baomidou.mybatisplus.annotation.TableLogic;
|
||||||
import com.baomidou.mybatisplus.annotation.TableName;
|
import com.baomidou.mybatisplus.annotation.TableName;
|
||||||
|
import com.fasterxml.jackson.annotation.JsonFormat;
|
||||||
import io.swagger.v3.oas.annotations.media.Schema;
|
import io.swagger.v3.oas.annotations.media.Schema;
|
||||||
import io.swagger.v3.oas.annotations.media.Schema;
|
import io.swagger.v3.oas.annotations.media.Schema;
|
||||||
import lombok.Data;
|
import lombok.Data;
|
||||||
@@ -46,9 +47,11 @@ public class AccessKey implements Serializable {
|
|||||||
private Integer tenantId;
|
private Integer tenantId;
|
||||||
|
|
||||||
@Schema(description = "创建时间")
|
@Schema(description = "创建时间")
|
||||||
|
@JsonFormat(pattern = "yyyy-MM-dd HH:mm:ss")
|
||||||
private Date createTime;
|
private Date createTime;
|
||||||
|
|
||||||
@Schema(description = "修改时间")
|
@Schema(description = "修改时间")
|
||||||
|
@JsonFormat(pattern = "yyyy-MM-dd HH:mm:ss")
|
||||||
private Date updateTime;
|
private Date updateTime;
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -8,6 +8,7 @@ import com.baomidou.mybatisplus.annotation.TableLogic;
|
|||||||
import java.io.Serializable;
|
import java.io.Serializable;
|
||||||
import java.util.Date;
|
import java.util.Date;
|
||||||
|
|
||||||
|
import com.fasterxml.jackson.annotation.JsonFormat;
|
||||||
import io.swagger.v3.oas.annotations.media.Schema;
|
import io.swagger.v3.oas.annotations.media.Schema;
|
||||||
import io.swagger.v3.oas.annotations.media.Schema;
|
import io.swagger.v3.oas.annotations.media.Schema;
|
||||||
import lombok.Data;
|
import lombok.Data;
|
||||||
@@ -47,9 +48,11 @@ public class AuthorizeCode implements Serializable {
|
|||||||
private Integer tenantId;
|
private Integer tenantId;
|
||||||
|
|
||||||
@Schema(description = "创建时间")
|
@Schema(description = "创建时间")
|
||||||
|
@JsonFormat(pattern = "yyyy-MM-dd HH:mm:ss")
|
||||||
private Date createTime;
|
private Date createTime;
|
||||||
|
|
||||||
@Schema(description = "修改时间")
|
@Schema(description = "修改时间")
|
||||||
|
@JsonFormat(pattern = "yyyy-MM-dd HH:mm:ss")
|
||||||
private Date updateTime;
|
private Date updateTime;
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -4,6 +4,7 @@ import com.baomidou.mybatisplus.annotation.IdType;
|
|||||||
import com.baomidou.mybatisplus.annotation.TableField;
|
import com.baomidou.mybatisplus.annotation.TableField;
|
||||||
import com.baomidou.mybatisplus.annotation.TableId;
|
import com.baomidou.mybatisplus.annotation.TableId;
|
||||||
import com.baomidou.mybatisplus.annotation.TableName;
|
import com.baomidou.mybatisplus.annotation.TableName;
|
||||||
|
import com.fasterxml.jackson.annotation.JsonFormat;
|
||||||
import io.swagger.v3.oas.annotations.media.Schema;
|
import io.swagger.v3.oas.annotations.media.Schema;
|
||||||
import io.swagger.v3.oas.annotations.media.Schema;
|
import io.swagger.v3.oas.annotations.media.Schema;
|
||||||
import lombok.Data;
|
import lombok.Data;
|
||||||
@@ -83,9 +84,11 @@ public class Cart implements Serializable {
|
|||||||
private Integer tenantId;
|
private Integer tenantId;
|
||||||
|
|
||||||
@Schema(description = "创建时间")
|
@Schema(description = "创建时间")
|
||||||
|
@JsonFormat(pattern = "yyyy-MM-dd HH:mm:ss")
|
||||||
private Date createTime;
|
private Date createTime;
|
||||||
|
|
||||||
@Schema(description = "修改时间")
|
@Schema(description = "修改时间")
|
||||||
|
@JsonFormat(pattern = "yyyy-MM-dd HH:mm:ss")
|
||||||
private Date updateTime;
|
private Date updateTime;
|
||||||
|
|
||||||
@Schema(description = "商品描述")
|
@Schema(description = "商品描述")
|
||||||
|
|||||||
@@ -8,6 +8,7 @@ import com.baomidou.mybatisplus.annotation.TableLogic;
|
|||||||
import java.io.Serializable;
|
import java.io.Serializable;
|
||||||
import java.util.Date;
|
import java.util.Date;
|
||||||
|
|
||||||
|
import com.fasterxml.jackson.annotation.JsonFormat;
|
||||||
import io.swagger.v3.oas.annotations.media.Schema;
|
import io.swagger.v3.oas.annotations.media.Schema;
|
||||||
import io.swagger.v3.oas.annotations.media.Schema;
|
import io.swagger.v3.oas.annotations.media.Schema;
|
||||||
import lombok.Data;
|
import lombok.Data;
|
||||||
@@ -56,9 +57,11 @@ public class ChatConversation implements Serializable {
|
|||||||
private Integer tenantId;
|
private Integer tenantId;
|
||||||
|
|
||||||
@Schema(description = "注册时间")
|
@Schema(description = "注册时间")
|
||||||
|
@JsonFormat(pattern = "yyyy-MM-dd HH:mm:ss")
|
||||||
private Date createTime;
|
private Date createTime;
|
||||||
|
|
||||||
@Schema(description = "修改时间")
|
@Schema(description = "修改时间")
|
||||||
|
@JsonFormat(pattern = "yyyy-MM-dd HH:mm:ss")
|
||||||
private Date updateTime;
|
private Date updateTime;
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -6,6 +6,7 @@ import java.util.Date;
|
|||||||
import java.io.Serializable;
|
import java.io.Serializable;
|
||||||
import java.util.Date;
|
import java.util.Date;
|
||||||
|
|
||||||
|
import com.fasterxml.jackson.annotation.JsonFormat;
|
||||||
import io.swagger.v3.oas.annotations.media.Schema;
|
import io.swagger.v3.oas.annotations.media.Schema;
|
||||||
import io.swagger.v3.oas.annotations.media.Schema;
|
import io.swagger.v3.oas.annotations.media.Schema;
|
||||||
import lombok.Data;
|
import lombok.Data;
|
||||||
@@ -66,9 +67,11 @@ public class ChatMessage implements Serializable {
|
|||||||
private Integer tenantId;
|
private Integer tenantId;
|
||||||
|
|
||||||
@Schema(description = "注册时间")
|
@Schema(description = "注册时间")
|
||||||
|
@JsonFormat(pattern = "yyyy-MM-dd HH:mm:ss")
|
||||||
private Date createTime;
|
private Date createTime;
|
||||||
|
|
||||||
@Schema(description = "修改时间")
|
@Schema(description = "修改时间")
|
||||||
|
@JsonFormat(pattern = "yyyy-MM-dd HH:mm:ss")
|
||||||
private Date updateTime;
|
private Date updateTime;
|
||||||
|
|
||||||
@Schema(description = "发送人昵称")
|
@Schema(description = "发送人昵称")
|
||||||
|
|||||||
@@ -2,6 +2,7 @@ package com.gxwebsoft.common.system.entity;
|
|||||||
|
|
||||||
import cn.hutool.core.util.DesensitizedUtil;
|
import cn.hutool.core.util.DesensitizedUtil;
|
||||||
import com.baomidou.mybatisplus.annotation.*;
|
import com.baomidou.mybatisplus.annotation.*;
|
||||||
|
import com.fasterxml.jackson.annotation.JsonFormat;
|
||||||
import io.swagger.v3.oas.annotations.media.Schema;
|
import io.swagger.v3.oas.annotations.media.Schema;
|
||||||
import io.swagger.v3.oas.annotations.media.Schema;
|
import io.swagger.v3.oas.annotations.media.Schema;
|
||||||
import lombok.Data;
|
import lombok.Data;
|
||||||
@@ -100,9 +101,11 @@ public class Company implements Serializable {
|
|||||||
private String invoiceHeader;
|
private String invoiceHeader;
|
||||||
|
|
||||||
@Schema(description = "服务开始时间")
|
@Schema(description = "服务开始时间")
|
||||||
|
@JsonFormat(pattern = "yyyy-MM-dd HH:mm:ss")
|
||||||
private Date startTime;
|
private Date startTime;
|
||||||
|
|
||||||
@Schema(description = "服务到期时间")
|
@Schema(description = "服务到期时间")
|
||||||
|
@JsonFormat(pattern = "yyyy-MM-dd HH:mm:ss")
|
||||||
private Date expirationTime;
|
private Date expirationTime;
|
||||||
|
|
||||||
@Schema(description = "即将过期")
|
@Schema(description = "即将过期")
|
||||||
@@ -245,9 +248,11 @@ public class Company implements Serializable {
|
|||||||
private Integer deleted;
|
private Integer deleted;
|
||||||
|
|
||||||
@Schema(description = "创建时间")
|
@Schema(description = "创建时间")
|
||||||
|
@JsonFormat(pattern = "yyyy-MM-dd HH:mm:ss")
|
||||||
private Date createTime;
|
private Date createTime;
|
||||||
|
|
||||||
@Schema(description = "修改时间")
|
@Schema(description = "修改时间")
|
||||||
|
@JsonFormat(pattern = "yyyy-MM-dd HH:mm:ss")
|
||||||
private Date updateTime;
|
private Date updateTime;
|
||||||
|
|
||||||
@Schema(description = "是否默认企业主体")
|
@Schema(description = "是否默认企业主体")
|
||||||
|
|||||||
@@ -3,6 +3,7 @@ package com.gxwebsoft.common.system.entity;
|
|||||||
import com.baomidou.mybatisplus.annotation.IdType;
|
import com.baomidou.mybatisplus.annotation.IdType;
|
||||||
import com.baomidou.mybatisplus.annotation.TableId;
|
import com.baomidou.mybatisplus.annotation.TableId;
|
||||||
import com.baomidou.mybatisplus.annotation.TableName;
|
import com.baomidou.mybatisplus.annotation.TableName;
|
||||||
|
import com.fasterxml.jackson.annotation.JsonFormat;
|
||||||
import io.swagger.v3.oas.annotations.media.Schema;
|
import io.swagger.v3.oas.annotations.media.Schema;
|
||||||
import io.swagger.v3.oas.annotations.media.Schema;
|
import io.swagger.v3.oas.annotations.media.Schema;
|
||||||
import lombok.Data;
|
import lombok.Data;
|
||||||
@@ -54,6 +55,7 @@ public class CompanyComment implements Serializable {
|
|||||||
private Integer tenantId;
|
private Integer tenantId;
|
||||||
|
|
||||||
@Schema(description = "创建时间")
|
@Schema(description = "创建时间")
|
||||||
|
@JsonFormat(pattern = "yyyy-MM-dd HH:mm:ss")
|
||||||
private Date createTime;
|
private Date createTime;
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -3,6 +3,7 @@ package com.gxwebsoft.common.system.entity;
|
|||||||
import com.baomidou.mybatisplus.annotation.IdType;
|
import com.baomidou.mybatisplus.annotation.IdType;
|
||||||
import com.baomidou.mybatisplus.annotation.TableId;
|
import com.baomidou.mybatisplus.annotation.TableId;
|
||||||
import com.baomidou.mybatisplus.annotation.TableName;
|
import com.baomidou.mybatisplus.annotation.TableName;
|
||||||
|
import com.fasterxml.jackson.annotation.JsonFormat;
|
||||||
import io.swagger.v3.oas.annotations.media.Schema;
|
import io.swagger.v3.oas.annotations.media.Schema;
|
||||||
import io.swagger.v3.oas.annotations.media.Schema;
|
import io.swagger.v3.oas.annotations.media.Schema;
|
||||||
import lombok.Data;
|
import lombok.Data;
|
||||||
@@ -37,6 +38,7 @@ public class CompanyContent implements Serializable {
|
|||||||
private Integer tenantId;
|
private Integer tenantId;
|
||||||
|
|
||||||
@Schema(description = "创建时间")
|
@Schema(description = "创建时间")
|
||||||
|
@JsonFormat(pattern = "yyyy-MM-dd HH:mm:ss")
|
||||||
private Date createTime;
|
private Date createTime;
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -3,6 +3,7 @@ package com.gxwebsoft.common.system.entity;
|
|||||||
import com.baomidou.mybatisplus.annotation.IdType;
|
import com.baomidou.mybatisplus.annotation.IdType;
|
||||||
import com.baomidou.mybatisplus.annotation.TableId;
|
import com.baomidou.mybatisplus.annotation.TableId;
|
||||||
import com.baomidou.mybatisplus.annotation.TableName;
|
import com.baomidou.mybatisplus.annotation.TableName;
|
||||||
|
import com.fasterxml.jackson.annotation.JsonFormat;
|
||||||
import io.swagger.v3.oas.annotations.media.Schema;
|
import io.swagger.v3.oas.annotations.media.Schema;
|
||||||
import io.swagger.v3.oas.annotations.media.Schema;
|
import io.swagger.v3.oas.annotations.media.Schema;
|
||||||
import lombok.Data;
|
import lombok.Data;
|
||||||
@@ -59,6 +60,7 @@ public class CompanyGit implements Serializable {
|
|||||||
private Integer status;
|
private Integer status;
|
||||||
|
|
||||||
@Schema(description = "创建时间")
|
@Schema(description = "创建时间")
|
||||||
|
@JsonFormat(pattern = "yyyy-MM-dd HH:mm:ss")
|
||||||
private Date createTime;
|
private Date createTime;
|
||||||
|
|
||||||
@Schema(description = "租户id")
|
@Schema(description = "租户id")
|
||||||
|
|||||||
@@ -3,6 +3,7 @@ package com.gxwebsoft.common.system.entity;
|
|||||||
import com.baomidou.mybatisplus.annotation.IdType;
|
import com.baomidou.mybatisplus.annotation.IdType;
|
||||||
import com.baomidou.mybatisplus.annotation.TableId;
|
import com.baomidou.mybatisplus.annotation.TableId;
|
||||||
import com.baomidou.mybatisplus.annotation.TableName;
|
import com.baomidou.mybatisplus.annotation.TableName;
|
||||||
|
import com.fasterxml.jackson.annotation.JsonFormat;
|
||||||
import io.swagger.v3.oas.annotations.media.Schema;
|
import io.swagger.v3.oas.annotations.media.Schema;
|
||||||
import io.swagger.v3.oas.annotations.media.Schema;
|
import io.swagger.v3.oas.annotations.media.Schema;
|
||||||
import lombok.Data;
|
import lombok.Data;
|
||||||
@@ -47,6 +48,7 @@ public class CompanyParameter implements Serializable {
|
|||||||
private Integer status;
|
private Integer status;
|
||||||
|
|
||||||
@Schema(description = "创建时间")
|
@Schema(description = "创建时间")
|
||||||
|
@JsonFormat(pattern = "yyyy-MM-dd HH:mm:ss")
|
||||||
private Date createTime;
|
private Date createTime;
|
||||||
|
|
||||||
@Schema(description = "租户id")
|
@Schema(description = "租户id")
|
||||||
|
|||||||
@@ -3,6 +3,7 @@ package com.gxwebsoft.common.system.entity;
|
|||||||
import com.baomidou.mybatisplus.annotation.IdType;
|
import com.baomidou.mybatisplus.annotation.IdType;
|
||||||
import com.baomidou.mybatisplus.annotation.TableId;
|
import com.baomidou.mybatisplus.annotation.TableId;
|
||||||
import com.baomidou.mybatisplus.annotation.TableName;
|
import com.baomidou.mybatisplus.annotation.TableName;
|
||||||
|
import com.fasterxml.jackson.annotation.JsonFormat;
|
||||||
import io.swagger.v3.oas.annotations.media.Schema;
|
import io.swagger.v3.oas.annotations.media.Schema;
|
||||||
import io.swagger.v3.oas.annotations.media.Schema;
|
import io.swagger.v3.oas.annotations.media.Schema;
|
||||||
import lombok.Data;
|
import lombok.Data;
|
||||||
@@ -56,6 +57,7 @@ public class CompanyUrl implements Serializable {
|
|||||||
private Integer status;
|
private Integer status;
|
||||||
|
|
||||||
@Schema(description = "创建时间")
|
@Schema(description = "创建时间")
|
||||||
|
@JsonFormat(pattern = "yyyy-MM-dd HH:mm:ss")
|
||||||
private Date createTime;
|
private Date createTime;
|
||||||
|
|
||||||
@Schema(description = "租户id")
|
@Schema(description = "租户id")
|
||||||
|
|||||||
@@ -7,6 +7,7 @@ import java.util.Date;
|
|||||||
import java.io.Serializable;
|
import java.io.Serializable;
|
||||||
import java.util.Date;
|
import java.util.Date;
|
||||||
|
|
||||||
|
import com.fasterxml.jackson.annotation.JsonFormat;
|
||||||
import io.swagger.v3.oas.annotations.media.Schema;
|
import io.swagger.v3.oas.annotations.media.Schema;
|
||||||
import io.swagger.v3.oas.annotations.media.Schema;
|
import io.swagger.v3.oas.annotations.media.Schema;
|
||||||
import lombok.Data;
|
import lombok.Data;
|
||||||
@@ -66,6 +67,7 @@ public class Components implements Serializable {
|
|||||||
private Integer tenantId;
|
private Integer tenantId;
|
||||||
|
|
||||||
@Schema(description = "创建时间")
|
@Schema(description = "创建时间")
|
||||||
|
@JsonFormat(pattern = "yyyy-MM-dd HH:mm:ss")
|
||||||
private Date createTime;
|
private Date createTime;
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,6 +1,7 @@
|
|||||||
package com.gxwebsoft.common.system.entity;
|
package com.gxwebsoft.common.system.entity;
|
||||||
|
|
||||||
import com.baomidou.mybatisplus.annotation.*;
|
import com.baomidou.mybatisplus.annotation.*;
|
||||||
|
import com.fasterxml.jackson.annotation.JsonFormat;
|
||||||
import io.swagger.v3.oas.annotations.media.Schema;
|
import io.swagger.v3.oas.annotations.media.Schema;
|
||||||
import io.swagger.v3.oas.annotations.media.Schema;
|
import io.swagger.v3.oas.annotations.media.Schema;
|
||||||
import lombok.Data;
|
import lombok.Data;
|
||||||
@@ -42,9 +43,11 @@ public class Dict implements Serializable {
|
|||||||
private Integer deleted;
|
private Integer deleted;
|
||||||
|
|
||||||
@Schema(description = "创建时间")
|
@Schema(description = "创建时间")
|
||||||
|
@JsonFormat(pattern = "yyyy-MM-dd HH:mm:ss")
|
||||||
private Date createTime;
|
private Date createTime;
|
||||||
|
|
||||||
@Schema(description = "修改时间")
|
@Schema(description = "修改时间")
|
||||||
|
@JsonFormat(pattern = "yyyy-MM-dd HH:mm:ss")
|
||||||
private Date updateTime;
|
private Date updateTime;
|
||||||
|
|
||||||
@Schema(description = "租户id")
|
@Schema(description = "租户id")
|
||||||
|
|||||||
@@ -1,6 +1,7 @@
|
|||||||
package com.gxwebsoft.common.system.entity;
|
package com.gxwebsoft.common.system.entity;
|
||||||
|
|
||||||
import com.baomidou.mybatisplus.annotation.*;
|
import com.baomidou.mybatisplus.annotation.*;
|
||||||
|
import com.fasterxml.jackson.annotation.JsonFormat;
|
||||||
import io.swagger.v3.oas.annotations.media.Schema;
|
import io.swagger.v3.oas.annotations.media.Schema;
|
||||||
import io.swagger.v3.oas.annotations.media.Schema;
|
import io.swagger.v3.oas.annotations.media.Schema;
|
||||||
import lombok.Data;
|
import lombok.Data;
|
||||||
@@ -62,9 +63,11 @@ public class DictData implements Serializable {
|
|||||||
private Integer deleted;
|
private Integer deleted;
|
||||||
|
|
||||||
@Schema(description = "创建时间")
|
@Schema(description = "创建时间")
|
||||||
|
@JsonFormat(pattern = "yyyy-MM-dd HH:mm:ss")
|
||||||
private Date createTime;
|
private Date createTime;
|
||||||
|
|
||||||
@Schema(description = "修改时间")
|
@Schema(description = "修改时间")
|
||||||
|
@JsonFormat(pattern = "yyyy-MM-dd HH:mm:ss")
|
||||||
private Date updateTime;
|
private Date updateTime;
|
||||||
|
|
||||||
@Schema(description = "字典代码")
|
@Schema(description = "字典代码")
|
||||||
|
|||||||
@@ -8,6 +8,7 @@ import com.baomidou.mybatisplus.annotation.TableLogic;
|
|||||||
import java.util.Date;
|
import java.util.Date;
|
||||||
import java.io.Serializable;
|
import java.io.Serializable;
|
||||||
|
|
||||||
|
import com.fasterxml.jackson.annotation.JsonFormat;
|
||||||
import io.swagger.v3.oas.annotations.media.Schema;
|
import io.swagger.v3.oas.annotations.media.Schema;
|
||||||
import io.swagger.v3.oas.annotations.media.Schema;
|
import io.swagger.v3.oas.annotations.media.Schema;
|
||||||
import lombok.Data;
|
import lombok.Data;
|
||||||
@@ -45,9 +46,11 @@ public class Dictionary implements Serializable {
|
|||||||
private Integer deleted;
|
private Integer deleted;
|
||||||
|
|
||||||
@Schema(description = "创建时间")
|
@Schema(description = "创建时间")
|
||||||
|
@JsonFormat(pattern = "yyyy-MM-dd HH:mm:ss")
|
||||||
private Date createTime;
|
private Date createTime;
|
||||||
|
|
||||||
@Schema(description = "修改时间")
|
@Schema(description = "修改时间")
|
||||||
|
@JsonFormat(pattern = "yyyy-MM-dd HH:mm:ss")
|
||||||
private Date updateTime;
|
private Date updateTime;
|
||||||
|
|
||||||
@Schema(description = "租户id")
|
@Schema(description = "租户id")
|
||||||
|
|||||||
@@ -5,6 +5,7 @@ import com.baomidou.mybatisplus.annotation.*;
|
|||||||
import java.util.Date;
|
import java.util.Date;
|
||||||
import java.io.Serializable;
|
import java.io.Serializable;
|
||||||
|
|
||||||
|
import com.fasterxml.jackson.annotation.JsonFormat;
|
||||||
import io.swagger.v3.oas.annotations.media.Schema;
|
import io.swagger.v3.oas.annotations.media.Schema;
|
||||||
import io.swagger.v3.oas.annotations.media.Schema;
|
import io.swagger.v3.oas.annotations.media.Schema;
|
||||||
import lombok.Data;
|
import lombok.Data;
|
||||||
@@ -51,9 +52,11 @@ public class DictionaryData implements Serializable {
|
|||||||
private Integer deleted;
|
private Integer deleted;
|
||||||
|
|
||||||
@Schema(description = "创建时间")
|
@Schema(description = "创建时间")
|
||||||
|
@JsonFormat(pattern = "yyyy-MM-dd HH:mm:ss")
|
||||||
private Date createTime;
|
private Date createTime;
|
||||||
|
|
||||||
@Schema(description = "修改时间")
|
@Schema(description = "修改时间")
|
||||||
|
@JsonFormat(pattern = "yyyy-MM-dd HH:mm:ss")
|
||||||
private Date updateTime;
|
private Date updateTime;
|
||||||
|
|
||||||
@Schema(description = "字典代码")
|
@Schema(description = "字典代码")
|
||||||
|
|||||||
@@ -3,6 +3,7 @@ package com.gxwebsoft.common.system.entity;
|
|||||||
import com.baomidou.mybatisplus.annotation.IdType;
|
import com.baomidou.mybatisplus.annotation.IdType;
|
||||||
import com.baomidou.mybatisplus.annotation.TableId;
|
import com.baomidou.mybatisplus.annotation.TableId;
|
||||||
import com.baomidou.mybatisplus.annotation.TableName;
|
import com.baomidou.mybatisplus.annotation.TableName;
|
||||||
|
import com.fasterxml.jackson.annotation.JsonFormat;
|
||||||
import io.swagger.v3.oas.annotations.media.Schema;
|
import io.swagger.v3.oas.annotations.media.Schema;
|
||||||
import io.swagger.v3.oas.annotations.media.Schema;
|
import io.swagger.v3.oas.annotations.media.Schema;
|
||||||
import lombok.Data;
|
import lombok.Data;
|
||||||
@@ -48,9 +49,11 @@ public class EmailRecord implements Serializable {
|
|||||||
private Integer tenantId;
|
private Integer tenantId;
|
||||||
|
|
||||||
@Schema(description = "创建时间")
|
@Schema(description = "创建时间")
|
||||||
|
@JsonFormat(pattern = "yyyy-MM-dd HH:mm:ss")
|
||||||
private Date createTime;
|
private Date createTime;
|
||||||
|
|
||||||
@Schema(description = "修改时间")
|
@Schema(description = "修改时间")
|
||||||
|
@JsonFormat(pattern = "yyyy-MM-dd HH:mm:ss")
|
||||||
private Date updateTime;
|
private Date updateTime;
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -8,6 +8,7 @@ import com.baomidou.mybatisplus.annotation.TableLogic;
|
|||||||
import java.io.Serializable;
|
import java.io.Serializable;
|
||||||
import java.util.Date;
|
import java.util.Date;
|
||||||
|
|
||||||
|
import com.fasterxml.jackson.annotation.JsonFormat;
|
||||||
import io.swagger.v3.oas.annotations.media.Schema;
|
import io.swagger.v3.oas.annotations.media.Schema;
|
||||||
import io.swagger.v3.oas.annotations.media.Schema;
|
import io.swagger.v3.oas.annotations.media.Schema;
|
||||||
import lombok.Data;
|
import lombok.Data;
|
||||||
@@ -68,9 +69,11 @@ public class Environment implements Serializable {
|
|||||||
private Integer tenantId;
|
private Integer tenantId;
|
||||||
|
|
||||||
@Schema(description = "创建时间")
|
@Schema(description = "创建时间")
|
||||||
|
@JsonFormat(pattern = "yyyy-MM-dd HH:mm:ss")
|
||||||
private Date createTime;
|
private Date createTime;
|
||||||
|
|
||||||
@Schema(description = "修改时间")
|
@Schema(description = "修改时间")
|
||||||
|
@JsonFormat(pattern = "yyyy-MM-dd HH:mm:ss")
|
||||||
private Date updateTime;
|
private Date updateTime;
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -2,6 +2,7 @@ package com.gxwebsoft.common.system.entity;
|
|||||||
|
|
||||||
import cn.hutool.core.util.DesensitizedUtil;
|
import cn.hutool.core.util.DesensitizedUtil;
|
||||||
import com.baomidou.mybatisplus.annotation.*;
|
import com.baomidou.mybatisplus.annotation.*;
|
||||||
|
import com.fasterxml.jackson.annotation.JsonFormat;
|
||||||
import io.swagger.v3.oas.annotations.media.Schema;
|
import io.swagger.v3.oas.annotations.media.Schema;
|
||||||
import io.swagger.v3.oas.annotations.media.Schema;
|
import io.swagger.v3.oas.annotations.media.Schema;
|
||||||
import lombok.Data;
|
import lombok.Data;
|
||||||
@@ -70,9 +71,11 @@ public class FileRecord implements Serializable {
|
|||||||
private Integer tenantId;
|
private Integer tenantId;
|
||||||
|
|
||||||
@Schema(description = "创建时间")
|
@Schema(description = "创建时间")
|
||||||
|
@JsonFormat(pattern = "yyyy-MM-dd HH:mm:ss")
|
||||||
private Date createTime;
|
private Date createTime;
|
||||||
|
|
||||||
@Schema(description = "修改时间")
|
@Schema(description = "修改时间")
|
||||||
|
@JsonFormat(pattern = "yyyy-MM-dd HH:mm:ss")
|
||||||
private Date updateTime;
|
private Date updateTime;
|
||||||
|
|
||||||
@Schema(description = "文件访问地址")
|
@Schema(description = "文件访问地址")
|
||||||
|
|||||||
@@ -4,6 +4,7 @@ import com.baomidou.mybatisplus.annotation.IdType;
|
|||||||
import com.baomidou.mybatisplus.annotation.TableField;
|
import com.baomidou.mybatisplus.annotation.TableField;
|
||||||
import com.baomidou.mybatisplus.annotation.TableId;
|
import com.baomidou.mybatisplus.annotation.TableId;
|
||||||
import com.baomidou.mybatisplus.annotation.TableName;
|
import com.baomidou.mybatisplus.annotation.TableName;
|
||||||
|
import com.fasterxml.jackson.annotation.JsonFormat;
|
||||||
import io.swagger.v3.oas.annotations.media.Schema;
|
import io.swagger.v3.oas.annotations.media.Schema;
|
||||||
import io.swagger.v3.oas.annotations.media.Schema;
|
import io.swagger.v3.oas.annotations.media.Schema;
|
||||||
import lombok.Data;
|
import lombok.Data;
|
||||||
@@ -57,9 +58,11 @@ public class LoginRecord implements Serializable {
|
|||||||
private Integer tenantId;
|
private Integer tenantId;
|
||||||
|
|
||||||
@Schema(description = "操作时间")
|
@Schema(description = "操作时间")
|
||||||
|
@JsonFormat(pattern = "yyyy-MM-dd HH:mm:ss")
|
||||||
private Date createTime;
|
private Date createTime;
|
||||||
|
|
||||||
@Schema(description = "修改时间")
|
@Schema(description = "修改时间")
|
||||||
|
@JsonFormat(pattern = "yyyy-MM-dd HH:mm:ss")
|
||||||
private Date updateTime;
|
private Date updateTime;
|
||||||
|
|
||||||
@Schema(description = "用户id")
|
@Schema(description = "用户id")
|
||||||
|
|||||||
@@ -1,6 +1,7 @@
|
|||||||
package com.gxwebsoft.common.system.entity;
|
package com.gxwebsoft.common.system.entity;
|
||||||
|
|
||||||
import com.baomidou.mybatisplus.annotation.*;
|
import com.baomidou.mybatisplus.annotation.*;
|
||||||
|
import com.fasterxml.jackson.annotation.JsonFormat;
|
||||||
import com.fasterxml.jackson.annotation.JsonIgnoreProperties;
|
import com.fasterxml.jackson.annotation.JsonIgnoreProperties;
|
||||||
import io.swagger.v3.oas.annotations.media.Schema;
|
import io.swagger.v3.oas.annotations.media.Schema;
|
||||||
import io.swagger.v3.oas.annotations.media.Schema;
|
import io.swagger.v3.oas.annotations.media.Schema;
|
||||||
@@ -80,9 +81,11 @@ public class Menu implements GrantedAuthority {
|
|||||||
private Integer tenantId;
|
private Integer tenantId;
|
||||||
|
|
||||||
@Schema(description = "创建时间")
|
@Schema(description = "创建时间")
|
||||||
|
@JsonFormat(pattern = "yyyy-MM-dd HH:mm:ss")
|
||||||
private Date createTime;
|
private Date createTime;
|
||||||
|
|
||||||
@Schema(description = "修改时间")
|
@Schema(description = "修改时间")
|
||||||
|
@JsonFormat(pattern = "yyyy-MM-dd HH:mm:ss")
|
||||||
private Date updateTime;
|
private Date updateTime;
|
||||||
|
|
||||||
@Schema(description = "子菜单")
|
@Schema(description = "子菜单")
|
||||||
|
|||||||
@@ -1,6 +1,7 @@
|
|||||||
package com.gxwebsoft.common.system.entity;
|
package com.gxwebsoft.common.system.entity;
|
||||||
|
|
||||||
import com.baomidou.mybatisplus.annotation.*;
|
import com.baomidou.mybatisplus.annotation.*;
|
||||||
|
import com.fasterxml.jackson.annotation.JsonFormat;
|
||||||
import io.swagger.v3.oas.annotations.media.Schema;
|
import io.swagger.v3.oas.annotations.media.Schema;
|
||||||
import io.swagger.v3.oas.annotations.media.Schema;
|
import io.swagger.v3.oas.annotations.media.Schema;
|
||||||
import lombok.Data;
|
import lombok.Data;
|
||||||
@@ -113,6 +114,7 @@ public class Merchant implements Serializable {
|
|||||||
private Integer tenantId;
|
private Integer tenantId;
|
||||||
|
|
||||||
@Schema(description = "创建时间")
|
@Schema(description = "创建时间")
|
||||||
|
@JsonFormat(pattern = "yyyy-MM-dd HH:mm:ss")
|
||||||
private Date createTime;
|
private Date createTime;
|
||||||
|
|
||||||
@Schema(description = "默认商户管理员角色ID")
|
@Schema(description = "默认商户管理员角色ID")
|
||||||
|
|||||||
@@ -5,6 +5,7 @@ import com.baomidou.mybatisplus.annotation.IdType;
|
|||||||
import com.baomidou.mybatisplus.annotation.TableField;
|
import com.baomidou.mybatisplus.annotation.TableField;
|
||||||
import com.baomidou.mybatisplus.annotation.TableId;
|
import com.baomidou.mybatisplus.annotation.TableId;
|
||||||
import com.baomidou.mybatisplus.annotation.TableName;
|
import com.baomidou.mybatisplus.annotation.TableName;
|
||||||
|
import com.fasterxml.jackson.annotation.JsonFormat;
|
||||||
import io.swagger.v3.oas.annotations.media.Schema;
|
import io.swagger.v3.oas.annotations.media.Schema;
|
||||||
import io.swagger.v3.oas.annotations.media.Schema;
|
import io.swagger.v3.oas.annotations.media.Schema;
|
||||||
import lombok.Data;
|
import lombok.Data;
|
||||||
@@ -65,6 +66,7 @@ public class MerchantAccount implements Serializable {
|
|||||||
private Integer tenantId;
|
private Integer tenantId;
|
||||||
|
|
||||||
@Schema(description = "创建时间")
|
@Schema(description = "创建时间")
|
||||||
|
@JsonFormat(pattern = "yyyy-MM-dd HH:mm:ss")
|
||||||
private Date createTime;
|
private Date createTime;
|
||||||
|
|
||||||
@Schema(description = "商户名称")
|
@Schema(description = "商户名称")
|
||||||
|
|||||||
@@ -3,6 +3,7 @@ package com.gxwebsoft.common.system.entity;
|
|||||||
import com.baomidou.mybatisplus.annotation.IdType;
|
import com.baomidou.mybatisplus.annotation.IdType;
|
||||||
import com.baomidou.mybatisplus.annotation.TableId;
|
import com.baomidou.mybatisplus.annotation.TableId;
|
||||||
import com.baomidou.mybatisplus.annotation.TableName;
|
import com.baomidou.mybatisplus.annotation.TableName;
|
||||||
|
import com.fasterxml.jackson.annotation.JsonFormat;
|
||||||
import io.swagger.v3.oas.annotations.media.Schema;
|
import io.swagger.v3.oas.annotations.media.Schema;
|
||||||
import io.swagger.v3.oas.annotations.media.Schema;
|
import io.swagger.v3.oas.annotations.media.Schema;
|
||||||
import lombok.Data;
|
import lombok.Data;
|
||||||
@@ -81,6 +82,7 @@ public class MerchantApply implements Serializable {
|
|||||||
private Integer tenantId;
|
private Integer tenantId;
|
||||||
|
|
||||||
@Schema(description = "创建时间")
|
@Schema(description = "创建时间")
|
||||||
|
@JsonFormat(pattern = "yyyy-MM-dd HH:mm:ss")
|
||||||
private Date createTime;
|
private Date createTime;
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -3,6 +3,7 @@ package com.gxwebsoft.common.system.entity;
|
|||||||
import com.baomidou.mybatisplus.annotation.IdType;
|
import com.baomidou.mybatisplus.annotation.IdType;
|
||||||
import com.baomidou.mybatisplus.annotation.TableId;
|
import com.baomidou.mybatisplus.annotation.TableId;
|
||||||
import com.baomidou.mybatisplus.annotation.TableName;
|
import com.baomidou.mybatisplus.annotation.TableName;
|
||||||
|
import com.fasterxml.jackson.annotation.JsonFormat;
|
||||||
import io.swagger.v3.oas.annotations.media.Schema;
|
import io.swagger.v3.oas.annotations.media.Schema;
|
||||||
import io.swagger.v3.oas.annotations.media.Schema;
|
import io.swagger.v3.oas.annotations.media.Schema;
|
||||||
import lombok.Data;
|
import lombok.Data;
|
||||||
@@ -44,6 +45,7 @@ public class MerchantType implements Serializable {
|
|||||||
private Integer tenantId;
|
private Integer tenantId;
|
||||||
|
|
||||||
@Schema(description = "创建时间")
|
@Schema(description = "创建时间")
|
||||||
|
@JsonFormat(pattern = "yyyy-MM-dd HH:mm:ss")
|
||||||
private Date createTime;
|
private Date createTime;
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -7,6 +7,7 @@ import com.baomidou.mybatisplus.annotation.TableLogic;
|
|||||||
import java.io.Serializable;
|
import java.io.Serializable;
|
||||||
import java.util.Date;
|
import java.util.Date;
|
||||||
|
|
||||||
|
import com.fasterxml.jackson.annotation.JsonFormat;
|
||||||
import io.swagger.v3.oas.annotations.media.Schema;
|
import io.swagger.v3.oas.annotations.media.Schema;
|
||||||
import io.swagger.v3.oas.annotations.media.Schema;
|
import io.swagger.v3.oas.annotations.media.Schema;
|
||||||
import lombok.Data;
|
import lombok.Data;
|
||||||
@@ -55,6 +56,7 @@ public class Modules implements Serializable {
|
|||||||
private Integer tenantId;
|
private Integer tenantId;
|
||||||
|
|
||||||
@Schema(description = "创建时间")
|
@Schema(description = "创建时间")
|
||||||
|
@JsonFormat(pattern = "yyyy-MM-dd HH:mm:ss")
|
||||||
private Date createTime;
|
private Date createTime;
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,6 +1,7 @@
|
|||||||
package com.gxwebsoft.common.system.entity;
|
package com.gxwebsoft.common.system.entity;
|
||||||
|
|
||||||
import com.baomidou.mybatisplus.annotation.*;
|
import com.baomidou.mybatisplus.annotation.*;
|
||||||
|
import com.fasterxml.jackson.annotation.JsonFormat;
|
||||||
import io.swagger.v3.oas.annotations.media.Schema;
|
import io.swagger.v3.oas.annotations.media.Schema;
|
||||||
import io.swagger.v3.oas.annotations.media.Schema;
|
import io.swagger.v3.oas.annotations.media.Schema;
|
||||||
import lombok.Data;
|
import lombok.Data;
|
||||||
@@ -69,6 +70,7 @@ public class Mp implements Serializable {
|
|||||||
private String mainPath;
|
private String mainPath;
|
||||||
|
|
||||||
@Schema(description = "过期时间")
|
@Schema(description = "过期时间")
|
||||||
|
@JsonFormat(pattern = "yyyy-MM-dd HH:mm:ss")
|
||||||
private Date expirationTime;
|
private Date expirationTime;
|
||||||
|
|
||||||
@Schema(description = "排序(数字越小越靠前)")
|
@Schema(description = "排序(数字越小越靠前)")
|
||||||
@@ -91,6 +93,7 @@ public class Mp implements Serializable {
|
|||||||
private Integer tenantId;
|
private Integer tenantId;
|
||||||
|
|
||||||
@Schema(description = "注册时间")
|
@Schema(description = "注册时间")
|
||||||
|
@JsonFormat(pattern = "yyyy-MM-dd HH:mm:ss")
|
||||||
private Date createTime;
|
private Date createTime;
|
||||||
|
|
||||||
@Schema(description = "登录凭证")
|
@Schema(description = "登录凭证")
|
||||||
|
|||||||
@@ -6,6 +6,7 @@ import java.util.Date;
|
|||||||
import java.io.Serializable;
|
import java.io.Serializable;
|
||||||
import java.util.Date;
|
import java.util.Date;
|
||||||
|
|
||||||
|
import com.fasterxml.jackson.annotation.JsonFormat;
|
||||||
import io.swagger.v3.oas.annotations.media.Schema;
|
import io.swagger.v3.oas.annotations.media.Schema;
|
||||||
import io.swagger.v3.oas.annotations.media.Schema;
|
import io.swagger.v3.oas.annotations.media.Schema;
|
||||||
import lombok.Data;
|
import lombok.Data;
|
||||||
@@ -78,9 +79,11 @@ public class Notice implements Serializable {
|
|||||||
private Integer tenantId;
|
private Integer tenantId;
|
||||||
|
|
||||||
@Schema(description = "注册时间")
|
@Schema(description = "注册时间")
|
||||||
|
@JsonFormat(pattern = "yyyy-MM-dd HH:mm:ss")
|
||||||
private Date createTime;
|
private Date createTime;
|
||||||
|
|
||||||
@Schema(description = "修改时间")
|
@Schema(description = "修改时间")
|
||||||
|
@JsonFormat(pattern = "yyyy-MM-dd HH:mm:ss")
|
||||||
private Date updateTime;
|
private Date updateTime;
|
||||||
|
|
||||||
@Schema(description = "开发者名称")
|
@Schema(description = "开发者名称")
|
||||||
|
|||||||
@@ -4,6 +4,7 @@ import com.baomidou.mybatisplus.annotation.IdType;
|
|||||||
import com.baomidou.mybatisplus.annotation.TableField;
|
import com.baomidou.mybatisplus.annotation.TableField;
|
||||||
import com.baomidou.mybatisplus.annotation.TableId;
|
import com.baomidou.mybatisplus.annotation.TableId;
|
||||||
import com.baomidou.mybatisplus.annotation.TableName;
|
import com.baomidou.mybatisplus.annotation.TableName;
|
||||||
|
import com.fasterxml.jackson.annotation.JsonFormat;
|
||||||
import io.swagger.v3.oas.annotations.media.Schema;
|
import io.swagger.v3.oas.annotations.media.Schema;
|
||||||
import io.swagger.v3.oas.annotations.media.Schema;
|
import io.swagger.v3.oas.annotations.media.Schema;
|
||||||
import lombok.Data;
|
import lombok.Data;
|
||||||
@@ -79,9 +80,11 @@ public class OperationRecord implements Serializable {
|
|||||||
private Integer tenantId;
|
private Integer tenantId;
|
||||||
|
|
||||||
@Schema(description = "操作时间")
|
@Schema(description = "操作时间")
|
||||||
|
@JsonFormat(pattern = "yyyy-MM-dd HH:mm:ss")
|
||||||
private Date createTime;
|
private Date createTime;
|
||||||
|
|
||||||
@Schema(description = "修改时间")
|
@Schema(description = "修改时间")
|
||||||
|
@JsonFormat(pattern = "yyyy-MM-dd HH:mm:ss")
|
||||||
private Date updateTime;
|
private Date updateTime;
|
||||||
|
|
||||||
@Schema(description = "用户昵称")
|
@Schema(description = "用户昵称")
|
||||||
|
|||||||
@@ -1,6 +1,7 @@
|
|||||||
package com.gxwebsoft.common.system.entity;
|
package com.gxwebsoft.common.system.entity;
|
||||||
|
|
||||||
import com.baomidou.mybatisplus.annotation.*;
|
import com.baomidou.mybatisplus.annotation.*;
|
||||||
|
import com.fasterxml.jackson.annotation.JsonFormat;
|
||||||
import com.gxwebsoft.common.system.param.MenuParam;
|
import com.gxwebsoft.common.system.param.MenuParam;
|
||||||
import io.swagger.v3.oas.annotations.media.Schema;
|
import io.swagger.v3.oas.annotations.media.Schema;
|
||||||
import io.swagger.v3.oas.annotations.media.Schema;
|
import io.swagger.v3.oas.annotations.media.Schema;
|
||||||
@@ -102,15 +103,19 @@ public class Order implements Serializable {
|
|||||||
private String invoiceNo;
|
private String invoiceNo;
|
||||||
|
|
||||||
@Schema(description = "支付时间")
|
@Schema(description = "支付时间")
|
||||||
|
@JsonFormat(pattern = "yyyy-MM-dd HH:mm:ss")
|
||||||
private Date payTime;
|
private Date payTime;
|
||||||
|
|
||||||
@Schema(description = "退款时间")
|
@Schema(description = "退款时间")
|
||||||
|
@JsonFormat(pattern = "yyyy-MM-dd HH:mm:ss")
|
||||||
private Date refundTime;
|
private Date refundTime;
|
||||||
|
|
||||||
@Schema(description = "申请退款时间")
|
@Schema(description = "申请退款时间")
|
||||||
|
@JsonFormat(pattern = "yyyy-MM-dd HH:mm:ss")
|
||||||
private Date refundApplyTime;
|
private Date refundApplyTime;
|
||||||
|
|
||||||
@Schema(description = "过期时间")
|
@Schema(description = "过期时间")
|
||||||
|
@JsonFormat(pattern = "yyyy-MM-dd HH:mm:ss")
|
||||||
private Date expirationTime;
|
private Date expirationTime;
|
||||||
|
|
||||||
@Schema(description = "对账情况:0=未对账;1=已对账;3=已对账,金额对不上;4=未查询到该订单")
|
@Schema(description = "对账情况:0=未对账;1=已对账;3=已对账,金额对不上;4=未查询到该订单")
|
||||||
@@ -142,9 +147,11 @@ public class Order implements Serializable {
|
|||||||
private Integer tenantId;
|
private Integer tenantId;
|
||||||
|
|
||||||
@Schema(description = "修改时间")
|
@Schema(description = "修改时间")
|
||||||
|
@JsonFormat(pattern = "yyyy-MM-dd HH:mm:ss")
|
||||||
private Date updateTime;
|
private Date updateTime;
|
||||||
|
|
||||||
@Schema(description = "创建时间")
|
@Schema(description = "创建时间")
|
||||||
|
@JsonFormat(pattern = "yyyy-MM-dd HH:mm:ss")
|
||||||
private Date createTime;
|
private Date createTime;
|
||||||
|
|
||||||
@Schema(description = "购买时长")
|
@Schema(description = "购买时长")
|
||||||
|
|||||||
@@ -1,6 +1,7 @@
|
|||||||
package com.gxwebsoft.common.system.entity;
|
package com.gxwebsoft.common.system.entity;
|
||||||
|
|
||||||
import com.baomidou.mybatisplus.annotation.*;
|
import com.baomidou.mybatisplus.annotation.*;
|
||||||
|
import com.fasterxml.jackson.annotation.JsonFormat;
|
||||||
import io.swagger.v3.oas.annotations.media.Schema;
|
import io.swagger.v3.oas.annotations.media.Schema;
|
||||||
import io.swagger.v3.oas.annotations.media.Schema;
|
import io.swagger.v3.oas.annotations.media.Schema;
|
||||||
import lombok.Data;
|
import lombok.Data;
|
||||||
@@ -64,9 +65,11 @@ public class OrderGoods implements Serializable {
|
|||||||
private String invoiceNo;
|
private String invoiceNo;
|
||||||
|
|
||||||
@Schema(description = "支付时间")
|
@Schema(description = "支付时间")
|
||||||
|
@JsonFormat(pattern = "yyyy-MM-dd HH:mm:ss")
|
||||||
private Date payTime;
|
private Date payTime;
|
||||||
|
|
||||||
@Schema(description = "过期时间")
|
@Schema(description = "过期时间")
|
||||||
|
@JsonFormat(pattern = "yyyy-MM-dd HH:mm:ss")
|
||||||
private Date expirationTime;
|
private Date expirationTime;
|
||||||
|
|
||||||
@Schema(description = "用户id")
|
@Schema(description = "用户id")
|
||||||
@@ -92,9 +95,11 @@ public class OrderGoods implements Serializable {
|
|||||||
private Integer tenantId;
|
private Integer tenantId;
|
||||||
|
|
||||||
@Schema(description = "修改时间")
|
@Schema(description = "修改时间")
|
||||||
|
@JsonFormat(pattern = "yyyy-MM-dd HH:mm:ss")
|
||||||
private Date updateTime;
|
private Date updateTime;
|
||||||
|
|
||||||
@Schema(description = "创建时间")
|
@Schema(description = "创建时间")
|
||||||
|
@JsonFormat(pattern = "yyyy-MM-dd HH:mm:ss")
|
||||||
private Date createTime;
|
private Date createTime;
|
||||||
|
|
||||||
@Schema(description = "应用名称")
|
@Schema(description = "应用名称")
|
||||||
|
|||||||
@@ -8,6 +8,7 @@ import com.baomidou.mybatisplus.annotation.TableLogic;
|
|||||||
import java.io.Serializable;
|
import java.io.Serializable;
|
||||||
import java.util.Date;
|
import java.util.Date;
|
||||||
|
|
||||||
|
import com.fasterxml.jackson.annotation.JsonFormat;
|
||||||
import io.swagger.v3.oas.annotations.media.Schema;
|
import io.swagger.v3.oas.annotations.media.Schema;
|
||||||
import io.swagger.v3.oas.annotations.media.Schema;
|
import io.swagger.v3.oas.annotations.media.Schema;
|
||||||
import lombok.Data;
|
import lombok.Data;
|
||||||
@@ -94,9 +95,11 @@ public class OrderInfo implements Serializable {
|
|||||||
private Integer tenantId;
|
private Integer tenantId;
|
||||||
|
|
||||||
@Schema(description = "创建时间")
|
@Schema(description = "创建时间")
|
||||||
|
@JsonFormat(pattern = "yyyy-MM-dd HH:mm:ss")
|
||||||
private Date createTime;
|
private Date createTime;
|
||||||
|
|
||||||
@Schema(description = "修改时间")
|
@Schema(description = "修改时间")
|
||||||
|
@JsonFormat(pattern = "yyyy-MM-dd HH:mm:ss")
|
||||||
private Date updateTime;
|
private Date updateTime;
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -6,6 +6,7 @@ import java.math.BigDecimal;
|
|||||||
import java.util.Date;
|
import java.util.Date;
|
||||||
import java.io.Serializable;
|
import java.io.Serializable;
|
||||||
|
|
||||||
|
import com.fasterxml.jackson.annotation.JsonFormat;
|
||||||
import io.swagger.v3.oas.annotations.media.Schema;
|
import io.swagger.v3.oas.annotations.media.Schema;
|
||||||
import io.swagger.v3.oas.annotations.media.Schema;
|
import io.swagger.v3.oas.annotations.media.Schema;
|
||||||
import lombok.Data;
|
import lombok.Data;
|
||||||
@@ -69,6 +70,7 @@ public class Organization implements Serializable {
|
|||||||
private String email;
|
private String email;
|
||||||
|
|
||||||
@Schema(description = "成立时间")
|
@Schema(description = "成立时间")
|
||||||
|
@JsonFormat(pattern = "yyyy-MM-dd HH:mm:ss")
|
||||||
private Date establishTime;
|
private Date establishTime;
|
||||||
|
|
||||||
@Schema(description = "注册资金")
|
@Schema(description = "注册资金")
|
||||||
@@ -121,9 +123,11 @@ public class Organization implements Serializable {
|
|||||||
private Integer tenantId;
|
private Integer tenantId;
|
||||||
|
|
||||||
@Schema(description = "创建时间")
|
@Schema(description = "创建时间")
|
||||||
|
@JsonFormat(pattern = "yyyy-MM-dd HH:mm:ss")
|
||||||
private Date createTime;
|
private Date createTime;
|
||||||
|
|
||||||
@Schema(description = "修改时间")
|
@Schema(description = "修改时间")
|
||||||
|
@JsonFormat(pattern = "yyyy-MM-dd HH:mm:ss")
|
||||||
private Date updateTime;
|
private Date updateTime;
|
||||||
|
|
||||||
@Schema(description = "机构类型名称")
|
@Schema(description = "机构类型名称")
|
||||||
|
|||||||
@@ -8,6 +8,7 @@ import com.baomidou.mybatisplus.annotation.TableLogic;
|
|||||||
import java.io.Serializable;
|
import java.io.Serializable;
|
||||||
import java.util.Date;
|
import java.util.Date;
|
||||||
|
|
||||||
|
import com.fasterxml.jackson.annotation.JsonFormat;
|
||||||
import io.swagger.v3.oas.annotations.media.Schema;
|
import io.swagger.v3.oas.annotations.media.Schema;
|
||||||
import io.swagger.v3.oas.annotations.media.Schema;
|
import io.swagger.v3.oas.annotations.media.Schema;
|
||||||
import lombok.Data;
|
import lombok.Data;
|
||||||
@@ -89,9 +90,11 @@ public class Payment implements Serializable {
|
|||||||
private Integer tenantId;
|
private Integer tenantId;
|
||||||
|
|
||||||
@Schema(description = "注册时间")
|
@Schema(description = "注册时间")
|
||||||
|
@JsonFormat(pattern = "yyyy-MM-dd HH:mm:ss")
|
||||||
private Date createTime;
|
private Date createTime;
|
||||||
|
|
||||||
@Schema(description = "修改时间")
|
@Schema(description = "修改时间")
|
||||||
|
@JsonFormat(pattern = "yyyy-MM-dd HH:mm:ss")
|
||||||
private Date updateTime;
|
private Date updateTime;
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -9,6 +9,7 @@ import com.baomidou.mybatisplus.annotation.TableLogic;
|
|||||||
import java.io.Serializable;
|
import java.io.Serializable;
|
||||||
import java.util.Date;
|
import java.util.Date;
|
||||||
|
|
||||||
|
import com.fasterxml.jackson.annotation.JsonFormat;
|
||||||
import io.swagger.v3.oas.annotations.media.Schema;
|
import io.swagger.v3.oas.annotations.media.Schema;
|
||||||
import io.swagger.v3.oas.annotations.media.Schema;
|
import io.swagger.v3.oas.annotations.media.Schema;
|
||||||
import lombok.Data;
|
import lombok.Data;
|
||||||
@@ -75,9 +76,11 @@ public class Plug implements Serializable {
|
|||||||
private Integer tenantId;
|
private Integer tenantId;
|
||||||
|
|
||||||
@Schema(description = "创建时间")
|
@Schema(description = "创建时间")
|
||||||
|
@JsonFormat(pattern = "yyyy-MM-dd HH:mm:ss")
|
||||||
private Date createTime;
|
private Date createTime;
|
||||||
|
|
||||||
@Schema(description = "修改时间")
|
@Schema(description = "修改时间")
|
||||||
|
@JsonFormat(pattern = "yyyy-MM-dd HH:mm:ss")
|
||||||
private Date updateTime;
|
private Date updateTime;
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -2,6 +2,7 @@ package com.gxwebsoft.common.system.entity;
|
|||||||
|
|
||||||
import cn.hutool.core.util.DesensitizedUtil;
|
import cn.hutool.core.util.DesensitizedUtil;
|
||||||
import com.baomidou.mybatisplus.annotation.*;
|
import com.baomidou.mybatisplus.annotation.*;
|
||||||
|
import com.fasterxml.jackson.annotation.JsonFormat;
|
||||||
import io.swagger.v3.oas.annotations.media.Schema;
|
import io.swagger.v3.oas.annotations.media.Schema;
|
||||||
import io.swagger.v3.oas.annotations.media.Schema;
|
import io.swagger.v3.oas.annotations.media.Schema;
|
||||||
import lombok.Data;
|
import lombok.Data;
|
||||||
@@ -96,9 +97,11 @@ public class RechargeOrder implements Serializable {
|
|||||||
private Integer tenantId;
|
private Integer tenantId;
|
||||||
|
|
||||||
@Schema(description = "注册时间")
|
@Schema(description = "注册时间")
|
||||||
|
@JsonFormat(pattern = "yyyy-MM-dd HH:mm:ss")
|
||||||
private Date createTime;
|
private Date createTime;
|
||||||
|
|
||||||
@Schema(description = "修改时间")
|
@Schema(description = "修改时间")
|
||||||
|
@JsonFormat(pattern = "yyyy-MM-dd HH:mm:ss")
|
||||||
private Date updateTime;
|
private Date updateTime;
|
||||||
|
|
||||||
@Schema(description = "昵称")
|
@Schema(description = "昵称")
|
||||||
|
|||||||
@@ -1,6 +1,7 @@
|
|||||||
package com.gxwebsoft.common.system.entity;
|
package com.gxwebsoft.common.system.entity;
|
||||||
|
|
||||||
import com.baomidou.mybatisplus.annotation.*;
|
import com.baomidou.mybatisplus.annotation.*;
|
||||||
|
import com.fasterxml.jackson.annotation.JsonFormat;
|
||||||
import io.swagger.v3.oas.annotations.media.Schema;
|
import io.swagger.v3.oas.annotations.media.Schema;
|
||||||
import io.swagger.v3.oas.annotations.media.Schema;
|
import io.swagger.v3.oas.annotations.media.Schema;
|
||||||
import lombok.Data;
|
import lombok.Data;
|
||||||
@@ -44,9 +45,11 @@ public class Role implements Serializable {
|
|||||||
private Integer tenantId;
|
private Integer tenantId;
|
||||||
|
|
||||||
@Schema(description = "创建时间")
|
@Schema(description = "创建时间")
|
||||||
|
@JsonFormat(pattern = "yyyy-MM-dd HH:mm:ss")
|
||||||
private Date createTime;
|
private Date createTime;
|
||||||
|
|
||||||
@Schema(description = "修改时间")
|
@Schema(description = "修改时间")
|
||||||
|
@JsonFormat(pattern = "yyyy-MM-dd HH:mm:ss")
|
||||||
private Date updateTime;
|
private Date updateTime;
|
||||||
|
|
||||||
@Schema(hidden = true)
|
@Schema(hidden = true)
|
||||||
|
|||||||
@@ -3,6 +3,7 @@ package com.gxwebsoft.common.system.entity;
|
|||||||
import com.baomidou.mybatisplus.annotation.IdType;
|
import com.baomidou.mybatisplus.annotation.IdType;
|
||||||
import com.baomidou.mybatisplus.annotation.TableId;
|
import com.baomidou.mybatisplus.annotation.TableId;
|
||||||
import com.baomidou.mybatisplus.annotation.TableName;
|
import com.baomidou.mybatisplus.annotation.TableName;
|
||||||
|
import com.fasterxml.jackson.annotation.JsonFormat;
|
||||||
import io.swagger.v3.oas.annotations.media.Schema;
|
import io.swagger.v3.oas.annotations.media.Schema;
|
||||||
import io.swagger.v3.oas.annotations.media.Schema;
|
import io.swagger.v3.oas.annotations.media.Schema;
|
||||||
import lombok.Data;
|
import lombok.Data;
|
||||||
@@ -36,9 +37,11 @@ public class RoleMenu implements Serializable {
|
|||||||
private Integer tenantId;
|
private Integer tenantId;
|
||||||
|
|
||||||
@Schema(description = "创建时间")
|
@Schema(description = "创建时间")
|
||||||
|
@JsonFormat(pattern = "yyyy-MM-dd HH:mm:ss")
|
||||||
private Date createTime;
|
private Date createTime;
|
||||||
|
|
||||||
@Schema(description = "修改时间")
|
@Schema(description = "修改时间")
|
||||||
|
@JsonFormat(pattern = "yyyy-MM-dd HH:mm:ss")
|
||||||
private Date updateTime;
|
private Date updateTime;
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,6 +1,7 @@
|
|||||||
package com.gxwebsoft.common.system.entity;
|
package com.gxwebsoft.common.system.entity;
|
||||||
|
|
||||||
import com.baomidou.mybatisplus.annotation.*;
|
import com.baomidou.mybatisplus.annotation.*;
|
||||||
|
import com.fasterxml.jackson.annotation.JsonFormat;
|
||||||
import io.swagger.v3.oas.annotations.media.Schema;
|
import io.swagger.v3.oas.annotations.media.Schema;
|
||||||
import io.swagger.v3.oas.annotations.media.Schema;
|
import io.swagger.v3.oas.annotations.media.Schema;
|
||||||
import lombok.Data;
|
import lombok.Data;
|
||||||
@@ -46,9 +47,11 @@ public class Setting implements Serializable {
|
|||||||
private Integer tenantId;
|
private Integer tenantId;
|
||||||
|
|
||||||
@Schema(description = "创建时间")
|
@Schema(description = "创建时间")
|
||||||
|
@JsonFormat(pattern = "yyyy-MM-dd HH:mm:ss")
|
||||||
private Date createTime;
|
private Date createTime;
|
||||||
|
|
||||||
@Schema(description = "修改时间")
|
@Schema(description = "修改时间")
|
||||||
|
@JsonFormat(pattern = "yyyy-MM-dd HH:mm:ss")
|
||||||
private Date updateTime;
|
private Date updateTime;
|
||||||
|
|
||||||
@Schema(description = "修改租户名称")
|
@Schema(description = "修改租户名称")
|
||||||
|
|||||||
@@ -2,6 +2,7 @@ package com.gxwebsoft.common.system.entity;
|
|||||||
|
|
||||||
import com.baomidou.mybatisplus.annotation.IdType;
|
import com.baomidou.mybatisplus.annotation.IdType;
|
||||||
import com.baomidou.mybatisplus.annotation.TableId;
|
import com.baomidou.mybatisplus.annotation.TableId;
|
||||||
|
import com.fasterxml.jackson.annotation.JsonFormat;
|
||||||
import io.swagger.v3.oas.annotations.media.Schema;
|
import io.swagger.v3.oas.annotations.media.Schema;
|
||||||
import io.swagger.v3.oas.annotations.media.Schema;
|
import io.swagger.v3.oas.annotations.media.Schema;
|
||||||
import lombok.Data;
|
import lombok.Data;
|
||||||
@@ -39,6 +40,7 @@ public class SysFileType implements Serializable {
|
|||||||
private Integer tenantId;
|
private Integer tenantId;
|
||||||
|
|
||||||
@Schema(description = "创建时间")
|
@Schema(description = "创建时间")
|
||||||
|
@JsonFormat(pattern = "yyyy-MM-dd HH:mm:ss")
|
||||||
private Date createTime;
|
private Date createTime;
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -2,6 +2,7 @@ package com.gxwebsoft.common.system.entity;
|
|||||||
|
|
||||||
import cn.hutool.core.util.DesensitizedUtil;
|
import cn.hutool.core.util.DesensitizedUtil;
|
||||||
import com.baomidou.mybatisplus.annotation.*;
|
import com.baomidou.mybatisplus.annotation.*;
|
||||||
|
import com.fasterxml.jackson.annotation.JsonFormat;
|
||||||
import io.swagger.v3.oas.annotations.media.Schema;
|
import io.swagger.v3.oas.annotations.media.Schema;
|
||||||
import io.swagger.v3.oas.annotations.media.Schema;
|
import io.swagger.v3.oas.annotations.media.Schema;
|
||||||
import lombok.Data;
|
import lombok.Data;
|
||||||
@@ -53,6 +54,7 @@ public class Tenant implements Serializable {
|
|||||||
private Integer isTrial;
|
private Integer isTrial;
|
||||||
|
|
||||||
@Schema(description = "试用结束时间")
|
@Schema(description = "试用结束时间")
|
||||||
|
@JsonFormat(pattern = "yyyy-MM-dd HH:mm:ss")
|
||||||
private Date trialEndTime;
|
private Date trialEndTime;
|
||||||
|
|
||||||
@Schema(description = "自动续费")
|
@Schema(description = "自动续费")
|
||||||
@@ -63,9 +65,11 @@ public class Tenant implements Serializable {
|
|||||||
private Integer deleted;
|
private Integer deleted;
|
||||||
|
|
||||||
@Schema(description = "创建时间")
|
@Schema(description = "创建时间")
|
||||||
|
@JsonFormat(pattern = "yyyy-MM-dd HH:mm:ss")
|
||||||
private Date createTime;
|
private Date createTime;
|
||||||
|
|
||||||
@Schema(description = "修改时间")
|
@Schema(description = "修改时间")
|
||||||
|
@JsonFormat(pattern = "yyyy-MM-dd HH:mm:ss")
|
||||||
private Date updateTime;
|
private Date updateTime;
|
||||||
|
|
||||||
@Schema(description = "菜单信息")
|
@Schema(description = "菜单信息")
|
||||||
@@ -96,6 +100,18 @@ public class Tenant implements Serializable {
|
|||||||
@TableField(exist = false)
|
@TableField(exist = false)
|
||||||
private String phone;
|
private String phone;
|
||||||
|
|
||||||
|
@Schema(description = "管理地址")
|
||||||
|
@TableField(exist = false)
|
||||||
|
private String adminUrl;
|
||||||
|
|
||||||
|
@Schema(description = "顶级域名")
|
||||||
|
@TableField(exist = false)
|
||||||
|
private String domain;
|
||||||
|
|
||||||
|
@Schema(description = "免费域名")
|
||||||
|
@TableField(exist = false)
|
||||||
|
private String freeDomain;
|
||||||
|
|
||||||
public String getPhone(){
|
public String getPhone(){
|
||||||
return DesensitizedUtil.mobilePhone(this.phone);
|
return DesensitizedUtil.mobilePhone(this.phone);
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,6 +1,7 @@
|
|||||||
package com.gxwebsoft.common.system.entity;
|
package com.gxwebsoft.common.system.entity;
|
||||||
|
|
||||||
import com.baomidou.mybatisplus.annotation.*;
|
import com.baomidou.mybatisplus.annotation.*;
|
||||||
|
import com.fasterxml.jackson.annotation.JsonFormat;
|
||||||
import io.swagger.v3.oas.annotations.media.Schema;
|
import io.swagger.v3.oas.annotations.media.Schema;
|
||||||
import lombok.Data;
|
import lombok.Data;
|
||||||
import lombok.EqualsAndHashCode;
|
import lombok.EqualsAndHashCode;
|
||||||
@@ -66,8 +67,10 @@ public class TenantPackage implements Serializable {
|
|||||||
private Integer sortNumber;
|
private Integer sortNumber;
|
||||||
|
|
||||||
@Schema(description = "创建时间")
|
@Schema(description = "创建时间")
|
||||||
|
@JsonFormat(pattern = "yyyy-MM-dd HH:mm:ss", timezone = "GMT+8")
|
||||||
private Date createTime;
|
private Date createTime;
|
||||||
|
|
||||||
@Schema(description = "修改时间")
|
@Schema(description = "修改时间")
|
||||||
|
@JsonFormat(pattern = "yyyy-MM-dd HH:mm:ss", timezone = "GMT+8")
|
||||||
private Date updateTime;
|
private Date updateTime;
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,6 +1,7 @@
|
|||||||
package com.gxwebsoft.common.system.entity;
|
package com.gxwebsoft.common.system.entity;
|
||||||
|
|
||||||
import com.baomidou.mybatisplus.annotation.*;
|
import com.baomidou.mybatisplus.annotation.*;
|
||||||
|
import com.fasterxml.jackson.annotation.JsonFormat;
|
||||||
import io.swagger.v3.oas.annotations.media.Schema;
|
import io.swagger.v3.oas.annotations.media.Schema;
|
||||||
import lombok.Data;
|
import lombok.Data;
|
||||||
import lombok.EqualsAndHashCode;
|
import lombok.EqualsAndHashCode;
|
||||||
@@ -31,13 +32,18 @@ public class TenantSubscription implements Serializable {
|
|||||||
@Schema(description = "当前套餐ID")
|
@Schema(description = "当前套餐ID")
|
||||||
private Integer packageId;
|
private Integer packageId;
|
||||||
|
|
||||||
|
@Schema(description = "套餐名称")
|
||||||
|
private String packageName;
|
||||||
|
|
||||||
@Schema(description = "当前版本")
|
@Schema(description = "当前版本")
|
||||||
private Integer version;
|
private Integer version;
|
||||||
|
|
||||||
@Schema(description = "开始时间")
|
@Schema(description = "开始时间")
|
||||||
|
@JsonFormat(pattern = "yyyy-MM-dd HH:mm:ss", timezone = "GMT+8")
|
||||||
private Date startTime;
|
private Date startTime;
|
||||||
|
|
||||||
@Schema(description = "到期时间")
|
@Schema(description = "到期时间")
|
||||||
|
@JsonFormat(pattern = "yyyy-MM-dd HH:mm:ss", timezone = "GMT+8")
|
||||||
private Date endTime;
|
private Date endTime;
|
||||||
|
|
||||||
@Schema(description = "是否试用期")
|
@Schema(description = "是否试用期")
|
||||||
@@ -59,9 +65,11 @@ public class TenantSubscription implements Serializable {
|
|||||||
private Integer status;
|
private Integer status;
|
||||||
|
|
||||||
@Schema(description = "创建时间")
|
@Schema(description = "创建时间")
|
||||||
|
@JsonFormat(pattern = "yyyy-MM-dd HH:mm:ss", timezone = "GMT+8")
|
||||||
private Date createTime;
|
private Date createTime;
|
||||||
|
|
||||||
@Schema(description = "修改时间")
|
@Schema(description = "修改时间")
|
||||||
|
@JsonFormat(pattern = "yyyy-MM-dd HH:mm:ss", timezone = "GMT+8")
|
||||||
private Date updateTime;
|
private Date updateTime;
|
||||||
|
|
||||||
// 关联查询字段
|
// 关联查询字段
|
||||||
|
|||||||
@@ -1,6 +1,7 @@
|
|||||||
package com.gxwebsoft.common.system.entity;
|
package com.gxwebsoft.common.system.entity;
|
||||||
|
|
||||||
import com.baomidou.mybatisplus.annotation.*;
|
import com.baomidou.mybatisplus.annotation.*;
|
||||||
|
import com.fasterxml.jackson.annotation.JsonFormat;
|
||||||
import io.swagger.v3.oas.annotations.media.Schema;
|
import io.swagger.v3.oas.annotations.media.Schema;
|
||||||
import lombok.Data;
|
import lombok.Data;
|
||||||
import lombok.EqualsAndHashCode;
|
import lombok.EqualsAndHashCode;
|
||||||
@@ -54,9 +55,11 @@ public class TenantSubscriptionOrder implements Serializable {
|
|||||||
private BigDecimal actualPrice;
|
private BigDecimal actualPrice;
|
||||||
|
|
||||||
@Schema(description = "开始时间")
|
@Schema(description = "开始时间")
|
||||||
|
@JsonFormat(pattern = "yyyy-MM-dd HH:mm:ss", timezone = "GMT+8")
|
||||||
private Date startTime;
|
private Date startTime;
|
||||||
|
|
||||||
@Schema(description = "到期时间")
|
@Schema(description = "到期时间")
|
||||||
|
@JsonFormat(pattern = "yyyy-MM-dd HH:mm:ss", timezone = "GMT+8")
|
||||||
private Date endTime;
|
private Date endTime;
|
||||||
|
|
||||||
@Schema(description = "是否试用 0否 1是")
|
@Schema(description = "是否试用 0否 1是")
|
||||||
@@ -78,6 +81,7 @@ public class TenantSubscriptionOrder implements Serializable {
|
|||||||
private String paymentId;
|
private String paymentId;
|
||||||
|
|
||||||
@Schema(description = "支付时间")
|
@Schema(description = "支付时间")
|
||||||
|
@JsonFormat(pattern = "yyyy-MM-dd HH:mm:ss", timezone = "GMT+8")
|
||||||
private Date paymentTime;
|
private Date paymentTime;
|
||||||
|
|
||||||
@Schema(description = "订单状态 0待支付 1已支付 2已激活 3已取消 4已退款")
|
@Schema(description = "订单状态 0待支付 1已支付 2已激活 3已取消 4已退款")
|
||||||
@@ -90,8 +94,10 @@ public class TenantSubscriptionOrder implements Serializable {
|
|||||||
private Integer userId;
|
private Integer userId;
|
||||||
|
|
||||||
@Schema(description = "创建时间")
|
@Schema(description = "创建时间")
|
||||||
|
@JsonFormat(pattern = "yyyy-MM-dd HH:mm:ss", timezone = "GMT+8")
|
||||||
private Date createTime;
|
private Date createTime;
|
||||||
|
|
||||||
@Schema(description = "修改时间")
|
@Schema(description = "修改时间")
|
||||||
|
@JsonFormat(pattern = "yyyy-MM-dd HH:mm:ss", timezone = "GMT+8")
|
||||||
private Date updateTime;
|
private Date updateTime;
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,6 +1,7 @@
|
|||||||
package com.gxwebsoft.common.system.entity;
|
package com.gxwebsoft.common.system.entity;
|
||||||
|
|
||||||
import com.baomidou.mybatisplus.annotation.*;
|
import com.baomidou.mybatisplus.annotation.*;
|
||||||
|
import com.fasterxml.jackson.annotation.JsonFormat;
|
||||||
import io.swagger.v3.oas.annotations.media.Schema;
|
import io.swagger.v3.oas.annotations.media.Schema;
|
||||||
import io.swagger.v3.oas.annotations.media.Schema;
|
import io.swagger.v3.oas.annotations.media.Schema;
|
||||||
import lombok.Data;
|
import lombok.Data;
|
||||||
@@ -68,9 +69,11 @@ public class UserBalanceLog implements Serializable {
|
|||||||
private Integer tenantId;
|
private Integer tenantId;
|
||||||
|
|
||||||
@Schema(description = "注册时间")
|
@Schema(description = "注册时间")
|
||||||
|
@JsonFormat(pattern = "yyyy-MM-dd HH:mm:ss")
|
||||||
private Date createTime;
|
private Date createTime;
|
||||||
|
|
||||||
@Schema(description = "修改时间")
|
@Schema(description = "修改时间")
|
||||||
|
@JsonFormat(pattern = "yyyy-MM-dd HH:mm:ss")
|
||||||
private Date updateTime;
|
private Date updateTime;
|
||||||
|
|
||||||
@Schema(description = "昵称")
|
@Schema(description = "昵称")
|
||||||
|
|||||||
@@ -7,6 +7,7 @@ import java.util.Date;
|
|||||||
import java.io.Serializable;
|
import java.io.Serializable;
|
||||||
import java.util.Date;
|
import java.util.Date;
|
||||||
|
|
||||||
|
import com.fasterxml.jackson.annotation.JsonFormat;
|
||||||
import io.swagger.v3.oas.annotations.media.Schema;
|
import io.swagger.v3.oas.annotations.media.Schema;
|
||||||
import io.swagger.v3.oas.annotations.media.Schema;
|
import io.swagger.v3.oas.annotations.media.Schema;
|
||||||
import lombok.Data;
|
import lombok.Data;
|
||||||
@@ -39,6 +40,7 @@ public class UserCollection implements Serializable {
|
|||||||
private Integer tenantId;
|
private Integer tenantId;
|
||||||
|
|
||||||
@Schema(description = "注册时间")
|
@Schema(description = "注册时间")
|
||||||
|
@JsonFormat(pattern = "yyyy-MM-dd HH:mm:ss")
|
||||||
private Date createTime;
|
private Date createTime;
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -5,6 +5,7 @@ import com.baomidou.mybatisplus.annotation.*;
|
|||||||
import java.io.Serializable;
|
import java.io.Serializable;
|
||||||
import java.util.Date;
|
import java.util.Date;
|
||||||
|
|
||||||
|
import com.fasterxml.jackson.annotation.JsonFormat;
|
||||||
import io.swagger.v3.oas.annotations.media.Schema;
|
import io.swagger.v3.oas.annotations.media.Schema;
|
||||||
import io.swagger.v3.oas.annotations.media.Schema;
|
import io.swagger.v3.oas.annotations.media.Schema;
|
||||||
import lombok.Data;
|
import lombok.Data;
|
||||||
@@ -56,9 +57,11 @@ public class UserFile implements Serializable {
|
|||||||
private Integer tenantId;
|
private Integer tenantId;
|
||||||
|
|
||||||
@Schema(description = "创建时间")
|
@Schema(description = "创建时间")
|
||||||
|
@JsonFormat(pattern = "yyyy-MM-dd HH:mm:ss")
|
||||||
private Date createTime;
|
private Date createTime;
|
||||||
|
|
||||||
@Schema(description = "修改时间")
|
@Schema(description = "修改时间")
|
||||||
|
@JsonFormat(pattern = "yyyy-MM-dd HH:mm:ss")
|
||||||
private Date updateTime;
|
private Date updateTime;
|
||||||
|
|
||||||
@Schema(description = "文件访问地址")
|
@Schema(description = "文件访问地址")
|
||||||
|
|||||||
@@ -8,6 +8,7 @@ import com.baomidou.mybatisplus.annotation.TableLogic;
|
|||||||
import java.io.Serializable;
|
import java.io.Serializable;
|
||||||
import java.util.Date;
|
import java.util.Date;
|
||||||
|
|
||||||
|
import com.fasterxml.jackson.annotation.JsonFormat;
|
||||||
import io.swagger.v3.oas.annotations.media.Schema;
|
import io.swagger.v3.oas.annotations.media.Schema;
|
||||||
import io.swagger.v3.oas.annotations.media.Schema;
|
import io.swagger.v3.oas.annotations.media.Schema;
|
||||||
import lombok.Data;
|
import lombok.Data;
|
||||||
@@ -62,9 +63,11 @@ public class UserGrade implements Serializable {
|
|||||||
private Integer tenantId;
|
private Integer tenantId;
|
||||||
|
|
||||||
@Schema(description = "注册时间")
|
@Schema(description = "注册时间")
|
||||||
|
@JsonFormat(pattern = "yyyy-MM-dd HH:mm:ss")
|
||||||
private Date createTime;
|
private Date createTime;
|
||||||
|
|
||||||
@Schema(description = "修改时间")
|
@Schema(description = "修改时间")
|
||||||
|
@JsonFormat(pattern = "yyyy-MM-dd HH:mm:ss")
|
||||||
private Date updateTime;
|
private Date updateTime;
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -8,6 +8,7 @@ import com.baomidou.mybatisplus.annotation.TableLogic;
|
|||||||
import java.io.Serializable;
|
import java.io.Serializable;
|
||||||
import java.util.Date;
|
import java.util.Date;
|
||||||
|
|
||||||
|
import com.fasterxml.jackson.annotation.JsonFormat;
|
||||||
import io.swagger.v3.oas.annotations.media.Schema;
|
import io.swagger.v3.oas.annotations.media.Schema;
|
||||||
import io.swagger.v3.oas.annotations.media.Schema;
|
import io.swagger.v3.oas.annotations.media.Schema;
|
||||||
import lombok.Data;
|
import lombok.Data;
|
||||||
@@ -50,9 +51,11 @@ public class UserGroup implements Serializable {
|
|||||||
private Integer tenantId;
|
private Integer tenantId;
|
||||||
|
|
||||||
@Schema(description = "注册时间")
|
@Schema(description = "注册时间")
|
||||||
|
@JsonFormat(pattern = "yyyy-MM-dd HH:mm:ss")
|
||||||
private Date createTime;
|
private Date createTime;
|
||||||
|
|
||||||
@Schema(description = "修改时间")
|
@Schema(description = "修改时间")
|
||||||
|
@JsonFormat(pattern = "yyyy-MM-dd HH:mm:ss")
|
||||||
private Date updateTime;
|
private Date updateTime;
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -8,6 +8,7 @@ import com.baomidou.mybatisplus.annotation.TableLogic;
|
|||||||
import java.io.Serializable;
|
import java.io.Serializable;
|
||||||
import java.util.Date;
|
import java.util.Date;
|
||||||
|
|
||||||
|
import com.fasterxml.jackson.annotation.JsonFormat;
|
||||||
import io.swagger.v3.oas.annotations.media.Schema;
|
import io.swagger.v3.oas.annotations.media.Schema;
|
||||||
import io.swagger.v3.oas.annotations.media.Schema;
|
import io.swagger.v3.oas.annotations.media.Schema;
|
||||||
import lombok.Data;
|
import lombok.Data;
|
||||||
@@ -58,9 +59,11 @@ public class UserOauth implements Serializable {
|
|||||||
private Integer tenantId;
|
private Integer tenantId;
|
||||||
|
|
||||||
@Schema(description = "注册时间")
|
@Schema(description = "注册时间")
|
||||||
|
@JsonFormat(pattern = "yyyy-MM-dd HH:mm:ss")
|
||||||
private Date createTime;
|
private Date createTime;
|
||||||
|
|
||||||
@Schema(description = "修改时间")
|
@Schema(description = "修改时间")
|
||||||
|
@JsonFormat(pattern = "yyyy-MM-dd HH:mm:ss")
|
||||||
private Date updateTime;
|
private Date updateTime;
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -7,6 +7,7 @@ import java.io.Serializable;
|
|||||||
import java.util.Date;
|
import java.util.Date;
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
|
|
||||||
|
import com.fasterxml.jackson.annotation.JsonFormat;
|
||||||
import io.swagger.v3.oas.annotations.media.Schema;
|
import io.swagger.v3.oas.annotations.media.Schema;
|
||||||
import io.swagger.v3.oas.annotations.media.Schema;
|
import io.swagger.v3.oas.annotations.media.Schema;
|
||||||
import lombok.Data;
|
import lombok.Data;
|
||||||
@@ -49,9 +50,11 @@ public class UserReferee implements Serializable {
|
|||||||
private Integer tenantId;
|
private Integer tenantId;
|
||||||
|
|
||||||
@Schema(description = "创建时间")
|
@Schema(description = "创建时间")
|
||||||
|
@JsonFormat(pattern = "yyyy-MM-dd HH:mm:ss")
|
||||||
private Date createTime;
|
private Date createTime;
|
||||||
|
|
||||||
@Schema(description = "修改时间")
|
@Schema(description = "修改时间")
|
||||||
|
@JsonFormat(pattern = "yyyy-MM-dd HH:mm:ss")
|
||||||
private Date updateTime;
|
private Date updateTime;
|
||||||
|
|
||||||
@TableField(exist = false)
|
@TableField(exist = false)
|
||||||
|
|||||||
@@ -9,6 +9,7 @@ import java.time.LocalDateTime;
|
|||||||
import java.io.Serializable;
|
import java.io.Serializable;
|
||||||
import java.util.Date;
|
import java.util.Date;
|
||||||
|
|
||||||
|
import com.fasterxml.jackson.annotation.JsonFormat;
|
||||||
import io.swagger.v3.oas.annotations.media.Schema;
|
import io.swagger.v3.oas.annotations.media.Schema;
|
||||||
import io.swagger.v3.oas.annotations.media.Schema;
|
import io.swagger.v3.oas.annotations.media.Schema;
|
||||||
import lombok.Data;
|
import lombok.Data;
|
||||||
@@ -37,9 +38,11 @@ public class UserRole implements Serializable {
|
|||||||
private Integer roleId;
|
private Integer roleId;
|
||||||
|
|
||||||
@Schema(description = "创建时间")
|
@Schema(description = "创建时间")
|
||||||
|
@JsonFormat(pattern = "yyyy-MM-dd HH:mm:ss")
|
||||||
private Date createTime;
|
private Date createTime;
|
||||||
|
|
||||||
@Schema(description = "修改时间")
|
@Schema(description = "修改时间")
|
||||||
|
@JsonFormat(pattern = "yyyy-MM-dd HH:mm:ss")
|
||||||
private Date updateTime;
|
private Date updateTime;
|
||||||
|
|
||||||
@Schema(description = "角色名称")
|
@Schema(description = "角色名称")
|
||||||
|
|||||||
@@ -61,9 +61,13 @@ public class UserVerify implements Serializable {
|
|||||||
@Schema(description = "其他证件")
|
@Schema(description = "其他证件")
|
||||||
private String files;
|
private String files;
|
||||||
|
|
||||||
@Schema(description = "审核人")
|
@Schema(description = "操作员ID")
|
||||||
private Integer adminId;
|
private Integer adminId;
|
||||||
|
|
||||||
|
@Schema(description = "操作员名称")
|
||||||
|
@TableField(exist = false)
|
||||||
|
private String adminName;
|
||||||
|
|
||||||
@Schema(description = "机构ID")
|
@Schema(description = "机构ID")
|
||||||
private Integer organizationId;
|
private Integer organizationId;
|
||||||
|
|
||||||
|
|||||||
@@ -8,6 +8,7 @@ import com.baomidou.mybatisplus.annotation.TableLogic;
|
|||||||
import java.io.Serializable;
|
import java.io.Serializable;
|
||||||
import java.util.Date;
|
import java.util.Date;
|
||||||
|
|
||||||
|
import com.fasterxml.jackson.annotation.JsonFormat;
|
||||||
import io.swagger.v3.oas.annotations.media.Schema;
|
import io.swagger.v3.oas.annotations.media.Schema;
|
||||||
import io.swagger.v3.oas.annotations.media.Schema;
|
import io.swagger.v3.oas.annotations.media.Schema;
|
||||||
import lombok.Data;
|
import lombok.Data;
|
||||||
@@ -73,9 +74,11 @@ public class Version implements Serializable {
|
|||||||
private Integer tenantId;
|
private Integer tenantId;
|
||||||
|
|
||||||
@Schema(description = "注册时间")
|
@Schema(description = "注册时间")
|
||||||
|
@JsonFormat(pattern = "yyyy-MM-dd HH:mm:ss")
|
||||||
private Date createTime;
|
private Date createTime;
|
||||||
|
|
||||||
@Schema(description = "修改时间")
|
@Schema(description = "修改时间")
|
||||||
|
@JsonFormat(pattern = "yyyy-MM-dd HH:mm:ss")
|
||||||
private Date updateTime;
|
private Date updateTime;
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -8,6 +8,7 @@ import com.baomidou.mybatisplus.annotation.TableLogic;
|
|||||||
import java.io.Serializable;
|
import java.io.Serializable;
|
||||||
import java.util.Date;
|
import java.util.Date;
|
||||||
|
|
||||||
|
import com.fasterxml.jackson.annotation.JsonFormat;
|
||||||
import io.swagger.v3.oas.annotations.media.Schema;
|
import io.swagger.v3.oas.annotations.media.Schema;
|
||||||
import io.swagger.v3.oas.annotations.media.Schema;
|
import io.swagger.v3.oas.annotations.media.Schema;
|
||||||
import lombok.Data;
|
import lombok.Data;
|
||||||
@@ -59,6 +60,7 @@ public class WebsiteField implements Serializable {
|
|||||||
private Integer tenantId;
|
private Integer tenantId;
|
||||||
|
|
||||||
@Schema(description = "创建时间")
|
@Schema(description = "创建时间")
|
||||||
|
@JsonFormat(pattern = "yyyy-MM-dd HH:mm:ss")
|
||||||
private Date createTime;
|
private Date createTime;
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -8,6 +8,7 @@ import com.baomidou.mybatisplus.annotation.TableLogic;
|
|||||||
import java.io.Serializable;
|
import java.io.Serializable;
|
||||||
import java.util.Date;
|
import java.util.Date;
|
||||||
|
|
||||||
|
import com.fasterxml.jackson.annotation.JsonFormat;
|
||||||
import io.swagger.v3.oas.annotations.media.Schema;
|
import io.swagger.v3.oas.annotations.media.Schema;
|
||||||
import io.swagger.v3.oas.annotations.media.Schema;
|
import io.swagger.v3.oas.annotations.media.Schema;
|
||||||
import lombok.Data;
|
import lombok.Data;
|
||||||
@@ -50,9 +51,11 @@ public class WhiteDomain implements Serializable {
|
|||||||
private Integer tenantId;
|
private Integer tenantId;
|
||||||
|
|
||||||
@Schema(description = "创建时间")
|
@Schema(description = "创建时间")
|
||||||
|
@JsonFormat(pattern = "yyyy-MM-dd HH:mm:ss")
|
||||||
private Date createTime;
|
private Date createTime;
|
||||||
|
|
||||||
@Schema(description = "修改时间")
|
@Schema(description = "修改时间")
|
||||||
|
@JsonFormat(pattern = "yyyy-MM-dd HH:mm:ss")
|
||||||
private Date updateTime;
|
private Date updateTime;
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,5 +1,6 @@
|
|||||||
package com.gxwebsoft.common.system.mapper;
|
package com.gxwebsoft.common.system.mapper;
|
||||||
|
|
||||||
|
import com.baomidou.mybatisplus.annotation.InterceptorIgnore;
|
||||||
import com.baomidou.mybatisplus.core.mapper.BaseMapper;
|
import com.baomidou.mybatisplus.core.mapper.BaseMapper;
|
||||||
import com.gxwebsoft.common.system.entity.TenantPackage;
|
import com.gxwebsoft.common.system.entity.TenantPackage;
|
||||||
import org.apache.ibatis.annotations.Param;
|
import org.apache.ibatis.annotations.Param;
|
||||||
@@ -12,6 +13,7 @@ import java.util.List;
|
|||||||
* @author WebSoft
|
* @author WebSoft
|
||||||
* @since 2025-12-12
|
* @since 2025-12-12
|
||||||
*/
|
*/
|
||||||
|
@InterceptorIgnore(tenantLine = "true")
|
||||||
public interface TenantPackageMapper extends BaseMapper<TenantPackage> {
|
public interface TenantPackageMapper extends BaseMapper<TenantPackage> {
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
|||||||
@@ -1,5 +1,6 @@
|
|||||||
package com.gxwebsoft.common.system.mapper;
|
package com.gxwebsoft.common.system.mapper;
|
||||||
|
|
||||||
|
import com.baomidou.mybatisplus.annotation.InterceptorIgnore;
|
||||||
import com.baomidou.mybatisplus.core.mapper.BaseMapper;
|
import com.baomidou.mybatisplus.core.mapper.BaseMapper;
|
||||||
import com.baomidou.mybatisplus.core.metadata.IPage;
|
import com.baomidou.mybatisplus.core.metadata.IPage;
|
||||||
import com.gxwebsoft.common.system.entity.TenantSubscriptionOrder;
|
import com.gxwebsoft.common.system.entity.TenantSubscriptionOrder;
|
||||||
@@ -13,6 +14,7 @@ import java.util.List;
|
|||||||
* @author WebSoft
|
* @author WebSoft
|
||||||
* @since 2025-12-12
|
* @since 2025-12-12
|
||||||
*/
|
*/
|
||||||
|
@InterceptorIgnore(tenantLine = "true")
|
||||||
public interface TenantSubscriptionOrderMapper extends BaseMapper<TenantSubscriptionOrder> {
|
public interface TenantSubscriptionOrderMapper extends BaseMapper<TenantSubscriptionOrder> {
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
|||||||
@@ -16,6 +16,12 @@
|
|||||||
<if test="param.userId != null">
|
<if test="param.userId != null">
|
||||||
AND a.user_id = #{param.userId}
|
AND a.user_id = #{param.userId}
|
||||||
</if>
|
</if>
|
||||||
|
<if test="param.organizationIds != null and param.organizationIds.size() > 0">
|
||||||
|
AND b.organization_id IN
|
||||||
|
<foreach collection="param.organizationIds" item="item" separator="," open="(" close=")">
|
||||||
|
#{item}
|
||||||
|
</foreach>
|
||||||
|
</if>
|
||||||
<if test="param.module != null">
|
<if test="param.module != null">
|
||||||
AND a.module LIKE CONCAT('%', #{param.module}, '%')
|
AND a.module LIKE CONCAT('%', #{param.module}, '%')
|
||||||
</if>
|
</if>
|
||||||
|
|||||||
@@ -29,6 +29,12 @@
|
|||||||
<if test="param.organizationId != null">
|
<if test="param.organizationId != null">
|
||||||
AND a.organization_id = #{param.organizationId}
|
AND a.organization_id = #{param.organizationId}
|
||||||
</if>
|
</if>
|
||||||
|
<if test="param.organizationIds != null and param.organizationIds.size() > 0">
|
||||||
|
AND a.organization_id IN
|
||||||
|
<foreach collection="param.organizationIds" item="item" separator="," open="(" close=")">
|
||||||
|
#{item}
|
||||||
|
</foreach>
|
||||||
|
</if>
|
||||||
<if test="param.organizationIdWithChildren != null">
|
<if test="param.organizationIdWithChildren != null">
|
||||||
AND (a.organization_id = #{param.organizationIdWithChildren} OR a.parent_id = #{param.organizationIdWithChildren})
|
AND (a.organization_id = #{param.organizationIdWithChildren} OR a.parent_id = #{param.organizationIdWithChildren})
|
||||||
</if>
|
</if>
|
||||||
|
|||||||
@@ -4,7 +4,7 @@
|
|||||||
|
|
||||||
<!-- 关联查询sql -->
|
<!-- 关联查询sql -->
|
||||||
<sql id="selectSql">
|
<sql id="selectSql">
|
||||||
SELECT a.*,b.company_name,b.company_logo as logo
|
SELECT a.*,b.company_name,b.company_logo as logo,b.admin_url,b.domain,b.free_domain
|
||||||
FROM sys_tenant a
|
FROM sys_tenant a
|
||||||
LEFT JOIN sys_company b ON a.tenant_id = b.tenant_id
|
LEFT JOIN sys_company b ON a.tenant_id = b.tenant_id
|
||||||
<where>
|
<where>
|
||||||
@@ -43,8 +43,9 @@
|
|||||||
</if>
|
</if>
|
||||||
<if test="param.keywords != null">
|
<if test="param.keywords != null">
|
||||||
AND (
|
AND (
|
||||||
a.tenant_name LIKE CONCAT('%', #{param.keywords}, '%')
|
a.tenant_name LIKE CONCAT('%', #{param.keywords}, '%')
|
||||||
OR a.tenant_id = #{param.keywords}
|
OR a.tenant_code = #{param.keywords}
|
||||||
|
OR a.tenant_id = #{param.keywords}
|
||||||
)
|
)
|
||||||
</if>
|
</if>
|
||||||
</where>
|
</where>
|
||||||
|
|||||||
@@ -4,10 +4,11 @@
|
|||||||
|
|
||||||
<!-- 关联查询sql -->
|
<!-- 关联查询sql -->
|
||||||
<sql id="selectSql">
|
<sql id="selectSql">
|
||||||
SELECT a.*, b.phone, c.organization_name
|
SELECT a.*, b.phone, c.organization_name, d.nickname as adminName
|
||||||
FROM sys_user_verify a
|
FROM sys_user_verify a
|
||||||
LEFT JOIN sys_user b ON a.user_id = b.user_id
|
LEFT JOIN sys_user b ON a.user_id = b.user_id
|
||||||
LEFT JOIN sys_organization c ON a.organization_id = c.organization_id
|
LEFT JOIN sys_organization c ON a.organization_id = c.organization_id
|
||||||
|
LEFT JOIN sys_user d ON a.admin_id = d.user_id
|
||||||
<where>
|
<where>
|
||||||
<if test="param.id != null">
|
<if test="param.id != null">
|
||||||
AND a.id = #{param.id}
|
AND a.id = #{param.id}
|
||||||
@@ -77,6 +78,86 @@
|
|||||||
OR a.zz_code = #{param.keywords}
|
OR a.zz_code = #{param.keywords}
|
||||||
)
|
)
|
||||||
</if>
|
</if>
|
||||||
|
<!--
|
||||||
|
防止同一个 user_id 在 sys_user_verify 中存在多条记录时,列表查询返回 userId 重复。
|
||||||
|
这里保留每个 user_id 的最新一条记录(按 id 最大)。
|
||||||
|
注意:当按主键 id 精确查询时不做去重,避免把历史记录过滤掉。
|
||||||
|
-->
|
||||||
|
<if test="param.id == null">
|
||||||
|
AND a.id IN (
|
||||||
|
SELECT MAX(v.id)
|
||||||
|
FROM sys_user_verify v
|
||||||
|
LEFT JOIN sys_user u ON v.user_id = u.user_id
|
||||||
|
<where>
|
||||||
|
<if test="param.userId != null">
|
||||||
|
AND v.user_id = #{param.userId}
|
||||||
|
</if>
|
||||||
|
<if test="param.type != null">
|
||||||
|
AND v.type = #{param.type}
|
||||||
|
</if>
|
||||||
|
<if test="param.name != null">
|
||||||
|
AND v.name LIKE CONCAT('%', #{param.name}, '%')
|
||||||
|
</if>
|
||||||
|
<if test="param.realName != null">
|
||||||
|
AND v.real_name LIKE CONCAT('%', #{param.realName}, '%')
|
||||||
|
</if>
|
||||||
|
<if test="param.idCard != null">
|
||||||
|
AND v.id_card LIKE CONCAT('%', #{param.idCard}, '%')
|
||||||
|
</if>
|
||||||
|
<if test="param.birthday != null">
|
||||||
|
AND v.birthday LIKE CONCAT('%', #{param.birthday}, '%')
|
||||||
|
</if>
|
||||||
|
<if test="param.sfz1 != null">
|
||||||
|
AND v.sfz1 LIKE CONCAT('%', #{param.sfz1}, '%')
|
||||||
|
</if>
|
||||||
|
<if test="param.sfz2 != null">
|
||||||
|
AND v.sfz2 LIKE CONCAT('%', #{param.sfz2}, '%')
|
||||||
|
</if>
|
||||||
|
<if test="param.zzCode != null">
|
||||||
|
AND v.zz_code = #{param.zzCode}
|
||||||
|
</if>
|
||||||
|
<if test="param.adminId != null">
|
||||||
|
AND v.admin_id = #{param.adminId}
|
||||||
|
</if>
|
||||||
|
<if test="param.organizationId != null">
|
||||||
|
AND v.organization_id = #{param.organizationId}
|
||||||
|
</if>
|
||||||
|
<if test="param.comments != null">
|
||||||
|
AND v.comments LIKE CONCAT('%', #{param.comments}, '%')
|
||||||
|
</if>
|
||||||
|
<if test="param.status != null">
|
||||||
|
AND v.status = #{param.status}
|
||||||
|
</if>
|
||||||
|
<if test="param.deleted != null">
|
||||||
|
AND v.deleted = #{param.deleted}
|
||||||
|
</if>
|
||||||
|
<if test="param.deleted == null">
|
||||||
|
AND v.deleted = 0
|
||||||
|
</if>
|
||||||
|
<if test="param.createTimeStart != null">
|
||||||
|
AND v.create_time >= #{param.createTimeStart}
|
||||||
|
</if>
|
||||||
|
<if test="param.createTimeEnd != null">
|
||||||
|
AND v.create_time <= #{param.createTimeEnd}
|
||||||
|
</if>
|
||||||
|
<if test="param.organizationIds != null">
|
||||||
|
AND v.organization_id IN
|
||||||
|
<foreach collection="param.organizationIds" item="item" separator="," open="(" close=")">
|
||||||
|
#{item}
|
||||||
|
</foreach>
|
||||||
|
</if>
|
||||||
|
<if test="param.keywords != null">
|
||||||
|
AND (v.name LIKE CONCAT('%', #{param.keywords}, '%')
|
||||||
|
OR v.real_name LIKE CONCAT('%', #{param.keywords}, '%')
|
||||||
|
OR u.phone = #{param.keywords}
|
||||||
|
OR v.id_card = #{param.keywords}
|
||||||
|
OR v.zz_code = #{param.keywords}
|
||||||
|
)
|
||||||
|
</if>
|
||||||
|
</where>
|
||||||
|
GROUP BY v.user_id
|
||||||
|
)
|
||||||
|
</if>
|
||||||
</where>
|
</where>
|
||||||
</sql>
|
</sql>
|
||||||
|
|
||||||
|
|||||||
@@ -10,6 +10,8 @@ import io.swagger.v3.oas.annotations.media.Schema;
|
|||||||
import lombok.Data;
|
import lombok.Data;
|
||||||
import lombok.EqualsAndHashCode;
|
import lombok.EqualsAndHashCode;
|
||||||
|
|
||||||
|
import java.util.Set;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 操作日志参数
|
* 操作日志参数
|
||||||
*
|
*
|
||||||
@@ -31,6 +33,10 @@ public class OperationRecordParam extends BaseParam {
|
|||||||
@QueryField(type = QueryType.EQ)
|
@QueryField(type = QueryType.EQ)
|
||||||
private Integer userId;
|
private Integer userId;
|
||||||
|
|
||||||
|
@Schema(description = "机构id合集")
|
||||||
|
@TableField(exist = false)
|
||||||
|
private Set<Integer> organizationIds;
|
||||||
|
|
||||||
@Schema(description = "操作模块")
|
@Schema(description = "操作模块")
|
||||||
private String module;
|
private String module;
|
||||||
|
|
||||||
|
|||||||
@@ -12,6 +12,7 @@ import lombok.EqualsAndHashCode;
|
|||||||
|
|
||||||
import java.math.BigDecimal;
|
import java.math.BigDecimal;
|
||||||
import java.util.Date;
|
import java.util.Date;
|
||||||
|
import java.util.Set;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 组织机构查询参数
|
* 组织机构查询参数
|
||||||
@@ -30,6 +31,10 @@ public class OrganizationParam extends BaseParam {
|
|||||||
@QueryField(type = QueryType.EQ)
|
@QueryField(type = QueryType.EQ)
|
||||||
private Integer organizationId;
|
private Integer organizationId;
|
||||||
|
|
||||||
|
@Schema(description = "机构id合集")
|
||||||
|
@TableField(exist = false)
|
||||||
|
private Set<Integer> organizationIds;
|
||||||
|
|
||||||
@Schema(description = "上级id, 0是顶级")
|
@Schema(description = "上级id, 0是顶级")
|
||||||
@QueryField(type = QueryType.EQ)
|
@QueryField(type = QueryType.EQ)
|
||||||
private Integer parentId;
|
private Integer parentId;
|
||||||
|
|||||||
@@ -0,0 +1,24 @@
|
|||||||
|
package com.gxwebsoft.common.system.param;
|
||||||
|
|
||||||
|
import io.swagger.v3.oas.annotations.media.Schema;
|
||||||
|
import lombok.Data;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 订阅订单价格试算入参
|
||||||
|
*/
|
||||||
|
@Data
|
||||||
|
@Schema(description = "订阅订单价格试算参数")
|
||||||
|
public class SubscriptionOrderParam {
|
||||||
|
|
||||||
|
@Schema(description = "是否续费,1=续费 0=新购")
|
||||||
|
private Integer isRenewal;
|
||||||
|
|
||||||
|
@Schema(description = "是否升级,1=升级 0=非升级")
|
||||||
|
private Integer isUpgrade;
|
||||||
|
|
||||||
|
@Schema(description = "套餐ID")
|
||||||
|
private Integer packageId;
|
||||||
|
|
||||||
|
@Schema(description = "支付方式")
|
||||||
|
private Integer payType;
|
||||||
|
}
|
||||||
@@ -0,0 +1,18 @@
|
|||||||
|
package com.gxwebsoft.common.system.result;
|
||||||
|
|
||||||
|
import io.swagger.v3.oas.annotations.media.Schema;
|
||||||
|
import lombok.Data;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 订阅订单创建结果
|
||||||
|
*/
|
||||||
|
@Data
|
||||||
|
@Schema(description = "订阅订单创建结果")
|
||||||
|
public class SubscriptionOrderCreateResult {
|
||||||
|
|
||||||
|
@Schema(description = "订单号")
|
||||||
|
private String orderNo;
|
||||||
|
|
||||||
|
@Schema(description = "价格试算结果")
|
||||||
|
private SubscriptionPriceResult price;
|
||||||
|
}
|
||||||
@@ -0,0 +1,21 @@
|
|||||||
|
package com.gxwebsoft.common.system.result;
|
||||||
|
|
||||||
|
import io.swagger.v3.oas.annotations.media.Schema;
|
||||||
|
import lombok.Data;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 订阅订单支付结果
|
||||||
|
*/
|
||||||
|
@Data
|
||||||
|
@Schema(description = "订阅订单支付结果")
|
||||||
|
public class SubscriptionOrderPayResult {
|
||||||
|
|
||||||
|
@Schema(description = "订单号")
|
||||||
|
private String orderNo;
|
||||||
|
|
||||||
|
@Schema(description = "支付二维码链接")
|
||||||
|
private String codeUrl;
|
||||||
|
|
||||||
|
@Schema(description = "价格信息")
|
||||||
|
private SubscriptionPriceResult price;
|
||||||
|
}
|
||||||
@@ -0,0 +1,41 @@
|
|||||||
|
package com.gxwebsoft.common.system.result;
|
||||||
|
|
||||||
|
import io.swagger.v3.oas.annotations.media.Schema;
|
||||||
|
import lombok.Data;
|
||||||
|
|
||||||
|
import java.math.BigDecimal;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 订阅订单价格试算结果
|
||||||
|
*/
|
||||||
|
@Data
|
||||||
|
@Schema(description = "订阅订单价格试算结果")
|
||||||
|
public class SubscriptionPriceResult {
|
||||||
|
|
||||||
|
@Schema(description = "套餐ID")
|
||||||
|
private Integer packageId;
|
||||||
|
|
||||||
|
@Schema(description = "是否续费,1=续费 0=新购")
|
||||||
|
private Integer isRenewal;
|
||||||
|
|
||||||
|
@Schema(description = "是否升级,1=升级 0=非升级")
|
||||||
|
private Integer isUpgrade;
|
||||||
|
|
||||||
|
@Schema(description = "支付方式")
|
||||||
|
private Integer payType;
|
||||||
|
|
||||||
|
@Schema(description = "原价")
|
||||||
|
private BigDecimal originalPrice;
|
||||||
|
|
||||||
|
@Schema(description = "优惠金额")
|
||||||
|
private BigDecimal discountAmount;
|
||||||
|
|
||||||
|
@Schema(description = "应付金额")
|
||||||
|
private BigDecimal payPrice;
|
||||||
|
|
||||||
|
@Schema(description = "总价(同原价,用于兼容前端字段)")
|
||||||
|
private BigDecimal totalPrice;
|
||||||
|
|
||||||
|
@Schema(description = "价格说明")
|
||||||
|
private String remark;
|
||||||
|
}
|
||||||
@@ -0,0 +1,18 @@
|
|||||||
|
package com.gxwebsoft.common.system.service;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 微信小程序 access_token 获取服务(按租户)。
|
||||||
|
*
|
||||||
|
* <p>用于调用微信小程序开放接口(例如:上传发货信息)。</p>
|
||||||
|
*/
|
||||||
|
public interface WxMiniappAccessTokenService {
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 获取指定租户的小程序 access_token(内部带缓存)。
|
||||||
|
*
|
||||||
|
* @param tenantId 租户ID
|
||||||
|
* @return access_token
|
||||||
|
*/
|
||||||
|
String getAccessToken(Integer tenantId);
|
||||||
|
}
|
||||||
|
|
||||||
@@ -261,6 +261,9 @@ public class UserServiceImpl extends ServiceImpl<UserMapper, User> implements Us
|
|||||||
if(userParam.getRegion() != null){
|
if(userParam.getRegion() != null){
|
||||||
addUser.setRegion(userParam.getRegion());
|
addUser.setRegion(userParam.getRegion());
|
||||||
}
|
}
|
||||||
|
if(userParam.getIsAdmin() != null){
|
||||||
|
addUser.setIsAdmin(userParam.getIsAdmin());
|
||||||
|
}
|
||||||
if(userParam.getAddress() != null){
|
if(userParam.getAddress() != null){
|
||||||
addUser.setAddress(userParam.getAddress());
|
addUser.setAddress(userParam.getAddress());
|
||||||
}
|
}
|
||||||
@@ -273,7 +276,41 @@ public class UserServiceImpl extends ServiceImpl<UserMapper, User> implements Us
|
|||||||
}
|
}
|
||||||
addUser.setTenantId(userParam.getTenantId());
|
addUser.setTenantId(userParam.getTenantId());
|
||||||
addUser.setRecommend(0);
|
addUser.setRecommend(0);
|
||||||
Role role = roleService.getOne(new QueryWrapper<Role>().eq("role_code", "user"), false);
|
// Role assignment:
|
||||||
|
// - If roleId is provided (e.g. invite flow), use it (must belong to the same tenant).
|
||||||
|
// - Otherwise, fall back to roleCode; default to "user".
|
||||||
|
Role role = null;
|
||||||
|
if (userParam.getRoleId() != null) {
|
||||||
|
role = roleService.getById(userParam.getRoleId());
|
||||||
|
if (role != null
|
||||||
|
&& addUser.getTenantId() != null
|
||||||
|
&& role.getTenantId() != null
|
||||||
|
&& !addUser.getTenantId().equals(role.getTenantId())) {
|
||||||
|
throw new BusinessException("角色不属于当前租户");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
String roleCode = userParam.getRoleCode();
|
||||||
|
if (role == null) {
|
||||||
|
roleCode = StrUtil.blankToDefault(roleCode, "user");
|
||||||
|
QueryWrapper<Role> roleQw = new QueryWrapper<Role>().eq("role_code", roleCode);
|
||||||
|
if (addUser.getTenantId() != null) {
|
||||||
|
roleQw.eq("tenant_id", addUser.getTenantId());
|
||||||
|
}
|
||||||
|
role = roleService.getOne(roleQw, false);
|
||||||
|
// If the default "user" role is missing (fresh DB / incomplete init), create it to avoid empty roles.
|
||||||
|
if (role == null && addUser.getTenantId() != null && "user".equals(roleCode)) {
|
||||||
|
Role defaultRole = new Role();
|
||||||
|
defaultRole.setRoleName("注册用户");
|
||||||
|
defaultRole.setRoleCode("user");
|
||||||
|
defaultRole.setComments("普通注册用户");
|
||||||
|
defaultRole.setTenantId(addUser.getTenantId());
|
||||||
|
roleService.save(defaultRole);
|
||||||
|
role = defaultRole;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (role == null) {
|
||||||
|
throw new BusinessException("缺少默认角色(role_code=" + (roleCode == null ? "user" : roleCode) + "),请先初始化角色");
|
||||||
|
}
|
||||||
addUser.setRoleId(role.getRoleId());
|
addUser.setRoleId(role.getRoleId());
|
||||||
if (saveUser(addUser)) {
|
if (saveUser(addUser)) {
|
||||||
// 添加用户角色
|
// 添加用户角色
|
||||||
@@ -283,6 +320,9 @@ public class UserServiceImpl extends ServiceImpl<UserMapper, User> implements Us
|
|||||||
userRole.setRoleId(addUser.getRoleId());
|
userRole.setRoleId(addUser.getRoleId());
|
||||||
userRoleService.save(userRole);
|
userRoleService.save(userRole);
|
||||||
}
|
}
|
||||||
|
// Ensure caller (e.g. register / invite register) gets non-empty roles/authorities in response.
|
||||||
|
addUser.setRoles(userRoleService.listByUserId(addUser.getUserId()));
|
||||||
|
addUser.setAuthorities(roleMenuService.listMenuByUserId(addUser.getUserId(), null));
|
||||||
return addUser;
|
return addUser;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
53
src/main/resources/application-glt.yml
Normal file
53
src/main/resources/application-glt.yml
Normal file
@@ -0,0 +1,53 @@
|
|||||||
|
# 生产环境配置
|
||||||
|
|
||||||
|
# 数据源配置
|
||||||
|
spring:
|
||||||
|
datasource:
|
||||||
|
url: jdbc:mysql://1Panel-mysql-XsWW:3306/gxwebsoft_core?useSSL=false&serverTimezone=UTC
|
||||||
|
username: gxwebsoft_core
|
||||||
|
password: ZXT5FkBREBJQPiAs
|
||||||
|
driver-class-name: com.mysql.cj.jdbc.Driver
|
||||||
|
type: com.alibaba.druid.pool.DruidDataSource
|
||||||
|
redis:
|
||||||
|
database: 0
|
||||||
|
host: 1Panel-redis-GmNr
|
||||||
|
port: 6379
|
||||||
|
password: redis_t74P8C
|
||||||
|
|
||||||
|
# 日志配置
|
||||||
|
logging:
|
||||||
|
file:
|
||||||
|
name: websoft-core.log
|
||||||
|
level:
|
||||||
|
root: WARN
|
||||||
|
com.gxwebsoft: ERROR
|
||||||
|
com.baomidou.mybatisplus: ERROR
|
||||||
|
|
||||||
|
socketio:
|
||||||
|
host: 0.0.0.0 #IP地址
|
||||||
|
|
||||||
|
knife4j:
|
||||||
|
# 开启knife4j增强
|
||||||
|
enable: true
|
||||||
|
# 开启生产环境屏蔽,一定要先开启knife4j增强才会生效
|
||||||
|
production: false
|
||||||
|
|
||||||
|
# 框架配置
|
||||||
|
config:
|
||||||
|
# 生产环境接口
|
||||||
|
server-url: https://server.guiletao.com/api
|
||||||
|
upload-path: /www/wwwroot/file.ws
|
||||||
|
|
||||||
|
# 阿里云OSS云存储
|
||||||
|
endpoint: https://oss-cn-shenzhen.aliyuncs.com
|
||||||
|
accessKeyId: LTAI4GKGZ9Z2Z8JZ77c3GNZP
|
||||||
|
accessKeySecret: BiDkpS7UXj72HWwDWaFZxiXjNFBNCM
|
||||||
|
bucketName: oss-gxwebsoft
|
||||||
|
bucketDomain: https://oss.wsdns.cn
|
||||||
|
aliyunDomain: https://oss-gxwebsoft.oss-cn-shenzhen.aliyuncs.com
|
||||||
|
|
||||||
|
# 生产环境证书配置
|
||||||
|
certificate:
|
||||||
|
# 生产环境使用挂载卷模式
|
||||||
|
load-mode: VOLUME
|
||||||
|
cert-root-path: /app/certs
|
||||||
Reference in New Issue
Block a user