CLAUDE.md — 哈哈智能零售系统
项目概览
基于 Spring Boot 的 AI 智能视觉售卖机系统,包含用户端小程序、管理后台、硬件通信等模块。
技术栈
- 后端: Java 21, Spring Boot 4.0.3, MyBatis-Plus 3.5.16
- 前端: Vue 3 + Element Plus (admin-web), uni-app (mp)
- 数据库: MySQL, Redis
- 服务端口: miniapp 7077, admin 7070
- 支付: 微信支付 JSAPI + 支付分 (Pay Score)
模块结构
haha-parent
├── haha-common — 公共工具、枚举、VO
├── haha-entity — 实体类、DTO
├── haha-mapper — MyBatis Mapper
├── haha-service — 核心业务逻辑(回调处理、支付、订单、库存等)
├── haha-miniapp — 用户端小程序后端 (port 7077)
├── haha-admin — 管理后台后端 (port 7070)
├── haha-sdk — 哈哈平台 SDK (API调用、Token管理)
├── qdb-sdk — 千岛板 SDK
├── haha-mp — 用户端小程序前端 (uni-app)
├── haha-admin-web — 管理后台前端 (Vue 3)
└── haha-admin-mp — 管理端小程序
哈哈平台回调流程
两类回调
| 回调 |
路径 |
作用 |
| ORC_RESULT |
/api/callback/haha/message (notify_type=ORC_RESULT) |
AI 识别结果,触发订单创建 |
| ORDER |
/api/callback/haha/order |
设备端报价,写入金额 |
订单创建时序
1. 用户开门 → preCreatePayScoreOrder (微信支付分预授权) → 存 Redis (TTL 10min)
2. AI识别完成 → ORC_RESULT 回调 → 创建订单 + 关联支付分 → 清理Redis
3. 设备报价 → ORDER 回调 → validateSign → 写入 totalAmount/paidAmount
4. 消息推送 → 用户确认付款
签名验证 (重要!)
- 哈哈平台使用 MD5(signStr + ticket) 签名
- 签名原文: 参数按 key 排序,值 URL 编码后
key=value&... 拼接,末尾直接拼接 ticket
- ⚠️ 不能使用 Spring
@RequestParam 解析后的参数重建签名! Spring 会 URL-decode,Java URLEncoder 重新 encode 的结果与 PHP 原始 urlencode 不一致
- 必须从原始 request body 构建签名 →
buildSignContentFromRawBody()
- 见
HahaCallbackServiceImpl.java:620 的 validateSign(params, rawBody) 方法
支付分关键限制
- 同一实名用户 进行中订单 ≤ 3 笔 (微信硬限制)
- 超过 3 笔 → 用户无法扫码开门 (错误: "同一实名身份下进行中订单过多")
- 分级清理策略 (见
PayScoreServiceImpl.cancelStalePayScoreOrdersAndCount):
- 自动补扣: 有金额的待支付订单 (>1min)
- 取消 CREATED: 用户从未确认
- 清理超时孤儿: DOING/USER_PAYING + 无金额 + >30min
- Redis 追踪清理
支付分完结金额校验
- 微信要求
total_amount == sum(post_payments[].amount) 严格相等
- DB 中单价保留 2 位小数,乘数量后求和可能产生 1 分钱差额
- 解决方案:
buildPostPayments(orderId, totalAmount) 自动平账到末项
日志路径
- miniapp:
./logs/haha-miniapp/haha-miniapp.log
- admin:
./logs/haha-admin/haha-admin.log
- JVM 工作目录
/home/kym/application (服务器)
- prod 环境: logback-spring.xml 同时输出 CONSOLE + FILE
关键文件索引
| 文件 |
功能 |
HahaCallbackServiceImpl.java |
回调处理: 签名验证、订单创建、支付分完结 |
PayScoreServiceImpl.java |
支付分: 预授权、创建、完结、取消、限额清理 |
OrderServiceImpl.java |
订单: CRUD、支付分集成、库存扣减 |
CallbackController.java |
回调入口 (miniapp 7077) |
OrderController.java |
管理后台订单接口 (admin 7070) |
RequestParseUtil.java |
请求解析 (JSON/XML/Form) |
HahaClient.java |
哈哈平台 SDK (Token/Ticket管理) |
常见故障排查
| 现象 |
原因 |
解决方案 |
| 订单有商品无金额 |
ORDER 回调签名失败 |
检查签名日志,修复后用 SQL 补齐 |
| 支付分补扣失败 PARAM_ERROR |
post_payments 总额 ≠ total_amount |
已修复自动平账 |
| 支付分补扣失败 REVOKED |
新支付分订单创建导致旧单被撤销 |
新流程自动清理+前端拦截 |
| 用户无法开门 |
进行中订单 ≥ 3 笔 |
cancelStalePayScoreOrdersAndCount 自动清理 |
| 日志文件找不到 |
路径配错或权限问题 |
检查 logging.file.path 和 JVM 工作目录 |