订单服务完整逻辑代码Java微服务后端架构实战

1. 架构概述

订单服务系统是电商平台的核心业务模块,需要支持订单创建、支付、状态管理、库存扣减、用户验证和订单统计等功能。本篇文章将深入讲解如何基于Java微服务架构实现一个完整的订单服务系统,包含订单服务、支付服务、库存服务、用户服务等多个微服务的完整业务逻辑代码。

1.1 系统架构图

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
订单服务完整架构
├── 订单服务 (Order Service)
│ ├── 订单创建
│ ├── 订单查询
│ ├── 订单状态管理
│ └── 订单统计

├── 支付服务 (Payment Service)
│ ├── 支付处理
│ ├── 支付回调
│ ├── 支付状态查询
│ └── 退款处理

├── 库存服务 (Inventory Service)
│ ├── 库存查询
│ ├── 库存扣减
│ ├── 库存回滚
│ └── 库存统计

├── 用户服务 (User Service)
│ ├── 用户验证
│ ├── 用户信息查询
│ └── 用户积分管理

├── Kafka消息队列
│ ├── 订单创建Topic
│ ├── 订单支付Topic
│ ├── 订单状态变更Topic
│ ├── 库存扣减Topic
│ └── 订单统计Topic

└── 数据库/缓存
├── MySQL - 订单信息、支付记录、库存记录
└── Redis - 订单状态、库存缓存、分布式锁

1.2 核心组件

  • 订单服务(Order Service):负责订单创建、查询、状态管理、统计
  • 支付服务(Payment Service):负责支付处理、回调、状态查询、退款
  • 库存服务(Inventory Service):负责库存查询、扣减、回滚、统计
  • 用户服务(User Service):负责用户验证、信息查询、积分管理
  • Kafka消息队列:负责订单、支付、库存的异步处理和消息通知
  • 数据库(MySQL):持久化订单信息、支付记录、库存记录
  • 缓存(Redis):缓存订单状态、库存信息、分布式锁

2. 订单服务实现

2.1 订单服务控制器

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
/**
* 订单服务控制器
* 提供订单管理接口
*/
@RestController
@RequestMapping("/api/order")
@Slf4j
public class OrderController {

@Autowired
private OrderService orderService;

@Autowired
private OrderQueryService orderQueryService;

/**
* 创建订单
*/
@PostMapping("/create")
public Result<OrderInfo> createOrder(@RequestBody @Valid OrderCreateRequest request) {
try {
OrderInfo orderInfo = orderService.createOrder(request);
return Result.success(orderInfo);
} catch (Exception e) {
log.error("创建订单失败: error={}", e.getMessage(), e);
return Result.error("创建订单失败: " + e.getMessage());
}
}

/**
* 获取订单信息
*/
@GetMapping("/{orderId}")
public Result<OrderInfo> getOrderInfo(@PathVariable String orderId) {
try {
OrderInfo orderInfo = orderQueryService.getOrderInfo(orderId);
return Result.success(orderInfo);
} catch (Exception e) {
log.error("获取订单信息失败: orderId={}, error={}",
orderId, e.getMessage(), e);
return Result.error("获取订单信息失败: " + e.getMessage());
}
}

/**
* 更新订单状态
*/
@PutMapping("/{orderId}/status")
public Result<Void> updateOrderStatus(
@PathVariable String orderId,
@RequestBody @Valid OrderStatusUpdateRequest request) {
try {
orderService.updateOrderStatus(orderId, request.getStatus(), request.getRemark());
return Result.success();
} catch (Exception e) {
log.error("更新订单状态失败: orderId={}, error={}",
orderId, e.getMessage(), e);
return Result.error("更新订单状态失败: " + e.getMessage());
}
}

/**
* 取消订单
*/
@PostMapping("/{orderId}/cancel")
public Result<Void> cancelOrder(
@PathVariable String orderId,
@RequestBody @Valid OrderCancelRequest request) {
try {
orderService.cancelOrder(orderId, request.getCancelReason());
return Result.success();
} catch (Exception e) {
log.error("取消订单失败: orderId={}, error={}",
orderId, e.getMessage(), e);
return Result.error("取消订单失败: " + e.getMessage());
}
}

/**
* 获取订单列表
*/
@GetMapping("/list")
public Result<PageResult<OrderInfo>> getOrderList(
@RequestParam(required = false) String userId,
@RequestParam(required = false) String status,
@RequestParam(required = false) String startTime,
@RequestParam(required = false) String endTime,
@RequestParam(defaultValue = "1") Integer pageNum,
@RequestParam(defaultValue = "10") Integer pageSize) {
try {
PageResult<OrderInfo> result = orderQueryService.getOrderList(
userId, status, startTime, endTime, pageNum, pageSize);
return Result.success(result);
} catch (Exception e) {
log.error("获取订单列表失败: error={}", e.getMessage(), e);
return Result.error("获取订单列表失败: " + e.getMessage());
}
}

/**
* 获取订单统计
*/
@GetMapping("/statistics")
public Result<OrderStatistics> getOrderStatistics(
@RequestParam(required = false) String userId,
@RequestParam(required = false) String startTime,
@RequestParam(required = false) String endTime) {
try {
OrderStatistics statistics = orderQueryService.getOrderStatistics(
userId, startTime, endTime);
return Result.success(statistics);
} catch (Exception e) {
log.error("获取订单统计失败: error={}", e.getMessage(), e);
return Result.error("获取订单统计失败: " + e.getMessage());
}
}
}

2.2 订单服务实现

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
/**
* 订单服务实现
* 负责订单创建、状态管理、取消
*/
@Service
@Slf4j
public class OrderService {

@Autowired
private OrderMapper orderMapper;

@Autowired
private OrderItemMapper orderItemMapper;

@Autowired
private RedisTemplate<String, Object> redisTemplate;

@Autowired
private KafkaTemplate<String, String> kafkaTemplate;

@Autowired
private InventoryServiceClient inventoryServiceClient;

@Autowired
private UserServiceClient userServiceClient;

@Autowired
private PaymentServiceClient paymentServiceClient;

@Autowired
private DistributedLock distributedLock;

/**
* 创建订单
*/
@Transactional(rollbackFor = Exception.class)
public OrderInfo createOrder(OrderCreateRequest request) {
String lockKey = "order:create:" + request.getUserId();
String lockValue = UUID.randomUUID().toString();

try {
// 1. 获取分布式锁
boolean lockAcquired = distributedLock.tryLock(lockKey, lockValue, 10, TimeUnit.SECONDS);
if (!lockAcquired) {
throw new BusinessException("订单创建中,请稍候");
}

// 2. 验证用户信息
UserInfo userInfo = userServiceClient.getUserInfo(request.getUserId());
if (userInfo == null) {
throw new BusinessException("用户不存在");
}

// 3. 验证库存
for (OrderItemRequest item : request.getItems()) {
InventoryInfo inventory = inventoryServiceClient.getInventory(item.getProductId());
if (inventory == null || inventory.getAvailableStock() < item.getQuantity()) {
throw new BusinessException("商品库存不足: productId=" + item.getProductId());
}
}

// 4. 生成订单号
String orderNo = generateOrderNo();

// 5. 计算订单金额
BigDecimal totalAmount = calculateTotalAmount(request.getItems());

// 6. 创建订单
Order order = new Order();
order.setOrderNo(orderNo);
order.setUserId(request.getUserId());
order.setTotalAmount(totalAmount);
order.setStatus("PENDING");
order.setPaymentStatus("UNPAID");
order.setCreateTime(LocalDateTime.now());
order.setUpdateTime(LocalDateTime.now());

orderMapper.insert(order);

// 7. 创建订单明细
List<OrderItem> orderItems = new ArrayList<>();
for (OrderItemRequest item : request.getItems()) {
OrderItem orderItem = new OrderItem();
orderItem.setOrderId(order.getId());
orderItem.setOrderNo(orderNo);
orderItem.setProductId(item.getProductId());
orderItem.setProductName(item.getProductName());
orderItem.setQuantity(item.getQuantity());
orderItem.setPrice(item.getPrice());
orderItem.setAmount(item.getPrice().multiply(new BigDecimal(item.getQuantity())));
orderItem.setCreateTime(LocalDateTime.now());

orderItemMapper.insert(orderItem);
orderItems.add(orderItem);
}

// 8. 扣减库存
for (OrderItemRequest item : request.getItems()) {
boolean deducted = inventoryServiceClient.deductInventory(
item.getProductId(), item.getQuantity(), orderNo);
if (!deducted) {
throw new BusinessException("库存扣减失败: productId=" + item.getProductId());
}
}

// 9. 构建订单信息
OrderInfo orderInfo = convertToOrderInfo(order, orderItems);

// 10. 缓存订单信息
String cacheKey = "order:info:" + orderNo;
redisTemplate.opsForValue().set(cacheKey, orderInfo, 1, TimeUnit.HOURS);

// 11. 发送订单创建事件
sendOrderCreateEvent(orderInfo);

log.info("创建订单成功: orderNo={}, userId={}, totalAmount={}",
orderNo, request.getUserId(), totalAmount);

return orderInfo;

} catch (Exception e) {
log.error("创建订单失败: userId={}, error={}",
request.getUserId(), e.getMessage(), e);
throw new BusinessException("创建订单失败: " + e.getMessage());
} finally {
// 释放分布式锁
distributedLock.releaseLock(lockKey, lockValue);
}
}

/**
* 更新订单状态
*/
@Transactional(rollbackFor = Exception.class)
public void updateOrderStatus(String orderNo, String status, String remark) {
try {
// 1. 获取订单
Order order = orderMapper.selectOne(
new LambdaQueryWrapper<Order>()
.eq(Order::getOrderNo, orderNo));
if (order == null) {
throw new BusinessException("订单不存在");
}

// 2. 验证状态流转
if (!isValidStatusTransition(order.getStatus(), status)) {
throw new BusinessException("订单状态流转无效: " + order.getStatus() + " -> " + status);
}

// 3. 更新订单状态
String oldStatus = order.getStatus();
order.setStatus(status);
if (remark != null) {
order.setRemark(remark);
}
order.setUpdateTime(LocalDateTime.now());

orderMapper.updateById(order);

// 4. 清除缓存
String cacheKey = "order:info:" + orderNo;
redisTemplate.delete(cacheKey);

// 5. 发送订单状态变更事件
sendOrderStatusChangeEvent(orderNo, oldStatus, status);

log.info("更新订单状态成功: orderNo={}, oldStatus={}, newStatus={}",
orderNo, oldStatus, status);

} catch (Exception e) {
log.error("更新订单状态失败: orderNo={}, error={}",
orderNo, e.getMessage(), e);
throw new BusinessException("更新订单状态失败: " + e.getMessage());
}
}

/**
* 取消订单
*/
@Transactional(rollbackFor = Exception.class)
public void cancelOrder(String orderNo, String cancelReason) {
try {
// 1. 获取订单
Order order = orderMapper.selectOne(
new LambdaQueryWrapper<Order>()
.eq(Order::getOrderNo, orderNo));
if (order == null) {
throw new BusinessException("订单不存在");
}

// 2. 验证订单是否可以取消
if (!"PENDING".equals(order.getStatus()) && !"PAID".equals(order.getStatus())) {
throw new BusinessException("订单状态不允许取消: " + order.getStatus());
}

// 3. 如果已支付,需要退款
if ("PAID".equals(order.getStatus())) {
boolean refunded = paymentServiceClient.refund(orderNo, order.getTotalAmount(), cancelReason);
if (!refunded) {
throw new BusinessException("退款失败");
}
}

// 4. 回滚库存
List<OrderItem> orderItems = orderItemMapper.selectList(
new LambdaQueryWrapper<OrderItem>()
.eq(OrderItem::getOrderNo, orderNo));

for (OrderItem item : orderItems) {
boolean rolledBack = inventoryServiceClient.rollbackInventory(
item.getProductId(), item.getQuantity(), orderNo);
if (!rolledBack) {
log.warn("库存回滚失败: productId={}, orderNo={}",
item.getProductId(), orderNo);
}
}

// 5. 更新订单状态
order.setStatus("CANCELLED");
order.setCancelReason(cancelReason);
order.setCancelTime(LocalDateTime.now());
order.setUpdateTime(LocalDateTime.now());

orderMapper.updateById(order);

// 6. 清除缓存
String cacheKey = "order:info:" + orderNo;
redisTemplate.delete(cacheKey);

// 7. 发送订单取消事件
sendOrderCancelEvent(orderNo, cancelReason);

log.info("取消订单成功: orderNo={}, cancelReason={}", orderNo, cancelReason);

} catch (Exception e) {
log.error("取消订单失败: orderNo={}, error={}",
orderNo, e.getMessage(), e);
throw new BusinessException("取消订单失败: " + e.getMessage());
}
}

/**
* 生成订单号
*/
private String generateOrderNo() {
return "ORD" + System.currentTimeMillis() +
String.format("%04d", new Random().nextInt(10000));
}

/**
* 计算订单总金额
*/
private BigDecimal calculateTotalAmount(List<OrderItemRequest> items) {
return items.stream()
.map(item -> item.getPrice().multiply(new BigDecimal(item.getQuantity())))
.reduce(BigDecimal.ZERO, BigDecimal::add);
}

/**
* 验证状态流转
*/
private boolean isValidStatusTransition(String oldStatus, String newStatus) {
Map<String, List<String>> validTransitions = new HashMap<>();
validTransitions.put("PENDING", Arrays.asList("PAID", "CANCELLED"));
validTransitions.put("PAID", Arrays.asList("SHIPPED", "CANCELLED", "REFUNDING"));
validTransitions.put("SHIPPED", Arrays.asList("DELIVERED", "RETURNING"));
validTransitions.put("DELIVERED", Arrays.asList("COMPLETED", "RETURNING"));
validTransitions.put("REFUNDING", Arrays.asList("REFUNDED", "CANCELLED"));
validTransitions.put("RETURNING", Arrays.asList("RETURNED", "CANCELLED"));

List<String> allowedStatuses = validTransitions.get(oldStatus);
return allowedStatuses != null && allowedStatuses.contains(newStatus);
}

/**
* 转换为订单信息
*/
private OrderInfo convertToOrderInfo(Order order, List<OrderItem> orderItems) {
OrderInfo orderInfo = new OrderInfo();
orderInfo.setOrderNo(order.getOrderNo());
orderInfo.setUserId(order.getUserId());
orderInfo.setTotalAmount(order.getTotalAmount());
orderInfo.setStatus(order.getStatus());
orderInfo.setPaymentStatus(order.getPaymentStatus());
orderInfo.setCreateTime(order.getCreateTime());

List<OrderItemInfo> itemInfoList = orderItems.stream()
.map(this::convertToOrderItemInfo)
.collect(Collectors.toList());
orderInfo.setItems(itemInfoList);

return orderInfo;
}

/**
* 转换为订单明细信息
*/
private OrderItemInfo convertToOrderItemInfo(OrderItem orderItem) {
OrderItemInfo itemInfo = new OrderItemInfo();
itemInfo.setProductId(orderItem.getProductId());
itemInfo.setProductName(orderItem.getProductName());
itemInfo.setQuantity(orderItem.getQuantity());
itemInfo.setPrice(orderItem.getPrice());
itemInfo.setAmount(orderItem.getAmount());
return itemInfo;
}

/**
* 发送订单创建事件
*/
private void sendOrderCreateEvent(OrderInfo orderInfo) {
try {
OrderEvent event = new OrderEvent();
event.setEventType("ORDER_CREATE");
event.setOrderNo(orderInfo.getOrderNo());
event.setOrderInfo(orderInfo);
event.setEventTime(LocalDateTime.now());

String message = JSON.toJSONString(event);
kafkaTemplate.send("order.create", orderInfo.getOrderNo(), message);

} catch (Exception e) {
log.error("发送订单创建事件失败: error={}", e.getMessage(), e);
}
}

/**
* 发送订单状态变更事件
*/
private void sendOrderStatusChangeEvent(String orderNo, String oldStatus, String newStatus) {
try {
OrderStatusChangeEvent event = new OrderStatusChangeEvent();
event.setEventType("ORDER_STATUS_CHANGE");
event.setOrderNo(orderNo);
event.setOldStatus(oldStatus);
event.setNewStatus(newStatus);
event.setEventTime(LocalDateTime.now());

String message = JSON.toJSONString(event);
kafkaTemplate.send("order.status.change", orderNo, message);

} catch (Exception e) {
log.error("发送订单状态变更事件失败: error={}", e.getMessage(), e);
}
}

/**
* 发送订单取消事件
*/
private void sendOrderCancelEvent(String orderNo, String cancelReason) {
try {
OrderCancelEvent event = new OrderCancelEvent();
event.setEventType("ORDER_CANCEL");
event.setOrderNo(orderNo);
event.setCancelReason(cancelReason);
event.setEventTime(LocalDateTime.now());

String message = JSON.toJSONString(event);
kafkaTemplate.send("order.cancel", orderNo, message);

} catch (Exception e) {
log.error("发送订单取消事件失败: error={}", e.getMessage(), e);
}
}
}

2.3 订单查询服务实现

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
/**
* 订单查询服务实现
* 负责订单查询、统计
*/
@Service
@Slf4j
public class OrderQueryService {

@Autowired
private OrderMapper orderMapper;

@Autowired
private OrderItemMapper orderItemMapper;

@Autowired
private RedisTemplate<String, Object> redisTemplate;

/**
* 获取订单信息
*/
public OrderInfo getOrderInfo(String orderNo) {
try {
// 1. 从缓存获取
String cacheKey = "order:info:" + orderNo;
OrderInfo cachedInfo = (OrderInfo) redisTemplate.opsForValue().get(cacheKey);
if (cachedInfo != null) {
return cachedInfo;
}

// 2. 从数据库查询
Order order = orderMapper.selectOne(
new LambdaQueryWrapper<Order>()
.eq(Order::getOrderNo, orderNo));
if (order == null) {
throw new BusinessException("订单不存在");
}

// 3. 查询订单明细
List<OrderItem> orderItems = orderItemMapper.selectList(
new LambdaQueryWrapper<OrderItem>()
.eq(OrderItem::getOrderNo, orderNo));

// 4. 构建订单信息
OrderInfo orderInfo = convertToOrderInfo(order, orderItems);

// 5. 缓存订单信息
redisTemplate.opsForValue().set(cacheKey, orderInfo, 1, TimeUnit.HOURS);

return orderInfo;

} catch (Exception e) {
log.error("获取订单信息失败: orderNo={}, error={}",
orderNo, e.getMessage(), e);
throw new BusinessException("获取订单信息失败: " + e.getMessage());
}
}

/**
* 获取订单列表
*/
public PageResult<OrderInfo> getOrderList(String userId, String status,
String startTime, String endTime,
Integer pageNum, Integer pageSize) {
try {
// 1. 构建查询条件
LambdaQueryWrapper<Order> wrapper = new LambdaQueryWrapper<>();
if (userId != null && !userId.isEmpty()) {
wrapper.eq(Order::getUserId, userId);
}
if (status != null && !status.isEmpty()) {
wrapper.eq(Order::getStatus, status);
}
if (startTime != null && !startTime.isEmpty()) {
wrapper.ge(Order::getCreateTime, LocalDateTime.parse(startTime));
}
if (endTime != null && !endTime.isEmpty()) {
wrapper.le(Order::getCreateTime, LocalDateTime.parse(endTime));
}
wrapper.orderByDesc(Order::getCreateTime);

// 2. 分页查询
Page<Order> page = new Page<>(pageNum, pageSize);
Page<Order> result = orderMapper.selectPage(page, wrapper);

// 3. 转换为订单信息列表
List<OrderInfo> orderInfoList = result.getRecords().stream()
.map(order -> {
List<OrderItem> orderItems = orderItemMapper.selectList(
new LambdaQueryWrapper<OrderItem>()
.eq(OrderItem::getOrderNo, order.getOrderNo()));
return convertToOrderInfo(order, orderItems);
})
.collect(Collectors.toList());

// 4. 构建分页结果
PageResult<OrderInfo> pageResult = new PageResult<>();
pageResult.setList(orderInfoList);
pageResult.setTotal(result.getTotal());
pageResult.setPageNum(pageNum);
pageResult.setPageSize(pageSize);

return pageResult;

} catch (Exception e) {
log.error("获取订单列表失败: error={}", e.getMessage(), e);
throw new BusinessException("获取订单列表失败: " + e.getMessage());
}
}

/**
* 获取订单统计
*/
public OrderStatistics getOrderStatistics(String userId, String startTime, String endTime) {
try {
// 1. 构建查询条件
LambdaQueryWrapper<Order> wrapper = new LambdaQueryWrapper<>();
if (userId != null && !userId.isEmpty()) {
wrapper.eq(Order::getUserId, userId);
}
if (startTime != null && !startTime.isEmpty()) {
wrapper.ge(Order::getCreateTime, LocalDateTime.parse(startTime));
}
if (endTime != null && !endTime.isEmpty()) {
wrapper.le(Order::getCreateTime, LocalDateTime.parse(endTime));
}

// 2. 查询订单列表
List<Order> orders = orderMapper.selectList(wrapper);

// 3. 统计订单数据
OrderStatistics statistics = new OrderStatistics();
statistics.setTotalCount(orders.size());
statistics.setTotalAmount(orders.stream()
.map(Order::getTotalAmount)
.reduce(BigDecimal.ZERO, BigDecimal::add));

Map<String, Long> statusCount = orders.stream()
.collect(Collectors.groupingBy(Order::getStatus, Collectors.counting()));
statistics.setStatusCount(statusCount);

Map<String, BigDecimal> statusAmount = orders.stream()
.collect(Collectors.groupingBy(
Order::getStatus,
Collectors.reducing(BigDecimal.ZERO, Order::getTotalAmount, BigDecimal::add)));
statistics.setStatusAmount(statusAmount);

return statistics;

} catch (Exception e) {
log.error("获取订单统计失败: error={}", e.getMessage(), e);
throw new BusinessException("获取订单统计失败: " + e.getMessage());
}
}

/**
* 转换为订单信息
*/
private OrderInfo convertToOrderInfo(Order order, List<OrderItem> orderItems) {
OrderInfo orderInfo = new OrderInfo();
orderInfo.setOrderNo(order.getOrderNo());
orderInfo.setUserId(order.getUserId());
orderInfo.setTotalAmount(order.getTotalAmount());
orderInfo.setStatus(order.getStatus());
orderInfo.setPaymentStatus(order.getPaymentStatus());
orderInfo.setCreateTime(order.getCreateTime());
orderInfo.setUpdateTime(order.getUpdateTime());

List<OrderItemInfo> itemInfoList = orderItems.stream()
.map(this::convertToOrderItemInfo)
.collect(Collectors.toList());
orderInfo.setItems(itemInfoList);

return orderInfo;
}

/**
* 转换为订单明细信息
*/
private OrderItemInfo convertToOrderItemInfo(OrderItem orderItem) {
OrderItemInfo itemInfo = new OrderItemInfo();
itemInfo.setProductId(orderItem.getProductId());
itemInfo.setProductName(orderItem.getProductName());
itemInfo.setQuantity(orderItem.getQuantity());
itemInfo.setPrice(orderItem.getPrice());
itemInfo.setAmount(orderItem.getAmount());
return itemInfo;
}
}

3. 支付服务实现

3.1 支付服务控制器

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
/**
* 支付服务控制器
* 提供支付管理接口
*/
@RestController
@RequestMapping("/api/payment")
@Slf4j
public class PaymentController {

@Autowired
private PaymentService paymentService;

@Autowired
private PaymentQueryService paymentQueryService;

/**
* 创建支付
*/
@PostMapping("/create")
public Result<PaymentInfo> createPayment(@RequestBody @Valid PaymentCreateRequest request) {
try {
PaymentInfo paymentInfo = paymentService.createPayment(request);
return Result.success(paymentInfo);
} catch (Exception e) {
log.error("创建支付失败: error={}", e.getMessage(), e);
return Result.error("创建支付失败: " + e.getMessage());
}
}

/**
* 支付回调
*/
@PostMapping("/callback")
public Result<Void> paymentCallback(@RequestBody PaymentCallbackRequest request) {
try {
paymentService.handlePaymentCallback(request);
return Result.success();
} catch (Exception e) {
log.error("支付回调处理失败: error={}", e.getMessage(), e);
return Result.error("支付回调处理失败: " + e.getMessage());
}
}

/**
* 查询支付状态
*/
@GetMapping("/{paymentNo}")
public Result<PaymentInfo> getPaymentInfo(@PathVariable String paymentNo) {
try {
PaymentInfo paymentInfo = paymentQueryService.getPaymentInfo(paymentNo);
return Result.success(paymentInfo);
} catch (Exception e) {
log.error("查询支付状态失败: paymentNo={}, error={}",
paymentNo, e.getMessage(), e);
return Result.error("查询支付状态失败: " + e.getMessage());
}
}

/**
* 退款
*/
@PostMapping("/refund")
public Result<RefundInfo> refund(@RequestBody @Valid RefundRequest request) {
try {
RefundInfo refundInfo = paymentService.refund(request);
return Result.success(refundInfo);
} catch (Exception e) {
log.error("退款失败: error={}", e.getMessage(), e);
return Result.error("退款失败: " + e.getMessage());
}
}
}

3.2 支付服务实现

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
/**
* 支付服务实现
* 负责支付处理、回调、退款
*/
@Service
@Slf4j
public class PaymentService {

@Autowired
private PaymentMapper paymentMapper;

@Autowired
private OrderServiceClient orderServiceClient;

@Autowired
private KafkaTemplate<String, String> kafkaTemplate;

@Autowired
private RedisTemplate<String, Object> redisTemplate;

/**
* 创建支付
*/
@Transactional(rollbackFor = Exception.class)
public PaymentInfo createPayment(PaymentCreateRequest request) {
try {
// 1. 验证订单
OrderInfo orderInfo = orderServiceClient.getOrderInfo(request.getOrderNo());
if (orderInfo == null) {
throw new BusinessException("订单不存在");
}
if (!"PENDING".equals(orderInfo.getStatus())) {
throw new BusinessException("订单状态不允许支付: " + orderInfo.getStatus());
}
if (!"UNPAID".equals(orderInfo.getPaymentStatus())) {
throw new BusinessException("订单已支付");
}

// 2. 生成支付单号
String paymentNo = generatePaymentNo();

// 3. 创建支付记录
Payment payment = new Payment();
payment.setPaymentNo(paymentNo);
payment.setOrderNo(request.getOrderNo());
payment.setUserId(request.getUserId());
payment.setAmount(request.getAmount());
payment.setPaymentMethod(request.getPaymentMethod());
payment.setStatus("PENDING");
payment.setCreateTime(LocalDateTime.now());
payment.setUpdateTime(LocalDateTime.now());

paymentMapper.insert(payment);

// 4. 调用第三方支付接口(模拟)
boolean paymentResult = callThirdPartyPayment(paymentNo, request);
if (!paymentResult) {
payment.setStatus("FAILED");
payment.setErrorMessage("第三方支付失败");
paymentMapper.updateById(payment);
throw new BusinessException("支付失败");
}

// 5. 更新支付状态
payment.setStatus("SUCCESS");
payment.setPaymentTime(LocalDateTime.now());
paymentMapper.updateById(payment);

// 6. 更新订单状态
orderServiceClient.updateOrderStatus(request.getOrderNo(), "PAID", "支付成功");

// 7. 构建支付信息
PaymentInfo paymentInfo = convertToPaymentInfo(payment);

// 8. 发送支付成功事件
sendPaymentSuccessEvent(paymentInfo);

log.info("创建支付成功: paymentNo={}, orderNo={}, amount={}",
paymentNo, request.getOrderNo(), request.getAmount());

return paymentInfo;

} catch (Exception e) {
log.error("创建支付失败: orderNo={}, error={}",
request.getOrderNo(), e.getMessage(), e);
throw new BusinessException("创建支付失败: " + e.getMessage());
}
}

/**
* 处理支付回调
*/
@Transactional(rollbackFor = Exception.class)
public void handlePaymentCallback(PaymentCallbackRequest request) {
try {
// 1. 验证回调签名
if (!verifyCallbackSignature(request)) {
throw new BusinessException("回调签名验证失败");
}

// 2. 查询支付记录
Payment payment = paymentMapper.selectOne(
new LambdaQueryWrapper<Payment>()
.eq(Payment::getPaymentNo, request.getPaymentNo()));
if (payment == null) {
throw new BusinessException("支付记录不存在");
}

// 3. 防止重复处理
if ("SUCCESS".equals(payment.getStatus())) {
log.warn("支付回调已处理: paymentNo={}", request.getPaymentNo());
return;
}

// 4. 更新支付状态
if ("SUCCESS".equals(request.getStatus())) {
payment.setStatus("SUCCESS");
payment.setPaymentTime(LocalDateTime.now());
payment.setThirdPartyPaymentNo(request.getThirdPartyPaymentNo());
} else {
payment.setStatus("FAILED");
payment.setErrorMessage(request.getErrorMessage());
}
payment.setUpdateTime(LocalDateTime.now());

paymentMapper.updateById(payment);

// 5. 更新订单状态
if ("SUCCESS".equals(request.getStatus())) {
orderServiceClient.updateOrderStatus(payment.getOrderNo(), "PAID", "支付成功");
}

// 6. 发送支付回调事件
sendPaymentCallbackEvent(payment, request.getStatus());

log.info("处理支付回调成功: paymentNo={}, status={}",
request.getPaymentNo(), request.getStatus());

} catch (Exception e) {
log.error("处理支付回调失败: paymentNo={}, error={}",
request.getPaymentNo(), e.getMessage(), e);
throw new BusinessException("处理支付回调失败: " + e.getMessage());
}
}

/**
* 退款
*/
@Transactional(rollbackFor = Exception.class)
public RefundInfo refund(RefundRequest request) {
try {
// 1. 查询支付记录
Payment payment = paymentMapper.selectOne(
new LambdaQueryWrapper<Payment>()
.eq(Payment::getOrderNo, request.getOrderNo()));
if (payment == null) {
throw new BusinessException("支付记录不存在");
}
if (!"SUCCESS".equals(payment.getStatus())) {
throw new BusinessException("支付记录状态不允许退款: " + payment.getStatus());
}

// 2. 生成退款单号
String refundNo = generateRefundNo();

// 3. 创建退款记录
Refund refund = new Refund();
refund.setRefundNo(refundNo);
refund.setPaymentNo(payment.getPaymentNo());
refund.setOrderNo(request.getOrderNo());
refund.setAmount(request.getAmount());
refund.setRefundReason(request.getRefundReason());
refund.setStatus("PENDING");
refund.setCreateTime(LocalDateTime.now());
refund.setUpdateTime(LocalDateTime.now());

refundMapper.insert(refund);

// 4. 调用第三方退款接口(模拟)
boolean refundResult = callThirdPartyRefund(refundNo, payment, request);
if (!refundResult) {
refund.setStatus("FAILED");
refund.setErrorMessage("第三方退款失败");
refundMapper.updateById(refund);
throw new BusinessException("退款失败");
}

// 5. 更新退款状态
refund.setStatus("SUCCESS");
refund.setRefundTime(LocalDateTime.now());
refundMapper.updateById(refund);

// 6. 更新支付状态
payment.setStatus("REFUNDED");
paymentMapper.updateById(payment);

// 7. 构建退款信息
RefundInfo refundInfo = convertToRefundInfo(refund);

// 8. 发送退款成功事件
sendRefundSuccessEvent(refundInfo);

log.info("退款成功: refundNo={}, orderNo={}, amount={}",
refundNo, request.getOrderNo(), request.getAmount());

return refundInfo;

} catch (Exception e) {
log.error("退款失败: orderNo={}, error={}",
request.getOrderNo(), e.getMessage(), e);
throw new BusinessException("退款失败: " + e.getMessage());
}
}

/**
* 生成支付单号
*/
private String generatePaymentNo() {
return "PAY" + System.currentTimeMillis() +
String.format("%04d", new Random().nextInt(10000));
}

/**
* 生成退款单号
*/
private String generateRefundNo() {
return "REF" + System.currentTimeMillis() +
String.format("%04d", new Random().nextInt(10000));
}

/**
* 调用第三方支付接口
*/
private boolean callThirdPartyPayment(String paymentNo, PaymentCreateRequest request) {
// 模拟第三方支付接口调用
// 实际项目中应该调用真实的支付接口,如支付宝、微信支付等
return true;
}

/**
* 调用第三方退款接口
*/
private boolean callThirdPartyRefund(String refundNo, Payment payment, RefundRequest request) {
// 模拟第三方退款接口调用
// 实际项目中应该调用真实的退款接口
return true;
}

/**
* 验证回调签名
*/
private boolean verifyCallbackSignature(PaymentCallbackRequest request) {
// 模拟签名验证
// 实际项目中应该验证真实的签名
return true;
}

/**
* 转换为支付信息
*/
private PaymentInfo convertToPaymentInfo(Payment payment) {
PaymentInfo paymentInfo = new PaymentInfo();
paymentInfo.setPaymentNo(payment.getPaymentNo());
paymentInfo.setOrderNo(payment.getOrderNo());
paymentInfo.setUserId(payment.getUserId());
paymentInfo.setAmount(payment.getAmount());
paymentInfo.setPaymentMethod(payment.getPaymentMethod());
paymentInfo.setStatus(payment.getStatus());
paymentInfo.setPaymentTime(payment.getPaymentTime());
return paymentInfo;
}

/**
* 转换为退款信息
*/
private RefundInfo convertToRefundInfo(Refund refund) {
RefundInfo refundInfo = new RefundInfo();
refundInfo.setRefundNo(refund.getRefundNo());
refundInfo.setPaymentNo(refund.getPaymentNo());
refundInfo.setOrderNo(refund.getOrderNo());
refundInfo.setAmount(refund.getAmount());
refundInfo.setRefundReason(refund.getRefundReason());
refundInfo.setStatus(refund.getStatus());
refundInfo.setRefundTime(refund.getRefundTime());
return refundInfo;
}

/**
* 发送支付成功事件
*/
private void sendPaymentSuccessEvent(PaymentInfo paymentInfo) {
try {
PaymentEvent event = new PaymentEvent();
event.setEventType("PAYMENT_SUCCESS");
event.setPaymentNo(paymentInfo.getPaymentNo());
event.setOrderNo(paymentInfo.getOrderNo());
event.setAmount(paymentInfo.getAmount());
event.setEventTime(LocalDateTime.now());

String message = JSON.toJSONString(event);
kafkaTemplate.send("payment.success", paymentInfo.getPaymentNo(), message);

} catch (Exception e) {
log.error("发送支付成功事件失败: error={}", e.getMessage(), e);
}
}

/**
* 发送支付回调事件
*/
private void sendPaymentCallbackEvent(Payment payment, String status) {
try {
PaymentCallbackEvent event = new PaymentCallbackEvent();
event.setEventType("PAYMENT_CALLBACK");
event.setPaymentNo(payment.getPaymentNo());
event.setOrderNo(payment.getOrderNo());
event.setStatus(status);
event.setEventTime(LocalDateTime.now());

String message = JSON.toJSONString(event);
kafkaTemplate.send("payment.callback", payment.getPaymentNo(), message);

} catch (Exception e) {
log.error("发送支付回调事件失败: error={}", e.getMessage(), e);
}
}

/**
* 发送退款成功事件
*/
private void sendRefundSuccessEvent(RefundInfo refundInfo) {
try {
RefundEvent event = new RefundEvent();
event.setEventType("REFUND_SUCCESS");
event.setRefundNo(refundInfo.getRefundNo());
event.setOrderNo(refundInfo.getOrderNo());
event.setAmount(refundInfo.getAmount());
event.setEventTime(LocalDateTime.now());

String message = JSON.toJSONString(event);
kafkaTemplate.send("refund.success", refundInfo.getRefundNo(), message);

} catch (Exception e) {
log.error("发送退款成功事件失败: error={}", e.getMessage(), e);
}
}
}

4. 库存服务实现

4.1 库存服务控制器

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
/**
* 库存服务控制器
* 提供库存管理接口
*/
@RestController
@RequestMapping("/api/inventory")
@Slf4j
public class InventoryController {

@Autowired
private InventoryService inventoryService;

@Autowired
private InventoryQueryService inventoryQueryService;

/**
* 获取库存信息
*/
@GetMapping("/{productId}")
public Result<InventoryInfo> getInventory(@PathVariable String productId) {
try {
InventoryInfo inventoryInfo = inventoryQueryService.getInventory(productId);
return Result.success(inventoryInfo);
} catch (Exception e) {
log.error("获取库存信息失败: productId={}, error={}",
productId, e.getMessage(), e);
return Result.error("获取库存信息失败: " + e.getMessage());
}
}

/**
* 扣减库存
*/
@PostMapping("/deduct")
public Result<Boolean> deductInventory(@RequestBody @Valid InventoryDeductRequest request) {
try {
boolean result = inventoryService.deductInventory(
request.getProductId(),
request.getQuantity(),
request.getOrderNo());
return Result.success(result);
} catch (Exception e) {
log.error("扣减库存失败: productId={}, error={}",
request.getProductId(), e.getMessage(), e);
return Result.error("扣减库存失败: " + e.getMessage());
}
}

/**
* 回滚库存
*/
@PostMapping("/rollback")
public Result<Boolean> rollbackInventory(@RequestBody @Valid InventoryRollbackRequest request) {
try {
boolean result = inventoryService.rollbackInventory(
request.getProductId(),
request.getQuantity(),
request.getOrderNo());
return Result.success(result);
} catch (Exception e) {
log.error("回滚库存失败: productId={}, error={}",
request.getProductId(), e.getMessage(), e);
return Result.error("回滚库存失败: " + e.getMessage());
}
}
}

4.2 库存服务实现

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
/**
* 库存服务实现
* 负责库存扣减、回滚、查询
*/
@Service
@Slf4j
public class InventoryService {

@Autowired
private InventoryMapper inventoryMapper;

@Autowired
private InventoryRecordMapper inventoryRecordMapper;

@Autowired
private RedisTemplate<String, Object> redisTemplate;

@Autowired
private DistributedLock distributedLock;

/**
* 扣减库存
*/
@Transactional(rollbackFor = Exception.class)
public boolean deductInventory(String productId, Integer quantity, String orderNo) {
String lockKey = "inventory:deduct:" + productId;
String lockValue = UUID.randomUUID().toString();

try {
// 1. 获取分布式锁
boolean lockAcquired = distributedLock.tryLock(lockKey, lockValue, 10, TimeUnit.SECONDS);
if (!lockAcquired) {
throw new BusinessException("库存扣减中,请稍候");
}

// 2. 查询库存
Inventory inventory = inventoryMapper.selectOne(
new LambdaQueryWrapper<Inventory>()
.eq(Inventory::getProductId, productId));
if (inventory == null) {
throw new BusinessException("商品不存在");
}

// 3. 验证库存
if (inventory.getAvailableStock() < quantity) {
throw new BusinessException("库存不足: availableStock=" + inventory.getAvailableStock() + ", quantity=" + quantity);
}

// 4. 扣减库存
inventory.setAvailableStock(inventory.getAvailableStock() - quantity);
inventory.setLockedStock(inventory.getLockedStock() + quantity);
inventory.setUpdateTime(LocalDateTime.now());

inventoryMapper.updateById(inventory);

// 5. 记录库存变更
InventoryRecord record = new InventoryRecord();
record.setProductId(productId);
record.setOrderNo(orderNo);
record.setChangeType("DEDUCT");
record.setChangeQuantity(quantity);
record.setBeforeStock(inventory.getAvailableStock() + quantity);
record.setAfterStock(inventory.getAvailableStock());
record.setCreateTime(LocalDateTime.now());

inventoryRecordMapper.insert(record);

// 6. 更新Redis缓存
String cacheKey = "inventory:stock:" + productId;
redisTemplate.opsForValue().set(cacheKey, inventory.getAvailableStock(), 1, TimeUnit.HOURS);

log.info("扣减库存成功: productId={}, quantity={}, orderNo={}, availableStock={}",
productId, quantity, orderNo, inventory.getAvailableStock());

return true;

} catch (Exception e) {
log.error("扣减库存失败: productId={}, quantity={}, orderNo={}, error={}",
productId, quantity, orderNo, e.getMessage(), e);
throw new BusinessException("扣减库存失败: " + e.getMessage());
} finally {
// 释放分布式锁
distributedLock.releaseLock(lockKey, lockValue);
}
}

/**
* 回滚库存
*/
@Transactional(rollbackFor = Exception.class)
public boolean rollbackInventory(String productId, Integer quantity, String orderNo) {
String lockKey = "inventory:rollback:" + productId;
String lockValue = UUID.randomUUID().toString();

try {
// 1. 获取分布式锁
boolean lockAcquired = distributedLock.tryLock(lockKey, lockValue, 10, TimeUnit.SECONDS);
if (!lockAcquired) {
throw new BusinessException("库存回滚中,请稍候");
}

// 2. 查询库存
Inventory inventory = inventoryMapper.selectOne(
new LambdaQueryWrapper<Inventory>()
.eq(Inventory::getProductId, productId));
if (inventory == null) {
throw new BusinessException("商品不存在");
}

// 3. 验证锁定库存
if (inventory.getLockedStock() < quantity) {
log.warn("锁定库存不足: productId={}, lockedStock={}, quantity={}",
productId, inventory.getLockedStock(), quantity);
quantity = inventory.getLockedStock();
}

// 4. 回滚库存
inventory.setAvailableStock(inventory.getAvailableStock() + quantity);
inventory.setLockedStock(inventory.getLockedStock() - quantity);
inventory.setUpdateTime(LocalDateTime.now());

inventoryMapper.updateById(inventory);

// 5. 记录库存变更
InventoryRecord record = new InventoryRecord();
record.setProductId(productId);
record.setOrderNo(orderNo);
record.setChangeType("ROLLBACK");
record.setChangeQuantity(quantity);
record.setBeforeStock(inventory.getAvailableStock() - quantity);
record.setAfterStock(inventory.getAvailableStock());
record.setCreateTime(LocalDateTime.now());

inventoryRecordMapper.insert(record);

// 6. 更新Redis缓存
String cacheKey = "inventory:stock:" + productId;
redisTemplate.opsForValue().set(cacheKey, inventory.getAvailableStock(), 1, TimeUnit.HOURS);

log.info("回滚库存成功: productId={}, quantity={}, orderNo={}, availableStock={}",
productId, quantity, orderNo, inventory.getAvailableStock());

return true;

} catch (Exception e) {
log.error("回滚库存失败: productId={}, quantity={}, orderNo={}, error={}",
productId, quantity, orderNo, e.getMessage(), e);
throw new BusinessException("回滚库存失败: " + e.getMessage());
} finally {
// 释放分布式锁
distributedLock.releaseLock(lockKey, lockValue);
}
}
}

4.3 库存查询服务实现

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
/**
* 库存查询服务实现
* 负责库存查询
*/
@Service
@Slf4j
public class InventoryQueryService {

@Autowired
private InventoryMapper inventoryMapper;

@Autowired
private RedisTemplate<String, Object> redisTemplate;

/**
* 获取库存信息
*/
public InventoryInfo getInventory(String productId) {
try {
// 1. 从缓存获取
String cacheKey = "inventory:info:" + productId;
InventoryInfo cachedInfo = (InventoryInfo) redisTemplate.opsForValue().get(cacheKey);
if (cachedInfo != null) {
return cachedInfo;
}

// 2. 从数据库查询
Inventory inventory = inventoryMapper.selectOne(
new LambdaQueryWrapper<Inventory>()
.eq(Inventory::getProductId, productId));
if (inventory == null) {
throw new BusinessException("商品不存在");
}

// 3. 构建库存信息
InventoryInfo inventoryInfo = new InventoryInfo();
inventoryInfo.setProductId(inventory.getProductId());
inventoryInfo.setTotalStock(inventory.getTotalStock());
inventoryInfo.setAvailableStock(inventory.getAvailableStock());
inventoryInfo.setLockedStock(inventory.getLockedStock());

// 4. 缓存库存信息
redisTemplate.opsForValue().set(cacheKey, inventoryInfo, 1, TimeUnit.HOURS);

return inventoryInfo;

} catch (Exception e) {
log.error("获取库存信息失败: productId={}, error={}",
productId, e.getMessage(), e);
throw new BusinessException("获取库存信息失败: " + e.getMessage());
}
}
}

5. Kafka消费者实现

5.1 订单事件消费者

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
/**
* 订单事件消费者
* 消费Kafka订单事件消息
*/
@Component
@Slf4j
public class OrderEventConsumer {

@Autowired
private OrderService orderService;

@Autowired
private UserServiceClient userServiceClient;

/**
* 消费订单创建事件
*/
@KafkaListener(topics = "order.create", groupId = "order-event-group")
public void consumeOrderCreate(String message) {
try {
OrderEvent event = JSON.parseObject(message, OrderEvent.class);

// 处理订单创建事件,如发送通知、更新统计等
log.info("消费订单创建事件: orderNo={}", event.getOrderNo());

} catch (Exception e) {
log.error("消费订单创建事件失败: error={}", e.getMessage(), e);
}
}

/**
* 消费订单状态变更事件
*/
@KafkaListener(topics = "order.status.change", groupId = "order-event-group")
public void consumeOrderStatusChange(String message) {
try {
OrderStatusChangeEvent event = JSON.parseObject(message, OrderStatusChangeEvent.class);

// 处理订单状态变更事件,如发送通知、更新统计等
log.info("消费订单状态变更事件: orderNo={}, oldStatus={}, newStatus={}",
event.getOrderNo(), event.getOldStatus(), event.getNewStatus());

} catch (Exception e) {
log.error("消费订单状态变更事件失败: error={}", e.getMessage(), e);
}
}

/**
* 消费订单取消事件
*/
@KafkaListener(topics = "order.cancel", groupId = "order-event-group")
public void consumeOrderCancel(String message) {
try {
OrderCancelEvent event = JSON.parseObject(message, OrderCancelEvent.class);

// 处理订单取消事件,如发送通知、更新统计等
log.info("消费订单取消事件: orderNo={}, cancelReason={}",
event.getOrderNo(), event.getCancelReason());

} catch (Exception e) {
log.error("消费订单取消事件失败: error={}", e.getMessage(), e);
}
}
}

5.2 支付事件消费者

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
/**
* 支付事件消费者
* 消费Kafka支付事件消息
*/
@Component
@Slf4j
public class PaymentEventConsumer {

@Autowired
private PaymentService paymentService;

/**
* 消费支付成功事件
*/
@KafkaListener(topics = "payment.success", groupId = "payment-event-group")
public void consumePaymentSuccess(String message) {
try {
PaymentEvent event = JSON.parseObject(message, PaymentEvent.class);

// 处理支付成功事件,如发送通知、更新统计等
log.info("消费支付成功事件: paymentNo={}, orderNo={}, amount={}",
event.getPaymentNo(), event.getOrderNo(), event.getAmount());

} catch (Exception e) {
log.error("消费支付成功事件失败: error={}", e.getMessage(), e);
}
}

/**
* 消费支付回调事件
*/
@KafkaListener(topics = "payment.callback", groupId = "payment-event-group")
public void consumePaymentCallback(String message) {
try {
PaymentCallbackEvent event = JSON.parseObject(message, PaymentCallbackEvent.class);

// 处理支付回调事件,如发送通知、更新统计等
log.info("消费支付回调事件: paymentNo={}, orderNo={}, status={}",
event.getPaymentNo(), event.getOrderNo(), event.getStatus());

} catch (Exception e) {
log.error("消费支付回调事件失败: error={}", e.getMessage(), e);
}
}

/**
* 消费退款成功事件
*/
@KafkaListener(topics = "refund.success", groupId = "payment-event-group")
public void consumeRefundSuccess(String message) {
try {
RefundEvent event = JSON.parseObject(message, RefundEvent.class);

// 处理退款成功事件,如发送通知、更新统计等
log.info("消费退款成功事件: refundNo={}, orderNo={}, amount={}",
event.getRefundNo(), event.getOrderNo(), event.getAmount());

} catch (Exception e) {
log.error("消费退款成功事件失败: error={}", e.getMessage(), e);
}
}
}

6. 数据模型定义

6.1 订单实体

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
/**
* 订单实体
*/
@Data
@TableName("t_order")
public class Order {

@TableId(type = IdType.AUTO)
private Long id;

private String orderNo;

private String userId;

private BigDecimal totalAmount;

private String status;

private String paymentStatus;

private String remark;

private String cancelReason;

private LocalDateTime cancelTime;

private LocalDateTime createTime;

private LocalDateTime updateTime;
}

6.2 订单明细实体

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
/**
* 订单明细实体
*/
@Data
@TableName("t_order_item")
public class OrderItem {

@TableId(type = IdType.AUTO)
private Long id;

private Long orderId;

private String orderNo;

private String productId;

private String productName;

private Integer quantity;

private BigDecimal price;

private BigDecimal amount;

private LocalDateTime createTime;
}

6.3 支付实体

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
/**
* 支付实体
*/
@Data
@TableName("t_payment")
public class Payment {

@TableId(type = IdType.AUTO)
private Long id;

private String paymentNo;

private String orderNo;

private String userId;

private BigDecimal amount;

private String paymentMethod;

private String status;

private String thirdPartyPaymentNo;

private LocalDateTime paymentTime;

private String errorMessage;

private LocalDateTime createTime;

private LocalDateTime updateTime;
}

6.4 库存实体

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
/**
* 库存实体
*/
@Data
@TableName("t_inventory")
public class Inventory {

@TableId(type = IdType.AUTO)
private Long id;

private String productId;

private Integer totalStock;

private Integer availableStock;

private Integer lockedStock;

private LocalDateTime createTime;

private LocalDateTime updateTime;
}

7. 数据库设计

7.1 订单表

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
CREATE TABLE `t_order` (
`id` BIGINT(20) NOT NULL AUTO_INCREMENT COMMENT 'ID',
`order_no` VARCHAR(64) NOT NULL COMMENT '订单号',
`user_id` VARCHAR(64) NOT NULL COMMENT '用户ID',
`total_amount` DECIMAL(10,2) NOT NULL COMMENT '订单总金额',
`status` VARCHAR(32) NOT NULL DEFAULT 'PENDING' COMMENT '订单状态:PENDING-待支付, PAID-已支付, SHIPPED-已发货, DELIVERED-已送达, COMPLETED-已完成, CANCELLED-已取消',
`payment_status` VARCHAR(32) NOT NULL DEFAULT 'UNPAID' COMMENT '支付状态:UNPAID-未支付, PAID-已支付, REFUNDING-退款中, REFUNDED-已退款',
`remark` VARCHAR(512) DEFAULT NULL COMMENT '备注',
`cancel_reason` VARCHAR(512) DEFAULT NULL COMMENT '取消原因',
`cancel_time` DATETIME DEFAULT NULL COMMENT '取消时间',
`create_time` DATETIME NOT NULL DEFAULT CURRENT_TIMESTAMP COMMENT '创建时间',
`update_time` DATETIME NOT NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP COMMENT '更新时间',
PRIMARY KEY (`id`),
UNIQUE KEY `uk_order_no` (`order_no`),
KEY `idx_user_id` (`user_id`),
KEY `idx_status` (`status`),
KEY `idx_create_time` (`create_time`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COMMENT='订单表';

7.2 订单明细表

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
CREATE TABLE `t_order_item` (
`id` BIGINT(20) NOT NULL AUTO_INCREMENT COMMENT 'ID',
`order_id` BIGINT(20) NOT NULL COMMENT '订单ID',
`order_no` VARCHAR(64) NOT NULL COMMENT '订单号',
`product_id` VARCHAR(64) NOT NULL COMMENT '商品ID',
`product_name` VARCHAR(128) NOT NULL COMMENT '商品名称',
`quantity` INT(11) NOT NULL COMMENT '数量',
`price` DECIMAL(10,2) NOT NULL COMMENT '单价',
`amount` DECIMAL(10,2) NOT NULL COMMENT '金额',
`create_time` DATETIME NOT NULL DEFAULT CURRENT_TIMESTAMP COMMENT '创建时间',
PRIMARY KEY (`id`),
KEY `idx_order_id` (`order_id`),
KEY `idx_order_no` (`order_no`),
KEY `idx_product_id` (`product_id`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COMMENT='订单明细表';

7.3 支付表

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
CREATE TABLE `t_payment` (
`id` BIGINT(20) NOT NULL AUTO_INCREMENT COMMENT 'ID',
`payment_no` VARCHAR(64) NOT NULL COMMENT '支付单号',
`order_no` VARCHAR(64) NOT NULL COMMENT '订单号',
`user_id` VARCHAR(64) NOT NULL COMMENT '用户ID',
`amount` DECIMAL(10,2) NOT NULL COMMENT '支付金额',
`payment_method` VARCHAR(32) NOT NULL COMMENT '支付方式:ALIPAY-支付宝, WECHAT-微信, BANK-银行卡',
`status` VARCHAR(32) NOT NULL DEFAULT 'PENDING' COMMENT '支付状态:PENDING-待支付, SUCCESS-成功, FAILED-失败, REFUNDED-已退款',
`third_party_payment_no` VARCHAR(64) DEFAULT NULL COMMENT '第三方支付单号',
`payment_time` DATETIME DEFAULT NULL COMMENT '支付时间',
`error_message` VARCHAR(512) DEFAULT NULL COMMENT '错误信息',
`create_time` DATETIME NOT NULL DEFAULT CURRENT_TIMESTAMP COMMENT '创建时间',
`update_time` DATETIME NOT NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP COMMENT '更新时间',
PRIMARY KEY (`id`),
UNIQUE KEY `uk_payment_no` (`payment_no`),
KEY `idx_order_no` (`order_no`),
KEY `idx_user_id` (`user_id`),
KEY `idx_status` (`status`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COMMENT='支付表';

7.4 库存表

1
2
3
4
5
6
7
8
9
10
11
CREATE TABLE `t_inventory` (
`id` BIGINT(20) NOT NULL AUTO_INCREMENT COMMENT 'ID',
`product_id` VARCHAR(64) NOT NULL COMMENT '商品ID',
`total_stock` INT(11) NOT NULL DEFAULT 0 COMMENT '总库存',
`available_stock` INT(11) NOT NULL DEFAULT 0 COMMENT '可用库存',
`locked_stock` INT(11) NOT NULL DEFAULT 0 COMMENT '锁定库存',
`create_time` DATETIME NOT NULL DEFAULT CURRENT_TIMESTAMP COMMENT '创建时间',
`update_time` DATETIME NOT NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP COMMENT '更新时间',
PRIMARY KEY (`id`),
UNIQUE KEY `uk_product_id` (`product_id`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COMMENT='库存表';

8. 配置类

8.1 Kafka配置

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
# application.yml
spring:
kafka:
bootstrap-servers: localhost:9092
producer:
key-serializer: org.apache.kafka.common.serialization.StringSerializer
value-serializer: org.apache.kafka.common.serialization.StringSerializer
acks: all
retries: 3
consumer:
group-id: order-service-group
key-deserializer: org.apache.kafka.common.serialization.StringDeserializer
value-deserializer: org.apache.kafka.common.serialization.StringDeserializer
enable-auto-commit: false
auto-offset-reset: latest

8.2 Redis配置

1
2
3
4
5
6
7
8
9
10
11
12
13
# application.yml
spring:
redis:
host: localhost
port: 6379
password:
database: 0
timeout: 3000
lettuce:
pool:
max-active: 8
max-idle: 8
min-idle: 0

9. 总结

本文深入讲解了订单服务完整逻辑代码的Java微服务后端架构实战,涵盖了以下核心内容:

  1. 订单服务:实现订单创建、查询、状态管理、取消、统计
  2. 支付服务:实现支付处理、回调、状态查询、退款
  3. 库存服务:实现库存查询、扣减、回滚、统计
  4. 用户服务:实现用户验证、信息查询、积分管理
  5. Kafka消息队列:实现订单、支付、库存的异步处理和消息通知
  6. 多服务协作:通过Kafka和Feign实现订单服务、支付服务、库存服务、用户服务之间的解耦和协作
  7. 分布式事务:通过分布式锁、事务管理保证数据一致性
  8. 数据库设计:完整的订单、订单明细、支付、库存表设计
  9. 缓存优化:通过Redis缓存订单信息、库存信息、分布式锁
  10. 性能优化:通过连接池、批量处理、异步处理提升系统性能

通过本文的学习,读者可以掌握如何基于Java微服务架构实现一个完整的订单服务系统,包含订单创建、支付处理、库存管理、多服务协作等完整业务逻辑代码,为实际项目的订单服务开发提供参考和指导。

+