洁垫把移动 Web、微信身份、免费任务、在线支付和实体出垫设备连接在一起。当前目录只有 H5 与 API 两个代码库,但 API 还服务小程序管理端、第三方渠道和设备,因此“未出现在目录中的调用方”也必须被纳入系统边界。
代码库与系统边界
| 项目 | 主要技术 | 源码职责 | 运行方式 |
|---|---|---|---|
jd_h5 |
Vue 2.6、Vant 2、Axios、Vuex、ECharts | 扫码首页、免费领垫、购买、结果、故障反馈和运营大屏 | Vue CLI 构建的移动 Web 站点 |
jd_api |
ThinkPHP 6、多应用、EasyWeChat 5、Predis、OSS、phpMQTT | 用户、设备、订单、代理、钱包、回调、统计和第三方渠道 | PHP API 服务 |
API 中存在 mini 管理接口和 MQTT 通信能力,但对应的小程序前端、Broker 运维配置及设备固件不在当前目录。文档只描述已观察到的接口边界,不把这些外部组件误写成仓库内子项目。
总体拓扑
flowchart TB User[扫码用户] --> H5[jd_h5
Vue 2 + Vant] H5 --> H5API[h5 / jdauth] Mini[代理与商户小程序
外部客户端] --> MiniAPI[mini] Channel[支付 / 广告任务 / 微信] --> Notify[notify] Partner[合作渠道] --> ZI[zi] H5API --> Core[jd_api
共享业务与数据访问] MiniAPI --> Core Notify --> Core ZI --> Core Core --> DB[(MySQL
订单 / 设备 / 钱包)] Core --> Cache[(Redis
会话 / 锁 / 实时状态)] Core --> MQ[MQTT / 设备通知] MQ --> Device[马桶垫发放设备] Device --> Notify
H5 页面与职责
jd_h5 的路由已经形成一条完整用户旅程:
| 页面 | 用户动作 | 服务端事实 |
|---|---|---|
| 首页 | 查看免费领取或购买入口 | 根据设备、用户和规则返回可用方式 |
| 免费领取 | 完成关注、广告或活动任务 | 创建免费订单并等待渠道确认 |
| 购买 | 选择数量并发起支付 | 服务端计算金额并创建支付单 |
| 结果页 | 查看出垫中、成功或失败 | 读取订单和设备任务的最终状态 |
| 故障反馈 | 报告关注后未出垫、支付后未出垫 | 创建可关联用户、设备和订单的维修记录 |
| 数据大屏 | 展示设备、用户和出垫统计 | 读取聚合数据,不直接扫描全部明细 |
H5 只负责交互和状态展示。价格、免费次数、设备余量、支付结果和出垫结果全部由 API 决定,不能从前端参数直接写入订单。
API 应用入口
| 入口 | 主要接口 | 调用方与权限 |
|---|---|---|
h5 |
用户、设备、订单、广告、积分、运营数据 | 普通用户,使用用户 Token 和当前设备上下文 |
jdauth |
微信网页授权、JS 配置 | 微信浏览器跳转入口,负责建立 OpenID 与平台用户关系 |
mini |
代理、商户、设备、补垫、收入、钱包和提现 | 管理端 Token,并按代理层级限制数据范围 |
notify |
支付、DSP、阅读任务、MQTT 和设备回调 | 无浏览器会话,必须验签并幂等处理 |
zi |
手机登录、菜单、门店、文章和合作渠道接口 | 独立成员身份与授权范围 |
多应用目录隔离了路由和身份,但订单、设备、库存、收益规则仍应共享同一领域实现。尤其不能让 H5 订单和小程序设备管理分别维护两套“剩余垫数”。
核心领域模型
| 领域 | 主要数据对象 | 关键约束 |
|---|---|---|
| 用户与微信身份 | 用户、应用授权、关注关系、二维码 | 一个渠道身份可追溯到平台用户,授权状态可刷新 |
| 代理与商户 | 代理、门店、铺设位置、银行卡、提现账户 | 代理只能管理授权范围内的门店和设备 |
| 设备与耗材 | 设备、在线日志、出垫计数、补垫记录、维修反馈 | 在线、机械状态和剩余垫数是三个独立状态 |
| 订单与设备任务 | 订单、MQTT 命令、渠道请求、回执 | 一个有效订单最多产生一次成功出垫 |
| 收益与钱包 | 收益流水、代理返佣、钱包、提现 | 余额由流水推导,订单退款需反向冲正 |
| 内容与渠道 | 广告、文章、第三方任务、渠道数据 | 渠道完成状态必须由可信回调或主动查询确认 |
| 统计 | 设备、用户、免费与购买出垫数据 | 明细为事实,日统计为可重建的派生数据 |
身份、设备与位置校验
H5 请求携带用户 Token,同时在服务端建立当前设备上下文。API 需要按顺序校验:
- Token 是否映射到有效用户;
- 二维码中的设备是否存在、激活且未停用;
- 设备是否归属于有效商户和代理;
- 设备最近通信状态、机械故障和剩余垫数;
- 用户定位是否满足现场领取规则;
- 用户当日免费次数或支付状态是否允许创建订单。
定位只能降低远程滥用风险,不能替代设备凭据。设备二维码公开可见,不能把 IMEI 当成无需认证的控制密码。
订单与任务渠道
系统存在免费任务和在线支付两类资格来源:
- 支付订单通过服务端创建,支付回调确认后获得出垫资格;
- 广告、关注或阅读任务由不同渠道返回完成结果;
- 渠道逻辑最终映射为统一的“订单已授权”,再进入设备任务;
- 每个渠道流水与平台订单建立唯一关联,重复回调只更新原记录。
渠道超时不能立即判定失败。系统可以保存 pending 状态并主动查询,或等待重试回调。只有资格确认后,才能生成 MQTT 命令。
设备通信与状态
设备控制至少包含四种标识:用户订单号、平台设备任务号、MQTT 命令号和设备自身流水。它们需要建立映射,才能回答“哪次支付触发了哪台设备的哪次动作”。
推荐的状态边界是:
| 层次 | 示例状态 | 说明 |
|---|---|---|
| 业务订单 | 待资格、已授权、执行中、成功、失败、退款 | 面向用户和财务 |
| 设备任务 | 待下发、已发布、已接收、成功、失败、未知 | 面向设备控制与排障 |
| 设备状态 | 在线、离线、缺垫、机械故障 | 面向运营,不直接等同于订单状态 |
| 耗材库存 | 当前余量、补充、消耗、人工校正 | 面向库存核对和补货 |
设备回执可能重复、乱序或延迟。处理时应检查命令号和当前状态,只允许合法状态迁移;不能因为旧失败回执晚到,就把已经成功的订单改回失败。
数据与基础设施
MySQL
MySQL 保存用户、代理、设备、订单、渠道请求、命令、库存、维修、收益和提现等业务事实。支付确认、设备成功、库存扣减和收益分配之间需要明确的事务或补偿关系。
Redis
Redis 用于登录会话、短信校验、分布式锁、短期任务状态与实时信息。对于“同一订单只下发一次”和“同一回执只结算一次”,应同时使用数据库唯一约束,避免缓存过期后再次执行。
外部服务
- EasyWeChat 处理网页授权和公众号能力;
- 支付与任务渠道提供领取资格;
- OSS 保存图片、二维码和运营素材;
- MQTT 传递设备命令与状态;
- 日志服务记录回调和设备异常。
所有密钥、Broker 凭据和第三方 Token 都应由部署环境注入。H5 构建产物只能包含公开配置,日志也必须过滤敏感字段。
部署与故障域
| 运行单元 | 故障表现 | 系统应如何降级 |
|---|---|---|
| H5 静态站 | 用户无法进入页面 | 不影响既有设备状态和异步回调 |
| ThinkPHP API | 无法创建订单或查询结果 | 停止新订单,继续接收可恢复回调或进入队列 |
| MySQL | 事实无法可靠写入 | 禁止下发新出垫命令,避免无单执行 |
| Redis | 会话、锁或实时状态失效 | 对关键操作回退数据库校验,不允许重复执行 |
| MQTT | 命令或回执中断 | 订单保持确认中,设备自动重连并补传 |
| 支付或任务渠道 | 资格结果延迟 | 保留待确认状态,主动查询和定时对账 |
| 设备 | 离线、缺垫或机械失败 | 阻止新任务,触发补货或维修流程 |
当前架构债务与改进顺序
- 统一订单状态机:免费、支付和不同任务渠道最终进入同一授权与设备执行流程;
- 拆分渠道适配器:各渠道只负责请求、验签和结果转换,不直接修改库存与收益;
- 建立设备命令账本:订单、命令、回执和重试次数完整关联;
- 完善耗材流水:补垫、成功出垫、退款补偿与人工修正全部可追溯;
- 异步化统计与收益:设备回执先形成事实,再由幂等任务分配收益和汇总报表;
- 补齐外部组件文档:记录小程序端、Broker、设备固件的版本和接口契约;
- 升级运行基线:评估 PHP 7.1、Vue 2 和旧版依赖的安全更新,分阶段迁移。
一次免费领取或购买如何进入统一设备任务,可继续阅读领垫与设备执行流程。