订单模块设计思路

1. 核心设计理念

  • 分层架构:采用Controller-Service-DAO分层架构,职责分离清晰
  • 状态驱动:通过订单状态(0-待付款、1-待发货、2-已发货、3-已完成、4-已关闭)管理订单生命周期
  • 事务一致性:关键操作使用@Transactional确保数据一致性
  • 异步处理:通过RabbitMQ延迟队列处理超时订单

2. 订单生命周期管理

生成确认单
创建待付款订单
支付成功
订单发货
确认收货
订单完成
超时取消
用户取消

具体实现

1. 核心类结构

OmsPortalOrderController
+generateConfirmOrder()
+generateOrder()
+paySuccess()
+cancelOrder()
«interface»
OmsPortalOrderService
+generateConfirmOrder()
+generateOrder()
+paySuccess()
OmsPortalOrderServiceImpl
-memberService
-cartItemService
-redisService
+generateConfirmOrder()
+generateOrder()
+paySuccess()
OmsOrderController
+list()
+delivery()
+close()
+detail()
«interface»
OmsOrderService
+list()
+delivery()
+close()
+detail()

2. 订单生成流程实现

2.1 确认单生成
// 核心逻辑:组装购物车、地址、优惠券、积分等信息
public ConfirmOrderResult generateConfirmOrder(List<Long> cartIds) {
    ConfirmOrderResult result = new ConfirmOrderResult();
    // 获取购物车促销信息
    List<CartPromotionItem> cartPromotionItemList = cartItemService.listPromotion(currentMember.getId(), cartIds);
    // 获取收货地址
    List<UmsMemberReceiveAddress> memberReceiveAddressList = memberReceiveAddressService.list();
    // 获取可用优惠券
    List<SmsCouponHistoryDetail> couponHistoryDetailList = memberCouponService.listCart(cartPromotionItemList, 1);
    // 计算金额
    ConfirmOrderResult.CalcAmount calcAmount = calcCartAmount(cartPromotionItemList);
    return result;
}
2.2 订单创建
public Map<String, Object> generateOrder(OrderParam orderParam) {
    // 1. 校验收货地址和库存
    if (!hasStock(cartPromotionItemList)) {
        Asserts.fail("库存不足,无法下单");
    }
    
    // 2. 处理优惠券和积分
    handleCouponAmount(orderItemList, couponHistoryDetail);
    handleRealAmount(orderItemList);
    
    // 3. 锁定库存
    lockStock(cartPromotionItemList);
    
    // 4. 生成订单号(日期+类型+Redis自增)
    String orderSn = generateOrderSn(order);
    
    // 5. 保存订单和订单项
    orderMapper.insert(order);
    orderItemDao.insertList(orderItemList);
    
    // 6. 发送延迟取消消息
    sendDelayMessageCancelOrder(order.getId());
}

3. 支付回调处理

public Integer paySuccess(Long orderId, Integer payType) {
    // 1. 更新订单状态(只更新未付款订单)
    OmsOrderExample example = new OmsOrderExample();
    example.createCriteria()
            .andIdEqualTo(order.getId())
            .andDeleteStatusEqualTo(0)
            .andStatusEqualTo(0);
    int updateCount = orderMapper.updateByExampleSelective(order, example);
    
    // 2. 扣减真实库存,释放锁定库存
    OmsOrderDetail orderDetail = portalOrderDao.getDetail(orderId);
    for (OmsOrderItem orderItem : orderDetail.getOrderItemList()) {
        portalOrderDao.reduceSkuStock(orderItem.getProductSkuId(), orderItem.getProductQuantity());
    }
}

4. 超时订单处理

4.1 延迟队列配置
@Configuration
public class RabbitMqConfig {
    // 订单延迟队列(死信队列)
    @Bean
    public Queue orderTtlQueue() {
        return QueueBuilder.durable(QueueEnum.QUEUE_TTL_ORDER_CANCEL.getName())
                .withArgument("x-dead-letter-exchange", QueueEnum.QUEUE_ORDER_CANCEL.getExchange())
                .withArgument("x-dead-letter-routing-key", QueueEnum.QUEUE_ORDER_CANCEL.getRouteKey())
                .build();
    }
}
4.2 自动取消逻辑
public Integer cancelTimeOutOrder() {
    // 1. 查询超时未支付订单
    List<OmsOrderDetail> timeOutOrders = portalOrderDao.getTimeOutOrders(orderSetting.getNormalOrderOvertime());
    
    // 2. 批量更新状态为已关闭
    portalOrderDao.updateOrderStatus(ids, 4);
    
    // 3. 释放库存锁定,返还优惠券和积分
    portalOrderDao.releaseSkuStockLock(timeOutOrder.getOrderItemList());
    updateCouponStatus(timeOutOrder.getCouponId(), timeOutOrder.getMemberId(), 0);
}

5. 数据库设计

5.1 核心表结构
-- 订单主表
CREATE TABLE `oms_order` (
    `id` bigint(20) NOT NULL AUTO_INCREMENT,
    `order_sn` varchar(64) COMMENT '订单编号',
    `member_id` bigint(20) COMMENT '用户ID',
    `status` int(1) COMMENT '订单状态',
    `total_amount` decimal(10,2) COMMENT '订单总金额',
    `pay_amount` decimal(10,2) COMMENT '应付金额',
    `create_time` datetime COMMENT '提交时间',
    `payment_time` datetime COMMENT '支付时间',
    PRIMARY KEY (`id`)
);

-- 订单商品表
CREATE TABLE `oms_order_item` (
    `id` bigint(20) NOT NULL AUTO_INCREMENT,
    `order_id` bigint(20) COMMENT '订单ID',
    `product_name` varchar(500) COMMENT '商品名称',
    `product_price` decimal(10,2) COMMENT '销售价格',
    `product_quantity` int(11) COMMENT '购买数量',
    PRIMARY KEY (`id`)
);

-- 订单操作历史表
CREATE TABLE `oms_order_operate_history` (
    `id` bigint(20) NOT NULL AUTO_INCREMENT,
    `order_id` bigint(20) COMMENT '订单id',
    `operate_man` varchar(100) COMMENT '操作人',
    `order_status` int(1) COMMENT '订单状态',
    `note` varchar(500) COMMENT '备注',
    PRIMARY KEY (`id`)
);

6. 关键技术特性

6.1 订单号生成策略
private String generateOrderSn(OmsOrder order) {
    // 8位日期+2位平台+2位支付方式+6位自增
    String date = new SimpleDateFormat("yyyyMMdd").format(new Date());
    String key = REDIS_DATABASE + ":" + REDIS_KEY_ORDER_ID + date;
    Long increment = redisService.incr(key, 1);
    return date + String.format("%02d", order.getSourceType()) + 
           String.format("%02d", order.getPayType()) + 
           String.format("%06d", increment);
}
6.2 库存管理机制
  • 预占库存:下单时锁定库存(lock_stock)
  • 真实扣减:支付成功后扣减真实库存(stock)
  • 库存释放:订单取消时释放锁定库存
6.3 优惠计算策略
  • 促销优惠:单品促销、打折优惠、满减优惠
  • 优惠券分摊:按商品价格比例分摊优惠金额
  • 积分抵扣:根据积分规则计算抵扣金额

7. 异常处理机制

// 统一异常处理
public static void fail(String message) {
    throw new ApiException(message);
}

// 业务校验示例
if (!hasStock(cartPromotionItemList)) {
    Asserts.fail("库存不足,无法下单");
}
if (updateCount == 0) {
    Asserts.fail("订单不存在或订单状态不是未支付!");
}

设计亮点

  1. 完整的订单生命周期管理:从生成到完成的全流程覆盖
  2. 灵活的促销体系:支持多种促销方式和优惠券类型
  3. 可靠的库存控制:预占机制防止超卖
  4. 高效的批量操作:支持批量发货、关闭等管理功能
  5. 完善的日志记录:操作历史便于追踪和审计
  6. 良好的扩展性:通过配置化支持不同的业务场景

这套订单系统设计考虑了电商场景的典型需求,通过状态机、事务控制、异步处理等技术手段,确保了订单处理的可靠性、一致性和性能。

Logo

电商企业物流数字化转型必备!快递鸟 API 接口,72 小时快速完成物流系统集成。全流程实战1V1指导,营造开放的API技术生态圈。

更多推荐