|
@ -6,14 +6,15 @@ import cn.hutool.core.util.IdUtil; |
|
|
import cn.hutool.core.util.NumberUtil; |
|
|
import cn.hutool.core.util.NumberUtil; |
|
|
import cn.hutool.core.util.ObjectUtil; |
|
|
import cn.hutool.core.util.ObjectUtil; |
|
|
import cn.hutool.core.util.StrUtil; |
|
|
import cn.hutool.core.util.StrUtil; |
|
|
|
|
|
import com.alibaba.fastjson.JSONObject; |
|
|
import com.gxwebsoft.common.core.config.ConfigProperties; |
|
|
import com.gxwebsoft.common.core.config.ConfigProperties; |
|
|
import com.gxwebsoft.common.core.config.CertificateProperties; |
|
|
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.core.web.BaseController; |
|
|
|
|
|
import com.gxwebsoft.common.system.entity.DictData; |
|
|
import com.gxwebsoft.common.system.entity.Payment; |
|
|
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.ShopOrderGoodsService; |
|
|
import com.gxwebsoft.shop.service.ShopOrderService; |
|
|
import com.gxwebsoft.shop.service.ShopOrderService; |
|
|
import com.gxwebsoft.shop.service.OrderBusinessService; |
|
|
import com.gxwebsoft.shop.service.OrderBusinessService; |
|
@ -39,7 +40,9 @@ import org.springframework.security.access.prepost.PreAuthorize; |
|
|
import org.springframework.web.bind.annotation.*; |
|
|
import org.springframework.web.bind.annotation.*; |
|
|
|
|
|
|
|
|
import javax.annotation.Resource; |
|
|
import javax.annotation.Resource; |
|
|
|
|
|
import javax.validation.Valid; |
|
|
import java.math.BigDecimal; |
|
|
import java.math.BigDecimal; |
|
|
|
|
|
import java.util.LinkedHashMap; |
|
|
import java.util.List; |
|
|
import java.util.List; |
|
|
import java.util.Map; |
|
|
import java.util.Map; |
|
|
|
|
|
|
|
@ -72,8 +75,20 @@ public class ShopOrderController extends BaseController { |
|
|
private WechatCertAutoConfig wechatCertAutoConfig; |
|
|
private WechatCertAutoConfig wechatCertAutoConfig; |
|
|
@Resource |
|
|
@Resource |
|
|
private WechatPayConfigValidator wechatPayConfigValidator; |
|
|
private WechatPayConfigValidator wechatPayConfigValidator; |
|
|
|
|
|
@Resource |
|
|
|
|
|
private ShopGoodsService shopGoodsService; |
|
|
@Value("${spring.profiles.active}") |
|
|
@Value("${spring.profiles.active}") |
|
|
String 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); |
|
|
|
|
|
} |
|
|
|
|
|
|
|
|
@Operation(summary = "分页查询订单") |
|
|
@Operation(summary = "分页查询订单") |
|
|
@GetMapping("/page") |
|
|
@GetMapping("/page") |
|
@ -99,17 +114,37 @@ public class ShopOrderController extends BaseController { |
|
|
|
|
|
|
|
|
@Operation(summary = "添加订单") |
|
|
@Operation(summary = "添加订单") |
|
|
@PostMapping() |
|
|
@PostMapping() |
|
|
public ApiResult<?> save(@RequestBody OrderCreateRequest request) { |
|
|
|
|
|
|
|
|
public ApiResult<?> save(@Valid @RequestBody OrderCreateRequest request) { |
|
|
User loginUser = getLoginUser(); |
|
|
User loginUser = getLoginUser(); |
|
|
if (loginUser == null) { |
|
|
if (loginUser == null) { |
|
|
return fail("用户未登录"); |
|
|
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 { |
|
|
try { |
|
|
Map<String, String> wxOrderInfo = orderBusinessService.createOrder(request, loginUser); |
|
|
Map<String, String> wxOrderInfo = orderBusinessService.createOrder(request, loginUser); |
|
|
return success("下单成功", wxOrderInfo); |
|
|
return success("下单成功", wxOrderInfo); |
|
|
} catch (Exception e) { |
|
|
} catch (Exception e) { |
|
|
logger.error("创建订单失败 - 用户ID:{},请求:{}", loginUser.getUserId(), request, e); |
|
|
|
|
|
|
|
|
logger.error("创建订单失败", e); |
|
|
return fail(e.getMessage()); |
|
|
return fail(e.getMessage()); |
|
|
} |
|
|
} |
|
|
} |
|
|
} |
|
@ -206,12 +241,6 @@ public class ShopOrderController extends BaseController { |
|
|
return fail("修复失败"); |
|
|
return fail("修复失败"); |
|
|
} |
|
|
} |
|
|
|
|
|
|
|
|
@Operation(summary = "统计订单总金额") |
|
|
|
|
|
@GetMapping("/total") |
|
|
|
|
|
public ApiResult<BigDecimal> total() { |
|
|
|
|
|
return success(shopOrderService.total()); |
|
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
@Schema(description = "异步通知") |
|
|
@Schema(description = "异步通知") |
|
|
@PostMapping("/notify/{tenantId}") |
|
|
@PostMapping("/notify/{tenantId}") |
|
|
public String wxNotify(@RequestHeader Map<String, String> header, @RequestBody String body, @PathVariable("tenantId") Integer tenantId) { |
|
|
public String wxNotify(@RequestHeader Map<String, String> header, @RequestBody String body, @PathVariable("tenantId") Integer tenantId) { |
|
@ -249,41 +278,40 @@ public class ShopOrderController extends BaseController { |
|
|
// 创建通知配置 - 使用与下单方法相同的证书配置逻辑
|
|
|
// 创建通知配置 - 使用与下单方法相同的证书配置逻辑
|
|
|
NotificationConfig config; |
|
|
NotificationConfig config; |
|
|
try { |
|
|
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); |
|
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
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 { |
|
|
|
|
|
|
|
|
// 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 certRootPath = certConfig.getCertRootPath(); |
|
|
final String certBasePath = certRootPath + "/file"; |
|
|
final String certBasePath = certRootPath + "/file"; |
|
@ -304,7 +332,7 @@ public class ShopOrderController extends BaseController { |
|
|
.build(); |
|
|
.build(); |
|
|
|
|
|
|
|
|
logger.info("✅ 生产环境使用自动证书配置创建通知解析器成功"); |
|
|
logger.info("✅ 生产环境使用自动证书配置创建通知解析器成功"); |
|
|
} |
|
|
|
|
|
|
|
|
// }
|
|
|
} catch (Exception e) { |
|
|
} catch (Exception e) { |
|
|
logger.error("❌ 创建通知配置失败 - 租户ID: {}, 商户号: {}", tenantId, payment.getMchId(), e); |
|
|
logger.error("❌ 创建通知配置失败 - 租户ID: {}, 商户号: {}", tenantId, payment.getMchId(), e); |
|
|
logger.error("🔍 错误详情: {}", e.getMessage()); |
|
|
logger.error("🔍 错误详情: {}", e.getMessage()); |
|
|