|
|
@@ -1,218 +0,0 @@
|
|
|
-这是一份面向**CTO、架构师及核心开发人员**的《智能视觉售卖机系统技术开发指导文档》。
|
|
|
-
|
|
|
-该文档不讲业务故事,只讲**代码怎么写、库怎么建、第三方接口怎么接**,以及核心技术难点的解决方案。
|
|
|
-
|
|
|
----
|
|
|
-
|
|
|
-# 智能视觉售卖机系统 - 技术开发指导书 (Technical Guide)
|
|
|
-
|
|
|
-| 项目属性 | 定义 |
|
|
|
-| :--- | :--- |
|
|
|
-| **后端技术栈** | Java 21, Spring Boot 3.5.9, Maven, Lombok, MyBatis-Plus, Hutool |
|
|
|
-| **前端技术栈** | Uni-app (Vue 3 + TypeScript + Vite + Pinia) |
|
|
|
-| **中间件** | MySQL 8.0, Redis 7.0 (缓存/分布式锁/消息订阅) |
|
|
|
-| **第三方核心** | 哈哈零兽开放平台 API, 微信支付V3 (支付分) |
|
|
|
-| **开发模式** | 前后端分离,RESTful API |
|
|
|
-
|
|
|
----
|
|
|
-
|
|
|
-## 1. 核心架构与交互时序
|
|
|
-
|
|
|
-### 1.1 系统逻辑拓扑
|
|
|
-* **网关层**: Nginx/Spring Cloud Gateway (可选),负责SSL终结和路由。
|
|
|
-* **应用层**: Spring Boot 单体/微服务。
|
|
|
- * `Module-User`: C端用户、鉴权、支付分。
|
|
|
- * `Module-Device`: 设备状态、指令下发、哈哈API代理。
|
|
|
- * `Module-Order`: 订单状态机、回调处理、算费逻辑。
|
|
|
- * `Module-Admin`: 商家管理、商品库同步。
|
|
|
-* **数据层**:
|
|
|
- * **MySQL**: 核心业务数据。
|
|
|
- * **Redis**:
|
|
|
- * `Key: device_status:{sn}` -> 存储设备实时状态(在线/离线/购物中)。
|
|
|
- * `Key: lock:door:{sn}` -> 分布式锁,防止并发开门。
|
|
|
- * `Key: order:temp:{sn}` -> 临时存储回调数据。
|
|
|
-
|
|
|
-### 1.2 关键交互流程 (购物全链路)
|
|
|
-1. **开门请求**: 小程序 -> 后端 (校验余额/风控) -> **Redis加锁** -> 调用哈哈API (`apply_open_door`) -> 设备开门。
|
|
|
-2. **购物中**: 设备上传视频流至哈哈云端 (黑盒)。
|
|
|
-3. **结算回调**:
|
|
|
- * 哈哈云端 -> 后端 Webhook (`/api/callback/haha/notify`).
|
|
|
- * 后端 -> 匹配本地 `out_trade_no`.
|
|
|
- * 后端 -> 算费 -> **微信支付分扣款**.
|
|
|
- * 后端 -> WebSocket/Redis PubSub -> 前端提示“支付成功”。
|
|
|
-
|
|
|
----
|
|
|
-
|
|
|
-## 2. 数据库详细设计 (Schema Design)
|
|
|
-
|
|
|
-### 2.1 核心表结构 (MySQL 8.0)
|
|
|
-
|
|
|
-#### A. 商品表 (t_product)
|
|
|
-视觉柜的核心在于**商品与AI模型的绑定**。
|
|
|
-```sql
|
|
|
-CREATE TABLE `t_product` (
|
|
|
- `id` bigint NOT NULL AUTO_INCREMENT,
|
|
|
- `barcode` varchar(32) NOT NULL COMMENT '69码,全局唯一,核心识别键',
|
|
|
- `name` varchar(128) NOT NULL,
|
|
|
- `price` decimal(10,2) NOT NULL COMMENT '零售价',
|
|
|
- `image_url` varchar(512) NOT NULL COMMENT '白底图URL,用于展示及AI同步',
|
|
|
- `haha_sync_status` tinyint DEFAULT 0 COMMENT '0-未同步 1-已同步 2-同步失败',
|
|
|
- `haha_model_id` varchar(64) DEFAULT NULL COMMENT '哈哈侧返回的商品ID',
|
|
|
- `is_deleted` tinyint DEFAULT 0,
|
|
|
- `create_time` datetime DEFAULT CURRENT_TIMESTAMP,
|
|
|
- PRIMARY KEY (`id`),
|
|
|
- UNIQUE KEY `uk_barcode` (`barcode`)
|
|
|
-) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COMMENT='商品表';
|
|
|
-```
|
|
|
-
|
|
|
-#### B. 设备表 (t_device)
|
|
|
-```sql
|
|
|
-CREATE TABLE `t_device` (
|
|
|
- `id` bigint NOT NULL AUTO_INCREMENT,
|
|
|
- `device_id` varchar(64) NOT NULL COMMENT '哈哈设备SN序列号',
|
|
|
- `shop_id` bigint NOT NULL COMMENT '归属点位ID',
|
|
|
- `name` varchar(64) DEFAULT NULL,
|
|
|
- `auth_token` varchar(128) DEFAULT NULL COMMENT '设备端通信Token(如需)',
|
|
|
- `status` tinyint DEFAULT 1 COMMENT '0-离线 1-在线 2-购物中 3-故障',
|
|
|
- `current_inventory_hash` varchar(64) DEFAULT NULL COMMENT '当前库存快照Hash,用于补货比对',
|
|
|
- PRIMARY KEY (`id`),
|
|
|
- UNIQUE KEY `uk_sn` (`device_id`)
|
|
|
-) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COMMENT='设备表';
|
|
|
-```
|
|
|
-
|
|
|
-#### C. 订单表 (t_order)
|
|
|
-```sql
|
|
|
-CREATE TABLE `t_order` (
|
|
|
- `id` bigint NOT NULL AUTO_INCREMENT,
|
|
|
- `order_no` varchar(32) NOT NULL COMMENT '系统内部订单号',
|
|
|
- `out_trade_no` varchar(64) NOT NULL COMMENT '请求哈哈开门时的流水号',
|
|
|
- `haha_order_no` varchar(64) DEFAULT NULL COMMENT '哈哈侧订单号',
|
|
|
- `user_id` bigint NOT NULL,
|
|
|
- `device_id` varchar(64) NOT NULL,
|
|
|
- `total_amount` decimal(10,2) DEFAULT NULL,
|
|
|
- `pay_status` varchar(20) DEFAULT 'PENDING' COMMENT 'PENDING-识别中, WAIT_PAY-待支付, PAID-已支付, FAIL-失败, REVIEW-待人工',
|
|
|
- `video_url` varchar(512) DEFAULT NULL COMMENT '购物视频证据',
|
|
|
- `confidence` decimal(5,4) DEFAULT NULL COMMENT 'AI识别置信度(0.00-1.00)',
|
|
|
- `items_json` text COMMENT '识别到的原始商品JSON快照',
|
|
|
- `create_time` datetime DEFAULT CURRENT_TIMESTAMP,
|
|
|
- `pay_time` datetime DEFAULT NULL,
|
|
|
- PRIMARY KEY (`id`),
|
|
|
- UNIQUE KEY `uk_out_trade` (`out_trade_no`),
|
|
|
- INDEX `idx_user` (`user_id`),
|
|
|
- INDEX `idx_status` (`pay_status`)
|
|
|
-) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COMMENT='订单主表';
|
|
|
-```
|
|
|
-
|
|
|
----
|
|
|
-
|
|
|
-## 3. 哈哈零兽 API 对接指南 (核心难点)
|
|
|
-
|
|
|
-### 3.1 鉴权工具类封装
|
|
|
-所有请求 Header 必须包含签名。
|
|
|
-* **AppId**: 平台申请。
|
|
|
-* **Sign算法**: `MD5(app_id + app_secret + timestamp + body_json)`.
|
|
|
-* 建议封装 `HahaApiClient` 类,统一处理签名和 HTTP POST。
|
|
|
-
|
|
|
-### 3.2 关键接口映射
|
|
|
-
|
|
|
-| 业务动作 | 接口名 (参考) | 请求参数重点 | 回调处理 |
|
|
|
-| :--- | :--- | :--- | :--- |
|
|
|
-| **同步商品** | `goods/add` | `barcode`, `name`, `image`(Url或Base64) | 无 |
|
|
|
-| **申请开门** | `device/applyOpen` | `device_id`, **`out_order_no`** (关键关联键) | 仅返回开门指令发送结果,非订单结果 |
|
|
|
-| **订单结果** | (Webhook) | - | 接收 `out_order_no`, `goods_list`, `video_url` |
|
|
|
-| **设备状态** | (Webhook) | - | 接收 `device_id`, `status` (update Redis) |
|
|
|
-
|
|
|
-### 3.3 回调处理策略 (Spring Event 模式)
|
|
|
-为了解耦 HTTP 回调和业务逻辑:
|
|
|
-1. Controller 接收哈哈 Webhook JSON。
|
|
|
-2. 校验 `Sign` 确保安全。
|
|
|
-3. 发布 `Spring Event` (如 `HahaOrderEvent`)。
|
|
|
-4. `@EventListener` 异步处理:
|
|
|
- * 查询 `t_order` (通过 `out_trade_no`)。
|
|
|
- * 若订单存在且状态为 `PENDING` -> 计算金额 -> 扣款。
|
|
|
- * **幂等性保护**:如果 Redis 中已有该订单处理记录,直接返回 success。
|
|
|
-
|
|
|
----
|
|
|
-
|
|
|
-## 4. Phase 1: 用户端小程序开发要点
|
|
|
-
|
|
|
-### 4.1 支付分/信用分对接流程
|
|
|
-这是“先享后付”的基础。
|
|
|
-1. **查询授权**: `GET /api/user/credit_score_status`.
|
|
|
- * 后端调用微信支付 `v3/payscore/permissions` 查询。
|
|
|
-2. **申请授权**: 若未授权,前端拉起小程序插件 `plugin-private-wxpay`.
|
|
|
-3. **创单开门**:
|
|
|
- * 后端先调用微信支付分“创建订单”接口 (Status: DOING)。
|
|
|
- * **锁定成功后**,再调用哈哈 API 开门。
|
|
|
- * *原因:防止用户开门后无法扣款。*
|
|
|
-
|
|
|
-### 4.2 轮询与状态反馈
|
|
|
-用户关门后,订单生成有 5-15秒 延迟。
|
|
|
-* **方案 A (推荐)**: 简单轮询。
|
|
|
- * 前端每 2秒 调用 `GET /api/order/latest_status?device_id=xxx`.
|
|
|
- * 后端查询 Redis 或 DB 中的最新订单状态。
|
|
|
-* **方案 B (进阶)**: WebSocket。
|
|
|
- * 后端处理完回调后,通过 `SimpMessagingTemplate` 推送 `/topic/user/{userId}`。
|
|
|
-
|
|
|
----
|
|
|
-
|
|
|
-## 5. Phase 2: PC 运营端开发要点
|
|
|
-
|
|
|
-### 5.1 商品同步队列
|
|
|
-商品图片上传和同步可能耗时。
|
|
|
-* **实现**: 使用 Spring `ApplicationEventPublisher` 或 RabbitMQ。
|
|
|
-* **流程**: 管理员保存商品 -> DB 状态设为 `SYNCING` -> 异步线程上传图片给哈哈 -> 获取哈哈 `model_id` -> 更新 DB 为 `SYNCED`。
|
|
|
-
|
|
|
-### 5.2 挂起订单处理 (人工审核)
|
|
|
-针对置信度低的订单:
|
|
|
-* **后端逻辑**: 接收回调 -> 判断 `confidence < 0.85` -> 状态设为 `REVIEW` (不扣款)。
|
|
|
-* **PC前端**: 展示 `video_url` (引用哈哈CDN) -> 管理员勾选 `t_product` 中的商品 -> 提交 `/api/admin/order/audit_confirm`。
|
|
|
-* **后续**: 接口触发算费 -> 调用微信支付分“完结订单”接口扣款。
|
|
|
-
|
|
|
----
|
|
|
-
|
|
|
-## 6. Phase 3: 商家端小程序开发要点
|
|
|
-
|
|
|
-### 6.1 补货逻辑 (基于快照差异)
|
|
|
-**切记:视觉柜不手动输入数量。**
|
|
|
-1. **开门**: 调用 `/api/device/maintain_open` (类型: 补货)。
|
|
|
-2. **回调处理**:
|
|
|
- * 哈哈返回 `replenish_callback`,包含 `current_stock_list` (当前柜子里的所有东西)。
|
|
|
- * **后端逻辑**:
|
|
|
- * `Last_Stock` = 查询 DB 中该设备的上次库存。
|
|
|
- * `Current_Stock` = 回调数据。
|
|
|
- * `Diff` = `Current` - `Last` (计算出的补货量/取货量)。
|
|
|
- * 更新 DB `t_device_stock` 表为 `Current_Stock`。
|
|
|
- * 记录 `t_replenish_log` (补货日志)。
|
|
|
-
|
|
|
----
|
|
|
-
|
|
|
-## 7. 安全与风控实现
|
|
|
-
|
|
|
-### 7.1 防逃单
|
|
|
-* **问题**: 用户拿货,但微信余额不足,扣款失败。
|
|
|
-* **处理**:
|
|
|
- 1. 微信返回 `PAY_FAIL`。
|
|
|
- 2. 后端将 `t_order` 状态更为 `DEBT` (欠款)。
|
|
|
- 3. 后端将 `t_user` 标记为 `LOCKED`。
|
|
|
- 4. **Redis 锁**: `lock:user:forbidden:{userId}`。
|
|
|
- 5. 下次开门前,Filter 拦截器检测到锁,直接拒绝,并返回 `{code: 403, msg: "请先结清欠款"}`。
|
|
|
-
|
|
|
-### 7.2 接口安全
|
|
|
-* 小程序与后端通信:使用 JWT (JSON Web Token),Token 中包含 `userId` 和 `role`。
|
|
|
-* 后端与哈哈通信:严格校验 `Sign`。
|
|
|
-
|
|
|
----
|
|
|
-
|
|
|
-## 8. 部署建议
|
|
|
-
|
|
|
-* **JDK**: Dragonwell 21.
|
|
|
-* **Docker**:
|
|
|
- * 应用容器: `-m 512M` (JVM优化).
|
|
|
- * Redis: 需开启 AOF 持久化,防止宕机丢失设备状态。
|
|
|
-* **域名**: 必须配置 HTTPS (微信小程序强制要求)。
|
|
|
-* **内网穿透 (开发期)**: 使用 Ngrok 或 Cpolar 将本地 `7070` 端口暴露为公网域名,填入哈哈后台作为 `Notify Url`。
|
|
|
-
|
|
|
----
|
|
|
-
|
|
|
-这份指导文档作为开发实施的基准,请开发团队在编码前详细阅读,特别是 **3. 哈哈零兽 API 对接** 和 **6.1 补货逻辑** 部分,这是最容易出错的环节。
|