系统交互流程.md 19 KB

系统交互流程

1. 核心购物流程

用户通过小程序扫码开门、选购商品、自动结算的完整交互流程。

sequenceDiagram
    participant 用户
    participant 小程序 as haha-mp (小程序)
    participant 后端 as haha-miniapp (后端)
    participant SDK as HahaClient (SDK)
    participant 哈哈零兽 as 哈哈零兽平台
    participant 微信 as 微信支付分

    rect rgb(240, 248, 255)
        Note over 用户,微信: 阶段一:扫码开门
        用户->>小程序: 扫描设备二维码
        小程序->>小程序: 检查登录状态
        小程序->>后端: GET /api/payscore/check-enable
        后端-->>小程序: 支付分开通状态
        alt 未开通支付分
            小程序->>小程序: 跳转支付分开通页面
            小程序->>后端: POST /api/payscore/enable
            后端->>微信: 创建支付分服务订单
            微信-->>后端: 返回 outOrderNo
            后端-->>小程序: 返回开通参数
            小程序->>微信: wx.openBusinessView 调起授权
            微信-->>小程序: 用户授权结果
            小程序->>后端: POST /api/payscore/confirm-enable
            后端-->>小程序: 开通确认结果
        end
        小程序->>小程序: 弹窗选择:查看柜内商品 / 直接开门
        alt 直接开门
            小程序->>后端: POST /api/device/scan-open {deviceId}
            后端->>SDK: openDoor(deviceId, userId, OUT, doorIndex, MINIAPP)
            SDK->>哈哈零兽: POST /door/open
            哈哈零兽-->>SDK: {activity_id, user_id}
            SDK-->>后端: OpenDoorResult
            后端->>后端: 保存开门记录(数据库 + Redis)
            后端-->>小程序: Result<OpenDoorVO>
            小程序->>小程序: 跳转购物页面
        end
    end

    rect rgb(255, 248, 240)
        Note over 用户,微信: 阶段二:选购等待
        小程序->>小程序: 开始轮询设备状态
        loop 每 2 秒轮询
            小程序->>后端: GET /api/device/status?deviceId=xxx
            后端-->>小程序: 设备门状态
        end
        哈哈零兽->>后端: 回调 DEVICE_STATUS (status=OPENED)
        后端->>后端: 保存状态到 Redis + 更新数据库门状态
        Note over 用户: 用户选购商品...
        哈哈零兽->>后端: 回调 DEVICE_STATUS (status=CLOSED)
        后端->>后端: 更新开门记录关门状态 + 更新数据库门状态
    end

    rect rgb(240, 255, 240)
        Note over 用户,微信: 阶段三:AI识别
        哈哈零兽->>后端: 回调 ORC_RESULT (AI识别结果)
        后端->>后端: 保存识别结果到 Redis
        alt 有消费 (nobuy=0)
            后端->>后端: 获取或创建订单
            后端->>后端: 更新订单商品列表 + 视频URL(金额待订单回调更新)
            后端->>后端: 更新关门状态
        else 无消费 (nobuy=1)
            后端->>后端: 标记无消费 + 更新关门状态
        end
        后端-->>哈哈零兽: "success"
    end

    rect rgb(255, 240, 255)
        Note over 用户,微信: 阶段四:订单结算
        哈哈零兽->>后端: 回调 ORDER (订单信息 + 金额)
        后端->>后端: 更新订单号 + 订单金额 + 订单类型
        后端->>后端: 保存订单商品明细
        后端->>后端: 优惠券自动扣减(最先到期优先)
        后端->>后端: 更新优惠金额 + 实付金额
        alt 支付分订单
            后端->>微信: completePayScoreOrder (完结扣费)
            微信-->>后端: 扣费结果
        end
        后端->>后端: 保存订单信息到 Redis
        后端-->>哈哈零兽: "success"
        小程序->>后端: 轮询获取订单信息
        后端-->>小程序: 返回订单详情
        小程序->>小程序: 显示订单结果
    end

2. 回调通知体系

哈哈零兽平台通过两类回调地址推送通知,后端统一在 CallbackController 接收处理。

2.1 消息回调 (/callback/haha/message)

notify_type 说明 处理逻辑
DEVICE_STATUS 开关门状态通知 更新 Redis 缓存 + 数据库门状态 + 开门记录
ONLINE_STATUS 设备在线状态通知 更新 Redis 缓存 + 离线告警/上线恢复/弱信号告警
VOICE_RESULT 音量调节结果通知 更新 Redis 缓存
ORC_RESULT AI识别结果通知 保存识别结果 + 创建/更新订单 + 关门状态处理
CLIENT_NEW_PRODUCT 新品审核结果回调 更新申请记录 + 同步商品到商家库
MERGE_PRODUCT 商品合并结果通知 记录合并日志

2.2 订单回调 (/callback/haha/order)

哈哈零兽生成订单后推送的完整订单信息,包含订单号、金额、商品明细等。

2.3 回调处理流程

flowchart TD
    Callback[收到回调通知] --> VerifySign[验证签名]
    VerifySign --> ParseParams[解析回调参数]
    ParseParams --> CheckType{判断回调类型}

    CheckType --> |消息回调| CheckNotifyType{notify_type?}
    CheckType --> |订单回调| HandleOrder[处理订单回调]

    CheckNotifyType --> |DEVICE_STATUS| HandleDeviceStatus[处理开关门状态]
    CheckNotifyType --> |ONLINE_STATUS| HandleOnlineStatus[处理在线状态]
    CheckNotifyType --> |VOICE_RESULT| HandleVoiceResult[处理音量结果]
    CheckNotifyType --> |ORC_RESULT| HandleOrcResult[处理AI识别结果]
    CheckNotifyType --> |CLIENT_NEW_PRODUCT| HandleNewProduct[处理新品审核]
    CheckNotifyType --> |MERGE_PRODUCT| HandleMergeProduct[处理商品合并]

    HandleDeviceStatus --> SaveRedis1[保存状态到Redis]
    SaveRedis1 --> UpdateDB1[更新数据库门状态]
    UpdateDB1 --> UpdateRecord1[更新开门记录]

    HandleOnlineStatus --> SaveRedis2[保存在线状态到Redis]
    SaveRedis2 --> CheckOnline{在线/离线?}
    CheckOnline --> |离线| OfflineAlert[触发离线告警]
    CheckOnline --> |在线| BackOnline[发送恢复通知]
    BackOnline --> CheckSignal{信号强度?}
    CheckSignal --> |弱信号| WeakSignalAlert[触发弱信号告警]

    HandleOrcResult --> SaveRedis3[保存识别结果到Redis]
    SaveRedis3 --> CheckConsume{是否有消费?}
    CheckConsume --> |有消费| CreateOrder[创建/更新订单]
    CheckConsume --> |无消费| MarkNoConsume[标记无消费]

    HandleOrder --> UpdateOrderAmount[更新订单金额]
    UpdateOrderAmount --> SaveOrderGoods[保存订单商品]
    SaveOrderGoods --> CouponDiscount[优惠券自动扣减]
    CouponDiscount --> PayScorePayment[支付分扣费]
    PayScorePayment --> SaveRedis4[保存订单到Redis]

    RecordResult[返回 success]
    HandleVoiceResult --> SaveRedis5[保存音量到Redis] --> RecordResult
    HandleNewProduct --> UpdateApply[更新申请记录] --> SyncProduct[同步商品] --> RecordResult
    HandleMergeProduct --> LogMerge[记录合并日志] --> RecordResult
    MarkNoConsume --> RecordResult
    CreateOrder --> RecordResult
    SaveRedis4 --> RecordResult
    OfflineAlert --> RecordResult
    BackOnline --> RecordResult
    WeakSignalAlert --> RecordResult
    UpdateDB1 --> RecordResult

3. 扫码开门详细流程

sequenceDiagram
    participant 小程序
    participant 后端 as DeviceServiceImpl
    participant SDK as HahaClient
    participant 哈哈零兽
    participant Redis
    participant DB as 数据库

    小程序->>后端: scanOpenDoor(deviceId, userId)
    后端->>后端: checkUserPayscoreStatus(userId)
    后端->>SDK: getOnlineStatus(deviceId)
    SDK->>哈哈零兽: 查询设备在线状态
    哈哈零兽-->>SDK: DeviceOnlineStatus
    alt 设备离线
        SDK-->>后端: isOnline=0
        后端-->>小程序: BusinessException("设备当前离线")
    end
    后端->>SDK: isMultiDoorUnique(deviceId)
    SDK-->>后端: 多门单开类型
    alt 多门单开设备
        后端->>后端: doorIndex = "A"
    end
    后端->>SDK: openDoor(deviceId, userId, OUT, doorIndex, MINIAPP)
    SDK->>哈哈零兽: POST /door/open
    哈哈零兽-->>SDK: {activity_id, user_id}
    SDK-->>后端: OpenDoorResult
    后端->>DB: 保存开门记录 (DoorRecord)
    后端->>Redis: 保存设备状态
    后端-->>小程序: OpenDoorVO

4. 订单结算流程

订单回调触发完整的结算链路,包括金额更新、优惠券扣减、支付分扣费。

flowchart TD
    OrderCallback[收到订单回调] --> FindOrder[查找本地订单]
    FindOrder --> OrderExists{订单是否存在?}
    OrderExists --> |是| CheckDuplicate{是否已处理?}
    OrderExists --> |否| FetchRecognition[主动查询识别结果创建订单]

    CheckDuplicate --> |已处理| SaveRedis[保存到Redis]
    CheckDuplicate --> |未处理| UpdateOrder[更新订单信息]

    FetchRecognition --> CreateFromRecognition[根据识别结果创建订单]
    CreateFromRecognition --> UpdateOrder

    UpdateOrder --> SetAmount[设置订单金额 totalAmount]
    SetAmount --> InitDiscount[初始化 discountAmount=0, paidAmount=totalAmount]
    InitDiscount --> SaveGoods[保存订单商品明细]
    SaveGoods --> ProcessCoupon[优惠券自动扣减]

    ProcessCoupon --> QueryCoupons[查询用户可用优惠券]
    QueryCoupons --> SortByExpiry[按到期时间升序排序]
    SortByExpiry --> FindApplicable{找到适用优惠券?}
    FindApplicable --> |是| CalcDiscount[计算优惠金额]
    FindApplicable --> |否| UseOriginalAmount[使用原金额]

    CalcDiscount --> CheckCap{优惠金额 > 订单金额?}
    CheckCap --> |是| CapDiscount[优惠金额 = 订单金额]
    CheckCap --> |否| KeepDiscount[保持计算值]
    CapDiscount --> FinalAmount
    KeepDiscount --> FinalAmount[计算实付金额 paidAmount = total - discount]
    FinalAmount --> UseCoupon[标记优惠券已使用]
    UseCoupon --> UpdateOrderDiscount[更新订单 discountAmount + paidAmount]

    UseOriginalAmount --> PayScoreCheck
    UpdateOrderDiscount --> PayScoreCheck{支付分订单?}

    PayScoreCheck --> |是| DeductPayScore[支付分完结扣费]
    PayScoreCheck --> |否| SaveOrderRedis[保存订单到Redis]
    DeductPayScore --> SaveOrderRedis
    SaveOrderRedis --> Done[结算完成]

4.1 金额流转说明

阶段 负责方 totalAmount discountAmount paidAmount
开门记录 DeviceServiceImpl - - -
AI识别回调 HahaCallbackServiceImpl 0 0 0
订单回调 HahaCallbackServiceImpl 设备传来 0 = totalAmount
优惠券扣减 HahaCallbackServiceImpl 不变 优惠券金额 = total - discount
支付扣费 PayScoreService 不变 不变 使用此金额扣费

4.2 优惠券扣减规则

  • 排序策略:按到期时间升序,优先使用最先到期的券
  • 使用限制:一次订单只能使用一张优惠券
  • 适用范围
    • applyScope=1:全场通用
    • applyScope=2:指定门店
    • applyScope=3:指定商品
  • 优惠金额上限:不超过订单金额
  • 优惠券类型
    • type=1 满减券:直接返回 discountValue
    • type=2 折扣券:orderAmount × (1 - discountValue/10),受 maxDiscount 上限约束
    • type=3 抵扣券:直接返回 discountValue
    • type=4 兑换券:不参与金额扣减

5. 微信支付分集成流程

sequenceDiagram
    participant 用户
    participant 小程序
    participant 后端 as PayScoreServiceImpl
    participant 微信 as 微信支付分

    rect rgb(240, 255, 255)
        Note over 用户,微信: 支付分开通过程
        用户->>小程序: 点击开通支付分
        小程序->>后端: POST /api/payscore/enable
        后端->>微信: 创建支付分服务订单
        微信-->>后端: outOrderNo + serviceId
        后端-->>小程序: 开通参数
        小程序->>微信: wx.openBusinessView 调起授权页
        微信-->>用户: 展示授权页面
        用户->>微信: 确认授权
        微信-->>小程序: 授权结果回调
        小程序->>后端: POST /api/payscore/confirm-enable
        后端->>微信: 查询支付分状态
        微信-->>后端: 用户支付分状态
        后端->>后端: 更新用户 payscoreEnabled 状态
        后端-->>小程序: 开通成功
    end

    rect rgb(255, 255, 240)
        Note over 用户,微信: 开门时创建支付分服务订单
        小程序->>后端: POST /api/device/scan-open
        后端->>后端: scanOpenDoor()
        后端->>后端: 创建本地订单
        后端->>后端: 创建支付分服务订单
        后端->>微信: createPayScoreOrder(orderId, openId)
        微信-->>后端: 支付分服务订单号
        后端->>后端: 保存 payScoreOrderId 到订单
    end

    rect rgb(255, 240, 240)
        Note over 用户,微信: 订单完结自动扣费
        后端->>后端: processPayScorePayment(order, finalAmount)
        后端->>后端: 校验:支付分渠道 + 服务可用 + 订单未完结
        后端->>微信: completePayScoreOrder(orderId, finalAmount)
        微信->>微信: 自动扣款
        微信-->>后端: 扣款结果
        后端->>后端: 更新订单支付状态
    end

    rect rgb(245, 240, 255)
        Note over 用户,微信: 支付分回调
        微信->>后端: POST /api/payscore/callback
        后端->>后端: 解析回调参数
        后端->>后端: 更新订单支付分状态
        后端-->>微信: 返回成功响应
    end

5.1 支付分状态流转

stateDiagram-v2
    [*] --> CREATED: 创建服务订单
    CREATED --> DOING: 用户授权确认
    DOING --> DONE: 完结扣费成功
    DOING --> REVOKED: 取消订单
    DONE --> [*]
    REVOKED --> [*]

6. 购物页面状态流转

小程序购物页面的状态轮询与界面联动机制。

stateDiagram-v2
    [*] --> opened: 开门成功
    opened --> opened: 轮询设备状态(2s间隔)
    opened --> closing: 门已关闭
    opened --> error: 设备异常

    closing --> closed: 获取到订单信息
    closing --> error: 订单异常

    closed --> [*]: 倒计时结束返回首页
    error --> [*]: 返回首页

6.1 轮询机制

轮询类型 间隔 超时 说明
设备状态 2秒 120秒 等待门从 opened 变为 close
识别结果 3秒 - 门关后轮询 AI 识别结果
订单信息 3秒 - 识别完成后轮询订单详情

6.2 购物页生命周期

  • 组件激活 (onActivated):重新启动轮询
  • 组件失活 (onDeactivated):暂停轮询、清理定时器
  • 应用隐藏 (onHide):清理购物页面轮询状态
  • 组件卸载:清理所有定时器和轮询

7. 管理后台远程控制

运营平台通过管理后台远程控制设备。

sequenceDiagram
    participant 运营人员
    participant Web管理端 as haha-admin-web
    participant Admin后端 as haha-admin
    participant SDK as HahaClient
    participant 哈哈零兽

    rect rgb(245, 245, 245)
        Note over 运营人员,哈哈零兽: 远程开门
        运营人员->>Web管理端: 点击远程开门
        Web管理端->>Admin后端: POST /admin/devices/{id}/open
        Admin后端->>Admin后端: 查找设备
        Admin后端->>SDK: openDoor(deviceId, ADMIN+timestamp, IN, doorIndex)
        SDK->>哈哈零兽: POST /door/open
        哈哈零兽-->>SDK: {activity_id}
        SDK-->>Admin后端: OpenDoorResult
        Admin后端-->>Web管理端: 操作结果
    end

    rect rgb(245, 245, 245)
        Note over 运营人员,哈哈零兽: 设置温度
        运营人员->>Web管理端: 输入温度值(-30~30℃)
        Web管理端->>Admin后端: POST /admin/devices/{id}/temperature
        Admin后端->>SDK: setTemperature(deviceId, temperature)
        SDK->>哈哈零兽: 设置温度指令
        SDK-->>Admin后端: 设置结果
        Admin后端-->>Web管理端: 操作结果
    end

    rect rgb(245, 245, 245)
        Note over 运营人员,哈哈零兽: 音量调节
        运营人员->>Web管理端: 输入音量值(0~100)
        Web管理端->>Admin后端: POST /admin/devices/{id}/volume
        Admin后端->>SDK: setVolume(deviceId, volume)
        SDK->>哈哈零兽: 音量调节指令
        SDK-->>Admin后端: 设置结果
        Admin后端-->>Web管理端: 操作结果
    end

注意:管理后台开门默认为上货模式 (openType=IN),outUserId 格式为 ADMIN+时间戳;小程序开门为消费模式 (openType=OUT),source=MINIAPP

8. 设备告警体系

设备在线状态回调触发的告警流程。

flowchart TD
    OnlineCallback[收到 ONLINE_STATUS 回调] --> ParseOnline[解析在线状态]
    ParseOnline --> SaveOnlineRedis[保存在线状态到Redis 10min TTL]
    SaveOnlineRedis --> CheckOnlineStatus{is_online?}

    CheckOnlineStatus --> |0-离线| TriggerOfflineAlert[触发离线告警]
    CheckOnlineStatus --> |1-在线| CheckBackOnline[检查是否需要恢复通知]

    TriggerOfflineAlert --> AlertService[DeviceAlertService.processOfflineAlert]
    AlertService --> NotifyWeCom[发送企业微信告警通知]

    CheckBackOnline --> ProcessBackOnline[DeviceAlertService.processBackOnlineNotify]
    ProcessBackOnline --> SendRecoverNotify[发送恢复通知]
    SendRecoverNotify --> ExtractSignal[提取信号值 signal_val]
    ExtractSignal --> CheckSignal{信号强度 <= 阈值?}
    CheckSignal --> |是| WeakSignalAlert[触发弱信号告警]
    CheckSignal --> |否| Done[完成]
    WeakSignalAlert --> NotifyWeCom2[发送企业微信告警通知]

9. 系统角色说明

角色 说明 对应模块
用户 最终消费者,通过小程序扫码购物 haha-mp
运营人员 管理后台操作人员,远程控制设备 haha-admin-web
哈哈零兽 设备平台,负责设备控制、AI识别、订单生成 外部平台 (SDK对接)
haha-miniapp 小程序后端,处理回调、订单结算 haha-miniapp
haha-admin 运营平台后端,设备管理、营销管理 haha-admin
微信支付分 免密支付渠道,先享后付 外部平台 (API对接)

10. 关键接口索引

10.1 小程序端 API (/api)

接口 方法 说明
/api/device/scan-open POST 扫码开门
/api/payscore/check-enable GET 检查支付分开通状态
/api/payscore/enable POST 开通支付分
/api/payscore/confirm-enable POST 确认开通支付分
/api/payscore/callback POST 支付分回调通知

10.2 回调接口 (/callback/haha)

接口 方法 说明
/callback/haha/message POST 消息回调统一入口
/callback/haha/order POST 订单回调通知

10.3 管理端 API (/admin)

接口 方法 说明
/admin/devices/{id}/open POST 远程开门
/admin/devices/{id}/temperature POST 设置温度
/admin/devices/{id}/volume POST 音量调节