# 系统交互流程 ## 1. 核心购物流程 用户通过小程序扫码开门、选购商品、自动结算的完整交互流程。 ```mermaid 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 小程序->>小程序: 跳转购物页面 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](haha-miniapp/src/main/java/com/haha/miniapp/controller/CallbackController.java) 接收处理。 ### 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 回调处理流程 ```mermaid 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. 扫码开门详细流程 ```mermaid 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. 订单结算流程 订单回调触发完整的结算链路,包括金额更新、优惠券扣减、支付分扣费。 ```mermaid 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. 微信支付分集成流程 ```mermaid 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 支付分状态流转 ```mermaid stateDiagram-v2 [*] --> CREATED: 创建服务订单 CREATED --> DOING: 用户授权确认 DOING --> DONE: 完结扣费成功 DOING --> REVOKED: 取消订单 DONE --> [*] REVOKED --> [*] ``` ## 6. 购物页面状态流转 小程序购物页面的状态轮询与界面联动机制。 ```mermaid 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. 管理后台远程控制 运营平台通过管理后台远程控制设备。 ```mermaid 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. 设备告警体系 设备在线状态回调触发的告警流程。 ```mermaid 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 | 音量调节 |