📋 订单处理系统
# 📋 订单处理系统
"每一个订单都是一个承诺,从用户点击'购买'的那一刻起,我们就开始了一场跨越国界的信任之旅。"
# 🎬 故事开篇
当艾米莉在纽约的深夜浏览我们的跨境电商平台,看中了一款来自日本的限量版手表时,她轻点了"立即购买"按钮。这个看似简单的动作,却触发了一个复杂而精密的订单处理系统。
从订单创建、库存验证、支付处理,到物流安排、海关申报,每一个环节都需要在毫秒级的时间内完成精确的计算和判断。这就是我们今天要深入探讨的订单处理系统——跨境电商的核心引擎。
# 🎯 系统概述
# 核心功能
订单处理系统是跨境电商平台的核心业务系统,负责处理从订单创建到订单完成的整个生命周期:
- 订单创建与验证:订单信息校验、商品可用性检查
- 库存管理:库存预占、库存扣减、库存释放
- 支付集成:多种支付方式、支付状态管理
- 订单状态管理:订单状态流转、状态通知
- 物流集成:物流商选择、运单生成、物流跟踪
- 海关申报:报关单生成、清关状态跟踪
- 异常处理:订单取消、退款处理、异常恢复
# 🏗️ 系统架构设计
graph TB
subgraph "用户层"
A[Web前端] --> B[移动端App]
B --> C[API网关]
end
subgraph "业务层"
C --> D[订单服务]
D --> E[库存服务]
D --> F[支付服务]
D --> G[物流服务]
D --> H[海关服务]
end
subgraph "数据层"
E --> I[(订单数据库)]
E --> J[(库存数据库)]
F --> K[(支付数据库)]
G --> L[(物流数据库)]
end
subgraph "外部系统"
F --> M[支付网关]
G --> N[物流API]
H --> O[海关系统]
end
subgraph "消息队列"
D --> P[订单事件队列]
P --> Q[库存事件队列]
P --> R[支付事件队列]
P --> S[物流事件队列]
end
# 💻 核心代码实现
# 1. 订单实体模型
/**
* 跨境订单实体
*/
@Entity
@Table(name = "cross_border_orders")
public class CrossBorderOrder {
@Id
@GeneratedValue(strategy = GenerationType.IDENTITY)
private Long id;
/**
* 订单编号(全局唯一)
*/
@Column(unique = true, nullable = false)
private String orderNumber;
/**
* 用户ID
*/
@Column(nullable = false)
private Long userId;
/**
* 订单状态
*/
@Enumerated(EnumType.STRING)
@Column(nullable = false)
private OrderStatus status;
/**
* 订单类型
*/
@Enumerated(EnumType.STRING)
private OrderType orderType;
/**
* 收货地址信息
*/
@Embedded
private ShippingAddress shippingAddress;
/**
* 账单地址信息
*/
@Embedded
@AttributeOverrides({
@AttributeOverride(name = "country", column = @Column(name = "billing_country")),
@AttributeOverride(name = "province", column = @Column(name = "billing_province")),
@AttributeOverride(name = "city", column = @Column(name = "billing_city")),
@AttributeOverride(name = "address", column = @Column(name = "billing_address")),
@AttributeOverride(name = "zipCode", column = @Column(name = "billing_zip_code"))
})
private BillingAddress billingAddress;
/**
* 订单商品列表
*/
@OneToMany(mappedBy = "order", cascade = CascadeType.ALL, fetch = FetchType.LAZY)
private List<OrderItem> orderItems = new ArrayList<>();
/**
* 价格信息
*/
@Embedded
private OrderPricing pricing;
/**
* 支付信息
*/
@OneToOne(mappedBy = "order", cascade = CascadeType.ALL)
private OrderPayment payment;
/**
* 物流信息
*/
@OneToOne(mappedBy = "order", cascade = CascadeType.ALL)
private OrderShipping shipping;
/**
* 海关申报信息
*/
@OneToOne(mappedBy = "order", cascade = CascadeType.ALL)
private CustomsDeclaration customsDeclaration;
/**
* 订单创建时间
*/
@CreationTimestamp
private Instant createdAt;
/**
* 订单更新时间
*/
@UpdateTimestamp
private Instant updatedAt;
/**
* 订单过期时间(未支付订单的过期时间)
*/
private Instant expiresAt;
// 构造函数、getter、setter等
}
/**
* 订单状态枚举
*/
public enum OrderStatus {
PENDING_PAYMENT("待支付"),
PAYMENT_PROCESSING("支付处理中"),
PAID("已支付"),
INVENTORY_RESERVED("库存已预占"),
PROCESSING("处理中"),
SHIPPED("已发货"),
IN_TRANSIT("运输中"),
CUSTOMS_CLEARANCE("海关清关中"),
DELIVERED("已送达"),
COMPLETED("已完成"),
CANCELLED("已取消"),
REFUNDED("已退款"),
FAILED("失败");
private final String description;
OrderStatus(String description) {
this.description = description;
}
public String getDescription() {
return description;
}
}
# 4. 库存管理服务
/**
* 库存管理服务
*/
@Service
@Transactional
public class InventoryService {
private final InventoryRepository inventoryRepository;
private final InventoryReservationRepository reservationRepository;
private final RedisTemplate<String, Object> redisTemplate;
private final InventoryEventPublisher inventoryEventPublisher;
/**
* 检查库存可用性
*/
@Transactional(readOnly = true)
public InventoryCheckResult checkInventory(List<OrderItemRequest> orderItems) {
List<String> unavailableItems = new ArrayList<>();
for (OrderItemRequest item : orderItems) {
// 1. 获取库存信息
Inventory inventory = inventoryRepository.findByProductSku(item.getProductSku())
.orElse(null);
if (inventory == null) {
unavailableItems.add(item.getProductSku() + ": 商品不存在");
continue;
}
// 2. 检查可用库存
int availableStock = inventory.getAvailableStock();
if (availableStock < item.getQuantity()) {
unavailableItems.add(String.format("%s: 库存不足,需要%d,可用%d",
item.getProductSku(), item.getQuantity(), availableStock));
}
}
return InventoryCheckResult.builder()
.available(unavailableItems.isEmpty())
.unavailableItems(unavailableItems)
.build();
}
/**
* 预占库存
*/
public InventoryReservationResult reserveInventory(Long orderId, List<OrderItemRequest> orderItems) {
log.info("开始预占库存,订单ID: {}", orderId);
List<InventoryReservation> reservations = new ArrayList<>();
try {
for (OrderItemRequest item : orderItems) {
// 1. 使用分布式锁确保并发安全
String lockKey = "inventory_lock:" + item.getProductSku();
Boolean lockAcquired = redisTemplate.opsForValue()
.setIfAbsent(lockKey, "locked", Duration.ofSeconds(30));
if (!lockAcquired) {
throw new InventoryLockException("获取库存锁失败: " + item.getProductSku());
}
try {
// 2. 再次检查库存
Inventory inventory = inventoryRepository.findByProductSku(item.getProductSku())
.orElseThrow(() -> new InventoryNotFoundException("商品不存在: " + item.getProductSku()));
if (inventory.getAvailableStock() < item.getQuantity()) {
throw new InsufficientInventoryException(
String.format("库存不足: %s, 需要%d,可用%d",
item.getProductSku(), item.getQuantity(), inventory.getAvailableStock()));
}
// 3. 扣减可用库存
inventory.setAvailableStock(inventory.getAvailableStock() - item.getQuantity());
inventory.setReservedStock(inventory.getReservedStock() + item.getQuantity());
inventoryRepository.save(inventory);
// 4. 创建预占记录
InventoryReservation reservation = new InventoryReservation();
reservation.setOrderId(orderId);
reservation.setProductSku(item.getProductSku());
reservation.setQuantity(item.getQuantity());
reservation.setStatus(ReservationStatus.RESERVED);
reservation.setReservedAt(Instant.now());
reservation.setExpiresAt(Instant.now().plus(Duration.ofMinutes(30))); // 30分钟后过期
reservation = reservationRepository.save(reservation);
reservations.add(reservation);
log.info("库存预占成功: {}, 数量: {}", item.getProductSku(), item.getQuantity());
} finally {
// 释放分布式锁
redisTemplate.delete(lockKey);
}
}
// 5. 发布库存预占事件
inventoryEventPublisher.publishInventoryReserved(orderId, reservations);
return InventoryReservationResult.success(reservations);
} catch (Exception e) {
log.error("库存预占失败,订单ID: {}", orderId, e);
// 回滚已预占的库存
rollbackReservations(reservations);
return InventoryReservationResult.failure(e.getMessage());
}
}
/**
* 确认库存扣减(支付成功后调用)
*/
public void confirmInventoryReduction(Long orderId) {
log.info("确认库存扣减,订单ID: {}", orderId);
List<InventoryReservation> reservations = reservationRepository.findByOrderId(orderId);
for (InventoryReservation reservation : reservations) {
if (reservation.getStatus() != ReservationStatus.RESERVED) {
continue;
}
try {
// 1. 更新库存
Inventory inventory = inventoryRepository.findByProductSku(reservation.getProductSku())
.orElseThrow(() -> new InventoryNotFoundException(
"商品不存在: " + reservation.getProductSku()));
// 从预占库存转为已售库存
inventory.setReservedStock(inventory.getReservedStock() - reservation.getQuantity());
inventory.setSoldStock(inventory.getSoldStock() + reservation.getQuantity());
inventoryRepository.save(inventory);
// 2. 更新预占记录状态
reservation.setStatus(ReservationStatus.CONFIRMED);
reservation.setConfirmedAt(Instant.now());
reservationRepository.save(reservation);
log.info("库存扣减确认成功: {}, 数量: {}",
reservation.getProductSku(), reservation.getQuantity());
} catch (Exception e) {
log.error("库存扣减确认失败: {}, 订单ID: {}",
reservation.getProductSku(), orderId, e);
}
}
// 发布库存确认事件
inventoryEventPublisher.publishInventoryConfirmed(orderId, reservations);
}
/**
* 释放库存(订单取消时调用)
*/
public void releaseInventory(Long orderId) {
log.info("释放库存,订单ID: {}", orderId);
List<InventoryReservation> reservations = reservationRepository.findByOrderId(orderId);
for (InventoryReservation reservation : reservations) {
if (reservation.getStatus() != ReservationStatus.RESERVED) {
continue;
}
try {
// 1. 恢复库存
Inventory inventory = inventoryRepository.findByProductSku(reservation.getProductSku())
.orElseThrow(() -> new InventoryNotFoundException(
"商品不存在: " + reservation.getProductSku()));
inventory.setAvailableStock(inventory.getAvailableStock() + reservation.getQuantity());
inventory.setReservedStock(inventory.getReservedStock() - reservation.getQuantity());
inventoryRepository.save(inventory);
// 2. 更新预占记录状态
reservation.setStatus(ReservationStatus.RELEASED);
reservation.setReleasedAt(Instant.now());
reservationRepository.save(reservation);
log.info("库存释放成功: {}, 数量: {}",
reservation.getProductSku(), reservation.getQuantity());
} catch (Exception e) {
log.error("库存释放失败: {}, 订单ID: {}",
reservation.getProductSku(), orderId, e);
}
}
// 发布库存释放事件
inventoryEventPublisher.publishInventoryReleased(orderId, reservations);
}
/**
* 回滚预占
*/
private void rollbackReservations(List<InventoryReservation> reservations) {
for (InventoryReservation reservation : reservations) {
try {
Inventory inventory = inventoryRepository.findByProductSku(reservation.getProductSku())
.orElse(null);
if (inventory != null) {
inventory.setAvailableStock(inventory.getAvailableStock() + reservation.getQuantity());
inventory.setReservedStock(inventory.getReservedStock() - reservation.getQuantity());
inventoryRepository.save(inventory);
}
// 删除预占记录
reservationRepository.delete(reservation);
} catch (Exception e) {
log.error("回滚库存预占失败: {}", reservation.getProductSku(), e);
}
}
}
/**
* 定时清理过期的库存预占
*/
@Scheduled(fixedRate = 60000) // 每分钟执行一次
public void cleanupExpiredReservations() {
List<InventoryReservation> expiredReservations = reservationRepository
.findByStatusAndExpiresAtBefore(ReservationStatus.RESERVED, Instant.now());
for (InventoryReservation reservation : expiredReservations) {
try {
// 释放过期的预占库存
Inventory inventory = inventoryRepository.findByProductSku(reservation.getProductSku())
.orElse(null);
if (inventory != null) {
inventory.setAvailableStock(inventory.getAvailableStock() + reservation.getQuantity());
inventory.setReservedStock(inventory.getReservedStock() - reservation.getQuantity());
inventoryRepository.save(inventory);
}
// 更新预占记录状态
reservation.setStatus(ReservationStatus.EXPIRED);
reservation.setReleasedAt(Instant.now());
reservationRepository.save(reservation);
log.info("清理过期库存预占: {}, 订单ID: {}",
reservation.getProductSku(), reservation.getOrderId());
} catch (Exception e) {
log.error("清理过期库存预占失败: {}, 订单ID: {}",
reservation.getProductSku(), reservation.getOrderId(), e);
}
}
}
}
# 5. 异步事件处理
/**
* 订单事件监听器
*/
@Component
@RabbitListener(queues = "order.events")
public class OrderEventListener {
private final CrossBorderOrderService orderService;
private final NotificationService notificationService;
private final AnalyticsService analyticsService;
/**
* 处理支付成功事件
*/
@RabbitHandler
public void handlePaymentSuccess(PaymentSuccessEvent event) {
log.info("收到支付成功事件: {}", event);
try {
orderService.handlePaymentSuccess(event.getOrderId(), event);
} catch (Exception e) {
log.error("处理支付成功事件失败: {}", event, e);
// 可以考虑重试或者发送到死信队列
}
}
/**
* 处理支付失败事件
*/
@RabbitHandler
public void handlePaymentFailure(PaymentFailureEvent event) {
log.info("收到支付失败事件: {}", event);
try {
orderService.handlePaymentFailure(event.getOrderId(), event);
} catch (Exception e) {
log.error("处理支付失败事件失败: {}", event, e);
}
}
/**
* 处理物流状态更新事件
*/
@RabbitHandler
public void handleShippingStatusUpdate(ShippingStatusUpdateEvent event) {
log.info("收到物流状态更新事件: {}", event);
try {
orderService.handleShippingStatusUpdate(event.getOrderId(), event);
// 发送物流状态通知
notificationService.sendShippingStatusNotification(event);
} catch (Exception e) {
log.error("处理物流状态更新事件失败: {}", event, e);
}
}
/**
* 处理海关状态更新事件
*/
@RabbitHandler
public void handleCustomsStatusUpdate(CustomsStatusUpdateEvent event) {
log.info("收到海关状态更新事件: {}", event);
try {
orderService.handleCustomsStatusUpdate(event.getOrderId(), event);
// 发送海关状态通知
notificationService.sendCustomsStatusNotification(event);
} catch (Exception e) {
log.error("处理海关状态更新事件失败: {}", event, e);
}
}
/**
* 处理订单完成事件
*/
@RabbitHandler
public void handleOrderCompleted(OrderCompletedEvent event) {
log.info("收到订单完成事件: {}", event);
try {
// 1. 发送订单完成通知
notificationService.sendOrderCompletionNotification(event);
// 2. 更新用户积分
// userService.updateUserPoints(event.getUserId(), event.getOrderAmount());
// 3. 记录分析数据
analyticsService.recordOrderCompletion(event);
// 4. 触发推荐系统更新
// recommendationService.updateUserPreferences(event.getUserId(), event.getOrderItems());
} catch (Exception e) {
log.error("处理订单完成事件失败: {}", event, e);
}
}
}
/**
* 订单事件发布器
*/
@Component
public class OrderEventPublisher {
private final RabbitTemplate rabbitTemplate;
/**
* 发布订单创建事件
*/
public void publishOrderCreated(CrossBorderOrder order) {
OrderCreatedEvent event = OrderCreatedEvent.builder()
.orderId(order.getId())
.orderNumber(order.getOrderNumber())
.userId(order.getUserId())
.totalAmount(order.getPricing().getTotalAmount())
.currency(order.getPricing().getCurrency())
.createdAt(order.getCreatedAt())
.build();
rabbitTemplate.convertAndSend("order.exchange", "order.created", event);
log.info("发布订单创建事件: {}", event);
}
/**
* 发布支付成功事件
*/
public void publishPaymentSuccess(CrossBorderOrder order) {
PaymentSuccessEvent event = PaymentSuccessEvent.builder()
.orderId(order.getId())
.orderNumber(order.getOrderNumber())
.userId(order.getUserId())
.paymentId(order.getPayment().getPaymentId())
.paymentMethod(order.getPayment().getPaymentMethod())
.paymentAmount(order.getPricing().getTotalAmount())
.paymentTime(order.getPayment().getPaymentTime())
.build();
rabbitTemplate.convertAndSend("order.exchange", "payment.success", event);
log.info("发布支付成功事件: {}", event);
}
/**
* 发布订单取消事件
*/
public void publishOrderCancelled(CrossBorderOrder order, String reason) {
OrderCancelledEvent event = OrderCancelledEvent.builder()
.orderId(order.getId())
.orderNumber(order.getOrderNumber())
.userId(order.getUserId())
.cancellationReason(reason)
.cancelledAt(Instant.now())
.build();
rabbitTemplate.convertAndSend("order.exchange", "order.cancelled", event);
log.info("发布订单取消事件: {}", event);
}
}
# 🔧 技术亮点
# 1. 分布式事务处理
/**
* 基于Saga模式的分布式事务
*/
@Component
public class OrderSagaOrchestrator {
private final OrderService orderService;
private final InventoryService inventoryService;
private final PaymentService paymentService;
private final ShippingService shippingService;
/**
* 执行订单创建Saga
*/
public SagaExecutionResult executeOrderCreationSaga(OrderCreationRequest request) {
SagaTransaction saga = SagaTransaction.builder()
.sagaId(UUID.randomUUID().toString())
.build();
try {
// 步骤1: 创建订单
SagaStep createOrderStep = saga.addStep(
"CREATE_ORDER",
() -> orderService.createOrder(request),
(orderId) -> orderService.cancelOrder(orderId)
);
// 步骤2: 预占库存
SagaStep reserveInventoryStep = saga.addStep(
"RESERVE_INVENTORY",
() -> inventoryService.reserveInventory(createOrderStep.getResult()),
(reservationId) -> inventoryService.releaseInventory(reservationId)
);
// 步骤3: 创建支付
SagaStep createPaymentStep = saga.addStep(
"CREATE_PAYMENT",
() -> paymentService.createPayment(createOrderStep.getResult()),
(paymentId) -> paymentService.cancelPayment(paymentId)
);
// 执行Saga
return saga.execute();
} catch (Exception e) {
// 执行补偿操作
saga.compensate();
return SagaExecutionResult.failure(e.getMessage());
}
}
}
# 2. 订单超时处理
/**
* 订单超时处理服务
*/
@Component
public class OrderTimeoutService {
private final OrderRepository orderRepository;
private final OrderService orderService;
private final RedisTemplate<String, Object> redisTemplate;
/**
* 设置订单超时
*/
public void setOrderTimeout(Long orderId, Duration timeout) {
String timeoutKey = "order_timeout:" + orderId;
// 使用Redis的过期机制
redisTemplate.opsForValue().set(timeoutKey, orderId, timeout);
log.info("设置订单超时: {}, 超时时间: {}", orderId, timeout);
}
/**
* 处理订单超时
*/
@EventListener
public void handleOrderTimeout(OrderTimeoutEvent event) {
Long orderId = event.getOrderId();
log.info("处理订单超时: {}", orderId);
try {
CrossBorderOrder order = orderRepository.findById(orderId)
.orElse(null);
if (order == null) {
log.warn("订单不存在: {}", orderId);
return;
}
// 只有待支付状态的订单才会超时取消
if (order.getStatus() == OrderStatus.PENDING_PAYMENT) {
OrderCancellationRequest request = OrderCancellationRequest.builder()
.cancellationReason("订单超时未支付")
.build();
orderService.cancelOrder(order.getOrderNumber(), request);
log.info("订单超时取消成功: {}", order.getOrderNumber());
}
} catch (Exception e) {
log.error("处理订单超时失败: {}", orderId, e);
}
}
/**
* 定时检查过期订单
*/
@Scheduled(fixedRate = 60000) // 每分钟执行一次
public void checkExpiredOrders() {
List<CrossBorderOrder> expiredOrders = orderRepository
.findByStatusAndExpiresAtBefore(
OrderStatus.PENDING_PAYMENT,
Instant.now()
);
for (CrossBorderOrder order : expiredOrders) {
try {
OrderCancellationRequest request = OrderCancellationRequest.builder()
.cancellationReason("订单超时未支付")
.build();
orderService.cancelOrder(order.getOrderNumber(), request);
log.info("定时清理过期订单: {}", order.getOrderNumber());
} catch (Exception e) {
log.error("清理过期订单失败: {}", order.getOrderNumber(), e);
}
}
}
}
# 3. 订单重试机制
/**
* 订单重试服务
*/
@Component
public class OrderRetryService {
private final OrderRepository orderRepository;
private final RetryTemplate retryTemplate;
public OrderRetryService() {
this.retryTemplate = RetryTemplate.builder()
.maxAttempts(3)
.exponentialBackoff(1000, 2, 10000)
.retryOn(Exception.class)
.build();
}
/**
* 重试订单处理
*/
public void retryOrderProcessing(Long orderId) {
retryTemplate.execute(context -> {
log.info("重试订单处理: {}, 尝试次数: {}", orderId, context.getRetryCount() + 1);
CrossBorderOrder order = orderRepository.findById(orderId)
.orElseThrow(() -> new OrderNotFoundException("订单不存在: " + orderId));
// 根据订单状态执行相应的重试逻辑
switch (order.getStatus()) {
case PAYMENT_PROCESSING:
retryPaymentProcessing(order);
break;
case PROCESSING:
retryOrderProcessing(order);
break;
case SHIPPED:
retryShippingUpdate(order);
break;
default:
throw new IllegalStateException("订单状态不支持重试: " + order.getStatus());
}
return null;
});
}
/**
* 重试支付处理
*/
private void retryPaymentProcessing(CrossBorderOrder order) {
// 重新查询支付状态
// paymentService.queryPaymentStatus(order.getPayment().getPaymentId());
}
/**
* 重试订单处理
*/
private void retryOrderProcessing(CrossBorderOrder order) {
// 重新启动订单处理流程
// orderService.startOrderProcessing(order);
}
/**
* 重试物流更新
*/
private void retryShippingUpdate(CrossBorderOrder order) {
// 重新查询物流状态
// shippingService.queryShippingStatus(order.getShipping().getTrackingNumber());
}
}
# 📊 性能优化
# 1. 数据库优化
-- 订单表索引优化
CREATE INDEX idx_orders_user_status ON cross_border_orders(user_id, status);
CREATE INDEX idx_orders_status_created ON cross_border_orders(status, created_at);
CREATE INDEX idx_orders_expires_at ON cross_border_orders(expires_at) WHERE status = 'PENDING_PAYMENT';
-- 订单商品表索引
CREATE INDEX idx_order_items_order_id ON order_items(order_id);
CREATE INDEX idx_order_items_product_sku ON order_items(product_sku);
-- 库存预占表索引
CREATE INDEX idx_inventory_reservations_order_id ON inventory_reservations(order_id);
CREATE INDEX idx_inventory_reservations_status_expires ON inventory_reservations(status, expires_at);
# 2. 缓存策略
/**
* 订单缓存服务
*/
@Service
public class OrderCacheService {
private final RedisTemplate<String, Object> redisTemplate;
private final OrderRepository orderRepository;
/**
* 缓存订单信息
*/
@Cacheable(value = "orders", key = "#orderNumber")
public CrossBorderOrder getOrderByNumber(String orderNumber) {
return orderRepository.findByOrderNumber(orderNumber)
.orElseThrow(() -> new OrderNotFoundException("订单不存在: " + orderNumber));
}
/**
* 缓存用户订单列表
*/
@Cacheable(value = "user_orders", key = "#userId + ':' + #status")
public List<CrossBorderOrder> getUserOrders(Long userId, OrderStatus status) {
return orderRepository.findByUserIdAndStatus(userId, status);
}
/**
* 清除订单缓存
*/
@CacheEvict(value = "orders", key = "#orderNumber")
public void evictOrderCache(String orderNumber) {
// 缓存清除
}
/**
* 清除用户订单缓存
*/
@CacheEvict(value = "user_orders", key = "#userId + ':*'")
public void evictUserOrdersCache(Long userId) {
// 缓存清除
}
}
# 📈 监控与分析
# 1. 订单监控指标
/**
* 订单监控指标
*/
@Component
public class OrderMetrics {
private final MeterRegistry meterRegistry;
private final Counter orderCreatedCounter;
private final Counter orderCompletedCounter;
private final Counter orderCancelledCounter;
private final Timer orderProcessingTimer;
private final Gauge pendingOrdersGauge;
public OrderMetrics(MeterRegistry meterRegistry, OrderRepository orderRepository) {
this.meterRegistry = meterRegistry;
this.orderCreatedCounter = Counter.builder("orders.created.total")
.description("Total orders created")
.register(meterRegistry);
this.orderCompletedCounter = Counter.builder("orders.completed.total")
.description("Total orders completed")
.register(meterRegistry);
this.orderCancelledCounter = Counter.builder("orders.cancelled.total")
.description("Total orders cancelled")
.register(meterRegistry);
this.orderProcessingTimer = Timer.builder("orders.processing.duration")
.description("Order processing duration")
.register(meterRegistry);
this.pendingOrdersGauge = Gauge.builder("orders.pending.count")
.description("Number of pending orders")
.register(meterRegistry, this, metrics ->
orderRepository.countByStatus(OrderStatus.PENDING_PAYMENT));
}
public void recordOrderCreated(String country, String paymentMethod) {
orderCreatedCounter.increment(
Tags.of(
"country", country,
"payment_method", paymentMethod
)
);
}
public void recordOrderCompleted(Duration processingTime) {
orderCompletedCounter.increment();
orderProcessingTimer.record(processingTime);
}
public void recordOrderCancelled(String reason) {
orderCancelledCounter.increment(
Tags.of("reason", reason)
);
}
}
# 2. 订单分析服务
/**
* 订单分析服务
*/
@Service
public class OrderAnalyticsService {
private final OrderRepository orderRepository;
/**
* 订单转化率分析
*/
public OrderConversionAnalysis analyzeOrderConversion(LocalDate startDate, LocalDate endDate) {
// 1. 统计各状态订单数量
Map<OrderStatus, Long> statusCounts = orderRepository
.countOrdersByStatusAndDateRange(startDate.atStartOfDay(), endDate.atTime(23, 59, 59))
.stream()
.collect(Collectors.toMap(
result -> (OrderStatus) result[0],
result -> (Long) result[1]
));
// 2. 计算转化率
long totalOrders = statusCounts.values().stream().mapToLong(Long::longValue).sum();
long completedOrders = statusCounts.getOrDefault(OrderStatus.COMPLETED, 0L);
long cancelledOrders = statusCounts.getOrDefault(OrderStatus.CANCELLED, 0L);
double completionRate = totalOrders > 0 ? (double) completedOrders / totalOrders : 0.0;
double cancellationRate = totalOrders > 0 ? (double) cancelledOrders / totalOrders : 0.0;
return OrderConversionAnalysis.builder()
.period(startDate + " to " + endDate)
.totalOrders(totalOrders)
.completedOrders(completedOrders)
.cancelledOrders(cancelledOrders)
.completionRate(completionRate)
.cancellationRate(cancellationRate)
.statusDistribution(statusCounts)
.build();
}
/**
* 订单处理时长分析
*/
public OrderProcessingTimeAnalysis analyzeProcessingTime(LocalDate startDate, LocalDate endDate) {
List<Object[]> processingTimes = orderRepository
.findOrderProcessingTimes(startDate.atStartOfDay(), endDate.atTime(23, 59, 59));
List<Duration> durations = processingTimes.stream()
.map(result -> Duration.between((Instant) result[0], (Instant) result[1]))
.collect(Collectors.toList());
if (durations.isEmpty()) {
return OrderProcessingTimeAnalysis.empty();
}
// 计算统计指标
Duration avgProcessingTime = durations.stream()
.reduce(Duration.ZERO, Duration::plus)
.dividedBy(durations.size());
Duration minProcessingTime = durations.stream().min(Duration::compareTo).orElse(Duration.ZERO);
Duration maxProcessingTime = durations.stream().max(Duration::compareTo).orElse(Duration.ZERO);
// 计算百分位数
List<Duration> sortedDurations = durations.stream().sorted().collect(Collectors.toList());
Duration p50 = getPercentile(sortedDurations, 0.5);
Duration p90 = getPercentile(sortedDurations, 0.9);
Duration p95 = getPercentile(sortedDurations, 0.95);
return OrderProcessingTimeAnalysis.builder()
.period(startDate + " to " + endDate)
.totalOrders(durations.size())
.avgProcessingTime(avgProcessingTime)
.minProcessingTime(minProcessingTime)
.maxProcessingTime(maxProcessingTime)
.p50ProcessingTime(p50)
.p90ProcessingTime(p90)
.p95ProcessingTime(p95)
.build();
}
private Duration getPercentile(List<Duration> sortedDurations, double percentile) {
int index = (int) Math.ceil(sortedDurations.size() * percentile) - 1;
return sortedDurations.get(Math.max(0, index));
}
}
# 🎯 关键要点
# 1. 技术特色
- 状态机管理:严格的订单状态流转控制
- 分布式事务:基于Saga模式的最终一致性
- 库存预占:防止超卖的分布式锁机制
- 异步处理:基于消息队列的事件驱动架构
- 超时处理:自动清理过期订单和库存预占
- 重试机制:提高系统可靠性
# 2. 业务价值
- 数据一致性:确保订单、库存、支付数据的一致性
- 高可用性:通过重试和补偿机制提高系统可用性
- 用户体验:实时的订单状态更新和通知
- 运营效率:自动化的订单处理流程
- 风险控制:库存预占和超时机制防止业务风险
# 3. 未来发展
- 智能路由:基于AI的订单处理路径优化
- 预测分析:订单完成时间和异常预测
- 个性化处理:基于用户画像的差异化处理
- 全球化支持:多时区、多语言的订单处理
在下一篇文档中,我们将深入探讨支付网关系统,了解如何处理复杂的跨境支付场景,包括多币种支付、汇率处理、风控系统等关键技术。
# 2. 订单服务核心业务逻辑
/**
* 跨境订单服务
*/
@Service
@Transactional
public class CrossBorderOrderService {
private final OrderRepository orderRepository;
private final InventoryService inventoryService;
private final PaymentService paymentService;
private final ShippingService shippingService;
private final CustomsService customsService;
private final OrderEventPublisher orderEventPublisher;
private final OrderNumberGenerator orderNumberGenerator;
/**
* 创建订单
*/
public OrderCreationResult createOrder(OrderCreationRequest request) {
log.info("开始创建订单,用户ID: {}", request.getUserId());
try {
// 1. 订单基础验证
validateOrderRequest(request);
// 2. 商品可用性检查
ProductAvailabilityResult availabilityResult = checkProductAvailability(request);
if (!availabilityResult.isAvailable()) {
return OrderCreationResult.failure("商品不可用: " + availabilityResult.getReason());
}
// 3. 库存预检查
InventoryCheckResult inventoryResult = inventoryService.checkInventory(request.getOrderItems());
if (!inventoryResult.isAvailable()) {
return OrderCreationResult.failure("库存不足: " + inventoryResult.getUnavailableItems());
}
// 4. 价格计算
OrderPricing pricing = calculateOrderPricing(request);
// 5. 创建订单实体
CrossBorderOrder order = buildOrder(request, pricing);
// 6. 保存订单
order = orderRepository.save(order);
// 7. 预占库存
InventoryReservationResult reservationResult = inventoryService.reserveInventory(
order.getId(),
request.getOrderItems()
);
if (!reservationResult.isSuccess()) {
// 库存预占失败,取消订单
order.setStatus(OrderStatus.CANCELLED);
orderRepository.save(order);
return OrderCreationResult.failure("库存预占失败: " + reservationResult.getReason());
}
// 8. 更新订单状态
order.setStatus(OrderStatus.INVENTORY_RESERVED);
order = orderRepository.save(order);
// 9. 发布订单创建事件
orderEventPublisher.publishOrderCreated(order);
log.info("订单创建成功,订单号: {}", order.getOrderNumber());
return OrderCreationResult.success(order);
} catch (Exception e) {
log.error("订单创建失败,用户ID: {}", request.getUserId(), e);
return OrderCreationResult.failure("订单创建失败: " + e.getMessage());
}
}
/**
* 处理支付成功
*/
public void handlePaymentSuccess(Long orderId, PaymentSuccessEvent event) {
log.info("处理支付成功事件,订单ID: {}, 支付ID: {}", orderId, event.getPaymentId());
CrossBorderOrder order = orderRepository.findById(orderId)
.orElseThrow(() -> new OrderNotFoundException("订单不存在: " + orderId));
if (order.getStatus() != OrderStatus.PAYMENT_PROCESSING) {
log.warn("订单状态异常,当前状态: {}, 订单ID: {}", order.getStatus(), orderId);
return;
}
try {
// 1. 更新订单状态
order.setStatus(OrderStatus.PAID);
// 2. 更新支付信息
OrderPayment payment = order.getPayment();
payment.setPaymentId(event.getPaymentId());
payment.setPaymentMethod(event.getPaymentMethod());
payment.setPaymentTime(event.getPaymentTime());
payment.setStatus(PaymentStatus.SUCCESS);
// 3. 确认库存扣减
inventoryService.confirmInventoryReduction(orderId);
// 4. 保存订单
order = orderRepository.save(order);
// 5. 启动后续流程
startOrderProcessing(order);
// 6. 发布支付成功事件
orderEventPublisher.publishPaymentSuccess(order);
log.info("支付成功处理完成,订单号: {}", order.getOrderNumber());
} catch (Exception e) {
log.error("支付成功处理失败,订单ID: {}", orderId, e);
// 这里可能需要人工介入处理
order.setStatus(OrderStatus.FAILED);
orderRepository.save(order);
}
}
/**
* 启动订单处理流程
*/
private void startOrderProcessing(CrossBorderOrder order) {
// 1. 更新订单状态
order.setStatus(OrderStatus.PROCESSING);
// 2. 创建海关申报
createCustomsDeclaration(order);
// 3. 安排物流
arrangeShipping(order);
// 4. 保存订单
orderRepository.save(order);
}
/**
* 创建海关申报
*/
private void createCustomsDeclaration(CrossBorderOrder order) {
try {
CustomsDeclarationRequest request = CustomsDeclarationRequest.builder()
.orderId(order.getId())
.orderNumber(order.getOrderNumber())
.consignee(order.getShippingAddress())
.orderItems(order.getOrderItems())
.totalValue(order.getPricing().getTotalAmount())
.currency(order.getPricing().getCurrency())
.build();
CustomsDeclarationResult result = customsService.createDeclaration(request);
if (result.isSuccess()) {
CustomsDeclaration declaration = new CustomsDeclaration();
declaration.setOrder(order);
declaration.setDeclarationNumber(result.getDeclarationNumber());
declaration.setStatus(CustomsStatus.SUBMITTED);
declaration.setSubmittedAt(Instant.now());
order.setCustomsDeclaration(declaration);
log.info("海关申报创建成功,订单号: {}, 申报单号: {}",
order.getOrderNumber(), result.getDeclarationNumber());
} else {
log.error("海关申报创建失败,订单号: {}, 原因: {}",
order.getOrderNumber(), result.getErrorMessage());
}
} catch (Exception e) {
log.error("海关申报创建异常,订单号: {}", order.getOrderNumber(), e);
}
}
/**
* 安排物流
*/
private void arrangeShipping(CrossBorderOrder order) {
try {
ShippingArrangementRequest request = ShippingArrangementRequest.builder()
.orderId(order.getId())
.orderNumber(order.getOrderNumber())
.shippingAddress(order.getShippingAddress())
.orderItems(order.getOrderItems())
.totalWeight(calculateTotalWeight(order.getOrderItems()))
.declaredValue(order.getPricing().getTotalAmount())
.build();
ShippingArrangementResult result = shippingService.arrangeShipping(request);
if (result.isSuccess()) {
OrderShipping shipping = new OrderShipping();
shipping.setOrder(order);
shipping.setCarrier(result.getCarrier());
shipping.setTrackingNumber(result.getTrackingNumber());
shipping.setShippingMethod(result.getShippingMethod());
shipping.setEstimatedDeliveryDate(result.getEstimatedDeliveryDate());
shipping.setStatus(ShippingStatus.ARRANGED);
order.setShipping(shipping);
log.info("物流安排成功,订单号: {}, 运单号: {}, 承运商: {}",
order.getOrderNumber(), result.getTrackingNumber(), result.getCarrier());
} else {
log.error("物流安排失败,订单号: {}, 原因: {}",
order.getOrderNumber(), result.getErrorMessage());
}
} catch (Exception e) {
log.error("物流安排异常,订单号: {}", order.getOrderNumber(), e);
}
}
/**
* 订单状态查询
*/
@Transactional(readOnly = true)
public OrderStatusResult getOrderStatus(String orderNumber) {
CrossBorderOrder order = orderRepository.findByOrderNumber(orderNumber)
.orElseThrow(() -> new OrderNotFoundException("订单不存在: " + orderNumber));
return OrderStatusResult.builder()
.orderNumber(order.getOrderNumber())
.status(order.getStatus())
.statusDescription(order.getStatus().getDescription())
.createdAt(order.getCreatedAt())
.updatedAt(order.getUpdatedAt())
.paymentStatus(order.getPayment() != null ? order.getPayment().getStatus() : null)
.shippingStatus(order.getShipping() != null ? order.getShipping().getStatus() : null)
.customsStatus(order.getCustomsDeclaration() != null ?
order.getCustomsDeclaration().getStatus() : null)
.trackingNumber(order.getShipping() != null ?
order.getShipping().getTrackingNumber() : null)
.estimatedDeliveryDate(order.getShipping() != null ?
order.getShipping().getEstimatedDeliveryDate() : null)
.build();
}
/**
* 取消订单
*/
public OrderCancellationResult cancelOrder(String orderNumber, OrderCancellationRequest request) {
CrossBorderOrder order = orderRepository.findByOrderNumber(orderNumber)
.orElseThrow(() -> new OrderNotFoundException("订单不存在: " + orderNumber));
// 检查订单是否可以取消
if (!isOrderCancellable(order)) {
return OrderCancellationResult.failure(
"订单当前状态不允许取消: " + order.getStatus().getDescription());
}
try {
// 1. 更新订单状态
order.setStatus(OrderStatus.CANCELLED);
// 2. 释放库存
if (order.getStatus() == OrderStatus.INVENTORY_RESERVED ||
order.getStatus() == OrderStatus.PAID) {
inventoryService.releaseInventory(order.getId());
}
// 3. 处理退款
if (order.getStatus() == OrderStatus.PAID) {
RefundRequest refundRequest = RefundRequest.builder()
.orderId(order.getId())
.paymentId(order.getPayment().getPaymentId())
.refundAmount(order.getPricing().getTotalAmount())
.refundReason(request.getCancellationReason())
.build();
paymentService.processRefund(refundRequest);
}
// 4. 保存订单
order = orderRepository.save(order);
// 5. 发布订单取消事件
orderEventPublisher.publishOrderCancelled(order, request.getCancellationReason());
log.info("订单取消成功,订单号: {}, 取消原因: {}",
orderNumber, request.getCancellationReason());
return OrderCancellationResult.success(order);
} catch (Exception e) {
log.error("订单取消失败,订单号: {}", orderNumber, e);
return OrderCancellationResult.failure("订单取消失败: " + e.getMessage());
}
}
/**
* 检查订单是否可以取消
*/
private boolean isOrderCancellable(CrossBorderOrder order) {
return order.getStatus() == OrderStatus.PENDING_PAYMENT ||
order.getStatus() == OrderStatus.PAYMENT_PROCESSING ||
order.getStatus() == OrderStatus.INVENTORY_RESERVED ||
order.getStatus() == OrderStatus.PAID;
}
/**
* 订单基础验证
*/
private void validateOrderRequest(OrderCreationRequest request) {
if (request.getUserId() == null) {
throw new IllegalArgumentException("用户ID不能为空");
}
if (request.getOrderItems() == null || request.getOrderItems().isEmpty()) {
throw new IllegalArgumentException("订单商品不能为空");
}
if (request.getShippingAddress() == null) {
throw new IllegalArgumentException("收货地址不能为空");
}
// 验证商品数量
for (OrderItemRequest item : request.getOrderItems()) {
if (item.getQuantity() <= 0) {
throw new IllegalArgumentException("商品数量必须大于0");
}
if (item.getQuantity() > 999) {
throw new IllegalArgumentException("单个商品数量不能超过999");
}
}
}
/**
* 构建订单实体
*/
private CrossBorderOrder buildOrder(OrderCreationRequest request, OrderPricing pricing) {
CrossBorderOrder order = new CrossBorderOrder();
// 基础信息
order.setOrderNumber(orderNumberGenerator.generate());
order.setUserId(request.getUserId());
order.setStatus(OrderStatus.PENDING_PAYMENT);
order.setOrderType(OrderType.CROSS_BORDER);
// 地址信息
order.setShippingAddress(request.getShippingAddress());
order.setBillingAddress(request.getBillingAddress());
// 价格信息
order.setPricing(pricing);
// 订单商品
List<OrderItem> orderItems = request.getOrderItems().stream()
.map(itemRequest -> buildOrderItem(order, itemRequest))
.collect(Collectors.toList());
order.setOrderItems(orderItems);
// 过期时间(30分钟后过期)
order.setExpiresAt(Instant.now().plus(Duration.ofMinutes(30)));
return order;
}
/**
* 构建订单商品项
*/
private OrderItem buildOrderItem(CrossBorderOrder order, OrderItemRequest request) {
OrderItem item = new OrderItem();
item.setOrder(order);
item.setProductSku(request.getProductSku());
item.setProductName(request.getProductName());
item.setProductSpec(request.getProductSpec());
item.setQuantity(request.getQuantity());
item.setUnitPrice(request.getUnitPrice());
item.setTotalPrice(request.getUnitPrice().multiply(new BigDecimal(request.getQuantity())));
item.setCurrency(request.getCurrency());
item.setHsCode(request.getHsCode());
item.setWeight(request.getWeight());
return item;
}
}
# 3. 订单状态机
/**
* 订单状态机
*/
@Component
public class OrderStateMachine {
private final Map<OrderStatus, Set<OrderStatus>> allowedTransitions;
public OrderStateMachine() {
this.allowedTransitions = initializeTransitions();
}
/**
* 初始化状态转换规则
*/
private Map<OrderStatus, Set<OrderStatus>> initializeTransitions() {
Map<OrderStatus, Set<OrderStatus>> transitions = new HashMap<>();
// 待支付 -> 支付处理中、已取消
transitions.put(OrderStatus.PENDING_PAYMENT,
Set.of(OrderStatus.PAYMENT_PROCESSING, OrderStatus.CANCELLED));
// 支付处理中 -> 已支付、支付失败、已取消
transitions.put(OrderStatus.PAYMENT_PROCESSING,
Set.of(OrderStatus.PAID, OrderStatus.FAILED, OrderStatus.CANCELLED));
// 已支付 -> 库存已预占、处理中、已取消
transitions.put(OrderStatus.PAID,
Set.of(OrderStatus.INVENTORY_RESERVED, OrderStatus.PROCESSING, OrderStatus.CANCELLED));
// 库存已预占 -> 处理中、已取消
transitions.put(OrderStatus.INVENTORY_RESERVED,
Set.of(OrderStatus.PROCESSING, OrderStatus.CANCELLED));
// 处理中 -> 已发货、已取消
transitions.put(OrderStatus.PROCESSING,
Set.of(OrderStatus.SHIPPED, OrderStatus.CANCELLED));
// 已发货 -> 运输中
transitions.put(OrderStatus.SHIPPED,
Set.of(OrderStatus.IN_TRANSIT));
// 运输中 -> 海关清关中、已送达
transitions.put(OrderStatus.IN_TRANSIT,
Set.of(OrderStatus.CUSTOMS_CLEARANCE, OrderStatus.DELIVERED));
// 海关清关中 -> 已送达、运输中(清关失败退回)
transitions.put(OrderStatus.CUSTOMS_CLEARANCE,
Set.of(OrderStatus.DELIVERED, OrderStatus.IN_TRANSIT));
// 已送达 -> 已完成
transitions.put(OrderStatus.DELIVERED,
Set.of(OrderStatus.COMPLETED));
// 已取消和已退款是终态
transitions.put(OrderStatus.CANCELLED, Set.of());
transitions.put(OrderStatus.REFUNDED, Set.of());
transitions.put(OrderStatus.COMPLETED, Set.of());
transitions.put(OrderStatus.FAILED, Set.of());
return transitions;
}
/**
* 检查状态转换是否合法
*/
public boolean isTransitionAllowed(OrderStatus fromStatus, OrderStatus toStatus) {
Set<OrderStatus> allowedTargets = allowedTransitions.get(fromStatus);
return allowedTargets != null && allowedTargets.contains(toStatus);
}
/**
* 获取允许的下一状态
*/
public Set<OrderStatus> getAllowedNextStatuses(OrderStatus currentStatus) {
return allowedTransitions.getOrDefault(currentStatus, Set.of());
}
/**
* 执行状态转换
*/
public OrderStatusTransitionResult transition(CrossBorderOrder order,
OrderStatus targetStatus,
String reason) {
OrderStatus currentStatus = order.getStatus();
if (!isTransitionAllowed(currentStatus, targetStatus)) {
return OrderStatusTransitionResult.failure(
String.format("不允许从状态 %s 转换到 %s",
currentStatus.getDescription(),
targetStatus.getDescription()));
}
// 执行状态转换前的业务逻辑
OrderStatusTransitionResult preResult = executePreTransitionLogic(order, targetStatus);
if (!preResult.isSuccess()) {
return preResult;
}
// 更新订单状态
order.setStatus(targetStatus);
// 记录状态变更历史
recordStatusChange(order, currentStatus, targetStatus, reason);
// 执行状态转换后的业务逻辑
executePostTransitionLogic(order, currentStatus, targetStatus);
return OrderStatusTransitionResult.success();
}
/**
* 状态转换前的业务逻辑
*/
private OrderStatusTransitionResult executePreTransitionLogic(CrossBorderOrder order,
OrderStatus targetStatus) {
switch (targetStatus) {
case PAYMENT_PROCESSING:
// 检查支付信息是否完整
if (order.getPayment() == null) {
return OrderStatusTransitionResult.failure("支付信息不完整");
}
break;
case SHIPPED:
// 检查物流信息是否完整
if (order.getShipping() == null ||
order.getShipping().getTrackingNumber() == null) {
return OrderStatusTransitionResult.failure("物流信息不完整");
}
break;
case CUSTOMS_CLEARANCE:
// 检查海关申报信息是否完整
if (order.getCustomsDeclaration() == null ||
order.getCustomsDeclaration().getDeclarationNumber() == null) {
return OrderStatusTransitionResult.failure("海关申报信息不完整");
}
break;
}
return OrderStatusTransitionResult.success();
}
/**
* 状态转换后的业务逻辑
*/
private void executePostTransitionLogic(CrossBorderOrder order,
OrderStatus fromStatus,
OrderStatus toStatus) {
switch (toStatus) {
case SHIPPED:
// 发送发货通知
sendShippingNotification(order);
break;
case DELIVERED:
// 发送送达通知
sendDeliveryNotification(order);
break;
case COMPLETED:
// 订单完成后的处理
handleOrderCompletion(order);
break;
case CANCELLED:
// 订单取消后的处理
handleOrderCancellation(order);
break;
}
}
}