Browse Source

新增分佣

main
梁欣 2 weeks ago
parent
commit
5d55376ea7
  1. 3
      src/main/java/com/gxwebsoft/common/core/security/SecurityConfig.java
  2. 50
      src/main/java/com/gxwebsoft/common/core/utils/RequestUtil.java
  3. 91
      src/main/java/com/gxwebsoft/common/core/utils/WechatCertAutoConfig.java
  4. 2
      src/main/java/com/gxwebsoft/common/system/entity/User.java
  5. 620
      src/main/java/com/gxwebsoft/shop/controller/ShopOrderController.java
  6. 2
      src/main/java/com/gxwebsoft/shop/entity/ShopDealerOrder.java
  7. 3
      src/main/java/com/gxwebsoft/shop/entity/ShopGoods.java
  8. 1
      src/main/java/com/gxwebsoft/shop/service/ShopOrderGoodsService.java
  9. 9
      src/main/java/com/gxwebsoft/shop/service/impl/ShopOrderGoodsServiceImpl.java
  10. 127
      src/main/java/com/gxwebsoft/shop/service/impl/ShopOrderServiceImpl.java
  11. 4
      src/main/resources/application-prod.yml
  12. 2
      src/main/resources/application.yml

3
src/main/java/com/gxwebsoft/common/core/security/SecurityConfig.java

@ -73,7 +73,8 @@ public class SecurityConfig {
"/api/cms/form-record",
"/api/shop/merchant-account/getMerchantAccountByPhone",
"/api/hjm/hjm-car/**",
"/api/chat/**"
"/api/chat/**",
"/api/shop/shop-order/test"
)
.permitAll()
.anyRequest()

50
src/main/java/com/gxwebsoft/common/core/utils/RequestUtil.java

@ -4,6 +4,7 @@ import cn.hutool.http.HttpRequest;
import com.alibaba.fastjson.JSONObject;
import com.gxwebsoft.common.core.config.ConfigProperties;
import com.gxwebsoft.common.core.web.ApiResult;
import com.gxwebsoft.common.system.entity.DictData;
import com.gxwebsoft.common.system.entity.Payment;
import com.gxwebsoft.common.system.entity.User;
import com.gxwebsoft.common.system.entity.UserRole;
@ -121,6 +122,24 @@ public class RequestUtil {
return null;
}
public User getByUserIdWithoutLogin(Integer userId) {
String path = "/system/user/getByUserId/" + userId;
try {
// 链式构建请求
String result = HttpRequest.get(getServerUrl().concat(path))
.header("Tenantid", TENANT_ID)
.timeout(20000)//超时,毫秒
.execute().body();
JSONObject jsonObject = JSONObject.parseObject(result);
System.out.println("jsonObject = " + jsonObject);
final String data = jsonObject.getString("data");
return JSONObject.parseObject(data, User.class);
} catch (Exception e) {
e.printStackTrace();
}
return null;
}
// 新增用户
public boolean saveUserByPhone(ShopMerchantAccount merchantAccount) {
String path = "/system/user/";
@ -173,7 +192,6 @@ public class RequestUtil {
try {
// 链式构建请求
final String result = HttpRequest.get(getServerUrl().concat("/system/user-referee/getReferee/" + userId))
.header("Authorization", ACCESS_TOKEN)
.header("Tenantid", TENANT_ID)
.timeout(20000)
.execute().body();
@ -202,6 +220,21 @@ public class RequestUtil {
}
}
// 更新用户信息
public void updateWithoutLogin(User user) {
String path = "/system/user/updateWithoutLogin";
try {
// 链式构建请求
final String body = HttpRequest.put(getServerUrl().concat(path))
.header("Tenantid", TENANT_ID)
.body(JSONUtil.toJSONString(user))
.timeout(20000)
.execute().body();
} catch (Exception e) {
e.printStackTrace();
}
}
public String getMpOrderQrCode(String orderNo) {
String path = "/wx-login/getOrderQRCode/";
try {
@ -271,6 +304,21 @@ public class RequestUtil {
}
}
public ApiResult<?> pageDictData(Integer dictId) {
String path = "/system/dict-data/page";
try {
// 链式构建请求
final String body = HttpRequest.get(getServerUrl().concat(path).concat("?dictId=" + dictId))
.header("tenantId", TENANT_ID)
.timeout(20000)
.execute().body();
return JSONUtil.parseObject(body, ApiResult.class);
} catch (Exception e) {
e.printStackTrace();
return null;
}
}
// 余额支付通知
public void pushBalancePayNotify(Transaction transaction, Payment payment) {
System.out.println("payment = " + payment);

91
src/main/java/com/gxwebsoft/common/core/utils/WechatCertAutoConfig.java

@ -3,16 +3,12 @@ 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.beans.factory.annotation.Value;
import org.springframework.stereotype.Component;
import com.gxwebsoft.common.core.config.ConfigProperties;
import javax.annotation.Resource;
/**
* 微信支付证书自动配置工具类
* 使用RSAAutoCertificateConfig实现证书自动管理
*
*
* @author 科技小王子
* @since 2024-07-26
*/
@ -20,47 +16,38 @@ import javax.annotation.Resource;
@Component
public class WechatCertAutoConfig {
@Value("${spring.profiles.active:prod}")
private String activeProfile;
@Resource
private ConfigProperties configProperties;
@Resource
private ConfigProperties configProperties;
/**
* 创建微信支付自动证书配置
*
*
* @param merchantId 商户号
* @param privateKeyPath 私钥文件路径
* @param merchantSerialNumber 商户证书序列号
* @param apiV3Key APIv3密钥
* @return 微信支付配置对象
*/
public Config createAutoConfig(String merchantId, String privateKeyPath,
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安全功能");
@ -68,48 +55,28 @@ public class WechatCertAutoConfig {
log.error("3. 请验证APIv3密钥和证书序列号是否正确");
log.error("4. 请检查网络连接是否正常");
log.error("5. 请确认私钥文件路径是否正确: {}", privateKeyPath);
throw new RuntimeException("微信支付自动证书配置失败: " + e.getMessage(), e);
}
}
/**
* 使用默认开发环境配置创建自动证书配置
* 根据当前环境自动选择证书路径
* 开发环境拼接规则配置文件upload-path + dev/wechat/ + 租户ID
*
*
* @return 微信支付配置对象
*/
public Config createDefaultDevConfig() {
String merchantId = "1723321338";
String privateKeyPath;
String privateKeyPath = "src/main/resources/certs/dev/wechat/apiclient_key.pem";
String merchantSerialNumber = "2B933F7C35014A1C363642623E4A62364B34C4EB";
String apiV3Key = "0kF5OlPr482EZwtn9zGufUcqa7ovgxRL";
// 根据环境选择证书路径
if ("dev".equals(activeProfile)) {
// 开发环境:使用配置文件upload-path拼接证书路径
String uploadPath = configProperties.getUploadPath(); // 配置文件路径
String tenantId = "10550"; // 租户ID
String certPath = uploadPath + "dev/wechat/" + tenantId + "/";
privateKeyPath = certPath + "apiclient_key.pem";
log.info("开发环境:使用配置文件upload-path拼接证书路径");
log.info("配置文件upload-path: {}", uploadPath);
log.info("证书基础路径: {}", certPath);
log.info("私钥文件路径: {}", privateKeyPath);
} else {
// 生产环境:使用相对路径,由系统动态解析
privateKeyPath = "src/main/resources/certs/dev/wechat/apiclient_key.pem";
log.info("生产环境:使用相对证书路径 - {}", privateKeyPath);
}
return createAutoConfig(merchantId, privateKeyPath, merchantSerialNumber, apiV3Key);
}
/**
* 测试证书配置是否正常
*
*
* @param config 微信支付配置
* @return 是否配置成功
*/
@ -117,56 +84,56 @@ public class WechatCertAutoConfig {
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
""";

2
src/main/java/com/gxwebsoft/common/system/entity/User.java

@ -119,7 +119,7 @@ public class User implements UserDetails {
private String payMoney;
@Schema(description = "实际消费的金额(不含退款)")
private String expendMoney;
private BigDecimal expendMoney;
@Schema(description = "会员等级ID")
private Integer gradeId;

620
src/main/java/com/gxwebsoft/shop/controller/ShopOrderController.java

@ -6,14 +6,15 @@ 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.alibaba.fastjson.JSONObject;
import com.gxwebsoft.common.core.config.ConfigProperties;
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.utils.WechatCertAutoConfig;
import com.gxwebsoft.common.core.utils.WechatPayConfigValidator;
import com.gxwebsoft.common.core.utils.*;
import com.gxwebsoft.common.core.web.BaseController;
import com.gxwebsoft.common.system.entity.DictData;
import com.gxwebsoft.common.system.entity.Payment;
import com.gxwebsoft.shop.entity.ShopGoods;
import com.gxwebsoft.shop.service.ShopGoodsService;
import com.gxwebsoft.shop.service.ShopOrderGoodsService;
import com.gxwebsoft.shop.service.ShopOrderService;
import com.gxwebsoft.shop.service.OrderBusinessService;
@ -39,7 +40,9 @@ import org.springframework.security.access.prepost.PreAuthorize;
import org.springframework.web.bind.annotation.*;
import javax.annotation.Resource;
import javax.validation.Valid;
import java.math.BigDecimal;
import java.util.LinkedHashMap;
import java.util.List;
import java.util.Map;
@ -53,329 +56,354 @@ import java.util.Map;
@RestController
@RequestMapping("/api/shop/shop-order")
public class ShopOrderController extends BaseController {
private static final Logger logger = LoggerFactory.getLogger(ShopOrderController.class);
@Resource
private ShopOrderService shopOrderService;
@Resource
private ShopOrderGoodsService shopOrderGoodsService;
@Resource
private OrderBusinessService orderBusinessService;
@Resource
private RedisUtil redisUtil;
@Resource
private ConfigProperties conf;
@Resource
private CertificateProperties certConfig;
@Resource
private CertificateLoader certificateLoader;
@Resource
private WechatCertAutoConfig wechatCertAutoConfig;
@Resource
private WechatPayConfigValidator wechatPayConfigValidator;
@Value("${spring.profiles.active}")
String active;
@Operation(summary = "分页查询订单")
@GetMapping("/page")
public ApiResult<PageResult<ShopOrder>> page(ShopOrderParam param) {
// 使用关联查询
return success(shopOrderService.pageRel(param));
}
@Operation(summary = "查询全部订单")
@GetMapping()
public ApiResult<List<ShopOrder>> list(ShopOrderParam param) {
// 使用关联查询
return success(shopOrderService.listRel(param));
}
@PreAuthorize("hasAuthority('shop:shopOrder:list')")
@Operation(summary = "根据id查询订单")
@GetMapping("/{id}")
public ApiResult<ShopOrder> get(@PathVariable("id") Integer id) {
// 使用关联查询
return success(shopOrderService.getByIdRel(id));
}
@Operation(summary = "添加订单")
@PostMapping()
public ApiResult<?> save(@RequestBody OrderCreateRequest request) {
User loginUser = getLoginUser();
if (loginUser == null) {
return fail("用户未登录");
private static final Logger logger = LoggerFactory.getLogger(ShopOrderController.class);
@Resource
private ShopOrderService shopOrderService;
@Resource
private ShopOrderGoodsService shopOrderGoodsService;
@Resource
private OrderBusinessService orderBusinessService;
@Resource
private RedisUtil redisUtil;
@Resource
private ConfigProperties conf;
@Resource
private CertificateProperties certConfig;
@Resource
private CertificateLoader certificateLoader;
@Resource
private WechatCertAutoConfig wechatCertAutoConfig;
@Resource
private WechatPayConfigValidator wechatPayConfigValidator;
@Resource
private ShopGoodsService shopGoodsService;
@Value("${spring.profiles.active}")
String active;
@Resource
private RequestUtil requestUtil;
@Operation(summary = "分页查询订单")
@GetMapping("/test")
public ApiResult<?> test() {
requestUtil.setTenantId("10550");
User user = requestUtil.getByUserIdWithoutLogin(33035);
return success(user);
}
try {
Map<String, String> wxOrderInfo = orderBusinessService.createOrder(request, loginUser);
return success("下单成功", wxOrderInfo);
} catch (Exception e) {
logger.error("创建订单失败 - 用户ID:{},请求:{}", loginUser.getUserId(), request, e);
return fail(e.getMessage());
@Operation(summary = "分页查询订单")
@GetMapping("/page")
public ApiResult<PageResult<ShopOrder>> page(ShopOrderParam param) {
// 使用关联查询
return success(shopOrderService.pageRel(param));
}
}
@Operation(summary = "添加订单(兼容旧版本)")
@PostMapping("/legacy")
public ApiResult<?> saveLegacy(@RequestBody ShopOrder shopOrder) {
// 记录当前登录用户id
User loginUser = getLoginUser();
if (loginUser != null) {
shopOrder.setUserId(loginUser.getUserId());
shopOrder.setOpenid(loginUser.getOpenid());
shopOrder.setPayUserId(loginUser.getUserId());
if (shopOrder.getOrderNo() == null) {
shopOrder.setOrderNo(Long.toString(IdUtil.getSnowflakeNextId()));
}
if (shopOrder.getComments() == null) {
shopOrder.setComments("暂无");
}
// 微信支付(商品金额不能为0)
if (shopOrder.getTotalPrice().compareTo(BigDecimal.ZERO) == 0) {
return fail("商品金额不能为0");
}
// 百色中学项目捐赠金额不能低于20元
if (shopOrder.getTenantId().equals(10324) && shopOrder.getTotalPrice().compareTo(new BigDecimal("10")) < 0) {
return fail("捐款金额最低不能少于10元,感谢您的爱心捐赠^_^");
}
// 测试支付
if (loginUser.getPhone().equals("13737128880")) {
shopOrder.setPrice(new BigDecimal("0.01"));
shopOrder.setTotalPrice(new BigDecimal("0.01"));
}
if (shopOrderService.save(shopOrder)) {
return success("下单成功", shopOrderService.createWxOrder(shopOrder));
}
@Operation(summary = "查询全部订单")
@GetMapping()
public ApiResult<List<ShopOrder>> list(ShopOrderParam param) {
// 使用关联查询
return success(shopOrderService.listRel(param));
}
return fail("添加失败");
}
@PreAuthorize("hasAuthority('shop:shopOrder:update')")
@Operation(summary = "修改订单")
@PutMapping()
public ApiResult<?> update(@RequestBody ShopOrder shopOrder) {
if (shopOrderService.updateById(shopOrder)) {
return success("修改成功");
@PreAuthorize("hasAuthority('shop:shopOrder:list')")
@Operation(summary = "根据id查询订单")
@GetMapping("/{id}")
public ApiResult<ShopOrder> get(@PathVariable("id") Integer id) {
// 使用关联查询
return success(shopOrderService.getByIdRel(id));
}
return fail("修改失败");
}
@Operation(summary = "删除订单")
@DeleteMapping("/{id}")
public ApiResult<?> remove(@PathVariable("id") Integer id) {
if (shopOrderService.removeById(id)) {
return success("删除成功");
@Operation(summary = "添加订单")
@PostMapping()
public ApiResult<?> save(@Valid @RequestBody OrderCreateRequest request) {
User loginUser = getLoginUser();
if (loginUser == null) {
return fail("用户未登录");
}
if (request.getTotalPrice() == null || request.getTotalPrice().compareTo(BigDecimal.ZERO) <= 0) {
if (request.getGoodsItems() != null && !request.getGoodsItems().isEmpty()) {
BigDecimal totalPrice = BigDecimal.ZERO;
int totalNum = 0;
for (OrderCreateRequest.OrderGoodsItem item : request.getGoodsItems()) {
ShopGoods goods = shopGoodsService.getById(item.getGoodsId().toString());
if (goods != null) {
BigDecimal price = goods.getPrice().multiply(new BigDecimal(item.getQuantity().toString()));
totalPrice = totalPrice.add(price);
totalNum += Integer.parseInt(item.getQuantity().toString());
}
}
request.setTotalPrice(totalPrice);
request.setPayPrice(totalPrice);
request.setTotalNum(totalNum);
request.setFormId(Integer.parseInt(request.getGoodsItems().get(0).getQuantity().toString()));
}
}
if (request.getTenantId() == null) {
request.setTenantId(getTenantId());
}
try {
Map<String, String> wxOrderInfo = orderBusinessService.createOrder(request, loginUser);
return success("下单成功", wxOrderInfo);
} catch (Exception e) {
logger.error("创建订单失败", e);
return fail(e.getMessage());
}
}
return fail("删除失败");
}
@Operation(summary = "批量添加订单")
@PostMapping("/batch")
public ApiResult<?> saveBatch(@RequestBody List<ShopOrder> list) {
if (shopOrderService.saveBatch(list)) {
return success("添加成功");
@Operation(summary = "添加订单(兼容旧版本)")
@PostMapping("/legacy")
public ApiResult<?> saveLegacy(@RequestBody ShopOrder shopOrder) {
// 记录当前登录用户id
User loginUser = getLoginUser();
if (loginUser != null) {
shopOrder.setUserId(loginUser.getUserId());
shopOrder.setOpenid(loginUser.getOpenid());
shopOrder.setPayUserId(loginUser.getUserId());
if (shopOrder.getOrderNo() == null) {
shopOrder.setOrderNo(Long.toString(IdUtil.getSnowflakeNextId()));
}
if (shopOrder.getComments() == null) {
shopOrder.setComments("暂无");
}
// 微信支付(商品金额不能为0)
if (shopOrder.getTotalPrice().compareTo(BigDecimal.ZERO) == 0) {
return fail("商品金额不能为0");
}
// 百色中学项目捐赠金额不能低于20元
if (shopOrder.getTenantId().equals(10324) && shopOrder.getTotalPrice().compareTo(new BigDecimal("10")) < 0) {
return fail("捐款金额最低不能少于10元,感谢您的爱心捐赠^_^");
}
// 测试支付
if (loginUser.getPhone().equals("13737128880")) {
shopOrder.setPrice(new BigDecimal("0.01"));
shopOrder.setTotalPrice(new BigDecimal("0.01"));
}
if (shopOrderService.save(shopOrder)) {
return success("下单成功", shopOrderService.createWxOrder(shopOrder));
}
}
return fail("添加失败");
}
return fail("添加失败");
}
@Operation(summary = "批量修改订单")
@PutMapping("/batch")
public ApiResult<?> removeBatch(@RequestBody BatchParam<ShopOrder> batchParam) {
if (batchParam.update(shopOrderService, "order_id")) {
return success("修改成功");
@PreAuthorize("hasAuthority('shop:shopOrder:update')")
@Operation(summary = "修改订单")
@PutMapping()
public ApiResult<?> update(@RequestBody ShopOrder shopOrder) {
if (shopOrderService.updateById(shopOrder)) {
return success("修改成功");
}
return fail("修改失败");
}
return fail("修改失败");
}
@Operation(summary = "批量删除订单")
@DeleteMapping("/batch")
public ApiResult<?> removeBatch(@RequestBody List<Integer> ids) {
if (shopOrderService.removeByIds(ids)) {
return success("删除成功");
@Operation(summary = "删除订单")
@DeleteMapping("/{id}")
public ApiResult<?> remove(@PathVariable("id") Integer id) {
if (shopOrderService.removeById(id)) {
return success("删除成功");
}
return fail("删除失败");
}
return fail("删除失败");
}
@Operation(summary = "修复订单")
@PutMapping("/repair")
public ApiResult<?> repair(@RequestBody ShopOrder shopOrder) {
final ShopOrder order = shopOrderService.getByOutTradeNo(shopOrder.getOrderNo());
if(order != null){
shopOrderService.queryOrderByOutTradeNo(order);
return success("修复成功");
@Operation(summary = "批量添加订单")
@PostMapping("/batch")
public ApiResult<?> saveBatch(@RequestBody List<ShopOrder> list) {
if (shopOrderService.saveBatch(list)) {
return success("添加成功");
}
return fail("添加失败");
}
return fail("修复失败");
}
@Operation(summary = "统计订单总金额")
@GetMapping("/total")
public ApiResult<BigDecimal> total() {
return success(shopOrderService.total());
}
@Schema(description = "异步通知")
@PostMapping("/notify/{tenantId}")
public String wxNotify(@RequestHeader Map<String, String> header, @RequestBody String body, @PathVariable("tenantId") Integer tenantId) {
logger.info("异步通知*************** = " + tenantId);
// 获取支付配置信息用于解密
String key = "Payment:1:".concat(tenantId.toString());
Payment payment = redisUtil.get(key, Payment.class);
// 检查支付配置
if (ObjectUtil.isEmpty(payment)) {
throw new RuntimeException("未找到租户支付配置信息,租户ID: " + tenantId);
@Operation(summary = "批量修改订单")
@PutMapping("/batch")
public ApiResult<?> removeBatch(@RequestBody BatchParam<ShopOrder> batchParam) {
if (batchParam.update(shopOrderService, "order_id")) {
return success("修改成功");
}
return fail("修改失败");
}
logger.info("开始处理微信支付异步通知 - 租户ID: {}", tenantId);
logger.info("支付配置信息 - 商户号: {}, 应用ID: {}", payment.getMchId(), payment.getAppId());
// 验证微信支付配置
WechatPayConfigValidator.ValidationResult validation = wechatPayConfigValidator.validateWechatPayConfig(payment, tenantId);
if (!validation.isValid()) {
logger.error("❌ 微信支付配置验证失败: {}", validation.getErrors());
logger.info("📋 配置诊断报告:\n{}", wechatPayConfigValidator.generateDiagnosticReport(payment, tenantId));
throw new RuntimeException("微信支付配置验证失败: " + validation.getErrors());
@Operation(summary = "批量删除订单")
@DeleteMapping("/batch")
public ApiResult<?> removeBatch(@RequestBody List<Integer> ids) {
if (shopOrderService.removeByIds(ids)) {
return success("删除成功");
}
return fail("删除失败");
}
logger.info("✅ 微信支付配置验证通过");
RequestParam requestParam = new RequestParam.Builder()
.serialNumber(header.get("wechatpay-serial"))
.nonce(header.get("wechatpay-nonce"))
.signature(header.get("wechatpay-signature"))
.timestamp(header.get("wechatpay-timestamp"))
.body(body)
.build();
// 创建通知配置 - 使用与下单方法相同的证书配置逻辑
NotificationConfig config;
try {
if (active.equals("dev")) {
// 开发环境 - 使用配置文件的upload-path构建证书路径
String uploadPath = conf.getUploadPath();
String tenantCertPath = uploadPath + "dev/wechat/" + tenantId;
String privateKeyPath = tenantCertPath + "/" + certConfig.getWechatPay().getDev().getPrivateKeyFile();
logger.info("开发环境异步通知证书路径: {}", privateKeyPath);
logger.info("租户ID: {}, 证书目录: {}", tenantId, tenantCertPath);
// 检查证书文件是否存在
if (!certificateLoader.certificateExists(privateKeyPath)) {
logger.error("证书文件不存在: {}", privateKeyPath);
throw new RuntimeException("证书文件不存在: " + privateKeyPath);
@Operation(summary = "修复订单")
@PutMapping("/repair")
public ApiResult<?> repair(@RequestBody ShopOrder shopOrder) {
final ShopOrder order = shopOrderService.getByOutTradeNo(shopOrder.getOrderNo());
if (order != null) {
shopOrderService.queryOrderByOutTradeNo(order);
return success("修复成功");
}
return fail("修复失败");
}
String privateKey = certificateLoader.loadCertificatePath(privateKeyPath);
// 使用验证器获取有效的 APIv3 密钥
String apiV3Key = wechatPayConfigValidator.getValidApiV3Key(payment);
logger.info("私钥文件加载成功: {}", privateKey);
logger.info("使用APIv3密钥来源: {}", payment.getApiKey() != null && !payment.getApiKey().trim().isEmpty() ? "数据库配置" : "配置文件默认");
logger.info("APIv3密钥长度: {}", apiV3Key != null ? apiV3Key.length() : 0);
logger.info("商户证书序列号: {}", payment.getMerchantSerialNumber());
// 使用自动证书配置
config = new RSAAutoCertificateConfig.Builder()
.merchantId(payment.getMchId())
.privateKeyFromPath(privateKey)
.merchantSerialNumber(payment.getMerchantSerialNumber())
.apiV3Key(apiV3Key)
.build();
logger.info("✅ 开发环境使用自动证书配置创建通知解析器成功");
} else {
// 生产环境 - 使用自动证书配置
final String certRootPath = certConfig.getCertRootPath();
final String certBasePath = certRootPath + "/file";
String privateKeyRelativePath = payment.getApiclientKey();
String privateKeyFullPath = privateKeyRelativePath.startsWith("/")
? certBasePath + privateKeyRelativePath
: certBasePath + "/" + privateKeyRelativePath;
String privateKey = certificateLoader.loadCertificatePath(privateKeyFullPath);
String apiV3Key = payment.getApiKey();
// 使用自动证书配置
config = new RSAAutoCertificateConfig.Builder()
.merchantId(payment.getMchId())
.privateKeyFromPath(privateKey)
.merchantSerialNumber(payment.getMerchantSerialNumber())
.apiV3Key(apiV3Key)
.build();
@Schema(description = "异步通知")
@PostMapping("/notify/{tenantId}")
public String wxNotify(@RequestHeader Map<String, String> header, @RequestBody String body, @PathVariable("tenantId") Integer tenantId) {
logger.info("异步通知*************** = " + tenantId);
logger.info("✅ 生产环境使用自动证书配置创建通知解析器成功");
}
} catch (Exception e) {
logger.error("❌ 创建通知配置失败 - 租户ID: {}, 商户号: {}", tenantId, payment.getMchId(), e);
logger.error("🔍 错误详情: {}", e.getMessage());
logger.error("💡 请检查:");
logger.error("1. 证书文件是否存在且路径正确");
logger.error("2. APIv3密钥是否配置正确");
logger.error("3. 商户证书序列号是否正确");
logger.error("4. 网络连接是否正常");
throw new RuntimeException("微信支付通知配置失败: " + e.getMessage(), e);
}
// 获取支付配置信息用于解密
String key = "Payment:1:".concat(tenantId.toString());
Payment payment = redisUtil.get(key, Payment.class);
// 初始化 NotificationParser
NotificationParser parser = new NotificationParser(config);
logger.info("✅ 通知解析器创建成功,准备解析异步通知");
// 检查支付配置
if (ObjectUtil.isEmpty(payment)) {
throw new RuntimeException("未找到租户支付配置信息,租户ID: " + tenantId);
}
// 以支付通知回调为例,验签、解密并转换成 Transaction
try {
logger.info("开始解析微信支付异步通知...");
Transaction transaction = parser.parse(requestParam, Transaction.class);
logger.info("✅ 异步通知解析成功 - 交易状态: {}, 商户订单号: {}",
transaction.getTradeStateDesc(), transaction.getOutTradeNo());
logger.info("开始处理微信支付异步通知 - 租户ID: {}", tenantId);
logger.info("支付配置信息 - 商户号: {}, 应用ID: {}", payment.getMchId(), payment.getAppId());
if (StrUtil.equals("支付成功", transaction.getTradeStateDesc())) {
final String outTradeNo = transaction.getOutTradeNo();
final String transactionId = transaction.getTransactionId();
final Integer total = transaction.getAmount().getTotal();
final String tradeStateDesc = transaction.getTradeStateDesc();
final Transaction.TradeStateEnum tradeState = transaction.getTradeState();
final Transaction.TradeTypeEnum tradeType = transaction.getTradeType();
System.out.println("transaction = " + transaction);
System.out.println("tradeStateDesc = " + tradeStateDesc);
System.out.println("tradeType = " + tradeType);
System.out.println("tradeState = " + tradeState);
System.out.println("outTradeNo = " + outTradeNo);
System.out.println("amount = " + total);
// 1. 查询要处理的订单
ShopOrder order = shopOrderService.getByOutTradeNo(outTradeNo);
logger.info("order = " + order);
// 2. 已支付则跳过
if (order.getPayStatus().equals(true)) {
return "SUCCESS";
// 验证微信支付配置
WechatPayConfigValidator.ValidationResult validation = wechatPayConfigValidator.validateWechatPayConfig(payment, tenantId);
if (!validation.isValid()) {
logger.error("❌ 微信支付配置验证失败: {}", validation.getErrors());
logger.info("📋 配置诊断报告:\n{}", wechatPayConfigValidator.generateDiagnosticReport(payment, tenantId));
throw new RuntimeException("微信支付配置验证失败: " + validation.getErrors());
}
// 2. 未支付则处理更新订单状态
if (order.getPayStatus().equals(false)) {
// 5. TODO 处理订单状态
order.setPayTime(DateUtil.date());
order.setExpirationTime(order.getCreateTime());
order.setPayStatus(true);
order.setTransactionId(transactionId);
order.setPayPrice(new BigDecimal(NumberUtil.decimalFormat("0.00", total * 0.01)));
order.setExpirationTime(DateUtil.offset(DateUtil.date(), DateField.YEAR, 10));
System.out.println("实际付款金额 = " + order.getPayPrice());
shopOrderService.updateByOutTradeNo(order);
return "SUCCESS";
logger.info("✅ 微信支付配置验证通过");
RequestParam requestParam = new RequestParam.Builder()
.serialNumber(header.get("wechatpay-serial"))
.nonce(header.get("wechatpay-nonce"))
.signature(header.get("wechatpay-signature"))
.timestamp(header.get("wechatpay-timestamp"))
.body(body)
.build();
// 创建通知配置 - 使用与下单方法相同的证书配置逻辑
NotificationConfig config;
try {
// if (active.equals("dev")) {
// // 开发环境 - 构建包含租户号的私钥路径
// String tenantCertPath = "dev/wechat/" + tenantId;
// String privateKeyPath = tenantCertPath + "/" + certConfig.getWechatPay().getDev().getPrivateKeyFile();
//
// logger.info("开发环境异步通知证书路径: {}", privateKeyPath);
// logger.info("租户ID: {}, 证书目录: {}", tenantId, tenantCertPath);
//
// // 检查证书文件是否存在
// if (!certificateLoader.certificateExists(privateKeyPath)) {
// logger.error("证书文件不存在: {}", privateKeyPath);
// throw new RuntimeException("证书文件不存在: " + privateKeyPath);
// }
//
// String privateKey = certificateLoader.loadCertificatePath(privateKeyPath);
//
// // 使用验证器获取有效的 APIv3 密钥
// String apiV3Key = wechatPayConfigValidator.getValidApiV3Key(payment);
//
// logger.info("私钥文件加载成功: {}", privateKey);
// logger.info("使用APIv3密钥来源: {}", payment.getApiKey() != null && !payment.getApiKey().trim().isEmpty() ? "数据库配置" : "配置文件默认");
// logger.info("APIv3密钥长度: {}", apiV3Key != null ? apiV3Key.length() : 0);
// logger.info("商户证书序列号: {}", payment.getMerchantSerialNumber());
//
// // 使用自动证书配置
// config = new RSAAutoCertificateConfig.Builder()
// .merchantId(payment.getMchId())
// .privateKeyFromPath(privateKey)
// .merchantSerialNumber(payment.getMerchantSerialNumber())
// .apiV3Key(apiV3Key)
// .build();
//
// logger.info("✅ 开发环境使用自动证书配置创建通知解析器成功");
// } else {
// 生产环境 - 使用自动证书配置
final String certRootPath = certConfig.getCertRootPath();
final String certBasePath = certRootPath + "/file";
String privateKeyRelativePath = payment.getApiclientKey();
String privateKeyFullPath = privateKeyRelativePath.startsWith("/")
? certBasePath + privateKeyRelativePath
: certBasePath + "/" + privateKeyRelativePath;
String privateKey = certificateLoader.loadCertificatePath(privateKeyFullPath);
String apiV3Key = payment.getApiKey();
// 使用自动证书配置
config = new RSAAutoCertificateConfig.Builder()
.merchantId(payment.getMchId())
.privateKeyFromPath(privateKey)
.merchantSerialNumber(payment.getMerchantSerialNumber())
.apiV3Key(apiV3Key)
.build();
logger.info("✅ 生产环境使用自动证书配置创建通知解析器成功");
// }
} catch (Exception e) {
logger.error("❌ 创建通知配置失败 - 租户ID: {}, 商户号: {}", tenantId, payment.getMchId(), e);
logger.error("🔍 错误详情: {}", e.getMessage());
logger.error("💡 请检查:");
logger.error("1. 证书文件是否存在且路径正确");
logger.error("2. APIv3密钥是否配置正确");
logger.error("3. 商户证书序列号是否正确");
logger.error("4. 网络连接是否正常");
throw new RuntimeException("微信支付通知配置失败: " + e.getMessage(), e);
}
}
} catch (Exception e) {
logger.error("❌ 处理微信支付异步通知失败 - 租户ID: {}, 商户号: {}", tenantId, payment.getMchId(), e);
logger.error("🔍 异常详情: {}", e.getMessage());
logger.error("💡 可能的原因:");
logger.error("1. 证书配置错误或证书文件损坏");
logger.error("2. 微信支付平台证书已过期");
logger.error("3. 签名验证失败");
logger.error("4. 请求参数格式错误");
// 返回失败,微信会重试
return "fail";
}
// 初始化 NotificationParser
NotificationParser parser = new NotificationParser(config);
logger.info("✅ 通知解析器创建成功,准备解析异步通知");
// 以支付通知回调为例,验签、解密并转换成 Transaction
try {
logger.info("开始解析微信支付异步通知...");
Transaction transaction = parser.parse(requestParam, Transaction.class);
logger.info("✅ 异步通知解析成功 - 交易状态: {}, 商户订单号: {}",
transaction.getTradeStateDesc(), transaction.getOutTradeNo());
if (StrUtil.equals("支付成功", transaction.getTradeStateDesc())) {
final String outTradeNo = transaction.getOutTradeNo();
final String transactionId = transaction.getTransactionId();
final Integer total = transaction.getAmount().getTotal();
final String tradeStateDesc = transaction.getTradeStateDesc();
final Transaction.TradeStateEnum tradeState = transaction.getTradeState();
final Transaction.TradeTypeEnum tradeType = transaction.getTradeType();
System.out.println("transaction = " + transaction);
System.out.println("tradeStateDesc = " + tradeStateDesc);
System.out.println("tradeType = " + tradeType);
System.out.println("tradeState = " + tradeState);
System.out.println("outTradeNo = " + outTradeNo);
System.out.println("amount = " + total);
// 1. 查询要处理的订单
ShopOrder order = shopOrderService.getByOutTradeNo(outTradeNo);
logger.info("order = " + order);
// 2. 已支付则跳过
if (order.getPayStatus().equals(true)) {
return "SUCCESS";
}
// 2. 未支付则处理更新订单状态
if (order.getPayStatus().equals(false)) {
// 5. TODO 处理订单状态
order.setPayTime(DateUtil.date());
order.setExpirationTime(order.getCreateTime());
order.setPayStatus(true);
order.setTransactionId(transactionId);
order.setPayPrice(new BigDecimal(NumberUtil.decimalFormat("0.00", total * 0.01)));
order.setExpirationTime(DateUtil.offset(DateUtil.date(), DateField.YEAR, 10));
System.out.println("实际付款金额 = " + order.getPayPrice());
shopOrderService.updateByOutTradeNo(order);
return "SUCCESS";
}
}
} catch (Exception e) {
logger.error("❌ 处理微信支付异步通知失败 - 租户ID: {}, 商户号: {}", tenantId, payment.getMchId(), e);
logger.error("🔍 异常详情: {}", e.getMessage());
logger.error("💡 可能的原因:");
logger.error("1. 证书配置错误或证书文件损坏");
logger.error("2. 微信支付平台证书已过期");
logger.error("3. 签名验证失败");
logger.error("4. 请求参数格式错误");
// 返回失败,微信会重试
return "fail";
}
logger.warn("⚠️ 异步通知处理完成但未找到匹配的支付成功状态");
return "fail";
}
logger.warn("⚠️ 异步通知处理完成但未找到匹配的支付成功状态");
return "fail";
}
}

2
src/main/java/com/gxwebsoft/shop/entity/ShopDealerOrder.java

@ -60,7 +60,7 @@ public class ShopDealerOrder implements Serializable {
private Integer isSettled;
@Schema(description = "结算时间")
private Integer settleTime;
private Long settleTime;
@Schema(description = "商城ID")
private Integer tenantId;

3
src/main/java/com/gxwebsoft/shop/entity/ShopGoods.java

@ -69,6 +69,9 @@ public class ShopGoods implements Serializable {
@Schema(description = "经销商价格")
private BigDecimal dealerPrice;
@Schema(description = "佣金")
private BigDecimal commission;
@Schema(description = "库存计算方式(10下单减库存 20付款减库存)")
private Integer deductStockType;

1
src/main/java/com/gxwebsoft/shop/service/ShopOrderGoodsService.java

@ -39,4 +39,5 @@ public interface ShopOrderGoodsService extends IService<ShopOrderGoods> {
*/
ShopOrderGoods getByIdRel(Integer id);
List<ShopOrderGoods> getListByOrderId(Integer orderId);
}

9
src/main/java/com/gxwebsoft/shop/service/impl/ShopOrderGoodsServiceImpl.java

@ -1,5 +1,6 @@
package com.gxwebsoft.shop.service.impl;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.gxwebsoft.shop.mapper.ShopOrderGoodsMapper;
import com.gxwebsoft.shop.service.ShopOrderGoodsService;
@ -44,4 +45,12 @@ public class ShopOrderGoodsServiceImpl extends ServiceImpl<ShopOrderGoodsMapper,
return param.getOne(baseMapper.selectListRel(param));
}
@Override
public List<ShopOrderGoods> getListByOrderId(Integer orderId) {
return list(
new LambdaQueryWrapper<ShopOrderGoods>()
.eq(ShopOrderGoods::getOrderId, orderId)
);
}
}

127
src/main/java/com/gxwebsoft/shop/service/impl/ShopOrderServiceImpl.java

@ -4,30 +4,25 @@
import cn.hutool.core.util.StrUtil;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import org.springframework.util.CollectionUtils;
import com.gxwebsoft.common.core.config.ConfigProperties;
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.service.PaymentCacheService;
import com.gxwebsoft.common.core.utils.WechatPayDiagnostic;
import com.gxwebsoft.common.core.utils.WechatPayCertificateDiagnostic;
import com.gxwebsoft.common.core.utils.*;
import com.gxwebsoft.common.core.service.PaymentCacheService;
import com.gxwebsoft.common.core.web.ApiResult;
import com.gxwebsoft.common.system.entity.Payment;
import com.gxwebsoft.common.system.entity.User;
import com.gxwebsoft.shop.entity.*;
import com.gxwebsoft.shop.service.*;
import lombok.extern.slf4j.Slf4j;
import com.gxwebsoft.common.system.service.PaymentService;
import com.gxwebsoft.common.system.service.SettingService;
import com.gxwebsoft.shop.entity.ShopOrderGoods;
import com.gxwebsoft.shop.mapper.ShopOrderMapper;
import com.gxwebsoft.shop.service.ShopOrderGoodsService;
import com.gxwebsoft.shop.service.ShopOrderService;
import com.gxwebsoft.shop.entity.ShopOrder;
import com.gxwebsoft.shop.param.ShopOrderParam;
import com.gxwebsoft.common.core.web.PageParam;
import com.gxwebsoft.common.core.web.PageResult;
import com.wechat.pay.java.core.Config;
import com.wechat.pay.java.core.RSAConfig;
import com.wechat.pay.java.core.RSAPublicKeyConfig;
import com.gxwebsoft.common.core.utils.WechatCertAutoConfig;
import com.wechat.pay.java.core.exception.ServiceException;
import com.wechat.pay.java.service.payments.jsapi.JsapiServiceExtension;
import com.wechat.pay.java.service.payments.jsapi.model.*;
@ -38,10 +33,8 @@ import com.gxwebsoft.common.core.service.PaymentCacheService;
import javax.annotation.Resource;
import java.math.BigDecimal;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.Set;
import java.sql.Date;
import java.util.*;
import java.util.stream.Collectors;
/**
@ -62,6 +55,8 @@ import com.gxwebsoft.common.core.service.PaymentCacheService;
@Resource
private ShopOrderGoodsService shopOrderGoodsService;
@Resource
private ShopGoodsService shopGoodsService;
@Resource
private PaymentService paymentService;
@Resource
private SettingService settingService;
@ -77,6 +72,12 @@ import com.gxwebsoft.common.core.service.PaymentCacheService;
private WechatPayDiagnostic wechatPayDiagnostic;
@Resource
private WechatPayCertificateDiagnostic certificateDiagnostic;
@Resource
private RequestUtil requestUtil;
@Resource
private ShopDealerOrderService shopDealerOrderService;
@Resource
private ShopDealerCapitalService shopDealerCapitalService;
@Override
public PageResult<ShopOrder> pageRel(ShopOrderParam param) {
@ -243,6 +244,61 @@ import com.gxwebsoft.common.core.service.PaymentCacheService;
@Override
public void updateByOutTradeNo(ShopOrder order) {
baseMapper.updateByOutTradeNo(order);
if (order.getTenantId().equals(10550)) {
requestUtil.setTenantId(order.getTenantId().toString());
ApiResult<?> partnerConditionReq = requestUtil.pageDictData(1460);
if (partnerConditionReq.getCode().equals(0) && partnerConditionReq.getData() != null) {
LinkedHashMap<String, Object> dictDataMap = (LinkedHashMap<String, Object>) partnerConditionReq.getData();
List<LinkedHashMap> dictDataList = (List<LinkedHashMap>) dictDataMap.get("list");
String dictDataCode = (String) dictDataList.get(0).get("dictDataCode");
BigDecimal partnerCondition = new BigDecimal(dictDataCode);
User user = requestUtil.getByUserIdWithoutLogin(order.getUserId());
if (user != null) {
user.setExpendMoney(user.getExpendMoney().add(order.getPayPrice()));
if (user.getExpendMoney().compareTo(partnerCondition) >= 0) {
user.setGradeId(3);
}
requestUtil.updateWithoutLogin(user);
// 上级
User parent = requestUtil.getParent(order.getUserId());
if (parent != null) {
List<ShopOrderGoods> shopOrderGoodsList = shopOrderGoodsService.getListByOrderId(order.getOrderId());
List<Integer> goodsIds = shopOrderGoodsList.stream().map(ShopOrderGoods::getGoodsId).toList();
List<ShopGoods> shopGoodsList = shopGoodsService.listByIds(goodsIds);
BigDecimal commission = BigDecimal.ZERO;
for (ShopOrderGoods shopOrderGoods : shopOrderGoodsList) {
ShopGoods shopGoods = shopGoodsList.stream().filter(sG -> sG.getGoodsId().equals(shopOrderGoods.getGoodsId())).findFirst().orElse(null);
if (shopGoods != null) {
commission = commission.add(shopGoods.getCommission().multiply(BigDecimal.valueOf(shopOrderGoods.getTotalNum())));
}
}
parent.setBalance(parent.getBalance().add(commission));
requestUtil.updateWithoutLogin(user);
// 分销订单
ShopDealerOrder shopDealerOrder = new ShopDealerOrder();
shopDealerOrder.setUserId(parent.getUserId());
shopDealerOrder.setOrderId(order.getOrderId());
shopDealerOrder.setOrderPrice(order.getTotalPrice());
shopDealerOrder.setFirstUserId(order.getUserId());
shopDealerOrder.setFirstMoney(commission);
shopDealerOrder.setIsSettled(1);
shopDealerOrder.setSettleTime(DateUtil.currentSeconds());
shopDealerOrderService.save(shopDealerOrder);
// 分销资明细
ShopDealerCapital shopDealerCapital = new ShopDealerCapital();
shopDealerCapital.setUserId(parent.getUserId());
shopDealerCapital.setOrderId(order.getOrderId());
shopDealerCapital.setFlowType(10);
shopDealerCapitalService.save(shopDealerCapital);
}
}
}
}
}
/**
@ -304,9 +360,8 @@ import com.gxwebsoft.common.core.service.PaymentCacheService;
// 开发环境配置 - 使用自动证书配置
if (active.equals("dev")) {
// 开发环境 - 使用配置文件的upload-path构建证书路径
String uploadPath = config.getUploadPath();
String tenantCertPath = uploadPath + "dev/wechat/" + order.getTenantId();
// 构建包含租户号的证书路径: dev/wechat/{tenantId}/
String tenantCertPath = "dev/wechat/" + order.getTenantId();
String privateKeyPath = tenantCertPath + "/" + certConfig.getWechatPay().getDev().getPrivateKeyFile();
System.out.println("开发环境证书路径 - 租户ID: " + order.getTenantId());
@ -396,9 +451,8 @@ import com.gxwebsoft.common.core.service.PaymentCacheService;
payment.getPubKeyId() != null && !payment.getPubKeyId().isEmpty()) {
try {
// 开发环境使用配置文件的upload-path构建公钥路径
String uploadPath = config.getUploadPath();
String tenantCertPath = uploadPath + "dev/wechat/" + order.getTenantId();
// 开发环境固定使用 wechatpay_public_key.pem
String tenantCertPath = "dev/wechat/" + order.getTenantId();
String pubKeyPath = tenantCertPath + "/wechatpay_public_key.pem";
System.out.println("开发环境公钥文件路径: " + pubKeyPath);
@ -472,8 +526,7 @@ import com.gxwebsoft.common.core.service.PaymentCacheService;
System.err.println("⚠️ 开发环境回退到基础RSA配置...");
try {
// 方案1:尝试使用RSA证书配置(需要商户证书文件)
String uploadPath = config.getUploadPath();
String tenantCertPath = uploadPath + "dev/wechat/" + order.getTenantId();
String tenantCertPath = "dev/wechat/" + order.getTenantId();
String apiclientCertPath = tenantCertPath + "/" + certConfig.getWechatPay().getDev().getApiclientCertFile();
if (certificateLoader.certificateExists(apiclientCertPath)) {
@ -651,23 +704,23 @@ import com.gxwebsoft.common.core.service.PaymentCacheService;
}
}
@Override
public BigDecimal total() {
try {
// 使用数据库聚合查询统计订单总金额,性能更高
BigDecimal total = baseMapper.selectTotalAmount();
@Override
public BigDecimal total() {
try {
// 使用数据库聚合查询统计订单总金额,性能更高
BigDecimal total = baseMapper.selectTotalAmount();
if (total == null) {
total = BigDecimal.ZERO;
}
if (total == null) {
total = BigDecimal.ZERO;
}
log.info("统计订单总金额完成,总金额:{}", total);
return total;
log.info("统计订单总金额完成,总金额:{}", total);
return total;
} catch (Exception e) {
log.error("统计订单总金额失败", e);
return BigDecimal.ZERO;
} catch (Exception e) {
log.error("统计订单总金额失败", e);
return BigDecimal.ZERO;
}
}
}
}

4
src/main/resources/application-prod.yml

@ -3,7 +3,7 @@
# 数据源配置
spring:
datasource:
url: jdbc:mysql://1Panel-mysql-Bqdt:3306/website?useUnicode=true&characterEncoding=utf8&useSSL=false&serverTimezone=GMT%2B8
url: jdbc:mysql://1Panel-mysql-Bqdt:3306/modules?useUnicode=true&characterEncoding=utf8&useSSL=false&serverTimezone=GMT%2B8
username: modules
password: 8YdLnk7KsPAyDXGA
driver-class-name: com.mysql.cj.jdbc.Driver
@ -45,7 +45,7 @@ mqtt:
config:
# 生产环境接口
server-url: https://server.websoft.top/api
upload-path: /www/wwwroot/file.ws
upload-path: /www/wwwroot/file.ws/
# 阿里云OSS云存储
endpoint: https://oss-cn-shenzhen.aliyuncs.com

2
src/main/resources/application.yml

@ -4,7 +4,7 @@ server:
# 多环境配置
spring:
profiles:
active: dev
active: prod
application:
name: server

Loading…
Cancel
Save