10 KiB
portal-mini-go 接口文档
基于 Go + gin 的中后台/门户后端服务。本文档描述当前已实现的 HTTP 接口、鉴权方式、统一响应结构、错误码与数据模型。
1. 概述
- 基础路径:
/ - 服务地址:由
configs/config.yaml中server.port决定(默认8080),例如http://localhost:8080。 - 统一响应:所有接口均返回
HTTP 200,业务结果通过响应体中的code字段判断(见 §3)。 - 路由分层:
/api/ma:小程序端接口,通过请求头X-App-ID鉴权(校验小程序是否被纳管且启用)。/api/admin:后台管理接口,通过Authorization: Bearer <JWT>鉴权。/healthz:健康检查,无需鉴权。
2. 公共约定
2.1 请求头
| Header | 必填 | 说明 |
|---|---|---|
Content-Type |
是(POST/PUT) | 固定为 application/json。 |
X-App-ID |
是(小程序接口) | 微信小程序的 AppID,标识调用方小程序身份。 |
Authorization |
是(后台接口) | 后台登录后下发的 JWT,格式 Bearer <token>。 |
2.2 统一响应结构
{
"code": 0,
"msg": "ok",
"data": { }
}
| 字段 | 类型 | 说明 |
|---|---|---|
code |
int | 业务码。0 表示成功;非 0 表示失败(见 §3 错误码)。 |
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 <JWT>(HS256)。校验通过后将 admin_id 注入上下文。 |
| 全局 | Recovery / Trace / ErrorHandler |
panic 恢复、trace_id 注入、错误统一转换。 |
3. 错误码
| 业务码 | 常量 | 含义 |
|---|---|---|
0 |
— | 成功 |
40000 |
ErrBadRequest |
请求参数错误 / 非法输入(ext 非合法 JSON 等) |
40100 |
ErrUnauthorized |
未认证 / 登录失败 / token 无效或过期 |
40300 |
ErrForbidden |
禁止访问 |
40400 |
ErrNotFound |
资源不存在 / 小程序未注册 |
50000 |
ErrServer |
服务内部错误(含微信调用、会话写入、token 签发等) |
非
BizError的未知错误一律归为50000。
4. 接口列表
4.1 健康检查
GET /healthz
无需鉴权。
响应示例
{ "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>
请求体
{
"code": "081abc..." // 必填,微信登录 code
}
| 字段 | 类型 | 必填 | 说明 |
|---|---|---|---|
code |
string | 是 | 小程序 wx.login 获取的临时登录 code。 |
响应
{
"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 示例
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 <JWT>。
POST /api/admin/login
后台管理员登录,签发 JWT。
请求体
{
"username": "admin",
"password": "admin123"
}
| 字段 | 类型 | 必填 | 说明 |
|---|---|---|---|
username |
string | 是 | 管理员账号(当前示例固定 admin)。 |
password |
string | 是 | 密码(当前示例固定 admin123;生产应接 DB + 密码哈希)。 |
响应
{ "code": 0, "msg": "ok", "data": { "token": "<JWT>" } }
curl 示例
curl -X POST http://localhost:8080/api/admin/login \
-H "Content-Type: application/json" \
-d '{"username":"admin","password":"admin123"}'
GET /api/admin/info
受保护接口示例,需有效 JWT,返回当前管理员 ID。
响应
{ "code": 0, "msg": "ok", "data": { "admin_id": "1" } }
POST /api/admin/miniapps
新建被纳管小程序。
请求体
{
"name": "示例小程序",
"description": "用于演示",
"app_id": "wx1234567890",
"app_secret": "secret-xxxx",
"status": 1,
"ext": "{\"k\":\"v\"}"
}
| 字段 | 类型 | 必填 | 说明 |
|---|---|---|---|
name |
string | 是 | 小程序名称。 |
description |
string | 否 | 描述。 |
app_id |
string | 是 | 微信 AppID,全局唯一。 |
app_secret |
string | 是 | 微信 AppSecret(不会在响应中返回)。 |
status |
int8 | 否 | 状态:0 停用,1 启用。缺省为 1。 |
ext |
string | 否 | 扩展字段,必须为合法 JSON 字符串(允许空串)。 |
响应:返回创建后的 MiniProgram 对象(见 §5.1),app_secret 字段不返回。
PUT /api/admin/miniapps/:id
按 ID 局部更新小程序。
路径参数
| 参数 | 类型 | 说明 |
|---|---|---|
id |
uint64 | 小程序主键。 |
请求体(所有字段均为可选,仅在提供时更新;ext 若提供需为合法 JSON)
{
"name": "新名称",
"description": "新描述",
"app_secret": "new-secret",
"status": 0,
"ext": "{\"theme\":\"dark\"}"
}
字段以指针区分「未提供」与「置空」;若全部为空则不更新,直接返回原记录。
响应:返回更新后的 MiniProgram 对象。
GET /api/admin/miniapps/:id
查询单个小程序。
路径参数:id(uint64)。
响应:返回 MiniProgram 对象;不存在返回 40400。
GET /api/admin/miniapps
分页列表查询小程序。
查询参数
| 参数 | 类型 | 默认值 | 说明 |
|---|---|---|---|
status |
int8 | -1(全部) |
按状态筛选:0 停用,1 启用,-1 全部。 |
page |
int | 1 |
页码,从 1 开始。 |
size |
int | 20 |
每页条数。 |
响应
{
"code": 0,
"msg": "ok",
"data": {
"list": [ { "id": 1, "name": "示例小程序", "app_id": "wx123...", "status": 1, "...": "..." } ],
"total": 1,
"page": 1,
"size": 20
}
}
DELETE /api/admin/miniapps/:id
软删除小程序(置 deleted_at)。
路径参数:id(uint64)。
响应
{ "code": 0, "msg": "ok" }
curl 示例(列表)
curl "http://localhost:8080/api/admin/miniapps?status=1&page=1&size=20" \
-H "Authorization: Bearer <JWT>"
5. 数据模型
5.1 MiniProgram(被纳管小程序)
| 字段 | 类型 | JSON | 说明 |
|---|---|---|---|
ID |
uint64 | id |
主键,自增。 |
Name |
string | name |
名称。 |
Description |
string | description |
描述。 |
AppID |
string | app_id |
微信 AppID,全局唯一。 |
AppSecret |
string | app_secret |
不返回(json -)。 |
Status |
int8 | status |
0 停用,1 启用。 |
Ext |
string | ext |
扩展 JSON 文本。 |
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. 配置说明
配置由 configs/config.yaml + 环境变量(支持 ${ENV} 占位符)加载。敏感信息(DB 密码、JWT Secret)应通过环境变量注入,禁止硬编码。
| 配置项 | 说明 |
|---|---|
server.port / server.mode |
服务端口、运行模式(release 时 gin 进入 ReleaseMode)。 |
mysql.* |
MySQL 连接与连接池参数,拼装为 DSN。 |
logging.level / logging.format |
日志级别与格式(text/json)。 |
admin.jwt_secret |
后台 JWT 签名密钥。 |
admin.token_ttl |
后台 JWT 有效期(如 24h)。 |
7. 备注与后续扩展
- 小程序会话:
/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中注册即可,互不耦合。