StockApi
StockApi 是一个面向股票数据查询与访问控制场景的 Go 单体服务。 它将公开只读数据 API、用户门户和管理员后台统一在一个项目中,目标是提供一套清晰、可运行、便于联调和演示的股票数据服务样例。
StockApi
项目概述
StockApi 是一个基于 Go 的单体服务,当前统一承载三类能力:
- 公开只读数据 API:
/api/v1/* - 用户门户:
/portal/* - 管理后台:
/portal/admin/*
项目当前定位是“内部可用的预览版系统”:
- 数据 API 已可联调和内部使用
- 用户注册、邮箱验证码、TOTP 登录、Token 申请、管理员审核已成链
- 公开接口文档由代码生成 Swagger/OpenAPI
- 门户和后台均为 SSR 页面
当前治理结论
这次项目治理后,当前口径统一为:
- 运行方式只考虑 Docker
- 配置方式只考虑环境变量
- 仓库中不再提供任何 TOML 配置文件
- 公开接口文档只覆盖
/api/v1/* - 门户与后台不进入 Swagger
- 管理员身份只来自数据库
user_account.role = 'admin' - token 明文只在创建或重置时展示一次,服务端只保存
SHA-256hash
这几条是当前项目的硬边界,不再保留旧兼容文案。
文档结构与优先级
仓库当前保留两层文档:
当前生效文档
- 当前总说明:
readme.md - 公开 API 规范:
docs/api.md
归档文档
- 阶段性需求记录:
docs/requirements.md - 历史说明快照:
docs/readme.md
阅读优先级建议如下:
- 公开接口路径、字段、参数和值域,以
docs/api.md为准 - 运行方式、环境变量、门户流程、数据库说明,以本文档为准
- 归档文档仅作为历史背景参考,不作为当前运行口径
系统组成
1. 公开数据 API
公开接口统一挂在 /api/v1 下。
当前主要数据能力包括:
- 元信息
- 健康检查
- 各核心表最新日期
- 覆盖情况
- 失败任务
- 交易日历
- 板块
- 板块列表
- 板块详情
- 板块快照
- 板块历史
- 板块成分股
- 板块成分股快照
- 板块成分股覆盖
- 股票
- 股票列表
- 股票详情
- 历史行情
- 批量历史
- 实时快照
- 涨停池
- 涨停池列表
- 单股涨停历史
- 涨停池摘要
- 因子输入
- 板块强度
- 板块持续性
- 板块效应
- 板块角色
- 个股角色
- 板块-个股联动
- 涨停事件
公开接口文档入口:
- Swagger:
/swagger/ - Swagger JSON:
/swagger/swagger.json - Apifox 在线调试文档:https://s.apifox.cn/df15e990-b0be-4140-acfd-1b20c8d685d1
2. 用户门户
当前用户侧页面包括:
/portal/register/portal/login/portal//apply
用户当前可执行的动作:
- 通过邮箱验证码注册
- 绑定 TOTP
- 使用邮箱 + TOTP 登录
- 查看自己名下的 token
- 查看 token 当前 24 小时窗口额度
- 申请新增 token
- 重置自己的 token
3. 管理后台
当前管理员侧页面包括:
/portal/admin//portal/admin/applications
管理员当前可执行的动作:
- 查看健康状态、覆盖摘要、最新日期
- 查看 token 总量、状态和当前额度
- 创建 token
- 启用 / 禁用 token
- 修改 daily limit
- 重置限流窗口
- 重置 token 明文
- 删除 token
- 审核用户 token 申请
- 审核通过后直接发放 token
公开接口边界
Swagger 覆盖范围
Swagger 只描述以下公开接口:
/api/v1/meta/*/api/v1/calendar/*/api/v1/boards*/api/v1/board-snapshots*/api/v1/board-hist/*/api/v1/board-constituents/*/api/v1/stocks*/api/v1/limit-up-pool*/api/v1/factors/*
不进入 Swagger 的路径
以下路径是站内 SSR 页面,不属于公开 API 文档:
/portal/*/portal/admin/*/apply
鉴权、账号与 Token
公开 API 鉴权
除 /api/v1/meta/health 外,其余公开接口默认要求:
Authorization: Bearer <token>
账号模型
当前统一账号表为 user_account,角色只分两级:
- 普通用户:
role = 'user' - 管理员:
role = 'admin'
登录方式统一为:
email + TOTP
当前没有密码登录。
管理员识别规则
当前管理员识别规则已经收口为:
- 只认数据库
user_account.role = 'admin'
不再使用:
ADMIN_EMAILADMIN_TOTP_SECRET_ENC
Token 规则
当前 token 规则如下:
- token 明文由服务端生成
- 服务端只保存
SHA-256hash - 创建或重置后只展示一次明文
- 重置 token 后旧明文立即失效
- 用户允许持有多个 token
当前支持的只读 scope:
read:*read:metaread:calendarread:boardsread:stocksread:limitupread:factors
Token 申请与审核
当前申请流程仍使用独立 SSR 页面:
- 用户申请页:
/apply - 管理审核页:
/portal/admin/applications
申请记录写入:
token_application
审核通过后创建实际 token,写入:
api_token
限流
当前限流实现为:
- 24 小时滑动窗口
- Redis
DB 1 ZSET记录窗口请求- key 格式:
rl:v1:token:{token_id}
当前响应头:
X-RateLimit-LimitX-RateLimit-Remaining
X-RateLimit-Reset 当前尚未实现。
数据库说明
本项目自身初始化的表
stockapi-initdb 只初始化以下 4 张权限/门户相关表:
user_accountapi_tokentoken_applicationaudit_log
表定义见:
外部依赖的业务数据表
股票和板块等业务数据不由本项目建表,而是假设已经存在于 stocks 数据库。
当前核心依赖表包括:
trade_calendarboard_dimboard_snapshot_dailyboard_hist_dailyboard_constituentboard_constituent_snapshot_dailystock_dimstock_hist_dailystock_spot_snapshotstock_zt_pool_dailysync_job_statesync_job_log
这些表的字段、枚举和值域定义,请看:
环境变量
当前项目运行只认环境变量。
模板文件:
建议先复制:
cp .env.example .env
必要环境变量
MySQL:
MYSQL_HOSTMYSQL_PORTMYSQL_USERMYSQL_PASSWORDMYSQL_DATABASE
Redis:
REDIS_HOSTREDIS_PORTREDIS_PASSWORDREDIS_DATABASE
服务自身:
DASHBOARD_HOSTDASHBOARD_PORTADMIN_SESSION_TTL_MINUTESADMIN_TOTP_MASTER_KEY
注册邮件:
RESEND_API_KEYRESEND_FROM_EMAIL
辅助项:
SYNC_INITIAL_START_DATELOG_DIR
Docker 默认口径
既然当前项目只考虑 Docker 运行,.env.example 默认采用:
MYSQL_HOST=host.docker.internalREDIS_HOST=host.docker.internalDASHBOARD_HOST=0.0.0.0
这意味着容器会直接连接宿主机上的 MySQL 与 Redis。
敏感信息原则
以下内容必须放在 .env 或外部环境变量中,不能再写回仓库配置文件:
- MySQL 密码
- Redis 密码
ADMIN_TOTP_MASTER_KEYRESEND_API_KEYRESEND_FROM_EMAIL
Docker 运行
1. 准备环境变量
cp .env.example .env
填写实际数据库、Redis、邮件和 TOTP 主密钥。
2. 初始化权限表
docker compose --profile app run --rm api /app/stockapi-initdb
这一步只会初始化:
user_accountapi_tokentoken_applicationaudit_log
3. 构建并启动
docker compose --profile app build api
docker compose --profile app up -d api
如果你明确要关闭 BuildKit,直接走普通 Docker 构建:
DOCKER_BUILDKIT=0 COMPOSE_DOCKER_CLI_BUILD=0 docker compose --profile app build api
DOCKER_BUILDKIT=0 COMPOSE_DOCKER_CLI_BUILD=0 docker compose --profile app up -d api
4. 访问入口
- 首页:http://127.0.0.1:8788/
- 用户注册:http://127.0.0.1:8788/portal/register
- 统一登录:http://127.0.0.1:8788/portal/login
- 用户门户:http://127.0.0.1:8788/portal/
- Token 申请:http://127.0.0.1:8788/apply
- 管理后台:http://127.0.0.1:8788/portal/admin/
- Swagger:http://127.0.0.1:8788/swagger/
- 健康检查:http://127.0.0.1:8788/api/v1/meta/health
典型流程
用户流程
- 打开
/portal/register - 选择邮箱服务商并发送验证码
- 完成邮箱验证后绑定 TOTP
- 打开
/portal/login登录 - 进入
/portal/ - 如需调用 API,访问
/apply提交 token 申请 - 等待管理员审核
- 审核通过后在
/portal/查看 token 属性、状态和当前额度 - 使用 Bearer Token 调用
/api/v1/*
管理员流程
- 先在数据库中将管理员邮箱标记为
user_account.role='admin' - 打开
/portal/login - 首次完成管理员 TOTP 初始化
- 登录后进入
/portal/admin/ - 在
/portal/admin/applications审核申请 - 发放 token 后,用户在门户中查看,管理员在后台继续管理额度、状态和限流
代码结构
入口命令
- 服务入口:
cmd/stockapi/main.go - 权限表初始化:
cmd/stockapi-initdb/main.go - 辅助 CLI:
cmd/stockapi-admin/main.go
应用装配
负责:
- 连接 MySQL
- 连接 Redis
- 初始化 Resend 客户端
- 装配 store / service / router
配置层
当前只负责:
- 读取
.env - 应用环境变量覆盖
- 提供运行默认值
不再负责历史文件配置或配置文件路径兼容逻辑。
平台适配层
- MySQL:
internal/platform/mysql/mysql.go - Redis:
internal/platform/redisc/redis.go - Resend:
internal/platform/resend/client.go
业务与门户服务
- 门户:
internal/service/portal/service.go - 管理员认证:
internal/service/adminauth/service.go - Token 管理:
internal/service/tokenadmin/service.go - Token 鉴权:
internal/service/tokenauth/service.go - 业务 API:
HTTP 层
- 总路由:
internal/transport/http/router.go - 首页:
internal/transport/http/handlers/home.go - 用户门户:
internal/transport/http/handlers/portal_web.go - 管理后台:
internal/transport/http/handlers/admin_web.go - 审核页:
internal/transport/http/handlers/admin_applications.go - 公开 API handlers:
- Swagger DTO:
本地开发命令
虽然运行形态只推荐 Docker,但开发期仍保留这些本地命令:
格式化:
make fmt
测试:
make test
初始化权限表:
make initdb
本地直接启动服务:
make run
生成 Swagger:
make docs
辅助加密 TOTP secret:
make admin-encrypt-totp
已知边界
当前系统已经能内部使用,但仍有明确边界:
- 业务行情数据依赖外部 MySQL 既有表,不由本仓库托管
- Docker 是当前唯一推荐运行方式
/apply仍是独立 SSR 页面,还没有完全并回/portal/docs/requirements.md和docs/readme.md为归档文档,不保证逐字匹配当前实现
免责说明
本项目中的股票、板块、快照、涨停池和相关数据,本质上依赖公开互联网来源及既有数据库整理结果。
当前项目更适合:
- 学习交流
- 接口联调
- 鉴权 / 门户 / 限流流程演示
- 内部研究与验证
请勿将本项目及其数据直接用于商业用途、投资建议、交易决策或其他高风险场景。因使用本项目产生的任何直接或间接损失,项目维护方不承担责任。