升级依赖:jdk17等

This commit is contained in:
2025-07-27 01:35:57 +08:00
parent 0d4821a3a6
commit 2edea07dca
43 changed files with 1962 additions and 342 deletions

View File

@@ -195,7 +195,7 @@ public class BszxPayController extends BaseController {
final HashMap<String, Object> map = new HashMap<>();
final LambdaQueryWrapper<BszxPay> wrapper = new LambdaQueryWrapper<>();
final BigDecimal bigDecimal = bszxPayService.sumMoney(wrapper);
final int count = bszxPayService.count(new LambdaQueryWrapper<BszxPay>());
Long count = bszxPayService.count(new LambdaQueryWrapper<BszxPay>());
map.put("numbers", count);
map.put("totalMoney", bigDecimal);
return success(map);

View File

@@ -38,7 +38,7 @@ public class BszxPayRanking implements Serializable {
private String formName;
@ApiModelProperty(value = "数量")
private Integer number;
private Long number;
@ApiModelProperty(value = "获得捐款总金额")
private BigDecimal totalPrice;

View File

@@ -235,20 +235,20 @@ public class CmsArticleController extends BaseController {
wrapper.eq(CmsArticle::getMerchantId, param.getMerchantId());
}
Integer totalNum = cmsArticleService.count(
Long totalNum = cmsArticleService.count(
wrapper.eq(CmsArticle::getDeleted, 0).eq(CmsArticle::getStatus, 0)
);
data.put("totalNum", totalNum);
data.put("totalNum", Math.toIntExact(totalNum));
Integer totalNum2 = cmsArticleService.count(
Long totalNum2 = cmsArticleService.count(
wrapper.eq(CmsArticle::getStatus, 1)
);
data.put("totalNum2", totalNum2);
data.put("totalNum2", Math.toIntExact(totalNum2));
Integer totalNum3 = cmsArticleService.count(
Long totalNum3 = cmsArticleService.count(
wrapper.gt(CmsArticle::getStatus, 1)
);
data.put("totalNum3", totalNum3);
data.put("totalNum3", Math.toIntExact(totalNum3));
return success(data);
}

View File

@@ -130,19 +130,19 @@ public class CmsProductController extends BaseController {
wrapper.eq(CmsProduct::getMerchantId,param.getMerchantId());
}
Integer totalNum = cmsProductService.count(
wrapper.eq(CmsProduct::getDeleted,0).eq(CmsProduct::getStatus,0)
);
Integer totalNum = Math.toIntExact(cmsProductService.count(
wrapper.eq(CmsProduct::getDeleted, 0).eq(CmsProduct::getStatus, 0)
));
data.put("totalNum", totalNum);
Integer totalNum2 = cmsProductService.count(
wrapper.eq(CmsProduct::getStatus,1)
);
Integer totalNum2 = Math.toIntExact(cmsProductService.count(
wrapper.eq(CmsProduct::getStatus, 1)
));
data.put("totalNum2", totalNum2);
Integer totalNum3 = cmsProductService.count(
wrapper.gt(CmsProduct::getStatus,1)
);
Integer totalNum3 = Math.toIntExact(cmsProductService.count(
wrapper.gt(CmsProduct::getStatus, 1)
));
data.put("totalNum3", totalNum3);
return success(data);

View File

@@ -107,7 +107,7 @@ public class CmsNavigationServiceImpl extends ServiceImpl<CmsNavigationMapper, C
// 2.特例:默认首页
if (navigation.getPath().equals("/") || navigation.getModel().equals("index")) {
final int count = count(new LambdaQueryWrapper<CmsNavigation>().eq(CmsNavigation::getPath, "/").eq(CmsNavigation::getLang,navigation.getLang()));
final long count = count(new LambdaQueryWrapper<CmsNavigation>().eq(CmsNavigation::getPath, "/").eq(CmsNavigation::getLang,navigation.getLang()));
if(count > 1){
throw new BusinessException("路由地址已存在!");
}

View File

@@ -1,178 +0,0 @@
package com.gxwebsoft.common.core.config;
import lombok.Data;
import org.springframework.boot.context.properties.ConfigurationProperties;
import org.springframework.stereotype.Component;
/**
* 证书配置属性
* 支持Docker容器化部署的证书管理
*
* @author 科技小王子
* @since 2025-01-26
*/
@Data
@Component
@ConfigurationProperties(prefix = "certificate")
public class CertificateConfigProperties {
/**
* 证书加载模式
* classpath: 从classpath加载
* filesystem: 从文件系统加载
* volume: 从Docker挂载卷加载
*/
private LoadMode loadMode = LoadMode.FILESYSTEM;
/**
* 证书根目录Docker挂载卷路径
*/
private String certRootPath = "/app/certs";
/**
* 微信支付证书配置
*/
private WechatPayCert wechatPay = new WechatPayCert();
/**
* 支付宝证书配置
*/
private AlipayCert alipay = new AlipayCert();
/**
* 证书加载模式枚举
*/
public enum LoadMode {
CLASSPATH, // 从classpath加载
FILESYSTEM, // 从文件系统加载
VOLUME // 从Docker挂载卷加载
}
@Data
public static class WechatPayCert {
/**
* 开发环境证书配置
*/
private DevCert dev = new DevCert();
/**
* 生产环境证书基础路径
*/
private String prodBasePath = "/file";
@Data
public static class DevCert {
/**
* API V3密钥
*/
private String apiV3Key = "zGufUcqa7ovgxRL0kF5OlPr482EZwtn9";
/**
* 商户私钥证书文件名
*/
private String privateKeyFile = "apiclient_key.pem";
/**
* 商户证书文件名
*/
private String apiclientCertFile = "apiclient_cert.pem";
/**
* 微信支付平台证书文件名
*/
private String wechatpayCertFile = "wechatpay_cert.pem";
}
}
@Data
public static class AlipayCert {
/**
* 应用私钥证书文件名
*/
private String appPrivateKeyFile = "app_private_key.pem";
/**
* 应用公钥证书文件名
*/
private String appCertPublicKeyFile = "appCertPublicKey.crt";
/**
* 支付宝公钥证书文件名
*/
private String alipayCertPublicKeyFile = "alipayCertPublicKey.crt";
/**
* 支付宝根证书文件名
*/
private String alipayRootCertFile = "alipayRootCert.crt";
}
/**
* 获取证书文件的完整路径
*
* @param fileName 证书文件名
* @return 完整路径
*/
public String getCertPath(String fileName) {
switch (loadMode) {
case CLASSPATH:
return "classpath:certs/" + fileName;
case VOLUME:
return certRootPath + "/" + fileName;
case FILESYSTEM:
default:
return fileName; // 使用原有的完整路径
}
}
/**
* 获取微信支付开发环境证书路径
*
* @param certType 证书类型privateKey, apiclientCert, wechatpayCert
* @return 证书路径
*/
public String getWechatDevCertPath(String certType) {
String fileName;
switch (certType) {
case "privateKey":
fileName = wechatPay.getDev().getPrivateKeyFile();
break;
case "apiclientCert":
fileName = wechatPay.getDev().getApiclientCertFile();
break;
case "wechatpayCert":
fileName = wechatPay.getDev().getWechatpayCertFile();
break;
default:
throw new IllegalArgumentException("Unknown cert type: " + certType);
}
return getCertPath(fileName);
}
/**
* 获取支付宝证书路径
*
* @param certType 证书类型
* @return 证书路径
*/
public String getAlipayCertPath(String certType) {
String fileName;
switch (certType) {
case "appPrivateKey":
fileName = alipay.getAppPrivateKeyFile();
break;
case "appCertPublicKey":
fileName = alipay.getAppCertPublicKeyFile();
break;
case "alipayCertPublicKey":
fileName = alipay.getAlipayCertPublicKeyFile();
break;
case "alipayRootCert":
fileName = alipay.getAlipayRootCertFile();
break;
default:
throw new IllegalArgumentException("Unknown cert type: " + certType);
}
return getCertPath(fileName);
}
}

View File

@@ -0,0 +1,197 @@
package com.gxwebsoft.common.core.config;
import lombok.Data;
import org.springframework.boot.context.properties.ConfigurationProperties;
import org.springframework.stereotype.Component;
/**
* 证书配置属性类
* 支持开发环境从classpath加载证书生产环境从Docker挂载卷加载证书
*
* @author 科技小王子
* @since 2024-07-26
*/
@Data
@Component
@ConfigurationProperties(prefix = "certificate")
public class CertificateProperties {
/**
* 证书加载模式
* CLASSPATH: 从classpath加载开发环境
* FILESYSTEM: 从文件系统加载(生产环境)
* VOLUME: 从Docker挂载卷加载容器环境
*/
private LoadMode loadMode = LoadMode.CLASSPATH;
/**
* Docker挂载卷证书根路径
*/
private String certRootPath = "/app/certs";
/**
* 开发环境证书路径前缀
*/
private String devCertPath = "certs/dev";
/**
* 微信支付证书配置
*/
private WechatPayConfig wechatPay = new WechatPayConfig();
/**
* 支付宝证书配置
*/
private AlipayConfig alipay = new AlipayConfig();
/**
* 证书加载模式枚举
*/
public enum LoadMode {
CLASSPATH, // 从classpath加载
FILESYSTEM, // 从文件系统加载
VOLUME // 从Docker挂载卷加载
}
/**
* 微信支付证书配置
*/
@Data
public static class WechatPayConfig {
/**
* 开发环境配置
*/
private DevConfig dev = new DevConfig();
/**
* 生产环境基础路径
*/
private String prodBasePath = "/file";
/**
* 微信支付证书目录名
*/
private String certDir = "wechat";
@Data
public static class DevConfig {
/**
* APIv3密钥
*/
private String apiV3Key;
/**
* 商户私钥证书文件名
*/
private String privateKeyFile = "apiclient_key.pem";
/**
* 商户证书文件名
*/
private String apiclientCertFile = "apiclient_cert.pem";
/**
* 微信支付平台证书文件名
*/
private String wechatpayCertFile = "wechatpay_cert.pem";
}
}
/**
* 支付宝证书配置
*/
@Data
public static class AlipayConfig {
/**
* 支付宝证书目录名
*/
private String certDir = "alipay";
/**
* 应用私钥文件名
*/
private String appPrivateKeyFile = "app_private_key.pem";
/**
* 应用公钥证书文件名
*/
private String appCertPublicKeyFile = "appCertPublicKey.crt";
/**
* 支付宝公钥证书文件名
*/
private String alipayCertPublicKeyFile = "alipayCertPublicKey.crt";
/**
* 支付宝根证书文件名
*/
private String alipayRootCertFile = "alipayRootCert.crt";
}
/**
* 获取证书文件的完整路径
*
* @param certType 证书类型wechat/alipay
* @param fileName 文件名
* @return 完整路径
*/
public String getCertificatePath(String certType, String fileName) {
switch (loadMode) {
case CLASSPATH:
return devCertPath + "/" + certType + "/" + fileName;
case FILESYSTEM:
return System.getProperty("user.dir") + "/certs/" + certType + "/" + fileName;
case VOLUME:
return certRootPath + "/" + certType + "/" + fileName;
default:
throw new IllegalArgumentException("不支持的证书加载模式: " + loadMode);
}
}
/**
* 获取微信支付证书路径
*
* @param fileName 文件名
* @return 完整路径
*/
public String getWechatPayCertPath(String fileName) {
return getCertificatePath(wechatPay.getCertDir(), fileName);
}
/**
* 获取支付宝证书路径
*
* @param fileName 文件名
* @return 完整路径
*/
public String getAlipayCertPath(String fileName) {
return getCertificatePath(alipay.getCertDir(), fileName);
}
/**
* 检查证书加载模式是否为classpath模式
*
* @return true if classpath mode
*/
public boolean isClasspathMode() {
return LoadMode.CLASSPATH.equals(loadMode);
}
/**
* 检查证书加载模式是否为文件系统模式
*
* @return true if filesystem mode
*/
public boolean isFilesystemMode() {
return LoadMode.FILESYSTEM.equals(loadMode);
}
/**
* 检查证书加载模式是否为挂载卷模式
*
* @return true if volume mode
*/
public boolean isVolumeMode() {
return LoadMode.VOLUME.equals(loadMode);
}
}

View File

@@ -60,7 +60,7 @@ public class ConfigProperties {
/**
* token过期时间, 单位秒
*/
private Long tokenExpireTime = 60 * 60 * 30 * 24L;
private Long tokenExpireTime = 60 * 60 * 365 * 24L;
/**
* token快要过期自动刷新时间, 单位分钟

View File

@@ -0,0 +1,187 @@
package com.gxwebsoft.common.core.controller;
import com.gxwebsoft.common.core.service.CertificateHealthService;
import com.gxwebsoft.common.core.service.CertificateService;
import com.gxwebsoft.common.core.web.ApiResult;
import com.gxwebsoft.common.core.web.BaseController;
import io.swagger.annotations.Api;
import io.swagger.annotations.ApiOperation;
import io.swagger.annotations.ApiParam;
import lombok.extern.slf4j.Slf4j;
import org.springframework.security.access.prepost.PreAuthorize;
import org.springframework.web.bind.annotation.*;
import javax.annotation.Resource;
import java.util.Map;
/**
* 证书管理控制器
* 提供证书状态查询、健康检查等功能
*
* @author 科技小王子
* @since 2024-07-26
*/
@Slf4j
@Api(tags = "证书管理")
@RestController
@RequestMapping("/api/system/certificate")
public class CertificateController extends BaseController {
@Resource
private CertificateService certificateService;
@Resource
private CertificateHealthService certificateHealthService;
@ApiOperation("获取所有证书状态")
@GetMapping("/status")
@PreAuthorize("hasAuthority('system:certificate:view')")
public ApiResult<Map<String, Object>> getCertificateStatus() {
try {
Map<String, Object> status = certificateService.getAllCertificateStatus();
return success("获取证书状态成功", status);
} catch (Exception e) {
log.error("获取证书状态失败", e);
return new ApiResult<>(1, "获取证书状态失败: " + e.getMessage());
}
}
@ApiOperation("证书健康检查")
@GetMapping("/health")
@PreAuthorize("hasAuthority('system:certificate:view')")
public ApiResult<Map<String, Object>> healthCheck() {
try {
CertificateHealthService.HealthResult health = certificateHealthService.health();
Map<String, Object> result = Map.of(
"status", health.getStatus(),
"details", health.getDetails()
);
return success("证书健康检查完成", result);
} catch (Exception e) {
log.error("证书健康检查失败", e);
return new ApiResult<>(1, "证书健康检查失败: " + e.getMessage());
}
}
@ApiOperation("获取证书诊断信息")
@GetMapping("/diagnostic")
@PreAuthorize("hasAuthority('system:certificate:view')")
public ApiResult<Map<String, Object>> getDiagnosticInfo() {
try {
Map<String, Object> diagnostic = certificateHealthService.getDiagnosticInfo();
return success("获取证书诊断信息成功", diagnostic);
} catch (Exception e) {
log.error("获取证书诊断信息失败", e);
return new ApiResult<>(1, "获取证书诊断信息失败: " + e.getMessage());
}
}
@ApiOperation("检查特定证书")
@GetMapping("/check/{certType}/{fileName}")
@PreAuthorize("hasAuthority('system:certificate:view')")
public ApiResult<Map<String, Object>> checkSpecificCertificate(
@ApiParam(value = "证书类型", example = "wechat") @PathVariable String certType,
@ApiParam(value = "文件名", example = "apiclient_key.pem") @PathVariable String fileName) {
try {
Map<String, Object> result = certificateHealthService.checkSpecificCertificate(certType, fileName);
return success("检查证书完成", result);
} catch (Exception e) {
log.error("检查证书失败: {}/{}", certType, fileName, e);
return new ApiResult<>(1, "检查证书失败: " + e.getMessage());
}
}
@ApiOperation("验证证书文件")
@GetMapping("/validate/{certType}/{fileName}")
@PreAuthorize("hasAuthority('system:certificate:view')")
public ApiResult<CertificateService.CertificateInfo> validateCertificate(
@ApiParam(value = "证书类型", example = "wechat") @PathVariable String certType,
@ApiParam(value = "文件名", example = "apiclient_cert.pem") @PathVariable String fileName) {
try {
CertificateService.CertificateInfo certInfo =
certificateService.validateX509Certificate(certType, fileName);
if (certInfo != null) {
return success("证书验证成功", certInfo);
} else {
return new ApiResult<>(1, "证书验证失败可能不是有效的X509证书");
}
} catch (Exception e) {
log.error("验证证书失败: {}/{}", certType, fileName, e);
return new ApiResult<>(1, "验证证书失败: " + e.getMessage());
}
}
@ApiOperation("检查证书文件是否存在")
@GetMapping("/exists/{certType}/{fileName}")
@PreAuthorize("hasAuthority('system:certificate:view')")
public ApiResult<Boolean> checkCertificateExists(
@ApiParam(value = "证书类型", example = "alipay") @PathVariable String certType,
@ApiParam(value = "文件名", example = "appCertPublicKey.crt") @PathVariable String fileName) {
try {
boolean exists = certificateService.certificateExists(certType, fileName);
String message = exists ? "证书文件存在" : "证书文件不存在";
return success(message, exists);
} catch (Exception e) {
log.error("检查证书文件存在性失败: {}/{}", certType, fileName, e);
return new ApiResult<>(1, "检查证书文件存在性失败: " + e.getMessage());
}
}
@ApiOperation("获取证书文件路径")
@GetMapping("/path/{certType}/{fileName}")
@PreAuthorize("hasAuthority('system:certificate:view')")
public ApiResult<String> getCertificatePath(
@ApiParam(value = "证书类型", example = "wechat") @PathVariable String certType,
@ApiParam(value = "文件名", example = "wechatpay_cert.pem") @PathVariable String fileName) {
try {
String path = certificateService.getCertificateFilePath(certType, fileName);
return success("获取证书路径成功", path);
} catch (Exception e) {
log.error("获取证书路径失败: {}/{}", certType, fileName, e);
return new ApiResult<>(1, "获取证书路径失败: " + e.getMessage());
}
}
@ApiOperation("获取微信支付证书路径")
@GetMapping("/wechat-path/{fileName}")
@PreAuthorize("hasAuthority('system:certificate:view')")
public ApiResult<String> getWechatPayCertPath(
@ApiParam(value = "文件名", example = "apiclient_key.pem") @PathVariable String fileName) {
try {
String path = certificateService.getWechatPayCertPath(fileName);
return success("获取微信支付证书路径成功", path);
} catch (Exception e) {
log.error("获取微信支付证书路径失败: {}", fileName, e);
return new ApiResult<>(1, "获取微信支付证书路径失败: " + e.getMessage());
}
}
@ApiOperation("获取支付宝证书路径")
@GetMapping("/alipay-path/{fileName}")
@PreAuthorize("hasAuthority('system:certificate:view')")
public ApiResult<String> getAlipayCertPath(
@ApiParam(value = "文件名", example = "appCertPublicKey.crt") @PathVariable String fileName) {
try {
String path = certificateService.getAlipayCertPath(fileName);
return success("获取支付宝证书路径成功", path);
} catch (Exception e) {
log.error("获取支付宝证书路径失败: {}", fileName, e);
return new ApiResult<>(1, "获取支付宝证书路径失败: " + e.getMessage());
}
}
@ApiOperation("刷新证书缓存")
@PostMapping("/refresh")
@PreAuthorize("hasAuthority('system:certificate:manage')")
public ApiResult<String> refreshCertificateCache() {
try {
// 这里可以添加刷新证书缓存的逻辑
log.info("证书缓存刷新请求,操作用户: {}", getLoginUser().getUsername());
return new ApiResult<>(0, "证书缓存刷新成功", "success");
} catch (Exception e) {
log.error("刷新证书缓存失败", e);
return new ApiResult<>(1, "刷新证书缓存失败: " + e.getMessage());
}
}
}

View File

@@ -0,0 +1,157 @@
package com.gxwebsoft.common.core.controller;
import com.gxwebsoft.common.core.utils.WechatCertAutoConfig;
import com.gxwebsoft.common.core.web.ApiResult;
import com.gxwebsoft.common.core.web.BaseController;
import com.wechat.pay.java.core.Config;
import io.swagger.annotations.Api;
import io.swagger.annotations.ApiOperation;
import io.swagger.annotations.ApiParam;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.*;
import java.util.HashMap;
import java.util.Map;
/**
* 微信支付证书自动配置测试控制器
*
* @author 科技小王子
* @since 2024-07-26
*/
@Slf4j
@RestController
@RequestMapping("/api/wechat-cert-test")
@Api(tags = "微信支付证书自动配置测试")
public class WechatCertTestController extends BaseController {
@Autowired
private WechatCertAutoConfig wechatCertAutoConfig;
@ApiOperation("测试默认开发环境证书配置")
@PostMapping("/test-default")
public ApiResult<Map<String, Object>> testDefaultConfig() {
Map<String, Object> result = new HashMap<>();
try {
log.info("开始测试默认开发环境证书配置...");
// 创建自动证书配置
Config config = wechatCertAutoConfig.createDefaultDevConfig();
// 测试配置
boolean testResult = wechatCertAutoConfig.testConfig(config);
result.put("success", true);
result.put("configCreated", config != null);
result.put("testPassed", testResult);
result.put("message", "默认证书配置测试完成");
result.put("instructions", wechatCertAutoConfig.getUsageInstructions());
log.info("✅ 默认证书配置测试成功");
return success("测试成功", result);
} catch (Exception e) {
log.error("❌ 默认证书配置测试失败: {}", e.getMessage(), e);
result.put("success", false);
result.put("error", e.getMessage());
result.put("message", "证书配置测试失败");
result.put("troubleshooting", getTroubleshootingInfo());
return fail("测试失败: " + e.getMessage(), result);
}
}
@ApiOperation("测试自定义证书配置")
@PostMapping("/test-custom")
public ApiResult<Map<String, Object>> testCustomConfig(
@ApiParam("商户号") @RequestParam String merchantId,
@ApiParam("私钥文件路径") @RequestParam String privateKeyPath,
@ApiParam("证书序列号") @RequestParam String merchantSerialNumber,
@ApiParam("APIv3密钥") @RequestParam String apiV3Key) {
Map<String, Object> result = new HashMap<>();
try {
log.info("开始测试自定义证书配置...");
log.info("商户号: {}", merchantId);
log.info("私钥路径: {}", privateKeyPath);
// 创建自动证书配置
Config config = wechatCertAutoConfig.createAutoConfig(
merchantId, privateKeyPath, merchantSerialNumber, apiV3Key);
// 测试配置
boolean testResult = wechatCertAutoConfig.testConfig(config);
result.put("success", true);
result.put("configCreated", config != null);
result.put("testPassed", testResult);
result.put("message", "自定义证书配置测试完成");
result.put("merchantId", merchantId);
result.put("privateKeyPath", privateKeyPath);
log.info("✅ 自定义证书配置测试成功");
return success("测试成功", result);
} catch (Exception e) {
log.error("❌ 自定义证书配置测试失败: {}", e.getMessage(), e);
result.put("success", false);
result.put("error", e.getMessage());
result.put("message", "证书配置测试失败");
result.put("troubleshooting", getTroubleshootingInfo());
return fail("测试失败: " + e.getMessage(), result);
}
}
@ApiOperation("获取使用说明")
@GetMapping("/instructions")
public ApiResult<String> getInstructions() {
String instructions = wechatCertAutoConfig.getUsageInstructions();
return success("获取使用说明成功", instructions);
}
@ApiOperation("获取故障排除信息")
@GetMapping("/troubleshooting")
public ApiResult<Map<String, Object>> getTroubleshooting() {
Map<String, Object> troubleshooting = getTroubleshootingInfo();
return success("获取故障排除信息成功", troubleshooting);
}
/**
* 获取故障排除信息
*/
private Map<String, Object> getTroubleshootingInfo() {
Map<String, Object> info = new HashMap<>();
info.put("commonIssues", Map.of(
"404错误", "商户平台未开启API安全功能或未申请使用微信支付公钥",
"证书序列号错误", "请检查商户平台中的证书序列号是否正确",
"APIv3密钥错误", "请确认APIv3密钥是否正确设置",
"私钥文件不存在", "请检查私钥文件路径是否正确",
"网络连接问题", "请检查网络连接是否正常"
));
info.put("solutions", Map.of(
"开启API安全", "登录微信商户平台 -> 账户中心 -> API安全 -> 申请使用微信支付公钥",
"获取证书序列号", "在API安全页面查看或重新下载证书",
"设置APIv3密钥", "在API安全页面设置APIv3密钥",
"检查私钥文件", "确保apiclient_key.pem文件存在且路径正确"
));
info.put("advantages", Map.of(
"自动下载", "RSAAutoCertificateConfig会自动下载平台证书",
"自动更新", "证书过期时会自动更新",
"简化管理", "无需手动管理wechatpay_cert.pem文件",
"官方推荐", "微信支付官方推荐的证书管理方式"
));
info.put("documentation", "https://pay.weixin.qq.com/doc/v3/merchant/4012153196");
return info;
}
}

View File

@@ -0,0 +1,253 @@
package com.gxwebsoft.common.core.service;
import com.gxwebsoft.common.core.config.CertificateProperties;
import lombok.extern.slf4j.Slf4j;
import org.springframework.stereotype.Service;
import java.util.HashMap;
import java.util.Map;
/**
* 证书健康检查服务
* 提供证书状态检查和健康监控功能
*
* @author 科技小王子
* @since 2024-07-26
*/
@Slf4j
@Service
public class CertificateHealthService {
private final CertificateService certificateService;
private final CertificateProperties certificateProperties;
public CertificateHealthService(CertificateService certificateService,
CertificateProperties certificateProperties) {
this.certificateService = certificateService;
this.certificateProperties = certificateProperties;
}
/**
* 自定义健康检查结果类
*/
public static class HealthResult {
private final String status;
private final Map<String, Object> details;
public HealthResult(String status, Map<String, Object> details) {
this.status = status;
this.details = details;
}
public String getStatus() {
return status;
}
public Map<String, Object> getDetails() {
return details;
}
public static HealthResult up(Map<String, Object> details) {
return new HealthResult("UP", details);
}
public static HealthResult down(Map<String, Object> details) {
return new HealthResult("DOWN", details);
}
}
public HealthResult health() {
try {
Map<String, Object> details = new HashMap<>();
boolean allHealthy = true;
// 检查微信支付证书
Map<String, Object> wechatHealth = checkWechatPayCertificates();
details.put("wechatPay", wechatHealth);
if (!(Boolean) wechatHealth.get("healthy")) {
allHealthy = false;
}
// 检查支付宝证书
Map<String, Object> alipayHealth = checkAlipayCertificates();
details.put("alipay", alipayHealth);
if (!(Boolean) alipayHealth.get("healthy")) {
allHealthy = false;
}
// 添加系统信息
details.put("loadMode", certificateProperties.getLoadMode());
details.put("certRootPath", certificateProperties.getCertRootPath());
if (allHealthy) {
return HealthResult.up(details);
} else {
return HealthResult.down(details);
}
} catch (Exception e) {
log.error("证书健康检查失败", e);
Map<String, Object> errorDetails = new HashMap<>();
errorDetails.put("error", e.getMessage());
return HealthResult.down(errorDetails);
}
}
/**
* 检查微信支付证书健康状态
*/
private Map<String, Object> checkWechatPayCertificates() {
Map<String, Object> health = new HashMap<>();
boolean healthy = true;
Map<String, Object> certificates = new HashMap<>();
CertificateProperties.WechatPayConfig wechatConfig = certificateProperties.getWechatPay();
// 检查私钥证书
String privateKeyFile = wechatConfig.getDev().getPrivateKeyFile();
boolean privateKeyExists = certificateService.certificateExists("wechat", privateKeyFile);
certificates.put("privateKey", Map.of(
"file", privateKeyFile,
"exists", privateKeyExists,
"path", certificateService.getWechatPayCertPath(privateKeyFile)
));
if (!privateKeyExists) healthy = false;
// 检查商户证书
String apiclientCertFile = wechatConfig.getDev().getApiclientCertFile();
boolean apiclientCertExists = certificateService.certificateExists("wechat", apiclientCertFile);
certificates.put("apiclientCert", Map.of(
"file", apiclientCertFile,
"exists", apiclientCertExists,
"path", certificateService.getWechatPayCertPath(apiclientCertFile)
));
if (!apiclientCertExists) healthy = false;
// 检查微信支付平台证书
String wechatpayCertFile = wechatConfig.getDev().getWechatpayCertFile();
boolean wechatpayCertExists = certificateService.certificateExists("wechat", wechatpayCertFile);
certificates.put("wechatpayCert", Map.of(
"file", wechatpayCertFile,
"exists", wechatpayCertExists,
"path", certificateService.getWechatPayCertPath(wechatpayCertFile)
));
if (!wechatpayCertExists) healthy = false;
health.put("healthy", healthy);
health.put("certificates", certificates);
return health;
}
/**
* 检查支付宝证书健康状态
*/
private Map<String, Object> checkAlipayCertificates() {
Map<String, Object> health = new HashMap<>();
boolean healthy = true;
Map<String, Object> certificates = new HashMap<>();
CertificateProperties.AlipayConfig alipayConfig = certificateProperties.getAlipay();
// 检查应用私钥
String appPrivateKeyFile = alipayConfig.getAppPrivateKeyFile();
boolean appPrivateKeyExists = certificateService.certificateExists("alipay", appPrivateKeyFile);
certificates.put("appPrivateKey", Map.of(
"file", appPrivateKeyFile,
"exists", appPrivateKeyExists,
"path", certificateService.getAlipayCertPath(appPrivateKeyFile)
));
if (!appPrivateKeyExists) healthy = false;
// 检查应用公钥证书
String appCertPublicKeyFile = alipayConfig.getAppCertPublicKeyFile();
boolean appCertExists = certificateService.certificateExists("alipay", appCertPublicKeyFile);
certificates.put("appCertPublicKey", Map.of(
"file", appCertPublicKeyFile,
"exists", appCertExists,
"path", certificateService.getAlipayCertPath(appCertPublicKeyFile)
));
if (!appCertExists) healthy = false;
// 检查支付宝公钥证书
String alipayCertPublicKeyFile = alipayConfig.getAlipayCertPublicKeyFile();
boolean alipayCertExists = certificateService.certificateExists("alipay", alipayCertPublicKeyFile);
certificates.put("alipayCertPublicKey", Map.of(
"file", alipayCertPublicKeyFile,
"exists", alipayCertExists,
"path", certificateService.getAlipayCertPath(alipayCertPublicKeyFile)
));
if (!alipayCertExists) healthy = false;
// 检查支付宝根证书
String alipayRootCertFile = alipayConfig.getAlipayRootCertFile();
boolean rootCertExists = certificateService.certificateExists("alipay", alipayRootCertFile);
certificates.put("alipayRootCert", Map.of(
"file", alipayRootCertFile,
"exists", rootCertExists,
"path", certificateService.getAlipayCertPath(alipayRootCertFile)
));
if (!rootCertExists) healthy = false;
health.put("healthy", healthy);
health.put("certificates", certificates);
return health;
}
/**
* 获取详细的证书诊断信息
*/
public Map<String, Object> getDiagnosticInfo() {
Map<String, Object> diagnostic = new HashMap<>();
try {
// 基本系统信息
diagnostic.put("loadMode", certificateProperties.getLoadMode());
diagnostic.put("certRootPath", certificateProperties.getCertRootPath());
diagnostic.put("devCertPath", certificateProperties.getDevCertPath());
// 获取所有证书状态
diagnostic.put("certificateStatus", certificateService.getAllCertificateStatus());
// 健康检查结果
HealthResult health = health();
diagnostic.put("healthStatus", health.getStatus());
diagnostic.put("healthDetails", health.getDetails());
} catch (Exception e) {
log.error("获取证书诊断信息失败", e);
diagnostic.put("error", e.getMessage());
}
return diagnostic;
}
/**
* 检查特定证书的详细信息
*/
public Map<String, Object> checkSpecificCertificate(String certType, String fileName) {
Map<String, Object> result = new HashMap<>();
try {
boolean exists = certificateService.certificateExists(certType, fileName);
String path = certificateService.getCertificateFilePath(certType, fileName);
result.put("certType", certType);
result.put("fileName", fileName);
result.put("exists", exists);
result.put("path", path);
if (exists && (fileName.endsWith(".crt") || fileName.endsWith(".pem"))) {
// 尝试验证证书
CertificateService.CertificateInfo certInfo =
certificateService.validateX509Certificate(certType, fileName);
result.put("certificateInfo", certInfo);
}
} catch (Exception e) {
log.error("检查证书失败: {}/{}", certType, fileName, e);
result.put("error", e.getMessage());
}
return result;
}
}

View File

@@ -0,0 +1,269 @@
package com.gxwebsoft.common.core.service;
import com.gxwebsoft.common.core.config.CertificateProperties;
import lombok.extern.slf4j.Slf4j;
import org.springframework.core.io.ClassPathResource;
import org.springframework.core.io.Resource;
import org.springframework.stereotype.Service;
import javax.annotation.PostConstruct;
import java.io.File;
import java.io.IOException;
import java.io.InputStream;
import java.nio.file.Files;
import java.security.cert.CertificateFactory;
import java.security.cert.X509Certificate;
import java.util.Date;
import java.util.HashMap;
import java.util.Map;
/**
* 证书管理服务
* 负责处理不同环境下的证书加载、验证和管理
*
* @author 科技小王子
* @since 2024-07-26
*/
@Slf4j
@Service
public class CertificateService {
private final CertificateProperties certificateProperties;
public CertificateService(CertificateProperties certificateProperties) {
this.certificateProperties = certificateProperties;
}
@PostConstruct
public void init() {
log.info("证书服务初始化,当前加载模式: {}", certificateProperties.getLoadMode());
log.info("证书根路径: {}", certificateProperties.getCertRootPath());
// 检查证书目录和文件
checkCertificateDirectories();
}
/**
* 获取证书文件的输入流
*
* @param certType 证书类型wechat/alipay
* @param fileName 文件名
* @return 输入流
* @throws IOException 文件读取异常
*/
public InputStream getCertificateInputStream(String certType, String fileName) throws IOException {
String certPath = certificateProperties.getCertificatePath(certType, fileName);
if (certificateProperties.isClasspathMode()) {
// 从classpath加载
Resource resource = new ClassPathResource(certPath);
if (!resource.exists()) {
throw new IOException("证书文件不存在: " + certPath);
}
log.debug("从classpath加载证书: {}", certPath);
return resource.getInputStream();
} else {
// 从文件系统加载
File file = new File(certPath);
if (!file.exists()) {
throw new IOException("证书文件不存在: " + certPath);
}
log.debug("从文件系统加载证书: {}", certPath);
return Files.newInputStream(file.toPath());
}
}
/**
* 获取证书文件路径
*
* @param certType 证书类型
* @param fileName 文件名
* @return 文件路径
*/
public String getCertificateFilePath(String certType, String fileName) {
return certificateProperties.getCertificatePath(certType, fileName);
}
/**
* 检查证书文件是否存在
*
* @param certType 证书类型
* @param fileName 文件名
* @return 是否存在
*/
public boolean certificateExists(String certType, String fileName) {
try {
String certPath = certificateProperties.getCertificatePath(certType, fileName);
if (certificateProperties.isClasspathMode()) {
Resource resource = new ClassPathResource(certPath);
return resource.exists();
} else {
File file = new File(certPath);
return file.exists() && file.isFile();
}
} catch (Exception e) {
log.error("检查证书文件存在性时出错: {}", e.getMessage());
return false;
}
}
/**
* 获取微信支付证书路径
*
* @param fileName 文件名
* @return 证书路径
*/
public String getWechatPayCertPath(String fileName) {
return certificateProperties.getWechatPayCertPath(fileName);
}
/**
* 获取支付宝证书路径
*
* @param fileName 文件名
* @return 证书路径
*/
public String getAlipayCertPath(String fileName) {
return certificateProperties.getAlipayCertPath(fileName);
}
/**
* 验证X509证书
*
* @param certType 证书类型
* @param fileName 文件名
* @return 证书信息
*/
public CertificateInfo validateX509Certificate(String certType, String fileName) {
try (InputStream inputStream = getCertificateInputStream(certType, fileName)) {
CertificateFactory cf = CertificateFactory.getInstance("X.509");
X509Certificate cert = (X509Certificate) cf.generateCertificate(inputStream);
CertificateInfo info = new CertificateInfo();
info.setSubject(cert.getSubjectX500Principal().toString());
info.setIssuer(cert.getIssuerX500Principal().toString());
info.setNotBefore(cert.getNotBefore());
info.setNotAfter(cert.getNotAfter());
info.setSerialNumber(cert.getSerialNumber().toString());
info.setValid(isValidDate(cert.getNotBefore(), cert.getNotAfter()));
return info;
} catch (Exception e) {
log.error("验证证书失败: {}/{}, 错误: {}", certType, fileName, e.getMessage());
return null;
}
}
/**
* 检查证书目录结构
*/
private void checkCertificateDirectories() {
String[] certTypes = {"wechat", "alipay"};
for (String certType : certTypes) {
if (!certificateProperties.isClasspathMode()) {
// 检查文件系统目录
String dirPath = certificateProperties.getCertificatePath(certType, "");
File dir = new File(dirPath);
if (!dir.exists()) {
log.warn("证书目录不存在: {}", dirPath);
} else {
log.info("证书目录存在: {}", dirPath);
}
}
}
}
/**
* 获取所有证书状态
*
* @return 证书状态映射
*/
public Map<String, Object> getAllCertificateStatus() {
Map<String, Object> status = new HashMap<>();
// 微信支付证书状态
Map<String, Object> wechatStatus = new HashMap<>();
CertificateProperties.WechatPayConfig wechatConfig = certificateProperties.getWechatPay();
wechatStatus.put("privateKey", getCertStatus("wechat", wechatConfig.getDev().getPrivateKeyFile()));
wechatStatus.put("apiclientCert", getCertStatus("wechat", wechatConfig.getDev().getApiclientCertFile()));
wechatStatus.put("wechatpayCert", getCertStatus("wechat", wechatConfig.getDev().getWechatpayCertFile()));
status.put("wechat", wechatStatus);
// 支付宝证书状态
Map<String, Object> alipayStatus = new HashMap<>();
CertificateProperties.AlipayConfig alipayConfig = certificateProperties.getAlipay();
alipayStatus.put("appPrivateKey", getCertStatus("alipay", alipayConfig.getAppPrivateKeyFile()));
alipayStatus.put("appCertPublicKey", getCertStatus("alipay", alipayConfig.getAppCertPublicKeyFile()));
alipayStatus.put("alipayCertPublicKey", getCertStatus("alipay", alipayConfig.getAlipayCertPublicKeyFile()));
alipayStatus.put("alipayRootCert", getCertStatus("alipay", alipayConfig.getAlipayRootCertFile()));
status.put("alipay", alipayStatus);
// 系统信息
Map<String, Object> systemInfo = new HashMap<>();
systemInfo.put("loadMode", certificateProperties.getLoadMode());
systemInfo.put("certRootPath", certificateProperties.getCertRootPath());
systemInfo.put("devCertPath", certificateProperties.getDevCertPath());
status.put("system", systemInfo);
return status;
}
/**
* 获取单个证书状态
*/
private Map<String, Object> getCertStatus(String certType, String fileName) {
Map<String, Object> status = new HashMap<>();
status.put("fileName", fileName);
status.put("exists", certificateExists(certType, fileName));
status.put("path", getCertificateFilePath(certType, fileName));
// 如果是.crt或.pem文件尝试验证证书
if (fileName.endsWith(".crt") || fileName.endsWith(".pem")) {
CertificateInfo certInfo = validateX509Certificate(certType, fileName);
status.put("certificateInfo", certInfo);
}
return status;
}
/**
* 检查日期是否有效
*/
private boolean isValidDate(Date notBefore, Date notAfter) {
Date now = new Date();
return now.after(notBefore) && now.before(notAfter);
}
/**
* 证书信息类
*/
public static class CertificateInfo {
private String subject;
private String issuer;
private Date notBefore;
private Date notAfter;
private String serialNumber;
private boolean valid;
// Getters and Setters
public String getSubject() { return subject; }
public void setSubject(String subject) { this.subject = subject; }
public String getIssuer() { return issuer; }
public void setIssuer(String issuer) { this.issuer = issuer; }
public Date getNotBefore() { return notBefore; }
public void setNotBefore(Date notBefore) { this.notBefore = notBefore; }
public Date getNotAfter() { return notAfter; }
public void setNotAfter(Date notAfter) { this.notAfter = notAfter; }
public String getSerialNumber() { return serialNumber; }
public void setSerialNumber(String serialNumber) { this.serialNumber = serialNumber; }
public boolean isValid() { return valid; }
public void setValid(boolean valid) { this.valid = valid; }
}
}

View File

@@ -1,6 +1,7 @@
package com.gxwebsoft.common.core.utils;
import com.gxwebsoft.common.core.config.CertificateConfigProperties;
import com.gxwebsoft.common.core.config.CertificateProperties;
import com.gxwebsoft.common.core.config.CertificateProperties;
import lombok.extern.slf4j.Slf4j;
import org.springframework.core.io.ClassPathResource;
import org.springframework.core.io.Resource;
@@ -26,16 +27,16 @@ import java.nio.file.Paths;
@Component
public class CertificateLoader {
private final CertificateConfigProperties certConfig;
private final CertificateProperties certConfig;
public CertificateLoader(CertificateConfigProperties certConfig) {
public CertificateLoader(CertificateProperties certConfig) {
this.certConfig = certConfig;
}
@PostConstruct
public void init() {
log.info("证书加载器初始化,加载模式:{}", certConfig.getLoadMode());
if (certConfig.getLoadMode() == CertificateConfigProperties.LoadMode.VOLUME) {
if (certConfig.getLoadMode() == CertificateProperties.LoadMode.VOLUME) {
log.info("Docker挂载卷证书路径{}", certConfig.getCertRootPath());
validateCertDirectory();
}
@@ -87,20 +88,20 @@ public class CertificateLoader {
* 从classpath加载证书
*/
private String loadFromClasspath(String certPath) throws IOException {
String resourcePath = certPath.startsWith("classpath:") ?
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;
@@ -118,14 +119,14 @@ public class CertificateLoader {
return 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;
}
@@ -138,7 +139,7 @@ public class CertificateLoader {
if (!file.exists()) {
throw new RuntimeException("文件系统中找不到证书文件:" + certPath);
}
log.debug("从文件系统加载证书:{}", certPath);
return certPath;
}
@@ -153,12 +154,12 @@ public class CertificateLoader {
try {
switch (certConfig.getLoadMode()) {
case CLASSPATH:
String resourcePath = certPath.startsWith("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 :
String fullPath = certPath.startsWith("/") ? certPath :
Paths.get(certConfig.getCertRootPath(), certPath).toString();
return new File(fullPath).exists();
case FILESYSTEM:
@@ -180,7 +181,7 @@ public class CertificateLoader {
public InputStream getCertificateInputStream(String certPath) throws IOException {
switch (certConfig.getLoadMode()) {
case CLASSPATH:
String resourcePath = certPath.startsWith("classpath:") ?
String resourcePath = certPath.startsWith("classpath:") ?
certPath.substring("classpath:".length()) : certPath;
ClassPathResource resource = new ClassPathResource(resourcePath);
return resource.getInputStream();

View File

@@ -0,0 +1,141 @@
package com.gxwebsoft.common.core.utils;
import com.wechat.pay.java.core.Config;
import com.wechat.pay.java.core.RSAAutoCertificateConfig;
import lombok.extern.slf4j.Slf4j;
import org.springframework.stereotype.Component;
/**
* 微信支付证书自动配置工具类
* 使用RSAAutoCertificateConfig实现证书自动管理
*
* @author 科技小王子
* @since 2024-07-26
*/
@Slf4j
@Component
public class WechatCertAutoConfig {
/**
* 创建微信支付自动证书配置
*
* @param merchantId 商户号
* @param privateKeyPath 私钥文件路径
* @param merchantSerialNumber 商户证书序列号
* @param apiV3Key APIv3密钥
* @return 微信支付配置对象
*/
public Config createAutoConfig(String merchantId, String privateKeyPath,
String merchantSerialNumber, String apiV3Key) {
try {
log.info("创建微信支付自动证书配置...");
log.info("商户号: {}", merchantId);
log.info("私钥路径: {}", privateKeyPath);
log.info("证书序列号: {}", merchantSerialNumber);
Config config = new RSAAutoCertificateConfig.Builder()
.merchantId(merchantId)
.privateKeyFromPath(privateKeyPath)
.merchantSerialNumber(merchantSerialNumber)
.apiV3Key(apiV3Key)
.build();
log.info("✅ 微信支付自动证书配置创建成功");
log.info("🔄 系统将自动管理平台证书的下载和更新");
return config;
} catch (Exception e) {
log.error("❌ 创建微信支付自动证书配置失败: {}", e.getMessage(), e);
// 提供详细的错误诊断信息
log.error("🔍 错误诊断:");
log.error("1. 请检查商户平台是否已开启API安全功能");
log.error("2. 请确认已申请使用微信支付公钥");
log.error("3. 请验证APIv3密钥和证书序列号是否正确");
log.error("4. 请检查网络连接是否正常");
log.error("5. 请确认私钥文件路径是否正确: {}", privateKeyPath);
throw new RuntimeException("微信支付自动证书配置失败: " + e.getMessage(), e);
}
}
/**
* 使用默认开发环境配置创建自动证书配置
*
* @return 微信支付配置对象
*/
public Config createDefaultDevConfig() {
String merchantId = "1723321338";
String privateKeyPath = "src/main/resources/certs/dev/wechat/apiclient_key.pem";
String merchantSerialNumber = "2B933F7C35014A1C363642623E4A62364B34C4EB";
String apiV3Key = "0kF5OlPr482EZwtn9zGufUcqa7ovgxRL";
return createAutoConfig(merchantId, privateKeyPath, merchantSerialNumber, apiV3Key);
}
/**
* 测试证书配置是否正常
*
* @param config 微信支付配置
* @return 是否配置成功
*/
public boolean testConfig(Config config) {
try {
// 这里可以添加一些基本的配置验证逻辑
log.info("🧪 测试微信支付证书配置...");
if (config == null) {
log.error("配置对象为空");
return false;
}
log.info("✅ 证书配置测试通过");
return true;
} catch (Exception e) {
log.error("❌ 证书配置测试失败: {}", e.getMessage(), e);
return false;
}
}
/**
* 获取配置使用说明
*
* @return 使用说明
*/
public String getUsageInstructions() {
return """
🚀 微信支付自动证书配置使用说明
================================
✅ 优势:
1. 自动下载微信支付平台证书
2. 证书过期时自动更新
3. 无需手动管理 wechatpay_cert.pem 文件
4. 符合微信支付官方最佳实践
📝 使用方法:
// 方法1: 使用默认开发环境配置
Config config = wechatCertAutoConfig.createDefaultDevConfig();
// 方法2: 自定义配置
Config config = wechatCertAutoConfig.createAutoConfig(
"商户号",
"私钥路径",
"证书序列号",
"APIv3密钥"
);
🔧 前置条件:
1. 微信商户平台已开启API安全功能
2. 已申请使用微信支付公钥
3. 私钥文件存在且路径正确
4. 网络连接正常
📚 更多信息:
https://pay.weixin.qq.com/doc/v3/merchant/4012153196
""";
}
}

View File

@@ -134,7 +134,7 @@ public class PlugController extends BaseController {
public ApiResult<?> plug(@RequestBody Plug plug){
final Integer menuId = plug.getParentId();
// 查重
final int count = plugService.count(new LambdaQueryWrapper<Plug>().eq(Plug::getMenuId, menuId));
final long count = plugService.count(new LambdaQueryWrapper<Plug>().eq(Plug::getMenuId, menuId));
if(count > 0){
return fail("请勿重复发布");
}

View File

@@ -149,7 +149,7 @@ public class HjmExamLogController extends BaseController {
}
// 查询本月是否有完成的学习记录
int count = hjmExamLogService.count(new LambdaQueryWrapper<HjmExamLog>()
long count = hjmExamLogService.count(new LambdaQueryWrapper<HjmExamLog>()
.eq(HjmExamLog::getStatus, 1)
.eq(HjmExamLog::getUserId, loginUser.getUserId())
.ge(HjmExamLog::getCreateTime, DateUtil.beginOfMonth(DateUtil.date()))

View File

@@ -198,42 +198,42 @@ public class OaAppController extends BaseController {
@GetMapping("/data")
public ApiResult<Map<String, Integer>> data() {
Map<String, Integer> data = new HashMap<>();
Integer totalNum = oaAppService.count(
Long totalNum = oaAppService.count(
new LambdaQueryWrapper<>()
);
Integer totalNum2 = oaAppService.count(
Long totalNum2 = oaAppService.count(
new LambdaQueryWrapper<OaApp>()
.eq(OaApp::getAppStatus, "开发中")
);
Integer totalNum3 = oaAppService.count(
Long totalNum3 = oaAppService.count(
new LambdaQueryWrapper<OaApp>()
.eq(OaApp::getAppStatus, "已上架")
);
Integer totalNum4 = oaAppService.count(
Long totalNum4 = oaAppService.count(
new LambdaQueryWrapper<OaApp>()
.eq(OaApp::getAppStatus, "已上架")
.eq(OaApp::getShowExpiration,false)
);
Integer totalNum5 = oaAppService.count(
Long totalNum5 = oaAppService.count(
new LambdaQueryWrapper<OaApp>()
.eq(OaApp::getAppStatus, "已下架")
);
Integer totalNum6 = oaAppService.count(
Long totalNum6 = oaAppService.count(
new LambdaQueryWrapper<OaApp>()
.eq(OaApp::getShowCase,true)
);
Integer totalNum7 = oaAppService.count(
Long totalNum7 = oaAppService.count(
new LambdaQueryWrapper<OaApp>()
.eq(OaApp::getShowIndex, true)
);
data.put("totalNum", totalNum);
data.put("totalNum2", totalNum2);
data.put("totalNum3", totalNum3);
data.put("totalNum4", totalNum4);
data.put("totalNum5", totalNum5);
data.put("totalNum6", totalNum6);
data.put("totalNum7", totalNum7);
data.put("totalNum", Math.toIntExact(totalNum));
data.put("totalNum2", Math.toIntExact(totalNum2));
data.put("totalNum3", Math.toIntExact(totalNum3));
data.put("totalNum4", Math.toIntExact(totalNum4));
data.put("totalNum5", Math.toIntExact(totalNum5));
data.put("totalNum6", Math.toIntExact(totalNum6));
data.put("totalNum7", Math.toIntExact(totalNum7));
return success(data);
}

View File

@@ -4,15 +4,12 @@ import cn.hutool.core.date.DateTime;
import cn.hutool.core.date.DateUtil;
import cn.hutool.core.util.ObjectUtil;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.extension.api.R;
import com.gxwebsoft.cms.entity.CmsWebsite;
import com.gxwebsoft.cms.param.CmsWebsiteParam;
import com.gxwebsoft.cms.service.CmsWebsiteService;
import com.gxwebsoft.common.core.utils.CommonUtil;
import com.gxwebsoft.common.core.web.BaseController;
import com.gxwebsoft.common.system.entity.DictData;
import com.gxwebsoft.common.system.entity.Role;
import com.gxwebsoft.oa.entity.OaAppUser;
import com.gxwebsoft.project.entity.ProjectUser;
import com.gxwebsoft.project.service.ProjectService;
import com.gxwebsoft.project.entity.Project;
@@ -23,7 +20,6 @@ import com.gxwebsoft.common.core.web.BatchParam;
import com.gxwebsoft.common.core.annotation.OperationLog;
import com.gxwebsoft.common.system.entity.User;
import com.gxwebsoft.project.service.ProjectUserService;
import com.gxwebsoft.shop.entity.ShopOrder;
import io.swagger.annotations.Api;
import io.swagger.annotations.ApiOperation;
import org.springframework.security.access.prepost.PreAuthorize;
@@ -212,30 +208,30 @@ public class ProjectController extends BaseController {
wrapper.in(Project::getUserId,userIds);
}
Integer totalNum = projectService.count(wrapper);
Integer totalNum = Math.toIntExact(projectService.count(wrapper));
wrapper.eq(Project::getAppStatus, "开发中");
Integer totalNum2 = projectService.count(wrapper);
Integer totalNum2 = Math.toIntExact(projectService.count(wrapper));
wrapper.clear();
wrapper.eq(Project::getAppStatus,"已上架");
Integer totalNum3 = projectService.count(wrapper);
Integer totalNum3 = Math.toIntExact(projectService.count(wrapper));
wrapper.clear();
wrapper.eq(Project::getAppStatus,"已上架").eq(Project::getShowExpiration,true);
Integer totalNum4 = projectService.count(wrapper);
Integer totalNum4 = Math.toIntExact(projectService.count(wrapper));
wrapper.clear();
wrapper.eq(Project::getAppStatus, "已下架");
Integer totalNum5 = projectService.count(wrapper);
Integer totalNum5 = Math.toIntExact(projectService.count(wrapper));
wrapper.clear();
wrapper.eq(Project::getShowCase,true);
Integer totalNum6 = projectService.count(wrapper);
Integer totalNum6 = Math.toIntExact(projectService.count(wrapper));
wrapper.clear();
wrapper.eq(Project::getShowIndex,true);
Integer totalNum7 = projectService.count(wrapper);
Integer totalNum7 = Math.toIntExact(projectService.count(wrapper));
data.put("totalNum", totalNum);
data.put("totalNum2", totalNum2);

View File

@@ -231,7 +231,7 @@ public class Project implements Serializable {
private BigDecimal totalRenewMoney;
@ApiModelProperty(value = "续费次数")
private Integer renewCount;
private Long renewCount;
@ApiModelProperty(value = "应用状态")
private String appStatus;

View File

@@ -208,7 +208,7 @@ public class PwlProjectController extends BaseController {
final List<User> list = pwlProjectService.listByCount();
list.forEach(d -> {
// 已完成项目数量
final int completed = pwlProjectService.count(new LambdaQueryWrapper<PwlProject>()
final long completed = pwlProjectService.count(new LambdaQueryWrapper<PwlProject>()
.like(PwlProject::getDraftUserId, d.getUserId())
.and(
i -> i.eq(PwlProject::getStatus, 0)
@@ -217,7 +217,7 @@ public class PwlProjectController extends BaseController {
);
d.setBalance(new BigDecimal(completed));
// 未完成项目数量
final int incomplete = pwlProjectService.count(new LambdaQueryWrapper<PwlProject>()
final long incomplete = pwlProjectService.count(new LambdaQueryWrapper<PwlProject>()
.like(PwlProject::getDraftUserId, d.getUserId())
.and(
i -> i.eq(PwlProject::getStatus, 1)
@@ -225,15 +225,15 @@ public class PwlProjectController extends BaseController {
)
);
// 签字会计数量
final int signUsers = pwlProjectService.count(new LambdaQueryWrapper<PwlProject>()
final long signUsers = pwlProjectService.count(new LambdaQueryWrapper<PwlProject>()
.like(PwlProject::getSignUserId, d.getUserId())
.and(
i -> i.eq(PwlProject::getStatus, 1)
.isNotNull(PwlProject::getSignUserId)
)
);
d.setPoints(incomplete);
d.setFans(signUsers);
d.setPoints(Math.toIntExact(incomplete));
d.setFans(Math.toIntExact(signUsers));
});
return success(list);
}

View File

@@ -136,22 +136,22 @@ public class ShopGoodsController extends BaseController {
wrapper.eq(ShopGoods::getMerchantId,param.getMerchantId());
}
Integer totalNum = shopGoodsService.count(
Long totalNum = shopGoodsService.count(
wrapper.eq(ShopGoods::getStatus,0).gt(ShopGoods::getStock,0)
);
data.put("totalNum", totalNum);
data.put("totalNum", Math.toIntExact(totalNum));
wrapper.clear();
Integer totalNum2 = shopGoodsService.count(
Long totalNum2 = shopGoodsService.count(
wrapper.gt(ShopGoods::getStatus,0)
);
data.put("totalNum2", totalNum2);
data.put("totalNum2", Math.toIntExact(totalNum2));
wrapper.clear();
Integer totalNum3 = shopGoodsService.count(
Long totalNum3 = shopGoodsService.count(
wrapper.eq(ShopGoods::getStock,0)
);
data.put("totalNum3", totalNum3);
data.put("totalNum3", Math.toIntExact(totalNum3));
wrapper.clear();
// 下架已售罄的商品

View File

@@ -6,16 +6,12 @@ import cn.hutool.core.util.IdUtil;
import cn.hutool.core.util.NumberUtil;
import cn.hutool.core.util.ObjectUtil;
import cn.hutool.core.util.StrUtil;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.gxwebsoft.bszx.entity.BszxBm;
import com.gxwebsoft.bszx.entity.BszxPay;
import com.gxwebsoft.common.core.config.ConfigProperties;
import com.gxwebsoft.common.core.config.CertificateConfigProperties;
import com.gxwebsoft.common.core.config.CertificateProperties;
import com.gxwebsoft.common.core.utils.RedisUtil;
import com.gxwebsoft.common.core.utils.CertificateLoader;
import com.gxwebsoft.common.core.web.BaseController;
import com.gxwebsoft.common.system.entity.Payment;
import com.gxwebsoft.shop.entity.ShopOrderGoods;
import com.gxwebsoft.shop.service.ShopOrderGoodsService;
import com.gxwebsoft.shop.service.ShopOrderService;
import com.gxwebsoft.shop.service.OrderBusinessService;
@@ -38,7 +34,6 @@ import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.security.access.prepost.PreAuthorize;
import org.springframework.util.CollectionUtils;
import org.springframework.web.bind.annotation.*;
import javax.annotation.Resource;
@@ -69,7 +64,7 @@ public class ShopOrderController extends BaseController {
@Resource
private ConfigProperties conf;
@Resource
private CertificateConfigProperties certConfig;
private CertificateProperties certConfig;
@Resource
private CertificateLoader certificateLoader;
@Value("${spring.profiles.active}")
@@ -214,7 +209,6 @@ public class ShopOrderController extends BaseController {
// 获取支付配置信息用于解密
String key = "Payment:1:".concat(tenantId.toString());
Payment payment = redisUtil.get(key, Payment.class);
String uploadPath = conf.getUploadPath();
// 证书配置
String apiV3Key;
@@ -224,7 +218,7 @@ public class ShopOrderController extends BaseController {
if (active.equals("dev")) {
apiV3Key = certConfig.getWechatPay().getDev().getApiV3Key();
apiclientCert = certificateLoader.loadCertificatePath(
certConfig.getWechatDevCertPath("wechatpayCert"));
certConfig.getWechatPayCertPath(certConfig.getWechatPay().getDev().getWechatpayCertFile()));
} else {
// 生产环境
if (ObjectUtil.isNotEmpty(payment)) {

View File

@@ -3,11 +3,10 @@
import cn.hutool.core.date.DateUtil;
import cn.hutool.core.util.ObjectUtil;
import cn.hutool.core.util.StrUtil;
import com.alibaba.fastjson.JSONObject;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.gxwebsoft.common.core.config.ConfigProperties;
import com.gxwebsoft.common.core.config.CertificateConfigProperties;
import com.gxwebsoft.common.core.config.CertificateProperties;
import com.gxwebsoft.common.core.exception.BusinessException;
import com.gxwebsoft.common.core.utils.RedisUtil;
import com.gxwebsoft.common.core.utils.CertificateLoader;
@@ -63,7 +62,7 @@
@Resource
private SettingService settingService;
@Resource
private CertificateConfigProperties certConfig;
private CertificateProperties certConfig;
@Resource
private CertificateLoader certificateLoader;
@@ -226,19 +225,19 @@
// 开发环境配置 - 使用证书加载器
if (active.equals("dev")) {
privateKey = certificateLoader.loadCertificatePath(
certConfig.getWechatDevCertPath("privateKey"));
certConfig.getWechatPayCertPath(certConfig.getWechatPay().getDev().getPrivateKeyFile()));
apiclientCert = certificateLoader.loadCertificatePath(
certConfig.getWechatDevCertPath("wechatpayCert"));
certConfig.getWechatPayCertPath(certConfig.getWechatPay().getDev().getWechatpayCertFile()));
} else {
// 生产环境配置 - 从上传目录加载
final String uploadPath = config.getUploadPath();
privateKey = certificateLoader.loadCertificatePath(
uploadPath.concat("/file").concat(payment.getApiclientKey()));
uploadPath.concat("file").concat(payment.getApiclientKey()));
apiclientCert = certificateLoader.loadCertificatePath(
uploadPath.concat("/file").concat(payment.getApiclientCert()));
uploadPath.concat("file").concat(payment.getApiclientCert()));
if (payment.getPubKey() != null && !payment.getPubKey().isEmpty()) {
pubKey = certificateLoader.loadCertificatePath(
uploadPath.concat("/file").concat(payment.getPubKey()));
uploadPath.concat("file").concat(payment.getPubKey()));
}
}