这是一份面向CTO、架构师及核心开发人员的《智能视觉售卖机系统技术开发指导文档》。
该文档不讲业务故事,只讲代码怎么写、库怎么建、第三方接口怎么接,以及核心技术难点的解决方案。
| 项目属性 | 定义 |
|---|---|
| 后端技术栈 | 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 |
Module-User: C端用户、鉴权、支付分。Module-Device: 设备状态、指令下发、哈哈API代理。Module-Order: 订单状态机、回调处理、算费逻辑。Module-Admin: 商家管理、商品库同步。Key: device_status:{sn} -> 存储设备实时状态(在线/离线/购物中)。Key: lock:door:{sn} -> 分布式锁,防止并发开门。Key: order:temp:{sn} -> 临时存储回调数据。apply_open_door) -> 设备开门。/api/callback/haha/notify).out_trade_no.视觉柜的核心在于商品与AI模型的绑定。
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='商品表';
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='设备表';
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='订单主表';
所有请求 Header 必须包含签名。
MD5(app_id + app_secret + timestamp + body_json).HahaApiClient 类,统一处理签名和 HTTP POST。| 业务动作 | 接口名 (参考) | 请求参数重点 | 回调处理 |
|---|---|---|---|
| 同步商品 | 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) |
为了解耦 HTTP 回调和业务逻辑:
Sign 确保安全。Spring Event (如 HahaOrderEvent)。@EventListener 异步处理:
t_order (通过 out_trade_no)。PENDING -> 计算金额 -> 扣款。这是“先享后付”的基础。
GET /api/user/credit_score_status.
v3/payscore/permissions 查询。plugin-private-wxpay.用户关门后,订单生成有 5-15秒 延迟。
GET /api/order/latest_status?device_id=xxx.SimpMessagingTemplate 推送 /topic/user/{userId}。商品图片上传和同步可能耗时。
ApplicationEventPublisher 或 RabbitMQ。SYNCING -> 异步线程上传图片给哈哈 -> 获取哈哈 model_id -> 更新 DB 为 SYNCED。针对置信度低的订单:
confidence < 0.85 -> 状态设为 REVIEW (不扣款)。video_url (引用哈哈CDN) -> 管理员勾选 t_product 中的商品 -> 提交 /api/admin/order/audit_confirm。切记:视觉柜不手动输入数量。
/api/device/maintain_open (类型: 补货)。replenish_callback,包含 current_stock_list (当前柜子里的所有东西)。Last_Stock = 查询 DB 中该设备的上次库存。Current_Stock = 回调数据。Diff = Current - Last (计算出的补货量/取货量)。t_device_stock 表为 Current_Stock。t_replenish_log (补货日志)。PAY_FAIL。t_order 状态更为 DEBT (欠款)。t_user 标记为 LOCKED。lock:user:forbidden:{userId}。{code: 403, msg: "请先结清欠款"}。userId 和 role。Sign。-m 512M (JVM优化).7070 端口暴露为公网域名,填入哈哈后台作为 Notify Url。这份指导文档作为开发实施的基准,请开发团队在编码前详细阅读,特别是 3. 哈哈零兽 API 对接 和 6.1 补货逻辑 部分,这是最容易出错的环节。