一、开发原则
- 前端只负责展示与交互,最终权限和数据范围由服务端判断。
- 控制器保持轻量,业务放在 Service,数据库操作集中在 Repository 或模型层。
- 所有写操作考虑幂等、事务、并发冲突和失败回滚。
- 敏感配置只放服务端配置文件或环境变量,禁止写入 uni-app 和网页源码。
二、推荐目录职责
api/ API 入口和路由
app/Controller/ 参数接收、鉴权、响应
app/Service/ 好友、消息、群聊、推送业务
app/Repository/ 数据库查询与事务
websocket/ Workerman 长连接服务
workers/ 推送、清理、异步任务
config/ 数据库、推送、存储、授权配置
storage/ 日志、缓存、临时文件
uniapp/ 移动端与 H5
pc/ PC 网页端三、API 响应规范
{
"success": true,
"code": "OK",
"message": "操作成功",
"data": {},
"request_id": "服务端请求追踪号"
}HTTP 状态码表达网络层结果,业务 code 表达具体原因。登录失效、权限不足、参数错误、频率限制和系统错误应使用不同 code,前端不能只判断 message 文本。
四、身份认证
- 登录成功后签发短期访问令牌和可轮换的刷新令牌。
- 服务端保存设备标识、令牌版本和最后活动时间。
- 退出登录、修改密码、封禁账号时主动失效相关令牌。
- WebSocket 握手使用短期连接票据,不直接在 URL 中长期暴露登录令牌。
五、WebSocket 消息协议
{
"event": "chat.message.send",
"request_id": "01J...",
"timestamp": 1760000000,
"data": {
"conversation_id": 1001,
"client_message_id": "device-uuid-0001",
"message_type": "text",
"content": {"text": "你好"}
}
}服务端必须校验
- 连接是否已经完成身份认证。
- 当前用户是否属于会话或群组。
- 消息类型、长度和文件引用是否合法。
- client_message_id 是否已经处理,防止重试产生重复消息。
- 发送频率是否触发限流、禁言或风控。
六、消息幂等与顺序
每条消息应同时具备客户端唯一号和服务端消息 ID。数据库对“用户或设备 + 客户端消息号”建立唯一约束。服务端收到重复请求时返回第一次处理结果,不重复写入。群聊中不要依赖客户端时间排序,应使用服务端序列号或服务端创建时间。
七、数据库事务
发送消息通常涉及消息表、会话表、未读计数和推送任务。需要原子一致的写操作应放在同一事务中。对群成员数量、用户数量或库存类限制,应使用行锁或原子更新,不能先查询再无锁写入。
八、好友与群聊事件
| 事件 | 用途 |
|---|---|
| friend.request.created | 新好友申请和红点更新 |
| friend.request.accepted | 双方通讯录实时增加联系人 |
| conversation.updated | 会话摘要、置顶和未读变化 |
| group.member.joined | 群成员加入 |
| group.member.removed | 移除成员或主动退出 |
| message.read | 同步已读位置和已读状态 |
九、文件上传
- 后端校验真实 MIME、扩展名、文件头、大小和用户权限。
- 上传后使用随机文件名,禁止执行脚本的目录保存。
- 私密文件通过鉴权下载接口输出,不直接公开真实路径。
- 大文件使用分片上传时,合并接口必须校验分片归属和完整哈希。
十、离线推送
业务服务只创建推送任务,不在消息事务中同步调用第三方推送。push-worker 读取任务后按设备、平台和用户通知设置发送,并记录成功、失败原因和重试次数。
十一、增加新消息类型
- 定义稳定的 message_type 和 content JSON 结构。
- 服务端增加参数白名单和内容校验。
- 数据库保持统一消息模型,避免每种消息建立完全独立表。
- WebSocket、推送摘要、移动端、H5、PC 和历史消息渲染同时适配。
- 增加旧版本客户端的降级文案。
十二、安全要求
- SQL 使用预处理,不拼接用户输入。
- 富文本和用户昵称输出前按场景转义。
- 后台所有写操作使用 CSRF 防护和权限校验。
- 验证码、登录、搜索用户、加好友、发送消息和上传接口分别限流。
- 日志禁止记录完整密码、令牌、短信验证码和私钥。
十三、版本升级
每次版本发布应包含版本号、变更清单、完整包、覆盖升级包、数据库补丁、回滚说明和 SHA-256。升级脚本必须可重复执行,旧数据字段要保持兼容。
十四、V6.9.2 真实入口与调用关系
uni-app / H5 / PC
│ HTTPS
├──────────────► api/index.php
│ │
│ ├── Auth / ImService / MessageService
│ ├── Group / Wallet / Payment / Push
│ └── LicenseService / SystemCheck
│
│ WSS
└──────────────► websocket/server.php
│
├── realtime_events
├── message_dispatch_jobs
├── notification_jobs
└── 定时消息、备份与授权周期检查
十五、客户端请求头约定
| 请求头 | 用途 |
|---|---|
| X-Request-ID | 一次请求的唯一追踪号,便于日志定位和幂等分析。 |
| X-Client-Version | 客户端版本号,用于兼容性检查和升级提醒。 |
| X-Client-Protocol | API 协议版本,避免新旧客户端误调用不兼容接口。 |
| X-Realtime-Protocol | 实时事件协议版本。 |
| X-Client-Platform | android、ios、h5、pc 等平台标识。 |
| X-Device-ID | 设备标识,用于设备会话、推送绑定和异常登录分析。 |
十六、实时事件设计
业务写入完成后,将事件写入实时事件表,再由 WebSocket 服务投递。这样即使发送接口和长连接服务不在同一进程,也能保持统一事件来源。事件应包含接收用户、事件类型、业务数据、创建时间和过期时间。
新增事件时必须同步检查
- 事件是否只发给有权限的用户。
- 移动端、H5 和 PC 是否都支持该事件。
- 重复事件是否会造成重复红点、重复消息或重复弹窗。
- 离线后重新拉取数据时能否恢复同样结果。
- 旧版本客户端无法识别时是否有降级策略。
十七、支付与钱包开发要求
- 支付回调必须验证第三方签名,不能只相信订单号和金额。
- 同一回调重复到达时只能处理一次。
- 钱包余额变动必须保存不可变流水,禁止只修改余额字段。
- 支付成功、退款、提现和人工调整均需审计记录。
- 回调接口不依赖普通用户登录,但必须经过渠道签名和订单状态校验。
十八、发布前开发自检
- 运行 PHP 语法检查和前端构建。
- 执行数据库补丁并验证可重复执行。
- 完成单聊、群聊、好友申请、红点、撤回、已读和多端同步测试。
- 完成 WebSocket 断开、重连、离线补拉和 push-worker 重启测试。
- 验证未授权、过期、暂停、撤销和授权中心短暂不可用场景。
- 检查日志中没有密码、令牌、验证码、私钥和完整支付参数。