修复下单接口

This commit is contained in:
2025-08-09 14:43:47 +08:00
parent 1bda2263c0
commit eb1f5efc10
6 changed files with 706 additions and 25 deletions

View File

@@ -0,0 +1,180 @@
# 下单报错修复说明
## 问题分析
根据您提供的请求数据,发现下单报错的主要原因是:
### 1. 字段映射不匹配
前端发送的请求数据格式与后端期望的字段名不一致:
**前端发送的数据:**
```json
{
"goodsItems": [{"goodsId": 10021, "quantity": 1}],
"addressId": 10832,
"payType": 1,
"comments": "扎尔伯特五谷礼盒",
"deliveryType": 0,
"goodsId": 10021,
"quantity": 1
}
```
**后端期望的字段:**
- `formId` (而不是 `goodsId`)
- `totalNum` (而不是 `quantity`)
- `totalPrice` (缺失)
- `tenantId` (缺失)
- `type` (缺失)
### 2. 缺少必填字段
- `totalPrice`:订单总额
- `tenantId`租户ID
- `type`:订单类型
## 修复方案
### 1. 增强 OrderCreateRequest 兼容性
`OrderCreateRequest` 中添加了兼容性字段和方法:
```java
// 兼容字段
@JsonProperty("goodsId")
private Integer goodsId;
@JsonProperty("quantity")
private Integer quantity;
@JsonProperty("goodsItems")
private List<GoodsItem> goodsItems;
// 兼容性方法
public Integer getActualFormId() {
if (formId != null) return formId;
if (goodsId != null) return goodsId;
if (goodsItems != null && !goodsItems.isEmpty()) {
return goodsItems.get(0).getGoodsId();
}
return null;
}
public Integer getActualTotalNum() {
if (totalNum != null) return totalNum;
if (quantity != null) return quantity;
if (goodsItems != null && !goodsItems.isEmpty()) {
return goodsItems.get(0).getQuantity();
}
return 1; // 默认数量为1
}
```
### 2. 修改业务逻辑
更新了 `OrderBusinessService` 中的验证和构建逻辑:
- 使用 `getActualFormId()``getActualTotalNum()` 获取实际值
- 增强了参数验证,支持缺失字段的默认值设置
- 改进了错误信息,提供更详细的调试信息
### 3. 增强错误处理
在控制器中添加了详细的日志记录:
```java
logger.info("收到下单请求 - 用户ID{}商品ID{},数量:{},总价:{}租户ID{}",
loginUser.getUserId(), request.getActualFormId(), request.getActualTotalNum(),
request.getTotalPrice(), request.getTenantId());
```
## 支持的请求格式
修复后,系统现在支持以下多种请求格式:
### 格式1原有格式
```json
{
"formId": 10021,
"totalNum": 1,
"totalPrice": 99.00,
"tenantId": 10832,
"type": 0,
"payType": 1,
"comments": "扎尔伯特五谷礼盒"
}
```
### 格式2新的兼容格式
```json
{
"goodsId": 10021,
"quantity": 1,
"totalPrice": 99.00,
"tenantId": 10832,
"type": 0,
"payType": 1,
"comments": "扎尔伯特五谷礼盒"
}
```
### 格式3批量商品格式
```json
{
"goodsItems": [
{"goodsId": 10021, "quantity": 1, "price": 99.00}
],
"totalPrice": 99.00,
"tenantId": 10832,
"type": 0,
"payType": 1,
"comments": "扎尔伯特五谷礼盒"
}
```
## 自动处理的字段
系统现在会自动处理以下情况:
1. **缺失 totalPrice**:根据商品价格和数量自动计算
2. **缺失 type**:默认设置为 0商城订单
3. **缺失 tenantId**:会提示错误,需要前端提供
4. **字段名不匹配**:自动映射 goodsId→formId, quantity→totalNum
## 测试验证
创建了完整的单元测试来验证修复效果:
- ✅ 正常下单流程测试
- ✅ 商品不存在异常测试
- ✅ 库存不足异常测试
- ✅ 价格验证异常测试
- ✅ 兼容性字段测试
## 建议
### 前端调整建议
为了确保下单成功,建议前端在请求中包含以下必填字段:
```json
{
"goodsId": 10021, // 商品ID
"quantity": 1, // 购买数量
"totalPrice": 99.00, // 订单总额(可选,系统会自动计算)
"tenantId": 10832, // 租户ID必填
"type": 0, // 订单类型可选默认为0
"payType": 1, // 支付类型
"comments": "商品备注", // 备注
"deliveryType": 0, // 配送方式
"addressId": 10832 // 收货地址ID
}
```
### 后端监控建议
建议在生产环境中监控以下指标:
1. 下单失败率
2. 常见错误类型
3. 字段缺失情况
4. 价格验证失败次数
这样可以及时发现和解决问题。

View File

@@ -0,0 +1,122 @@
# 订单下单方法改进说明
## 问题分析
通过分析您的下单方法,发现了以下安全和业务逻辑问题:
### 原有问题:
1. **缺乏商品验证**:没有从数据库查询商品信息进行验证
2. **价格安全风险**:完全依赖前端传递的价格,存在被篡改的风险
3. **库存未验证**:没有检查商品库存是否充足
4. **商品状态未检查**:没有验证商品是否上架、是否删除等
## 改进方案
### 1. 新增商品验证逻辑
`OrderBusinessService.createOrder()` 方法中添加了商品验证步骤:
```java
// 2. 验证商品信息(从数据库查询)
ShopGoods goods = validateAndGetGoods(request);
```
### 2. 实现商品信息验证方法
新增 `validateAndGetGoods()` 方法,包含以下验证:
- **商品存在性验证**检查商品ID是否存在
- **商品状态验证**
- 检查商品是否已删除 (`deleted != 1`)
- 检查商品是否上架 (`status == 0`)
- 检查商品是否展示 (`isShow == true`)
- **库存验证**:检查库存是否充足
- **价格验证**对比数据库价格与请求价格允许0.01元误差)
### 3. 价格安全保护
修改 `buildShopOrder()` 方法,使用数据库中的商品价格:
```java
// 使用数据库中的商品信息覆盖价格(确保价格准确性)
if (goods.getPrice() != null && request.getTotalNum() != null) {
BigDecimal totalPrice = goods.getPrice().multiply(new BigDecimal(request.getTotalNum()));
shopOrder.setTotalPrice(totalPrice);
shopOrder.setPrice(totalPrice);
}
```
### 4. 空指针保护
为所有配置相关的调用添加了空指针检查,提高代码健壮性。
## 主要改进点
### 安全性提升
- ✅ 防止价格篡改:使用数据库价格计算订单金额
- ✅ 商品状态验证:确保只能购买正常上架的商品
- ✅ 库存保护:防止超卖
### 业务逻辑完善
- ✅ 商品存在性检查
- ✅ 商品状态检查(上架、展示、未删除)
- ✅ 库存充足性检查
- ✅ 价格一致性验证
### 代码质量
- ✅ 添加详细的日志记录
- ✅ 异常信息更加明确
- ✅ 空指针保护
- ✅ 单元测试覆盖
## 使用示例
### 正常下单流程
```java
OrderCreateRequest request = new OrderCreateRequest();
request.setFormId(1); // 商品ID
request.setTotalNum(2); // 购买数量
request.setTotalPrice(new BigDecimal("200.00")); // 前端计算的总价
request.setTenantId(1);
// 系统会自动:
// 1. 查询商品ID=1的商品信息
// 2. 验证商品状态(上架、未删除、展示中)
// 3. 检查库存是否>=2
// 4. 验证价格是否与数据库一致
// 5. 使用数据库价格重新计算订单金额
```
### 异常处理
系统会在以下情况抛出异常:
- 商品不存在:`"商品不存在"`
- 商品已删除:`"商品已删除"`
- 商品未上架:`"商品未上架"`
- 库存不足:`"商品库存不足当前库存X"`
- 价格异常:`"商品价格异常数据库价格X请求价格Y"`
## 测试验证
创建了完整的单元测试 `OrderBusinessServiceTest.java`,覆盖:
- 正常下单流程
- 商品不存在场景
- 库存不足场景
- 价格不匹配场景
- 商品状态异常场景
## 建议
1. **运行测试**:执行单元测试确保功能正常
2. **前端配合**前端仍需传递商品ID和数量但价格以服务端计算为准
3. **监控日志**:关注商品验证相关的日志,及时发现异常情况
4. **性能优化**:如果商品查询频繁,可考虑添加缓存
## 总结
通过这次改进,您的下单方法现在:
-**安全可靠**:防止价格篡改和恶意下单
-**业务完整**:包含完整的商品验证逻辑
-**代码健壮**:有完善的异常处理和空指针保护
-**易于维护**:有清晰的日志和测试覆盖
这样的改进确保了订单系统的安全性和可靠性,符合电商系统的最佳实践。