Files
ledgerly-docs/dev/api.md
T
rosercode 5eb1d331f9 docs: 补充接口加解密、代码检查与安全配置等开发文档
同步 ledgerly 近期开发改动(接口请求/响应体加解密、代码检查工具、安全与稳定性修复、AI 提示词模板抽取),补齐对应开发文档并修正过时表述,同时在快速开始补充小屏适配说明。

变更内容:
- dev/api.md:新增「接口数据加密」小节,说明 RSA + AES-GCM 握手流程、信封格式、会话有效期与失效码、豁免范围及编译期开关。
- dev/architecture.md:请求处理流程补入加密会话拦截器与请求/响应体 Advice,关键设计亮点新增接口数据加密一条。
- dev/development.md:新增「代码检查」小节,登记 Spotless / Checkstyle / SpotBugs 与前端 ESLint / Prettier 配置及运行命令。
- dev/build-deploy.md:新增「安全配置」(JWT_SECRET 覆盖、CORS 放行来源),构建任务链补入前端 lint 校验说明。
- dev/ai.md:修正已重命名的提示词模板名,补充「提示词模板」片段机制与图片记账 SSE 超时、心跳说明。
- dev/project-structure.md:补充 config.crypto / util.crypto 包、prompts 资源目录、crypto-keys.json 运行时文件与交易服务拆分说明。
- guide/getting-started.md:新增「小屏与移动端适配」说明。
- guide/transactions.md:导出说明补充单次 10000 条上限。
2026-10-13 21:02:53 +08:00

109 lines
7.5 KiB
Markdown
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
# API 文档
系统使用 **Knife4j(OpenAPI 3)** 生成接口文档,后端启动后可直接访问。
## 访问入口
| 入口 | 地址 | 说明 |
|---|---|---|
| Knife4j UI | `http://<host>:<port>/doc.html` | 增强版接口文档界面 |
| OpenAPI JSON | `http://<host>:<port>/v3/api-docs` | 标准 OpenAPI 描述 |
| Swagger UI | `http://<host>:<port>/swagger-ui/index.html` | 原生界面 |
开发模式下默认端口为 8080,例如 http://localhost:8080/doc.html。
## 认证
- 接口统一使用 **JWT Bearer** 鉴权,登录接口返回 token 后,在请求头携带:
```text
Authorization: Bearer <token>
```
- Knife4j 配置中已声明全局 `Bearer` 安全方案,可在文档界面直接填入 token 调试。
- 无需鉴权的接口:`/api/user/login`、`/api/user/register`、`/api/user/registration-status`、`/api/database/status`。
- 日志实时推送等 SSE 接口因 `EventSource` 无法自定义请求头,兼容通过 `?token=` 查询参数鉴权。
## 接口数据加密
后端支持对 `/api/**` 的**请求体与响应体**做端到端加密(RSA + AES-GCM),浏览器登录后自动完成握手,对使用者透明。该能力为**机会式**:未携带加密会话头的请求按明文处理,因此 Knife4j 等工具仍可直接明文调试接口。
- **握手**:前端先 `GET /api/crypto/public-key` 获取 RSA 公钥(返回 `{enabled, keyId, algorithm, publicKey}`),本地生成 32 字节 AES 密钥并用 **RSA-OAEP(SHA-256)** 加密,再 `POST /api/crypto/handshake`(body `{keyId, key}`)换取 `sessionId`;此后请求统一携带 `X-Crypto-Session: <sessionId>` 头。
- **算法**:**AES-256-GCM**(IV 12 字节、认证标签 128 位),GCM 的 AAD 绑定 `sessionId` 以防跨会话重放;AES 会话密钥仅存后端内存,RSA 密钥对在首次启动时自动生成并持久化到运行目录 `config/crypto-keys.json`。
- **信封格式**:加解密对象为 JSON 信封 `{"enc":"A256GCM","iv":"<Base64>","data":"<Base64 密文+标签>"}`。
- **会话**:有效期 2 小时、上限 2000 个;失效返回业务码 `4201`,前端自动重新握手并重试一次。
- **豁免范围**:SSE 流式接口、multipart 文件上传、二进制下载/图片(导出、`/api/ai/image/**`)与握手接口本身不做加解密;`/api/crypto/**` 无需鉴权。
- **开关**:由编译期常量 `CryptoConstants.API_ENCRYPTION_ENABLED` 控制;关闭后 `public-key` 返回 `enabled:false`,前端自动回退明文。
## 接口分组
| 控制器 | 路径前缀 | 说明 |
|---|---|---|
| `UserController` | `/api/user` | 登录、注册、用户信息、注册开关、修改密码 |
| `TransactionController` | `/api/transaction` | 收支记录增删改查、批量创建与操作、备注隐藏、导出、交易渠道选项 |
| `TransactionGroupController` | `/api/transaction/group` | 账单关系组的查询、创建、更新、删除与名称历史 |
| `BillImportController` | `/api/transaction/import` | 账单解析与确认导入 |
| `ChannelController` | `/api/channel` | 用户自定义交易渠道的增删改查 |
| `CategoryController` | `/api/category` | 分类管理 |
| `TagController` | `/api/tag` | 标签管理 |
| `RuleController` | `/api/rule` | 自定义规则(列表、分页查询、增删改、启停、批量删除) |
| `StatisticsController` | `/api/statistics` | 统计汇总、分类、趋势、分组 |
| `AiController` | `/api/ai` | AI 建议、查询、智能查数、文字/图片记账、渠道/关系/规则生成、统计搜索、用量 |
| `NotificationController` | `/api/notification` | 通知配置、渠道、发送日志 |
| `EmailBillController` | `/api/email-bill` | 邮箱配置、发件人规则、待处理账单 |
| `LogController` | `/api/log` | 访问日志、登录日志、运行日志与 SSE |
| `DatabaseController` | `/api/database` | 数据库状态、测试与配置(含 SSE 进度) |
| `AppConfigController` | `/api/app` | 应用配置(通知链接、日志保留) |
| `UserSettingController` | `/api/setting` | 用户偏好(账单来源统计默认值、展示样式、隐藏备注显示、分页、导航) |
## 关键接口
| 方法 | 路径 | 说明 |
|---|---|---|
| GET | `/api/transaction/channels` | 获取交易渠道选项(内置 + 当前用户自定义,含 `code`/`name`/`builtin`) |
| POST | `/api/transaction/batch` | 批量创建交易记录(逐条可带 `imageId`/`rawData`),导入时按「类型+金额+时间」跳过重复 |
| PUT | `/api/transaction/{id}/remark-hidden` | 隐藏 / 取消隐藏某条记录的备注 |
| GET / POST / PUT / DELETE | `/api/channel`、`/api/channel/{id}` | 自定义渠道列表(含使用账单数)、新建、改名、删除 |
| GET | `/api/transaction/group/by-transaction/{id}` | 查询某笔账单所属的全部关系组(含成员快照) |
| GET | `/api/transaction/group/names` | 关系名称历史(可按 `type` 过滤,去重、倒序) |
| POST / PUT / DELETE | `/api/transaction/group`、`/api/transaction/group/{id}` | 创建 / 更新 / 删除账单关系组(删除仅解除关联,不删除账单) |
| PUT | `/api/user/password` | 修改当前登录用户的密码(校验原密码,新旧需不同) |
| POST | `/api/ai/record/image` | 上传一至多张账单/支付截图(字段 `files`),调用视觉模型识别为多条交易记录 |
| POST | `/api/ai/record/image/stream` | 图片记账(SSE):实时推送识别进度,结束返回完整结果 |
| GET | `/api/ai/image/{id}` | 查看本人上传的图片记账图片,`?thumbnail=true` 返回缩略图 |
| POST | `/api/ai/channel` | 由自然语言描述生成交易渠道名称 |
| POST | `/api/ai/relation` | 由关联账单生成关系名称与备注 |
| POST | `/api/ai/sql` | 智能查数:自然语言生成只读 SQL 并执行 |
| GET / DELETE | `/api/ai/sql/history` | 查询 / 清空智能查数提问历史(`limit` 上限 200) |
| GET | `/api/rule/page` | 分页查询规则(`keyword` / `enabled` / `type`) |
| DELETE | `/api/rule/batch` | 批量删除规则(body `{ ids }`,返回实际删除数) |
| POST | `/api/ai/rule/suggest` | 依据所选已打标签记录生成规则建议(含 `duplicate` 标记) |
| POST | `/api/ai/rule/apply` | 批量创建规则(自动去重、按需新建分类/标签) |
| POST | `/api/ai/statistics` | 自然语言解析为统计面板参数 |
| GET / PUT | `/api/setting/excluded-display-style` | 查询 / 更新「不计入统计」记录展示样式 |
| GET / PUT | `/api/setting/show-hidden-data` | 查询 / 更新是否显示已隐藏备注的记录 |
| GET / PUT | `/api/setting/chart-click-navigation` | 查询 / 更新统计面板图表点击是否跳转明细 |
| GET / PUT | `/api/setting/pagination-prefs` | 查询 / 更新表格分页候选列表与默认每页条数 |
| GET / PUT | `/api/setting/nav-menu` | 查询 / 更新左侧导航顺序与显隐 |
| GET / PUT | `/api/setting/bill-source-include-in-stats` | 查询 / 更新按账单来源的「计入统计」默认值 |
| POST | `/api/database/config/stream` | 应用数据库配置并通过 SSE 推送进度(另有 `/api/database/test/stream`) |
## 统一响应结构
```json
{
"code": 200,
"message": "success",
"data": {}
}
```
- `code` 非 200 表示业务失败,`message` 为错误信息。
- 分页接口的 `data` 为 `PageResult`(`records` / `total` 等)。
- 数据库未配置时返回业务码 `5031`,前端据此跳转初始化引导页。
## 相关文档
- [整体架构](/dev/architecture)
- [项目结构](/dev/project-structure)