From 30e5a6bed0bda7f668eab93be9f4673eca00e54f Mon Sep 17 00:00:00 2001 From: wangrui233 Date: Sun, 25 Oct 2026 20:34:52 +0800 Subject: [PATCH] md --- .codebuddy/docs/{API.md => admin-api.md} | 195 ++++++----------------- .codebuddy/docs/miniapp-api.md | 137 ++++++++++++++++ 2 files changed, 190 insertions(+), 142 deletions(-) rename .codebuddy/docs/{API.md => admin-api.md} (50%) create mode 100644 .codebuddy/docs/miniapp-api.md diff --git a/.codebuddy/docs/API.md b/.codebuddy/docs/admin-api.md similarity index 50% rename from .codebuddy/docs/API.md rename to .codebuddy/docs/admin-api.md index 1e5292f..fea1690 100644 --- a/.codebuddy/docs/API.md +++ b/.codebuddy/docs/admin-api.md @@ -1,16 +1,14 @@ -# portal-mini-go 接口文档 +# portal-mini-go 后台管理接口文档 -> 基于 Go + gin 的中后台/门户后端服务。本文档描述当前已实现的 HTTP 接口、鉴权方式、统一响应结构、错误码与数据模型。 +> 基于 Go + gin 的中后台管理后端服务。本文档描述**后台管理(`/api/admin`)**相关接口。小程序端接口见 `miniapp-api.md`。 ## 1. 概述 -- **基础路径**:`/` +- **基础路径**:`/api/admin` - **服务地址**:由 `configs/config.yaml` 中 `server.port` 决定(默认 `8080`),例如 `http://localhost:8080`。 -- **统一响应**:所有接口均返回 `HTTP 200`,业务结果通过响应体中的 `code` 字段判断(见 §3)。 -- **路由分层**: - - `/api/ma`:小程序端接口,通过请求头 `X-App-ID` 鉴权(校验小程序是否被纳管且启用)。 - - `/api/admin`:后台管理接口,通过 `Authorization: Bearer ` 鉴权。 - - `/healthz`:健康检查,无需鉴权。 +- **统一响应**:所有接口均返回 `HTTP 200`,业务结果通过响应体中的 `code` 字段判断(见 §2.4)。 +- **鉴权方式**:后台接口需在请求头携带 `Authorization: Bearer `,由 `AdminAuth` 中间件校验(登录接口除外)。 +- **全局接口**:`GET /healthz` 为健康检查,无需鉴权,返回 `{"code":0,"msg":"ok","data":{"status":"ok"}}`。 ## 2. 公共约定 @@ -19,8 +17,7 @@ | Header | 必填 | 说明 | | --- | --- | --- | | `Content-Type` | 是(POST/PUT) | 固定为 `application/json`。 | -| `X-App-ID` | 是(小程序接口) | 微信小程序的 AppID,标识调用方小程序身份。 | -| `Authorization` | 是(后台接口) | 后台登录后下发的 JWT,格式 `Bearer `。 | +| `Authorization` | 是(登录除外) | 后台登录后下发的 JWT,格式 `Bearer `。 | ### 2.2 统一响应结构 @@ -34,21 +31,19 @@ | 字段 | 类型 | 说明 | | --- | --- | --- | -| `code` | int | 业务码。`0` 表示成功;非 `0` 表示失败(见 §3 错误码)。 | +| `code` | int | 业务码。`0` 表示成功;非 `0` 表示失败(见 §2.4)。 | | `msg` | string | 结果描述。`0` 时为 `ok`,失败时为人可读信息。 | | `data` | object/null | 业务数据,成功时有内容,失败时通常省略。 | -> 约定:错误统一由 `ErrorHandler` 中间件转换,handler 内不直接散落 `c.JSON` 处理错误。 - ### 2.3 鉴权中间件 -| 分组 | 中间件 | 校验逻辑 | -| --- | --- | --- | -| `/api/ma` | `MiniAppAuth` | 校验请求头 `X-App-ID` 对应一个「已启用且未删除」的被纳管小程序;通过后将 `app_id` 与小程序主键 `mini_id` 注入上下文。 | -| `/api/admin` | `AdminAuth` | 校验 `Authorization: Bearer `(HS256)。校验通过后将 `admin_id` 注入上下文。 | -| 全局 | `Recovery` / `Trace` / `ErrorHandler` | panic 恢复、trace_id 注入、错误统一转换。 | +| 中间件 | 校验逻辑 | +| --- | --- | +| `AdminAuth` | 校验 `Authorization: Bearer `(HS256)。校验通过后将 `admin_id` 注入上下文;登录接口 `POST /api/admin/login` 不挂载此中间件。 | -## 3. 错误码 +> 全局还挂载 `Recovery`(panic 恢复)、`Trace`(注入 trace_id)、`ErrorHandler`(统一错误转换)。错误由中间件转换,handler 内不直接散落 `c.JSON` 处理错误。 + +### 2.4 错误码 | 业务码 | 常量 | 含义 | | --- | --- | --- | @@ -56,95 +51,16 @@ | `40000` | `ErrBadRequest` | 请求参数错误 / 非法输入(`ext` 非合法 JSON 等) | | `40100` | `ErrUnauthorized` | 未认证 / 登录失败 / token 无效或过期 | | `40300` | `ErrForbidden` | 禁止访问 | -| `40400` | `ErrNotFound` | 资源不存在 / 小程序未注册 | -| `50000` | `ErrServer` | 服务内部错误(含微信调用、会话写入、token 签发等) | +| `40400` | `ErrNotFound` | 资源不存在(如小程序 ID 不存在) | +| `50000` | `ErrServer` | 服务内部错误(含 token 签发等) | > 非 `BizError` 的未知错误一律归为 `50000`。 -## 4. 接口列表 +## 3. 接口列表 -### 4.1 健康检查 +### 3.1 `POST /api/admin/login` -#### `GET /healthz` - -无需鉴权。 - -**响应示例** - -```json -{ "code": 0, "msg": "ok", "data": { "status": "ok" } } -``` - ---- - -### 4.2 小程序接口(前缀 `/api/ma`) - -所有接口需在请求头携带 `X-App-ID`(已启用且被纳管的小程序)。当前示例实现为 `app1`,后续小程序按相同结构扩展。 - -#### `POST /api/ma/login` - -小程序登录:通过微信 `code2session` 换取 `openid`/`unionid`,落库用户并向客户端下发会话 token。 - -**请求头** - -``` -X-App-ID: <微信小程序 AppID> -``` - -**请求体** - -```json -{ - "code": "081abc..." // 必填,微信登录 code -} -``` - -| 字段 | 类型 | 必填 | 说明 | -| --- | --- | --- | --- | -| `code` | string | 是 | 小程序 `wx.login` 获取的临时登录 code。 | - -**响应** - -```json -{ - "code": 0, - "msg": "ok", - "data": { - "token": "a1b2c3...48位hex字符串", - "user": { - "id": 1, - "mini_id": 3, - "openid": "oABC...", - "union_id": "oXYZ...", - "nickname": "", - "avatar": "", - "created_at": "2026-10-25T10:00:00Z", - "updated_at": "2026-10-25T10:00:00Z" - } - } -} -``` - -> `token` 为 `24` 字节随机值的 hex 编码(48 字符),对应会话在 Redis/内存存储中保留 `7` 天。后续小程序业务接口应携带该 token 完成用户身份识别。 - -**curl 示例** - -```bash -curl -X POST http://localhost:8080/api/ma/login \ - -H "Content-Type: application/json" \ - -H "X-App-ID: wx1234567890" \ - -d '{"code":"081abc..."}' -``` - ---- - -### 4.3 后台管理接口(前缀 `/api/admin`) - -所有接口需在请求头携带 `Authorization: Bearer `。 - -#### `POST /api/admin/login` - -后台管理员登录,签发 JWT。 +后台管理员登录,签发 JWT。无需 `Authorization` 头。 **请求体** @@ -174,20 +90,24 @@ curl -X POST http://localhost:8080/api/admin/login \ -d '{"username":"admin","password":"admin123"}' ``` -#### `GET /api/admin/info` +### 3.2 `GET /api/admin/info` 受保护接口示例,需有效 JWT,返回当前管理员 ID。 +**请求头**:`Authorization: Bearer ` + **响应** ```json { "code": 0, "msg": "ok", "data": { "admin_id": "1" } } ``` -#### `POST /api/admin/miniapps` +### 3.3 `POST /api/admin/miniapps` 新建被纳管小程序。 +**请求头**:`Authorization: Bearer ` + **请求体** ```json @@ -206,16 +126,18 @@ curl -X POST http://localhost:8080/api/admin/login \ | `name` | string | 是 | 小程序名称。 | | `description` | string | 否 | 描述。 | | `app_id` | string | 是 | 微信 AppID,全局唯一。 | -| `app_secret` | string | 是 | 微信 AppSecret(不会在响应中返回)。 | +| `app_secret` | string | 是 | 微信 AppSecret(**不会在响应中返回**)。 | | `status` | int8 | 否 | 状态:`0` 停用,`1` 启用。缺省为 `1`。 | | `ext` | string | 否 | 扩展字段,必须为合法 JSON 字符串(允许空串)。 | -**响应**:返回创建后的 `MiniProgram` 对象(见 §5.1),`app_secret` 字段不返回。 +**响应**:返回创建后的 `MiniProgram` 对象(见 §4.1),`app_secret` 字段不返回。 -#### `PUT /api/admin/miniapps/:id` +### 3.4 `PUT /api/admin/miniapps/:id` 按 ID 局部更新小程序。 +**请求头**:`Authorization: Bearer ` + **路径参数** | 参数 | 类型 | 说明 | @@ -238,18 +160,22 @@ curl -X POST http://localhost:8080/api/admin/login \ **响应**:返回更新后的 `MiniProgram` 对象。 -#### `GET /api/admin/miniapps/:id` +### 3.5 `GET /api/admin/miniapps/:id` 查询单个小程序。 +**请求头**:`Authorization: Bearer ` + **路径参数**:`id`(uint64)。 **响应**:返回 `MiniProgram` 对象;不存在返回 `40400`。 -#### `GET /api/admin/miniapps` +### 3.6 `GET /api/admin/miniapps` 分页列表查询小程序。 +**请求头**:`Authorization: Bearer ` + **查询参数** | 参数 | 类型 | 默认值 | 说明 | @@ -265,7 +191,7 @@ curl -X POST http://localhost:8080/api/admin/login \ "code": 0, "msg": "ok", "data": { - "list": [ { "id": 1, "name": "示例小程序", "app_id": "wx123...", "status": 1, "...": "..." } ], + "list": [ { "id": 1, "name": "示例小程序", "app_id": "wx123...", "status": 1 } ], "total": 1, "page": 1, "size": 20 @@ -273,10 +199,19 @@ curl -X POST http://localhost:8080/api/admin/login \ } ``` -#### `DELETE /api/admin/miniapps/:id` +**curl 示例** + +```bash +curl "http://localhost:8080/api/admin/miniapps?status=1&page=1&size=20" \ + -H "Authorization: Bearer " +``` + +### 3.7 `DELETE /api/admin/miniapps/:id` 软删除小程序(置 `deleted_at`)。 +**请求头**:`Authorization: Bearer ` + **路径参数**:`id`(uint64)。 **响应** @@ -285,16 +220,9 @@ curl -X POST http://localhost:8080/api/admin/login \ { "code": 0, "msg": "ok" } ``` -**curl 示例(列表)** +## 4. 数据模型 -```bash -curl "http://localhost:8080/api/admin/miniapps?status=1&page=1&size=20" \ - -H "Authorization: Bearer " -``` - -## 5. 数据模型 - -### 5.1 MiniProgram(被纳管小程序) +### 4.1 MiniProgram(被纳管小程序) | 字段 | 类型 | JSON | 说明 | | --- | --- | --- | --- | @@ -308,22 +236,7 @@ curl "http://localhost:8080/api/admin/miniapps?status=1&page=1&size=20" \ | `CreatedAt` | time | `created_at` | 创建时间。 | | `UpdatedAt` | time | `updated_at` | 更新时间。 | -### 5.2 User(小程序用户) - -| 字段 | 类型 | JSON | 说明 | -| --- | --- | --- | --- | -| `ID` | uint64 | `id` | 主键,自增。 | -| `MiniID` | uint64 | `mini_id` | 所属小程序主键(关联 `mini_programs.id`)。 | -| `OpenID` | string | `openid` | 微信 openid。 | -| `UnionID` | string | `union_id` | 微信 unionid(可为空)。 | -| `Nickname` | string | `nickname` | 昵称。 | -| `Avatar` | string | `avatar` | 头像 URL。 | -| `CreatedAt` | time | `created_at` | 创建时间。 | -| `UpdatedAt` | time | `updated_at` | 更新时间。 | - -> 用户由 `(mini_id, open_id)` 唯一标识。 - -## 6. 配置说明 +## 5. 配置说明(后台相关) 配置由 `configs/config.yaml` + 环境变量(支持 `${ENV}` 占位符)加载。敏感信息(DB 密码、JWT Secret)应通过环境变量注入,禁止硬编码。 @@ -335,9 +248,7 @@ curl "http://localhost:8080/api/admin/miniapps?status=1&page=1&size=20" \ | `admin.jwt_secret` | 后台 JWT 签名密钥。 | | `admin.token_ttl` | 后台 JWT 有效期(如 `24h`)。 | -## 7. 备注与后续扩展 +## 6. 备注 -- **小程序会话**:`/api/ma/login` 返回的 token 为会话凭证,当前示例在 `/api/ma` 下仅实现 `login`;业务接口应在路由中增加基于该 token 的用户身份中间件后再登记。 -- **后台账号**:`/api/admin/login` 当前为固定示例账号,生产环境需接入数据库与密码哈希校验。 -- **会话存储**:默认 `MemoryStore`(单实例),多实例部署应替换为 Redis 实现(复用 `session.Store` 接口)。 -- **多小程序**:新增 `app2`..`app10` 时,按 `internal/handler/miniapp/app1`、`internal/service/miniapp/app1` 的目录结构各自建包,在 `router.New` 中注册即可,互不耦合。 +- **后台账号**:`POST /api/admin/login` 当前为固定示例账号,生产环境需接入数据库与密码哈希校验。 +- **小程序管理**:本分组下的 `miniapps` 接口用于纳管微信小程序配置(增删改查),是小程序端 `X-App-ID` 鉴权的数据来源。新增/修改这些接口时须同步更新本文档。 diff --git a/.codebuddy/docs/miniapp-api.md b/.codebuddy/docs/miniapp-api.md new file mode 100644 index 0000000..83cfb8b --- /dev/null +++ b/.codebuddy/docs/miniapp-api.md @@ -0,0 +1,137 @@ +# portal-mini-go 小程序端接口文档 + +> 基于 Go + gin 的微信小程序后端服务。本文档描述**小程序端(`/api/ma`)**相关接口。后台管理接口见 `admin-api.md`。 + +## 1. 概述 + +- **基础路径**:`/api/ma` +- **服务地址**:由 `configs/config.yaml` 中 `server.port` 决定(默认 `8080`),例如 `http://localhost:8080`。 +- **统一响应**:所有接口均返回 `HTTP 200`,业务结果通过响应体中的 `code` 字段判断(见 §2.4)。 +- **鉴权方式**:小程序端所有接口需在请求头携带 `X-App-ID`,由 `MiniAppAuth` 中间件校验该小程序是否被纳管且启用。 +- **全局接口**:`GET /healthz` 为健康检查,无需鉴权,返回 `{"code":0,"msg":"ok","data":{"status":"ok"}}`。 + +## 2. 公共约定 + +### 2.1 请求头 + +| Header | 必填 | 说明 | +| --- | --- | --- | +| `Content-Type` | 是(POST/PUT) | 固定为 `application/json`。 | +| `X-App-ID` | 是 | 微信小程序的 AppID,标识调用方小程序身份;必须对应一个「已启用且未删除」的被纳管小程序。 | + +### 2.2 统一响应结构 + +```json +{ + "code": 0, + "msg": "ok", + "data": { } +} +``` + +| 字段 | 类型 | 说明 | +| --- | --- | --- | +| `code` | int | 业务码。`0` 表示成功;非 `0` 表示失败(见 §2.4)。 | +| `msg` | string | 结果描述。`0` 时为 `ok`,失败时为人可读信息。 | +| `data` | object/null | 业务数据,成功时有内容,失败时通常省略。 | + +### 2.3 鉴权中间件 + +| 中间件 | 校验逻辑 | +| --- | --- | +| `MiniAppAuth` | 校验请求头 `X-App-ID` 对应一个「已启用且未删除」的被纳管小程序;通过后将 `app_id` 与小程序主键 `mini_id` 注入上下文,供后续 handler/service 使用。 | + +> 全局还挂载 `Recovery`(panic 恢复)、`Trace`(注入 trace_id)、`ErrorHandler`(统一错误转换)。错误由中间件转换,handler 内不直接散落 `c.JSON` 处理错误。 + +### 2.4 错误码 + +| 业务码 | 常量 | 含义 | +| --- | --- | --- | +| `0` | — | 成功 | +| `40000` | `ErrBadRequest` | 请求参数错误 / 非法输入 | +| `40100` | `ErrUnauthorized` | 未认证 / 登录失败 / token 无效或过期 | +| `40300` | `ErrForbidden` | 禁止访问 | +| `40400` | `ErrNotFound` | 资源不存在 / 小程序未注册(如 `X-App-ID` 无效) | +| `50000` | `ErrServer` | 服务内部错误(含微信调用、会话写入等) | + +> 非 `BizError` 的未知错误一律归为 `50000`。 + +## 3. 接口列表 + +### 3.1 `POST /api/ma/login` + +小程序登录:通过微信 `code2session` 换取 `openid`/`unionid`,落库用户并向客户端下发会话 token。 + +**请求头** + +``` +X-App-ID: <微信小程序 AppID> +``` + +**请求体** + +```json +{ + "code": "081abc..." // 必填,微信登录 code +} +``` + +| 字段 | 类型 | 必填 | 说明 | +| --- | --- | --- | --- | +| `code` | string | 是 | 小程序 `wx.login` 获取的临时登录 code。 | + +**响应** + +```json +{ + "code": 0, + "msg": "ok", + "data": { + "token": "a1b2c3...48位hex字符串", + "user": { + "id": 1, + "mini_id": 3, + "openid": "oABC...", + "union_id": "oXYZ...", + "nickname": "", + "avatar": "", + "created_at": "2026-10-25T10:00:00Z", + "updated_at": "2026-10-25T10:00:00Z" + } + } +} +``` + +> `token` 为 `24` 字节随机值的 hex 编码(48 字符),对应会话保留 `7` 天。后续小程序业务接口应携带该 token 完成用户身份识别(当前示例仅实现 `login`)。 + +**curl 示例** + +```bash +curl -X POST http://localhost:8080/api/ma/login \ + -H "Content-Type: application/json" \ + -H "X-App-ID: wx1234567890" \ + -d '{"code":"081abc..."}' +``` + +## 4. 数据模型 + +### 4.1 User(小程序用户) + +| 字段 | 类型 | JSON | 说明 | +| --- | --- | --- | --- | +| `ID` | uint64 | `id` | 主键,自增。 | +| `MiniID` | uint64 | `mini_id` | 所属小程序主键(关联 `mini_programs.id`)。 | +| `OpenID` | string | `openid` | 微信 openid。 | +| `UnionID` | string | `union_id` | 微信 unionid(可为空)。 | +| `Nickname` | string | `nickname` | 昵称。 | +| `Avatar` | string | `avatar` | 头像 URL。 | +| `CreatedAt` | time | `created_at` | 创建时间。 | +| `UpdatedAt` | time | `updated_at` | 更新时间。 | + +> 用户由 `(mini_id, open_id)` 唯一标识。 + +## 5. 备注与后续扩展 + +- **多小程序**:新增 `app2`..`app10` 时,按 `internal/handler/miniapp/app1`、`internal/service/miniapp/app1` 的目录结构各自建包,在 `router.New` 中注册即可,互不耦合。新增小程序后须在本文档补充其接口。 +- **会话存储**:默认 `MemoryStore`(单实例),多实例部署应替换为 Redis 实现(复用 `session.Store` 接口)。 +- **业务接口**:当前 `/api/ma` 下仅实现 `login`;新增业务接口时,应在路由中增加基于会话 token 的用户身份中间件后再登记,并同步更新本文档 §3。