帮助文档
{{userInfo.nickname}}
用户设置 退出登录

{{wikiTitle}}

订单流程说明

CRMEB多店系统订单流程说明

概述

本文档详细介绍CRMEB多店系统的完整订单处理流程,从用户下单到订单完成的各个环节,包括订单状态变更、支付处理、发货、退款等关键业务逻辑。


订单状态流转图

    ┌─────────────┐
    │  用户下单    │
    └──────┬──────┘
           │
    ┌──────▼──────┐
    │  待支付      │ ──── 超时未支付 ──→ 订单取消
    │  (paid=0)   │
    └──────┬──────┘
           │ 支付成功
    ┌──────▼──────┐
    │  待发货      │ ──── 申请退款 ──→ 退款流程
    │  (status=0) │
    └──────┬──────┘
           │ 商家发货
    ┌──────▼──────┐
    │  待收货      │ ──── 申请退款 ──→ 退款流程
    │  (status=1) │
    └──────┬──────┘
           │ 确认收货
    ┌──────▼──────┐
    │  已收货      │
    │  (status=2) │
    └──────┬──────┘
           │
    ┌──────▼──────┐
    │  待评价      │
    │  (status=3) │
    └──────┬──────┘
           │ 提交评价
    ┌──────▼──────┐
    │  订单完成    │
    └─────────────┘

核心服务类

订单服务类位置

app/services/order/
├── StoreOrderServices.php          # 订单核心服务(149KB)
├── StoreOrderCreateServices.php    # 订单创建服务
├── StoreOrderComputedServices.php  # 订单计算服务
├── StoreOrderDeliveryServices.php  # 订单发货服务
├── StoreOrderRefundServices.php    # 订单退款服务
├── StoreOrderTakeServices.php      # 订单收货服务
├── StoreOrderSplitServices.php     # 订单拆分服务
├── StoreOrderWriteOffServices.php  # 订单核销服务
├── StoreCartServices.php           # 购物车服务
└── ...

订单创建流程

1. 购物车加入商品

// 控制器: app/controller/api/v1/order/CartController.php
// 服务: app/services/order/StoreCartServices.php

public function addCart($uid, $productId, $cartNum, $attrUnique, ...)
{
    // 1. 验证商品信息
    // 2. 验证库存
    // 3. 验证限购
    // 4. 计算价格
    // 5. 写入购物车表
    // 6. 触发购物车添加事件
    event('cart.add', [$cartInfo]);
}

2. 订单确认页

// 获取订单确认信息
public function getOrderConfirmData($uid, $cartIds, $addressId, ...)
{
    // 1. 获取购物车商品信息
    // 2. 计算商品总价
    // 3. 计算运费
    // 4. 获取可用优惠券
    // 5. 计算积分抵扣
    // 6. 获取收货地址
    // 7. 返回确认页数据
}

3. 提交订单

// 服务: StoreOrderCreateServices.php

public function createOrder($uid, $key, $group, $activity, ...)
{
    // 1. 验证订单缓存数据
    $computeData = $this->getOrderConfirmData(...);

    // 2. 验证地址信息
    $this->validateAddress($addressId);

    // 3. 计算订单金额
    $totalPrice = $this->computeTotalPrice($cartInfo);
    $payPrice = $this->computePayPrice($totalPrice, $coupon, $integral);

    // 4. 扣减库存
    $this->decProductStock($cartInfo);

    // 5. 生成订单号
    $orderId = $this->getNewOrderId();

    // 6. 写入订单数据
    $order = $this->transaction(function() {
        // 写入订单主表
        $orderData = [...];
        $order = $this->dao->save($orderData);

        // 写入订单商品表
        $this->saveOrderCartInfo($order->id, $cartInfo);

        return $order;
    });

    // 7. 触发订单创建事件
    event('order.create', [$order, $group, $activity, $invoiceId]);

    return $order;
}

订单创建事件监听器

// app/listener/order/Create.php

class Create implements ListenerInterface
{
    public function handle($event): void
    {
        [$orderInfo, $group, $activity, $invoice_id] = $event;

        // 计算订单实际金额
        OrderJob::dispatchDo('computeOrderProductTruePrice', [...]);

        // 设置默认地址
        OrderCreateAfterJob::dispatchDo('updateUser', [...]);

        // 清理购物车
        OrderCreateAfterJob::dispatchDo('delCart', [...]);

        // 写入订单状态记录
        OrderStatusJob::dispatch([$oid, 'create', [...]]);

        // 订单自动取消任务
        $this->pushJob($oid, $type);
    }
}

订单支付流程

1. 发起支付

// 服务: app/services/pay/PayServices.php

public function pay($orderInfo, $payType, $from)
{
    switch ($payType) {
        case 'weixin':
            // 微信支付
            return $this->wechatPay($orderInfo, $from);
        case 'alipay':
            // 支付宝支付
            return $this->aliPay($orderInfo);
        case 'yue':
            // 余额支付
            return $this->yuePay($orderInfo);
        case 'offline':
            // 线下支付
            return $this->offlinePay($orderInfo);
    }
}

2. 支付回调处理

// 服务: app/services/pay/PayNotifyServices.php

public function notify($type, $data)
{
    // 1. 验证支付结果
    $payInfo = $this->verifyPayResult($type, $data);

    // 2. 查询订单
    $order = $this->getOrderByOrderId($payInfo['order_id']);

    // 3. 更新订单状态
    $this->updateOrderPaid($order, $payInfo);

    // 4. 触发支付成功事件
    event('order.pay', [$order->id, $order]);
}

3. 支付成功事件

// app/listener/order/Pay.php

class Pay implements ListenerInterface
{
    public function handle($event): void
    {
        [$id, $orderInfo] = $event;

        // 计算订单佣金
        OrderJob::dispatchDo('computeOrderBrokerage', [...]);

        // 拼团订单处理
        if ($orderInfo['type'] == 3) {
            PinkJob::dispatchDo('createPink', [$orderInfo]);
        }

        // 写入支付记录
        OrderStatusJob::dispatch([$id, 'pay_success', [...]]);

        // 赠送优惠券和积分
        OrderJob::dispatchDo('giveOrderProductCouponAndIntegral', [...]);

        // 检测会员等级
        UserLevelJob::dispatch([(int)$orderInfo['uid']]);

        // 处理分销等级升级
        AgentJob::dispatch([(int)$orderInfo['uid']]);

        // 自动分配订单
        ShareOrderJob::dispatch([$id]);
    }
}

订单发货流程

1. 商家发货

// 服务: StoreOrderDeliveryServices.php

public function delivery($id, $deliveryData, $adminId)
{
    // 1. 验证订单状态
    $order = $this->validDelivery($id);

    // 2. 根据发货类型处理
    switch ($deliveryData['type']) {
        case 'express':
            // 快递发货
            $this->deliveryByExpress($order, $deliveryData);
            break;
        case 'send':
            // 商家配送
            $this->deliveryBySend($order, $deliveryData);
            break;
        case 'fictitious':
            // 虚拟发货
            $this->deliveryByFictitious($order);
            break;
        case 'city':
            // 同城配送
            $this->deliveryByCity($order, $deliveryData);
            break;
    }

    // 3. 更新订单状态
    $this->updateOrderStatus($order, 1);

    // 4. 触发发货事件
    event('order.delivery', [$order]);
}

2. 发货事件处理

// app/listener/order/Delivery.php

class Delivery implements ListenerInterface
{
    public function handle($event): void
    {
        [$orderInfo] = $event;

        // 发送发货通知
        NoticeJob::dispatch(['deliver_goods', $orderInfo]);

        // 写入订单状态记录
        OrderStatusJob::dispatch([$orderInfo['id'], 'delivery', [...]]);

        // 设置自动收货任务
        OrderTakeJob::dispatchSece($autoTakeTime, [$orderInfo['id']]);
    }
}

订单收货流程

1. 用户确认收货

// 服务: StoreOrderTakeServices.php

public function take($orderId, $uid)
{
    // 1. 验证订单
    $order = $this->validTake($orderId, $uid);

    // 2. 更新订单状态
    $this->dao->update($orderId, ['status' => 2]);

    // 3. 触发收货事件
    event('order.take', [$order]);

    return true;
}

2. 收货事件处理

// app/listener/order/Take.php

class Take implements ListenerInterface
{
    public function handle($event): void
    {
        [$orderInfo] = $event;

        // 结算佣金
        BrokerageJob::dispatch([$orderInfo]);

        // 赠送积分
        UserIntegralJob::dispatch([$orderInfo]);

        // 发送收货通知
        NoticeJob::dispatch(['take_delivery', $orderInfo]);

        // 写入订单状态记录
        OrderStatusJob::dispatch([$orderInfo['id'], 'take', [...]]);
    }
}

订单退款流程

1. 申请退款

// 服务: StoreOrderRefundServices.php

public function applyRefund($uid, $orderId, $refundData)
{
    // 1. 验证订单
    $order = $this->validRefund($orderId, $uid);

    // 2. 创建退款记录
    $refund = $this->createRefundOrder($order, $refundData);

    // 3. 更新订单退款状态
    $this->updateOrderRefundStatus($order, 1);

    // 4. 触发退款申请事件
    event('order.applyRefund', [$order, $refund]);

    return $refund;
}

2. 商家审核退款

public function agreeRefund($refundId, $adminId)
{
    // 1. 验证退款单
    $refund = $this->validRefundOrder($refundId);

    // 2. 执行退款
    $this->refundPrice($refund);

    // 3. 回退库存
    $this->returnProductStock($refund);

    // 4. 回退积分/优惠券
    $this->returnUserAssets($refund);

    // 5. 触发退款成功事件
    event('order.refund', [$refund]);
}

3. 退款金额返还

protected function refundPrice($refund)
{
    $order = $this->getOrder($refund['store_order_id']);

    // 原路返回
    switch ($order['pay_type']) {
        case 'weixin':
            // 微信退款
            $this->wechatRefund($order, $refund['refund_price']);
            break;
        case 'alipay':
            // 支付宝退款
            $this->alipayRefund($order, $refund['refund_price']);
            break;
        case 'yue':
            // 余额退款
            $this->yueRefund($order['uid'], $refund['refund_price']);
            break;
    }
}

订单核销流程(自提订单)

// 服务: StoreOrderWriteOffServices.php

public function writeOff($verifyCode, $staffId)
{
    // 1. 验证核销码
    $order = $this->getOrderByVerifyCode($verifyCode);

    // 2. 验证订单状态
    $this->validWriteOff($order);

    // 3. 执行核销
    $this->doWriteOff($order);

    // 4. 更新订单状态
    $this->updateOrderStatus($order, 2);

    // 5. 触发核销事件
    event('order.writeoff', [$order]);
}

订单状态说明

订单主状态 (status)

状态 说明
0 待发货 已支付,等待商家发货
1 待收货 商家已发货,等待用户收货
2 已收货 用户已确认收货
3 待评价 等待用户评价

支付状态 (paid)

状态
0 未支付
1 已支付

退款状态 (refund_status)

状态
0 未申请退款
1 申请退款中
2 部分退款
3 全部退款

配送方式 (shipping_type)

方式
1 快递配送
2 门店自提
3 门店配送
4 收银台订单

订单相关队列任务

任务类 说明
OrderCreateAfterJob 订单创建后任务
OrderPayHandelJob 订单支付处理任务
OrderDeliveryJob 订单发货任务
OrderTakeJob 订单收货任务
UnpaidOrderCancelJob 未支付订单取消
UnpaidOrderSend 未支付订单提醒
OrderStatusJob 订单状态记录
OrderSyncJob 订单同步ERP

代码示例:完整订单创建

// 1. 控制器入口
public function createOrder(Request $request)
{
    $uid = $request->uid;
    $key = $request->post('key');
    $addressId = $request->post('address_id');
    $payType = $request->post('pay_type');
    $couponId = $request->post('coupon_id');
    $useIntegral = $request->post('use_integral', 0);
    $mark = $request->post('mark', '');

    // 调用创建订单服务
    $orderInfo = app()->make(StoreOrderCreateServices::class)
        ->createOrder($uid, $key, compact(
            'addressId', 'payType', 'couponId', 'useIntegral', 'mark'
        ));

    // 如果需要支付
    if ($orderInfo['pay_price'] > 0) {
        $payInfo = app()->make(PayServices::class)
            ->pay($orderInfo, $payType, $request->getFromType());
        return $this->success($payInfo);
    }

    return $this->success(['order_id' => $orderInfo['order_id']]);
}

注意事项

  1. 事务处理:订单创建、支付、退款等操作必须使用数据库事务
  2. 库存控制:下单扣库存,取消/退款回库存,防止超卖
  3. 幂等性:支付回调需要处理幂等性,防止重复处理
  4. 异步处理:耗时操作使用队列异步处理
  5. 状态机:订单状态变更需遵循状态机规则

常见问题

Q: 订单超时未支付如何自动取消?

A: 通过延迟队列实现,订单创建时加入取消任务:

UnpaidOrderCancelJob::dispatchSece($cancelTime, [$orderId]);

Q: 如何处理拆单发货?

A: 使用 StoreOrderSplitServices 服务将订单拆分为多个子订单

{{cateWiki.like_num}}人点赞
0人点赞
评论({{cateWiki.comment_num}}) {{commentWhere.order ? '评论从旧到新':'评论从新到旧'}} {{cateWiki.page_view_num}}人看过该文档
评论(0) {{commentWhere.order ? '评论从旧到新':'评论从新到旧'}} 18人看过该文档
评论
{{item.user ? item.user.nickname : ''}} (自评)
{{item.content}}
{{item.create_time}} 删除
{{item.like ? item.like.like_num : 0}} {{replyIndex == index ? '取消回复' : '回复'}}
评论
{{items.user ? items.user.nickname : '暂无昵称'}} (自评)
{{items.content}}
{{items.create_time}} 删除
{{items.like ? items.like.like_num : 0}} {{replyIndexJ == (index+'|'+indexJ) ? '取消回复' : '回复'}}
评论
目录
  • {{item}}