CRMEB Pro + AI 风控提醒:退款异常、库存异常、秒杀异常怎么提前发现?

摘要

商城二开最怕的不是多写一个功能,而是订单、退款、库存、活动这些关键链路出问题以后,等用户投诉才发现。AI 在这里最适合做的不是"自动处理退款"或"自动改库存",而是把系统已经产生的事件、日志、统计数据整理成风险提醒,让运营和技术提前看到异常。

这篇做一个 AI 风控提醒思路:退款异常、库存异常、秒杀异常怎么从 CRMEB Pro 现有代码里找信号,怎么交给 AI 生成可读预警,以及哪些动作绝不能让 AI 自动执行。

1. 风控提醒应该先看哪些链路

推荐先从三条链路做:

text 复制代码
退款链路:退款状态、拆单退款、赠品订单、优惠券回退、外部推送
库存链路:SKU 库存、商品总库存、库存流水、库存预警
活动链路:秒杀/直播/促销活动库存、限购、活动状态、订单扣减

对应核心文件:

text 复制代码
app/listener/order/Refund.php
app/services/order/StoreOrderRefundServices.php
app/services/order/StoreOrderCreateServices.php
app/services/product/product/StoreProductServices.php
app/jobs/product/ProductLogJob.php
app/jobs/product/ProductStockTips.php
app/services/activity/seckill/StoreSeckillServices.php
app/services/statistic/TradeStatisticServices.php

AI 的定位是"读取信号、解释风险、给出建议",不是代替系统处理订单。

2. 退款事件里已经有很多风险信号

退款监听器在:

text 复制代码
app/listener/order/Refund.php

它不是只把订单改成已退款,而是会牵动发票、供应商流水、资金流水、商品日志、优惠券、小程序同步、外部推送和直播统计。

关键逻辑如下:

php 复制代码
public function handle($event): void
{
    [$data, $order] = $event;
    $order = is_array($order) ? $order : $order->toArray();

    $orderInvoiceServices = app()->make(StoreOrderInvoiceServices::class);
    $orderInvoiceServices->update(['order_id' => $order['id']], ['is_refund' => 1]);

    SupplierFinanceJob::dispatch([$order['id'], 2]);
    CapitalFlowJob::dispatch([array_merge($order, [
        'refund_price' => $data['refund_price']
    ]), 'refund']);

    if ($order['supplier_id']) {
        SupplierFinanceJob::dispatchDo('takeDoJob', [$order, time()]);
    }

    ProductLogJob::dispatch(['refund', [
        'uid' => $order['uid'],
        'order_id' => $order['id']
    ]]);

    event('notice.notice', [['data' => $data, 'order' => $order], 'order_refund']);
}

这些都是 AI 风控可以利用的信号:

text 复制代码
某商品退款日志突然增多
供应商订单退款集中出现
退款金额和订单金额接近或异常
退款后资金流水、发票、小程序同步是否完整

AI 不需要知道用户隐私,只需要订单维度的脱敏统计。

3. 拆单退款和赠品订单是高风险点

退款监听器里对主子订单做了专门处理:

php 复制代码
if ($order['pid']) {
    $id = (int)$order['pid'];
    $refund_data = ['refund_status' => 2, 'refund_type' => 6];
    $change_type = 'refund_split';
    $change_message = '已拆分退款';

    $noRefundOrders = $orderServices->getList([
        'pid' => $id,
        'refund_status' => 0
    ]);

    $normalOrderCount = 0;
    $giftOrderIds = [];

    foreach ($noRefundOrders as $noRefundOrder) {
        $is_gift = $storeOrderCartInfoServices->value(
            ['oid' => $noRefundOrder['id']],
            'is_gift'
        );

        if ($is_gift) {
            $giftOrderIds[] = $noRefundOrder['id'];
        } else {
            $normalOrderCount++;
        }
    }

    if ($normalOrderCount == 0) {
        foreach ($giftOrderIds as $giftOrderId) {
            $orderServices->update($giftOrderId, $refund_data);
            OrderStatusJob::dispatch([$giftOrderId, $change_type, [
                'change_message' => $change_message,
                'change_manager_id' => request()->adminId(),
                'change_manager_type' => 'admin'
            ]]);
        }
    } else {
        $refund_data = ['refund_status' => '3', 'refund_type' => 4];
        $change_type = 'refund_part_split';
        $change_message = '已拆分部分退款';
    }

    $orderServices->update($id, $refund_data);
    OrderStatusJob::dispatch([$id, $change_type, [
        'change_message' => $change_message,
        'change_manager_id' => request()->adminId(),
        'change_manager_type' => 'admin'
    ]]);
}

这里最适合做 AI 风控提醒:

text 复制代码
同一主订单下子订单连续退款
普通商品都退款后,赠品订单是否被正确处理
部分退款状态是否长期停留
订单状态记录是否缺失

AI 可以生成这样的提醒:

text 复制代码
风险类型:拆单退款异常
影响对象:主订单维度
判断依据:近 30 分钟内同一主订单出现多笔子订单退款,且仍有赠品订单未同步退款状态
建议动作:运营复查售后单;技术检查退款监听器和状态 Job 是否执行成功

4. 退款完成后还有优惠券和外部同步

退款监听器后半段还有这些动作:

php 复制代码
ProductCouponJob::dispatchSece(5, 'failureProductCoupon', [$order]);

$id = $order['pid'] ? $order['pid'] : $order['id'];
$orderInfo = $orderServices->get($id);
$orderInfo = $orderInfo->toArray();

if ($orderInfo['refund_status'] == 2) {
    StorePromotionsJob::dispatchSece(10, 'failureCoupon', [$orderInfo]);
    $storeOrderRefundfoServices->syncRefundToMiniProgram($orderInfo);
}

event('out.outPush', ['refund_create_push', [
    'order_id' => (int)$order['id']
]]);

event('live.order.stats', [$order]);

这说明退款风控不能只看 refund_status,还要看后续动作是否完成:

text 复制代码
赠品优惠券是否失效
营销活动赠券是否回退
小程序订单管理是否同步
对外接口是否推送
直播订单统计是否刷新

AI 可以把"退款状态已完成,但后续动作失败或延迟"的订单列成异常清单。

5. 库存异常从哪里抓信号

普通商品库存扣减在 StoreProductServices::decProductStock()

php 复制代码
public function decProductStock(int $num, int $productId, string $unique = '')
{
    $res = true;

    if ($unique) {
        $skuValueServices = app()->make(StoreProductAttrValueServices::class);
        $res = $res && $skuValueServices->decProductAttrStock($productId, $unique, $num);
        $skuValueServices->decMarketingProductStock($productId, $unique, $num);
    }

    $res = $res && $this->dao->decStockIncSales(['id' => $productId], $num);

    if ($res) {
        $this->workSendStock($productId);
    }

    $this->clearProductCache();

    return $res;
}

这里有几个可用于风控的点:

text 复制代码
SKU 库存扣减是否成功
营销活动库存是否同步扣减
商品主表销量和库存是否同步变化
库存预警 Job 是否触发
缓存是否清理

库存增加也要关注:

php 复制代码
public function incProductStock(int $num, int $productId, string $unique = '')
{
    $res = true;

    if ($unique) {
        $skuValueServices = app()->make(StoreProductAttrValueServices::class);
        $res = $res && $skuValueServices->incProductAttrStock($productId, $unique, $num);
    }

    $res = $res && $this->dao->incStockDecSales(['id' => $productId], $num);
    $this->clearProductCache();

    return $res;
}

AI 风控可以做成每天或每小时扫描:

text 复制代码
库存低于警戒线但仍在售
SKU 库存为 0 但商品主表未售罄
活动库存和普通库存差异异常
短时间扣库存失败集中出现
退款后库存回退异常

6. 秒杀异常要同时看活动库存和普通库存

秒杀下单不是只扣普通商品库存,订单创建时会根据活动类型扣不同库存:

php 复制代码
if ($type == 1) {
    $seckillServices = app()->make(StoreSeckillServices::class);
    $res5 = $res5 && $seckillServices->decSeckillStock(
        $cart_num,
        $activity_id,
        $unique,
        $store_id
    );
} else {
    $productServices = app()->make(StoreProductServices::class);
    $res5 = $res5 && $productServices->decProductStock(
        $cart_num,
        $product_id,
        $unique
    );
}

if (!$res5) {
    throw new ValidateException('库存不足!');
}

AI 风控适合识别这些情况:

text 复制代码
秒杀活动显示还有库存,但下单连续提示库存不足
普通商品库存充足,活动库存不足
同一 SKU 在活动库存和普通库存之间出现异常差异
活动结束后仍有扣减请求

这些问题不适合让 AI 自动修复,因为涉及订单和库存一致性;AI 只应该给出"风险提醒 + 需要人工检查的代码链路"。

7. 给 AI 的风控上下文应该脱敏

推荐传给 AI 的结构:

php 复制代码
[
    'window' => '最近30分钟',
    'refund' => [
        'total_refund_orders' => 18,
        'split_refund_orders' => 5,
        'gift_order_pending' => 2,
        'mini_program_sync_failed' => 1,
    ],
    'stock' => [
        'low_stock_products' => 12,
        'sku_zero_product_showing' => 3,
        'stock_dec_failed' => 4,
    ],
    'activity' => [
        'seckill_stock_warning' => 2,
        'activity_order_failed' => 3,
    ],
    'rules' => [
        '只输出风险等级、原因、建议动作',
        '不要输出用户手机号、地址、昵称',
        '不要自动修改订单、库存、退款状态',
    ],
]

推荐输出结构:

json 复制代码
{
  "level": "high",
  "title": "秒杀库存扣减异常升高",
  "reason": "最近30分钟同一活动出现多次库存不足失败,且普通商品库存仍充足",
  "impact": "可能影响用户下单成功率,也可能说明活动库存和普通库存口径不一致",
  "actions": [
    "检查 StoreSeckillServices::checkSeckillStock",
    "检查 StoreOrderCreateServices 扣库存分支",
    "核对活动 SKU 和普通商品 SKU 库存"
  ]
}

8. 风控提醒可以做成三个等级

建议把 AI 输出分成三类,不要一上来就做复杂自动化:

text 复制代码
低风险:数据波动,建议观察
中风险:需要运营复查,例如退款率、库存低、活动转化异常
高风险:需要技术介入,例如库存扣减失败、退款后续同步失败、活动下单失败集中出现

后台展示时可以按:

text 复制代码
风险等级
影响模块
命中规则
项目源码链路
建议动作
是否已处理
处理备注

这样比"AI 给一段大作文"更好落地。

9. 注意事项

  1. AI 风控只做提醒,不自动退款、不自动改库存、不自动上下架。
  2. 订单、库存、退款属于高风险业务,必须保留人工确认。
  3. 传给 AI 的数据要脱敏,不传手机号、地址、客户备注、支付流水号。
  4. 风控规则要先用后端代码算出命中结果,再让 AI 解释和总结。
  5. 退款、库存、活动的口径要复用现有 Service/Dao,不要在 Controller 里临时拼 SQL。
  6. 风控提醒需要有"已读、处理中、已处理、忽略"状态,避免每天重复告警。
  7. 高风险提醒建议同步到后台消息或企业微信,但发送前要控制频率。

标签建议

text 复制代码
CRMEB Pro
二次开发
AI风控
商城系统
订单退款
库存管理
秒杀活动
PHP
ThinkPHP