feat: 公共表更名 common/member 前缀 + 插件命令自动加载 + 版本 1.1.1
- 18 张公共表更名(addon/attachment/configure/links/spider_log/spider_stat/sms/notice/ad/task/prop/medal/help/card -> common_*,member_wallets->member_wallet,score_rule/score_log -> member_*,addon_config->common_addonconf),模型全部对齐新表名,Db 直引用清零 - Attachment 模型补 表名绑定,修复富文本上传查 wxapp_attachment 1146 隐患 - install.sql + 迁移 SQL:backend_admin/backend_role delete_at 默认 0,修复软删除(NULL != 0)误过滤导致后台菜单为空 - AppService::boot() 支持插件 info.php 声明 commands 自动注册插件命令(psr-4 自动加载,坏类名自动跳过) - 各插件(haonav/mqttbroker/wxchat/articles/blog/forum 等)字段与配置同步调整 - 框架版本 1.1.0 -> 1.1.1
This commit is contained in:
@@ -0,0 +1,597 @@
|
||||
{
|
||||
"openapi": "3.0.3",
|
||||
"info": {
|
||||
"title": "YwxApp 标准 App 接口 v1",
|
||||
"description": "YwxApp App/小程序/第三方客户端标准接口。\n\n统一响应:{\"code\":0,\"msg\":\"success\",\"data\":{},\"timestamp\":1765900000}\n- code=0 成功;code=1 业务失败;code=401 未登录/鉴权失败\n- 业务 code 与 HTTP 状态码解耦(未登录时 HTTP 状态也为 401)\n- 需登录接口在 Header 携带 Authorization: Bearer <access_token>\n- 登录类接口 data 内含 access_token / refresh_token / expires_in;响应顶层也回写 token 字段",
|
||||
"version": "1.0.0"
|
||||
},
|
||||
"servers": [
|
||||
{ "url": "http://localhost/api/v1", "description": "本地开发" }
|
||||
],
|
||||
"components": {
|
||||
"securitySchemes": {
|
||||
"bearerAuth": {
|
||||
"type": "http",
|
||||
"scheme": "bearer",
|
||||
"bearerFormat": "JWT"
|
||||
}
|
||||
},
|
||||
"schemas": {
|
||||
"ApiResponse": {
|
||||
"type": "object",
|
||||
"required": ["code", "msg", "timestamp"],
|
||||
"properties": {
|
||||
"code": { "type": "integer", "description": "0=成功 1=业务失败 401=未登录", "example": 0 },
|
||||
"msg": { "type": "string", "description": "提示信息", "example": "success" },
|
||||
"data": { "type": "object", "nullable": true, "description": "业务数据" },
|
||||
"timestamp": { "type": "integer", "description": "服务器时间戳(秒)", "example": 1765900000 }
|
||||
}
|
||||
},
|
||||
"LoginData": {
|
||||
"type": "object",
|
||||
"properties": {
|
||||
"uid": { "type": "integer", "example": 1 },
|
||||
"account": { "type": "string", "example": "testuser" },
|
||||
"nickname": { "type": "string", "example": "测试用户" },
|
||||
"mobile": { "type": "string", "example": "" },
|
||||
"email": { "type": "string", "example": "" },
|
||||
"avatar": { "type": "string", "example": "" },
|
||||
"status": { "type": "integer", "example": 1 },
|
||||
"access_token": { "type": "string", "example": "eyJ0eXAiOiJKV1Q..." },
|
||||
"refresh_token": { "type": "string", "example": "def50200..." },
|
||||
"expires_in": { "type": "integer", "example": 3600 },
|
||||
"token_type": { "type": "string", "example": "Bearer" }
|
||||
}
|
||||
},
|
||||
"ProfileData": {
|
||||
"type": "object",
|
||||
"properties": {
|
||||
"uid": { "type": "integer", "example": 1 },
|
||||
"account": { "type": "string", "example": "testuser" },
|
||||
"nickname": { "type": "string", "example": "测试用户" },
|
||||
"mobile": { "type": "string", "example": "" },
|
||||
"email": { "type": "string", "example": "" },
|
||||
"avatar": { "type": "string", "example": "" },
|
||||
"status": { "type": "integer", "example": 1 },
|
||||
"status_text": { "type": "string", "example": "正常" },
|
||||
"last_login": { "type": "string", "example": "2026-08-17 10:00:00" }
|
||||
}
|
||||
}
|
||||
}
|
||||
},
|
||||
"security": [{ "bearerAuth": [] }],
|
||||
"paths": {
|
||||
"/common/init": {
|
||||
"get": {
|
||||
"tags": ["Common"],
|
||||
"summary": "启动初始化",
|
||||
"description": "App 冷启动首屏调用,返回站点信息/注册方式/版本。公开。",
|
||||
"security": [],
|
||||
"responses": {
|
||||
"200": {
|
||||
"description": "成功",
|
||||
"content": {
|
||||
"application/json": {
|
||||
"schema": { "$ref": "#/components/schemas/ApiResponse" },
|
||||
"example": {
|
||||
"code": 0, "msg": "success",
|
||||
"data": { "site": {}, "register_type": "all", "version": "1.0.0" },
|
||||
"timestamp": 1765900000
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
},
|
||||
"/common/config": {
|
||||
"get": {
|
||||
"tags": ["Common"],
|
||||
"summary": "站点配置",
|
||||
"security": [],
|
||||
"responses": {
|
||||
"200": {
|
||||
"description": "成功",
|
||||
"content": {
|
||||
"application/json": {
|
||||
"schema": { "$ref": "#/components/schemas/ApiResponse" },
|
||||
"example": { "code": 0, "msg": "success", "data": { "site": {} }, "timestamp": 1765900000 }
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
},
|
||||
"/common/upload": {
|
||||
"post": {
|
||||
"tags": ["Common"],
|
||||
"summary": "文件上传(需登录)",
|
||||
"requestBody": {
|
||||
"content": {
|
||||
"multipart/form-data": {
|
||||
"schema": {
|
||||
"type": "object",
|
||||
"properties": { "file": { "type": "string", "format": "binary" } }
|
||||
}
|
||||
}
|
||||
}
|
||||
},
|
||||
"responses": {
|
||||
"200": {
|
||||
"description": "成功",
|
||||
"content": {
|
||||
"application/json": {
|
||||
"schema": { "$ref": "#/components/schemas/ApiResponse" },
|
||||
"example": {
|
||||
"code": 0, "msg": "上传成功",
|
||||
"data": { "url": "/storage/uploads/xxx.png", "path": "uploads/xxx.png" },
|
||||
"timestamp": 1765900000
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
},
|
||||
"/user/register": {
|
||||
"post": {
|
||||
"tags": ["User"],
|
||||
"summary": "注册",
|
||||
"security": [],
|
||||
"requestBody": {
|
||||
"required": true,
|
||||
"content": {
|
||||
"application/x-www-form-urlencoded": {
|
||||
"schema": {
|
||||
"type": "object",
|
||||
"required": ["account", "password"],
|
||||
"properties": {
|
||||
"account": { "type": "string", "example": "testuser" },
|
||||
"password": { "type": "string", "example": "123456", "description": "至少6位" },
|
||||
"nickname": { "type": "string", "example": "测试用户" },
|
||||
"mobile": { "type": "string", "example": "13800138000" },
|
||||
"email": { "type": "string", "example": "user@example.com" },
|
||||
"captcha": { "type": "string", "example": "1234", "description": "手机号注册时必填" }
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
},
|
||||
"responses": {
|
||||
"200": {
|
||||
"description": "注册成功并签发 token",
|
||||
"content": {
|
||||
"application/json": {
|
||||
"schema": { "$ref": "#/components/schemas/ApiResponse" },
|
||||
"example": {
|
||||
"code": 0, "msg": "注册成功",
|
||||
"data": { "uid": 1, "account": "testuser", "access_token": "eyJ...", "refresh_token": "def...", "expires_in": 3600, "token_type": "Bearer" },
|
||||
"access_token": "eyJ...", "access_expired": 3600, "refresh_token": "def...", "refresh_expired": 86400,
|
||||
"timestamp": 1765900000
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
},
|
||||
"/user/login": {
|
||||
"post": {
|
||||
"tags": ["User"],
|
||||
"summary": "账号密码登录",
|
||||
"security": [],
|
||||
"requestBody": {
|
||||
"required": true,
|
||||
"content": {
|
||||
"application/x-www-form-urlencoded": {
|
||||
"schema": {
|
||||
"type": "object",
|
||||
"required": ["account", "password"],
|
||||
"properties": {
|
||||
"account": { "type": "string", "example": "testuser" },
|
||||
"password": { "type": "string", "example": "123456" }
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
},
|
||||
"responses": {
|
||||
"200": {
|
||||
"description": "登录成功",
|
||||
"content": {
|
||||
"application/json": {
|
||||
"schema": { "$ref": "#/components/schemas/ApiResponse" },
|
||||
"example": {
|
||||
"code": 0, "msg": "登录成功",
|
||||
"data": { "uid": 1, "access_token": "eyJ...", "refresh_token": "def...", "expires_in": 3600 },
|
||||
"timestamp": 1765900000
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
},
|
||||
"/user/loginBySms": {
|
||||
"post": {
|
||||
"tags": ["User"],
|
||||
"summary": "短信验证码登录(未注册自动注册)",
|
||||
"security": [],
|
||||
"requestBody": {
|
||||
"required": true,
|
||||
"content": {
|
||||
"application/x-www-form-urlencoded": {
|
||||
"schema": {
|
||||
"type": "object",
|
||||
"required": ["mobile", "captcha"],
|
||||
"properties": {
|
||||
"mobile": { "type": "string", "example": "13800138000" },
|
||||
"captcha": { "type": "string", "example": "1234" }
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
},
|
||||
"responses": {
|
||||
"200": {
|
||||
"description": "成功",
|
||||
"content": {
|
||||
"application/json": {
|
||||
"schema": { "$ref": "#/components/schemas/ApiResponse" },
|
||||
"example": { "code": 0, "msg": "登录成功", "data": { "uid": 1, "access_token": "eyJ...", "refresh_token": "def..." }, "timestamp": 1765900000 }
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
},
|
||||
"/user/refresh": {
|
||||
"post": {
|
||||
"tags": ["User"],
|
||||
"summary": "刷新 access_token",
|
||||
"security": [],
|
||||
"requestBody": {
|
||||
"required": true,
|
||||
"content": {
|
||||
"application/x-www-form-urlencoded": {
|
||||
"schema": {
|
||||
"type": "object",
|
||||
"required": ["refresh_token"],
|
||||
"properties": { "refresh_token": { "type": "string", "example": "def50200..." } }
|
||||
}
|
||||
}
|
||||
}
|
||||
},
|
||||
"responses": {
|
||||
"200": {
|
||||
"description": "刷新成功",
|
||||
"content": {
|
||||
"application/json": {
|
||||
"schema": { "$ref": "#/components/schemas/ApiResponse" },
|
||||
"example": { "code": 0, "msg": "刷新成功", "data": { "access_token": "eyJ...", "refresh_token": "def...", "expires_in": 3600 }, "timestamp": 1765900000 }
|
||||
}
|
||||
}
|
||||
},
|
||||
"401": {
|
||||
"description": "refresh_token 失效",
|
||||
"content": {
|
||||
"application/json": {
|
||||
"schema": { "$ref": "#/components/schemas/ApiResponse" },
|
||||
"example": { "code": 401, "msg": "refresh_token 无效或已过期", "timestamp": 1765900000 }
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
},
|
||||
"/user/logout": {
|
||||
"post": {
|
||||
"tags": ["User"],
|
||||
"summary": "退出登录(需登录)",
|
||||
"responses": {
|
||||
"200": {
|
||||
"description": "成功",
|
||||
"content": {
|
||||
"application/json": {
|
||||
"schema": { "$ref": "#/components/schemas/ApiResponse" },
|
||||
"example": { "code": 0, "msg": "已登出", "data": [], "timestamp": 1765900000 }
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
},
|
||||
"/user/profile": {
|
||||
"get": {
|
||||
"tags": ["User"],
|
||||
"summary": "获取会员资料(需登录)",
|
||||
"responses": {
|
||||
"200": {
|
||||
"description": "成功",
|
||||
"content": {
|
||||
"application/json": {
|
||||
"schema": { "$ref": "#/components/schemas/ApiResponse" },
|
||||
"example": { "code": 0, "msg": "success", "data": { "uid": 1, "account": "testuser", "nickname": "测试", "status": 1, "status_text": "正常", "last_login": "2026-08-17 10:00:00" }, "timestamp": 1765900000 }
|
||||
}
|
||||
}
|
||||
},
|
||||
"401": {
|
||||
"description": "未登录",
|
||||
"content": {
|
||||
"application/json": {
|
||||
"schema": { "$ref": "#/components/schemas/ApiResponse" },
|
||||
"example": { "code": 401, "msg": "请先登录", "timestamp": 1765900000 }
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
},
|
||||
"/user/updateProfile": {
|
||||
"post": {
|
||||
"tags": ["User"],
|
||||
"summary": "修改资料(需登录)",
|
||||
"requestBody": {
|
||||
"content": {
|
||||
"application/x-www-form-urlencoded": {
|
||||
"schema": {
|
||||
"type": "object",
|
||||
"properties": {
|
||||
"nickname": { "type": "string", "example": "新昵称" },
|
||||
"mobile": { "type": "string", "example": "13800138000" },
|
||||
"email": { "type": "string", "example": "user@example.com" },
|
||||
"avatar": { "type": "string", "example": "" }
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
},
|
||||
"responses": {
|
||||
"200": {
|
||||
"description": "成功",
|
||||
"content": {
|
||||
"application/json": {
|
||||
"schema": { "$ref": "#/components/schemas/ApiResponse" },
|
||||
"example": { "code": 0, "msg": "保存成功", "data": { "uid": 1, "nickname": "新昵称" }, "timestamp": 1765900000 }
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
},
|
||||
"/user/changePwd": {
|
||||
"post": {
|
||||
"tags": ["User"],
|
||||
"summary": "修改密码(需登录)",
|
||||
"requestBody": {
|
||||
"required": true,
|
||||
"content": {
|
||||
"application/x-www-form-urlencoded": {
|
||||
"schema": {
|
||||
"type": "object",
|
||||
"required": ["oldpassword", "newpassword"],
|
||||
"properties": {
|
||||
"oldpassword": { "type": "string", "example": "123456" },
|
||||
"newpassword": { "type": "string", "example": "654321", "description": "至少6位" }
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
},
|
||||
"responses": {
|
||||
"200": {
|
||||
"description": "成功",
|
||||
"content": {
|
||||
"application/json": {
|
||||
"schema": { "$ref": "#/components/schemas/ApiResponse" },
|
||||
"example": { "code": 0, "msg": "密码修改成功", "data": [], "timestamp": 1765900000 }
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
},
|
||||
"/user/resetPwdBySms": {
|
||||
"post": {
|
||||
"tags": ["User"],
|
||||
"summary": "短信重置密码(免登录)",
|
||||
"security": [],
|
||||
"requestBody": {
|
||||
"required": true,
|
||||
"content": {
|
||||
"application/x-www-form-urlencoded": {
|
||||
"schema": {
|
||||
"type": "object",
|
||||
"required": ["mobile", "captcha", "newpassword"],
|
||||
"properties": {
|
||||
"mobile": { "type": "string", "example": "13800138000" },
|
||||
"captcha": { "type": "string", "example": "1234" },
|
||||
"newpassword": { "type": "string", "example": "654321" }
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
},
|
||||
"responses": {
|
||||
"200": {
|
||||
"description": "成功",
|
||||
"content": {
|
||||
"application/json": {
|
||||
"schema": { "$ref": "#/components/schemas/ApiResponse" },
|
||||
"example": { "code": 0, "msg": "密码重置成功", "data": [], "timestamp": 1765900000 }
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
},
|
||||
"/user/resetPwdByEmail": {
|
||||
"post": {
|
||||
"tags": ["User"],
|
||||
"summary": "邮箱重置密码(免登录)",
|
||||
"security": [],
|
||||
"requestBody": {
|
||||
"required": true,
|
||||
"content": {
|
||||
"application/x-www-form-urlencoded": {
|
||||
"schema": {
|
||||
"type": "object",
|
||||
"required": ["email", "captcha", "newpassword"],
|
||||
"properties": {
|
||||
"email": { "type": "string", "example": "user@example.com" },
|
||||
"captcha": { "type": "string", "example": "1234" },
|
||||
"newpassword": { "type": "string", "example": "654321" }
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
},
|
||||
"responses": {
|
||||
"200": {
|
||||
"description": "成功",
|
||||
"content": {
|
||||
"application/json": {
|
||||
"schema": { "$ref": "#/components/schemas/ApiResponse" },
|
||||
"example": { "code": 0, "msg": "密码重置成功", "data": [], "timestamp": 1765900000 }
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
},
|
||||
"/sms/send": {
|
||||
"post": {
|
||||
"tags": ["验证码"],
|
||||
"summary": "发送短信验证码",
|
||||
"security": [],
|
||||
"requestBody": {
|
||||
"required": true,
|
||||
"content": {
|
||||
"application/x-www-form-urlencoded": {
|
||||
"schema": {
|
||||
"type": "object",
|
||||
"required": ["mobile", "event"],
|
||||
"properties": {
|
||||
"mobile": { "type": "string", "example": "13800138000" },
|
||||
"event": { "type": "string", "example": "register", "description": "register/login/mobilelogin/resetpwd/changepwd/changemobile" }
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
},
|
||||
"responses": {
|
||||
"200": {
|
||||
"description": "成功",
|
||||
"content": {
|
||||
"application/json": {
|
||||
"schema": { "$ref": "#/components/schemas/ApiResponse" },
|
||||
"example": { "code": 0, "msg": "发送成功", "data": [], "timestamp": 1765900000 }
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
},
|
||||
"/sms/check": {
|
||||
"post": {
|
||||
"tags": ["验证码"],
|
||||
"summary": "校验短信验证码",
|
||||
"security": [],
|
||||
"requestBody": {
|
||||
"required": true,
|
||||
"content": {
|
||||
"application/x-www-form-urlencoded": {
|
||||
"schema": {
|
||||
"type": "object",
|
||||
"required": ["mobile", "event", "captcha"],
|
||||
"properties": {
|
||||
"mobile": { "type": "string", "example": "13800138000" },
|
||||
"event": { "type": "string", "example": "register" },
|
||||
"captcha": { "type": "string", "example": "1234" }
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
},
|
||||
"responses": {
|
||||
"200": {
|
||||
"description": "成功",
|
||||
"content": {
|
||||
"application/json": {
|
||||
"schema": { "$ref": "#/components/schemas/ApiResponse" },
|
||||
"example": { "code": 0, "msg": "成功", "data": [], "timestamp": 1765900000 }
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
},
|
||||
"/ems/send": {
|
||||
"post": {
|
||||
"tags": ["验证码"],
|
||||
"summary": "发送邮箱验证码",
|
||||
"security": [],
|
||||
"requestBody": {
|
||||
"required": true,
|
||||
"content": {
|
||||
"application/x-www-form-urlencoded": {
|
||||
"schema": {
|
||||
"type": "object",
|
||||
"required": ["email"],
|
||||
"properties": {
|
||||
"email": { "type": "string", "example": "user@example.com" },
|
||||
"event": { "type": "string", "example": "register" }
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
},
|
||||
"responses": {
|
||||
"200": {
|
||||
"description": "成功",
|
||||
"content": {
|
||||
"application/json": {
|
||||
"schema": { "$ref": "#/components/schemas/ApiResponse" },
|
||||
"example": { "code": 0, "msg": "发送成功", "data": [], "timestamp": 1765900000 }
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
},
|
||||
"/ems/check": {
|
||||
"post": {
|
||||
"tags": ["验证码"],
|
||||
"summary": "校验邮箱验证码",
|
||||
"security": [],
|
||||
"requestBody": {
|
||||
"required": true,
|
||||
"content": {
|
||||
"application/x-www-form-urlencoded": {
|
||||
"schema": {
|
||||
"type": "object",
|
||||
"required": ["email", "captcha"],
|
||||
"properties": {
|
||||
"email": { "type": "string", "example": "user@example.com" },
|
||||
"event": { "type": "string", "example": "register" },
|
||||
"captcha": { "type": "string", "example": "1234" }
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
},
|
||||
"responses": {
|
||||
"200": {
|
||||
"description": "成功",
|
||||
"content": {
|
||||
"application/json": {
|
||||
"schema": { "$ref": "#/components/schemas/ApiResponse" },
|
||||
"example": { "code": 0, "msg": "验证码正确", "data": [], "timestamp": 1765900000 }
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,209 @@
|
||||
# YwxApp 标准 App 接口 v1 测试文档
|
||||
|
||||
> 适用对象:App / 小程序 / 第三方客户端联调与测试(Apifox / Postman)
|
||||
> 基础路径:`/api/v1`(建议环境变量 `base_url = http://你的域名/api/v1`)
|
||||
> 最后更新:2026-08-17
|
||||
|
||||
---
|
||||
字段 值
|
||||
uid 88889464
|
||||
account testuser
|
||||
password Test@123456
|
||||
status 1(正常)
|
||||
gid 2(普通会员)
|
||||
|
||||
## 1. 通用约定
|
||||
|
||||
### 1.1 响应结构(统一 JSON)
|
||||
所有接口均返回以下结构(强制 JSON,不受请求类型影响):
|
||||
|
||||
```json
|
||||
{
|
||||
"code": 0,
|
||||
"msg": "success",
|
||||
"data": {},
|
||||
"timestamp": 1765900000
|
||||
}
|
||||
```
|
||||
|
||||
| 字段 | 类型 | 说明 |
|
||||
|---|---|---|
|
||||
| `code` | int | `0`=成功;`1`=业务失败;`401`=未登录/鉴权失败 |
|
||||
| `msg` | string | 提示信息 |
|
||||
| `data` | object/null | 业务数据;登录类接口含 `access_token` 等 |
|
||||
| `timestamp` | int | 服务器时间戳(秒) |
|
||||
|
||||
### 1.2 业务 code 与 HTTP 状态码
|
||||
- 业务 `code` 与 HTTP 状态码**解耦**:未登录时返回 `code=401` 且 HTTP 状态也为 `401`。
|
||||
- 业务失败时 HTTP 状态保持 `200`,仅 `code` 非 0(除 401 外)。
|
||||
|
||||
### 1.3 鉴权(Bearer Token)
|
||||
- 登录 / 注册成功后,响应 `data` 内含 `access_token`、`refresh_token`、`expires_in`。
|
||||
- 需登录接口在请求头携带:
|
||||
```
|
||||
Authorization: Bearer <access_token>
|
||||
```
|
||||
- 跨域:路由已挂载 `AllowCrossDomain` 中间件,前端联调无 CORS 问题。
|
||||
|
||||
### 1.4 接口清单一览
|
||||
| 接口 | 方法 | 鉴权 | 说明 |
|
||||
|---|---|---|---|
|
||||
| `/common/init` | GET | 否 | 启动初始化(站点/注册方式/版本) |
|
||||
| `/common/config` | GET | 否 | 站点配置 |
|
||||
| `/common/upload` | POST | 是 | 文件上传 |
|
||||
| `/user/register` | POST | 否 | 注册 |
|
||||
| `/user/login` | POST | 否 | 账号密码登录 |
|
||||
| `/user/loginBySms` | POST | 否 | 短信验证码登录(未注册自动注册) |
|
||||
| `/user/refresh` | POST | 否(refresh_token) | 刷新 access_token |
|
||||
| `/user/logout` | POST | 是 | 退出登录 |
|
||||
| `/user/profile` | GET | 是 | 获取会员资料 |
|
||||
| `/user/updateProfile` | POST | 是 | 修改资料 |
|
||||
| `/user/changePwd` | POST | 是 | 修改密码 |
|
||||
| `/user/resetPwdBySms` | POST | 否 | 短信重置密码 |
|
||||
| `/user/resetPwdByEmail` | POST | 否 | 邮箱重置密码 |
|
||||
| `/sms/send` | POST | 否 | 发送短信验证码 |
|
||||
| `/sms/check` | POST | 否 | 校验短信验证码 |
|
||||
| `/ems/send` | POST | 否 | 发送邮箱验证码 |
|
||||
| `/ems/check` | POST | 否 | 校验邮箱验证码 |
|
||||
|
||||
---
|
||||
|
||||
## 2. 接口详情
|
||||
|
||||
### 2.1 Common
|
||||
|
||||
#### GET /common/init
|
||||
启动初始化,App 冷启动首屏调用。
|
||||
- 响应示例:
|
||||
```json
|
||||
{ "code": 0, "msg": "success", "data": { "site": {...}, "register_type": "all", "version": "1.0.0" }, "timestamp": 1765900000 }
|
||||
```
|
||||
|
||||
#### GET /common/config
|
||||
站点配置(公开)。
|
||||
- 响应 `data` 结构同 `init` 中的 `site` 字段。
|
||||
|
||||
#### POST /common/upload
|
||||
文件上传(需登录),`Content-Type: multipart/form-data`,字段名 `file`。
|
||||
- 成功响应:
|
||||
```json
|
||||
{ "code": 0, "msg": "上传成功", "data": { "url": "/storage/uploads/xxx.png", "path": "uploads/xxx.png" }, "timestamp": 1765900000 }
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
### 2.2 User
|
||||
|
||||
#### POST /user/register
|
||||
注册账号。
|
||||
- 请求体(x-www-form-urlencoded):`account`(必填), `password`(必填,≥6位), `nickname`(可选), `mobile`(可选), `email`(可选), `captcha`(可选, 手机号注册时必填且需先调 `/sms/send`)
|
||||
- 成功响应(自动签发 token):
|
||||
```json
|
||||
{
|
||||
"code": 0, "msg": "注册成功", "timestamp": 1765900000,
|
||||
"data": { "uid": 1, "account": "testuser", "nickname": "测试", "access_token": "...", "refresh_token": "...", "expires_in": 3600, "token_type": "Bearer" },
|
||||
"access_token": "...", "access_expired": 3600, "refresh_token": "...", "refresh_expired": 86400
|
||||
}
|
||||
```
|
||||
> 说明:token 同时出现在 `data` 内与响应顶层(供不同客户端习惯取用)。
|
||||
|
||||
#### POST /user/login
|
||||
账号密码登录。
|
||||
- 请求体:`account`(必填), `password`(必填)
|
||||
- 响应结构同 `register`。
|
||||
|
||||
#### POST /user/loginBySms
|
||||
短信验证码登录;手机号未注册则自动注册。
|
||||
- 请求体:`mobile`(必填), `captcha`(必填)
|
||||
- 响应结构同 `register`,自动注册时初始密码为随机值(仅短信登录可用)。
|
||||
|
||||
#### POST /user/refresh
|
||||
使用 refresh_token 换取新 access_token。
|
||||
- 请求体:`refresh_token`(必填)
|
||||
- 成功响应:
|
||||
```json
|
||||
{ "code": 0, "msg": "刷新成功", "data": { "access_token": "...", "refresh_token": "...", "expires_in": 3600, "token_type": "Bearer" }, "timestamp": 1765900000 }
|
||||
```
|
||||
- 失败(refresh_token 无效/过期):`code=401`,HTTP 401。
|
||||
|
||||
#### POST /user/logout
|
||||
退出登录(需登录)。
|
||||
- 响应:`{ "code": 0, "msg": "已登出", "data": [], "timestamp": 1765900000 }`
|
||||
|
||||
#### GET /user/profile
|
||||
获取当前会员资料(需登录,Header 带 `Authorization: Bearer <token>`)。
|
||||
- 响应 `data` 字段(password/delete_at 已隐藏,附加 status_text/last_login):
|
||||
```json
|
||||
{
|
||||
"code": 0, "msg": "success",
|
||||
"data": { "uid": 1, "account": "testuser", "nickname": "测试", "mobile": "", "email": "", "avatar": "", "status": 1, "status_text": "正常", "last_login": "...", "create_at": 1765900000 },
|
||||
"timestamp": 1765900000
|
||||
}
|
||||
```
|
||||
|
||||
#### POST /user/updateProfile
|
||||
修改资料(需登录)。
|
||||
- 请求体(均可选):`nickname`, `mobile`, `email`, `avatar`
|
||||
- 响应 `data` 为更新后的会员数组。
|
||||
|
||||
#### POST /user/changePwd
|
||||
修改密码(需登录)。
|
||||
- 请求体:`oldpassword`(必填), `newpassword`(必填,≥6位)
|
||||
- 错误示例:`{ "code": 1, "msg": "原密码错误", "timestamp": 1765900000 }`
|
||||
|
||||
#### POST /user/resetPwdBySms
|
||||
短信重置密码(免登录)。
|
||||
- 请求体:`mobile`(必填), `captcha`(必填), `newpassword`(必填,≥6位)
|
||||
|
||||
#### POST /user/resetPwdByEmail
|
||||
邮箱重置密码(免登录)。
|
||||
- 请求体:`email`(必填), `captcha`(必填), `newpassword`(必填,≥6位)
|
||||
|
||||
---
|
||||
|
||||
### 2.3 验证码
|
||||
|
||||
#### POST /sms/send
|
||||
发送短信验证码。
|
||||
- 请求体:`mobile`(必填), `event`(必填, 如 register/login/mobilelogin/resetpwd/changepwd/changemobile)
|
||||
- 频率限制:同手机号 60 秒内不可重复;同 IP 1 小时上限 5 条。
|
||||
|
||||
#### POST /sms/check
|
||||
校验短信验证码。
|
||||
- 请求体:`mobile`(必填), `event`(必填), `captcha`(必填)
|
||||
|
||||
#### POST /ems/send
|
||||
发送邮箱验证码。请求体:`email`(必填), `event`(可选, 默认 register)。
|
||||
|
||||
#### POST /ems/check
|
||||
校验邮箱验证码。请求体:`email`(必填), `event`(可选), `captcha`(必填)。
|
||||
|
||||
---
|
||||
|
||||
## 3. Apifox / Postman 联调步骤
|
||||
|
||||
1. 导入集合文件 `docs/postman/ywxapp-api-v1.postman_collection.json`(Postman 直接导入;Apifox 选择「导入 → Postman 格式」)。
|
||||
2. 设置环境/变量 `base_url` 为你的本地域名,例如 `http://localhost/api/v1`。
|
||||
3. 先调试公开接口 `GET /common/init`,确认返回 JSON(非 HTML)即链路通。
|
||||
4. 调 `POST /user/login`(或先 `register`),登录成功后在 Tests 脚本里自动把 `access_token` 写入变量 `token`。
|
||||
5. 之后调 `/user/profile` 等需登录接口,自动带 `Authorization: Bearer {{token}}`。
|
||||
6. 故意不带 token 调 `/user/profile`,应得 `code=401` + HTTP 401。
|
||||
|
||||
### 排错
|
||||
- **全部 404**:清除路由缓存 `runtime/route_list.php` 后重试(TP 缓存机制)。
|
||||
- **返回 HTML 而非 JSON**:确认路径为小写 `/api/v1/...`,且域名正确(非后台 admin 域)。
|
||||
- **401 但 token 有效**:检查 token 是否过期,`/user/refresh` 用 `refresh_token` 换新;注意 access_token 默认有效期见 `expires_in`。
|
||||
|
||||
---
|
||||
|
||||
## 4. 测试 Checklist(建议用例)
|
||||
- [ ] init / config 公开可访问且返回 JSON
|
||||
- [ ] register 正常注册并拿到 token
|
||||
- [ ] register 重复账号 → `code=1` 提示「该账号已被注册」
|
||||
- [ ] login 密码错误 → `code=1` 提示「密码错误」
|
||||
- [ ] login 成功后 profile 返回会员资料
|
||||
- [ ] profile 不带 token → `code=401` HTTP 401
|
||||
- [ ] refresh 用 refresh_token 换发新 token 成功
|
||||
- [ ] refresh 用错误 token → `code=401`
|
||||
- [ ] changePwd 原密码错误 → `code=1`
|
||||
- [ ] logout 成功 → `code=0`
|
||||
Reference in New Issue
Block a user