# 第三方服务、接口及密钥说明 本文档记录第三方服务实际使用的网址、接口和密钥字段。 完整明文密钥不得提交到版本库;下文的密钥值使用登记占位符,真实值分别保存在生产环境文件或管理后台加密存储中。 ## 1. 第三方服务总览 | 第三方服务 | 用途 | 网址或接口入口 | 所需凭证 | 凭证保存位置 | | --- | --- | --- | --- | --- | | AP 渠道 | 文本、图片、视频任务及余额查询 | `https://api.apimart.ai/v1` | 渠道 API Key | PostgreSQL `channels.api_key_ciphertext` | | 腾讯云 COS | 上传、读取和删除图片、音频、视频等媒体文件 | `https://cos.ap-chengdu.myqcloud.com` | SecretId、SecretKey | `/etc/juyou_ai/juyou_ai.env` | | 腾讯云 COS 公开域名 | 向前端及第三方渠道提供可访问的媒体 URL | `https://cos.youjuhui.xyz` | 无单独运行时密钥 | `/etc/juyou_ai/juyou_ai.env` | | Let's Encrypt | 申请和续期 HTTPS 证书 | `https://acme-v02.api.letsencrypt.org/directory` | 证书联系邮箱,不使用 API Key | `/opt/juyou_ai/deploy/.deploy.conf` | | jsDelivr | 按需更新部署目录中的 `acme.sh` | `https://cdn.jsdelivr.net/gh/acmesh-official/acme.sh@master/acme.sh` | 无 | 不保存凭证 | | Hugging Face 下载源 | 首次在本地准备离线语音识别文件 | 由 `faster-whisper` 下载工具访问 | 当前未配置访问令牌 | 不保存凭证 | ## 2. AI 渠道 ### 2.1 当前渠道登记 | 渠道名称 | 渠道 URL | API Key | | --- | --- | --- | | AP | `https://api.apimart.ai/v1` | `<在管理后台维护>` | 渠道只需要登记基础网址和 API Key,具体模型不在本文档记录。 管理后台配置位置: ```text ADMIN → 渠道管理 → 新增或编辑渠道 → 渠道 URL、API Key ``` ### 2.2 认证方式 所有渠道请求使用 Bearer Token: ```http Authorization: Bearer <渠道 API Key> ``` 提交异步任务时还会根据任务请求编号发送: ```http Idempotency-Key: <请求编号> X-Request-ID: <请求编号> Content-Type: application/json ``` `Idempotency-Key` 和 `X-Request-ID` 是任务标识,不是密钥。 ### 2.3 项目调用的接口路径 项目会在渠道 URL 后拼接下列路径: | 请求 | 完整接口 | 用途 | | --- | --- | --- | | `POST` | `https://api.apimart.ai/v1/chat/completions` | 提交文本类请求,项目强制使用非流式响应 | | `POST` | `https://api.apimart.ai/v1/images/generations` | 提交图片生成任务 | | `POST` | `https://api.apimart.ai/v1/videos/generations` | 提交视频生成任务 | | `GET` | `https://api.apimart.ai/v1/tasks/{task_id}` | 查询异步任务状态和结果地址 | | `GET` | `https://api.apimart.ai/v1/user/balance` | 同步渠道余额 | 渠道至少需要兼容以上接口、Bearer 认证以及 JSON 请求和响应。图片或视频接口可以直接返回结果网址,也可以返回任务 ID 后由项目轮询。 ### 2.4 渠道密钥如何保存 1. 管理员在管理后台输入渠道 API Key。 2. API 使用 `CONFIG_ENCRYPTION_KEY` 对明文密钥进行 AES-256-GCM 加密。 3. 密文写入 PostgreSQL 的 `channels.api_key_ciphertext`。 4. 密钥末四位写入 `channels.api_key_last4`,用于无法解密时识别密钥。 5. 管理端查询渠道时不会返回完整明文,只显示前后部分字符的掩码。 6. Worker 执行任务或同步余额时,才在服务器内存中解密并放入 Authorization 请求头。 因此,数据库备份中的渠道密钥是密文,但同时取得数据库备份和 `CONFIG_ENCRYPTION_KEY` 的人员仍可恢复明文,两者必须分开保管。 ### 2.5 新增或更换渠道密钥 新增渠道: 1. 在渠道服务商处创建 API Key。 2. 在管理后台新增渠道。 3. 填写渠道名称、基础网址和 API Key。 4. 保存后确认后台显示的掩码尾号与新密钥一致。 5. 通过渠道余额同步或一项低成本任务验证权限。 更换密钥: 1. 先在渠道服务商处创建新密钥,不要立即删除旧密钥。 2. 在管理后台编辑渠道,选择“更换 API Key”并保存。 3. 确认余额同步和任务提交正常。 4. 再到渠道服务商处撤销旧密钥。 5. 更新本文档中的密钥尾号和轮换记录,不记录明文。 ## 3. 腾讯云 COS ### 3.1 当前存储配置 | 配置项 | 当前值或登记值 | 是否敏感 | | --- | --- | --- | | 腾讯云控制台 | `https://console.cloud.tencent.com/cos` | 否 | | `COS_SECRET_ID` | `<腾讯云子账号 SecretId>` | 是 | | `COS_SECRET_KEY` | `<腾讯云子账号 SecretKey>` | 是,禁止泄露 | | `COS_BUCKET` | `juyouai-1451538162` | 否 | | `COS_REGION` | `ap-chengdu` | 否 | | `COS_ENDPOINT` | `https://cos.ap-chengdu.myqcloud.com` | 否 | | `COS_PUBLIC_BASE_URL` | `https://cos.youjuhui.xyz` | 否 | 生产环境中的真实凭证保存在: ```text /etc/juyou_ai/juyou_ai.env ``` 本地开发凭证保存在: ```text API/.env ``` ### 3.2 使用的 COS 接口 项目通过 AWS S3 兼容协议访问 COS,区域使用 `ap-chengdu`,并使用虚拟主机寻址。实际执行的操作包括: | S3 操作 | 用途 | | --- | --- | | `PutObject` | 上传用户文件、抽帧、识别结果、任务原始响应和生成结果 | | `GetObject` | 后端读取已存储对象 | | `DeleteObject` | 删除业务数据时清理对应对象 | 腾讯云子账号至少需要目标存储桶的对象读取、写入和删除权限。若缺少删除权限,业务记录可以删除,但 COS 对象清理会失败并产生遗留文件。 ### 3.3 公开访问域名 `COS_PUBLIC_BASE_URL` 必须是外部可以访问的 HTTPS 地址。项目会按以下形式生成媒体地址: ```text https://cos.youjuhui.xyz/juyou_ran/<业务对象键> ``` 该网址会提供给: - WEB 和 ADMIN 页面展示媒体; - 第三方渠道读取参考图片、音频或视频; - 服务端重新下载上游生成结果。 公开域名不使用 SecretKey,但必须正确绑定 `juyouai-1451538162` 存储桶。第三方渠道无法访问该域名时,带参考媒体的任务会失败。 ### 3.4 COS CORS COS 存储桶需要允许实际 WEB 域名执行 `GET` 和 `HEAD`。建议规则: ```json [ { "AllowedOrigins": [ "https://实际WEB域名" ], "AllowedMethods": [ "GET", "HEAD" ], "AllowedHeaders": [ "*" ], "ExposeHeaders": [ "Accept-Ranges", "Content-Length", "Content-Range", "Content-Type", "ETag" ], "MaxAgeSeconds": 3600 } ] ``` 缺少 CORS 时,媒体可能仍能直接打开或播放,但浏览器中的抽帧、Blob 下载等功能会被拦截。 ### 3.5 更换 COS 密钥 1. 在腾讯云 CAM 中为程序子账号创建新的 API 密钥。 2. 备份 `/etc/juyou_ai/juyou_ai.env`。 3. 更新 `COS_SECRET_ID` 和 `COS_SECRET_KEY`。 4. 重启 `juyou_ai` 服务。 5. 验证上传、读取和删除操作。 6. 确认新密钥正常后撤销旧 API 密钥。 ```bash sudo systemctl restart juyou_ai sudo journalctl -u juyou_ai -n 100 --no-pager ``` ## 4. Let's Encrypt 与 acme.sh ### 4.1 服务信息 | 项目 | 值 | | --- | --- | | 正式 ACME 接口 | `https://acme-v02.api.letsencrypt.org/directory` | | 认证方式 | ACME HTTP-01 | | API Key | 不需要 | | 必需登记信息 | 证书联系邮箱、域名 | | 验证目录 | `/var/www/jcf-acme` | | 证书目录 | `/etc/nginx/ssl` | 域名和邮箱保存在: ```text /opt/juyou_ai/deploy/.deploy.conf ``` 部署脚本先让 Nginx 提供 `/.well-known/acme-challenge/`,再调用项目内的 `API/acme/acme.sh` 申请证书。证书申请要求域名已解析到服务器,并且公网可以访问 TCP 80。 已有匹配域名的证书和私钥时,部署脚本直接复用,不会重复申请。 ## 5. 部署阶段使用的无密钥第三方来源 ### 5.1 jsDelivr 只有手动执行以下脚本时才访问 jsDelivr: ```bash sudo bash /opt/juyou_ai/deploy/update_acme.sh ``` 下载地址: ```text https://cdn.jsdelivr.net/gh/acmesh-official/acme.sh@master/acme.sh ``` 该请求不使用 API Key。脚本下载后会检查内容中是否存在 `VER=` 版本标识,再替换项目中的 `acme.sh`。 ### 5.2 Hugging Face 下载源 当服务器缺少离线语音识别文件时,`push.bat` 会在 Windows 本机调用 Python 下载工具准备文件,然后上传服务器。当前代码未读取或配置 Hugging Face Access Token,服务器部署和运行阶段不会访问该下载源。 如果以后使用需要授权的资源,应通过受保护的本机环境变量或 Hugging Face 凭证存储配置,不得把令牌写入部署脚本或本文档。 ## 6. 不是第三方接口密钥的项目安全配置 下列配置同样敏感,但不属于第三方 API 凭证: | 配置项 | 用途 | 保存位置 | | --- | --- | --- | | `CONFIG_ENCRYPTION_KEY` | 加密和解密渠道 API Key | 生产环境文件 | | `JWT_SECRET_KEY` | 签发和校验用户、管理员登录令牌 | 生产环境文件 | | `DATABASE_PASSWORD` | PostgreSQL 应用账号密码 | 生产环境文件 | | `REDIS_PASSWORD` | Redis 密码,当前为空时不启用认证 | 生产环境文件 | | `ADMIN_BOOTSTRAP_PASSWORD` | 数据库没有管理员时创建初始管理员 | 生产环境文件 | 其中 `CONFIG_ENCRYPTION_KEY` 必须是 32 字节随机值的标准 Base64 编码。丢失该密钥后,数据库中已有的渠道密钥无法解密,只能逐个重新录入;更换它时也不能只修改环境变量,必须先完成渠道密文重加密方案。 ## 7. 密钥存放与权限要求 - 生产第三方密钥只保存在 `/etc/juyou_ai/juyou_ai.env` 或数据库加密字段中。 - `/etc/juyou_ai/juyou_ai.env` 权限应为 `root:root`、`600`。 - `API/.env` 不得提交到 Git,也不得通过普通聊天、邮件或工单正文传递。 - Markdown 文档只记录密钥负责人、用途、尾号和轮换时间,不记录完整明文。 - 渠道密钥、COS 密钥和 `CONFIG_ENCRYPTION_KEY` 不应由同一个公开位置统一保存。 - 日志中不得打印 Authorization 请求头、COS SecretKey 或解密后的渠道密钥。 - 人员离职、权限范围变化或怀疑泄露时,应立即轮换对应密钥。 ## 8. 密钥轮换登记 | 服务 | 密钥标识或尾号 | 最近轮换时间 | 负责人 | 下次计划时间 | | --- | --- | --- | --- | --- | | AP 渠道 | `7MNC` | `<填写>` | `<填写>` | `<填写>` | | 腾讯云 COS | `` | `<填写>` | `<填写>` | `<填写>` | | Let's Encrypt 邮箱 | `<邮箱>` | `<填写>` | `<填写>` | `<填写>` | 轮换登记只用于识别凭证,不填写完整密钥。