# wordcloud 外部服务契约 v1.1 本文档冻结 `wxmp_backend` 与 `/Users/broccoli/Project/wordcloud` 之间依赖的最小接口。 wordcloud 项目内部仍在大量变更,但只要不违反本文档,`wxmp_backend` 的适配层不受影响。 ## 1. 版本与状态 - 契约版本:`v1.1`(相对 v1 为**兼容扩展**,仅新增可选字段,未改任何既有字段语义)。 - 状态:*.xlsx 名单模式冻结;`names` 直接文本/JSON 模式为推荐扩展点,尚未冻结; **WCD 生产任务输入(`wcd_file`)已冻结(v1.1)**,wordcloud 侧实现可后置。 - 服务地址:由 `wxmp_backend` 环境变量 `WORDCLOUD_API_URL` 配置,禁止硬编码到代码或小程序前端。 - 小程序前端永远不直接访问 wordcloud,只访问 `wxmp_backend`。 ## 2. 冻结接口 ### POST /api/jobs 创建词云任务,`multipart/form-data`: | 字段 | 必填 | 说明 | |---|---|---| | `name_list` | 与 `wcd_file` 二选一 | `.xlsx` 名单文件,v1 必填 | | `wcd_file` | 与 `name_list` 二选一 | `.wcd` 画布导入导出包(v1.1 新增)。存在时进入“还原设计 → 生产任务”模式 | | `mask_image` | IMAGE 模式必填 | `.png/.jpg/.jpeg` 掩膜;`wcd_file` 模式下不要求 | | `font_file` | 否 | `.ttf/.ttc/.otf` 临时字体 | | `font_id` | 否 | 已上传字体 id | | `params` | 否 | JSON 字符串,顶层必须是对象 | `wcd_file` 模式下 `params` 关键值建议带: ```json { "MODE": "WCD", "SEED": 42, "ENABLE_STROKE_WEIGHTS": false, "FONT_COLOR": "#000000" } ``` 响应与既有模式一致:`{ "job_id": "..." }`。 **WCD 包结构**(wxmp_backend 构造,校验逻辑对齐 wordcloud 现有 `POST /api/design-templates/import`): ``` {wcd}.wcd ├── manifest.json // { format: "wordcloud-canvas", version: 1, canvas: {width,height,background}, │ // assets: [{id,name,type,mimeType,sha256,size}], meta?: {...} } ├── document.json // CanvasDocument:{width,height,background,layers,layerFolders,elements} └── assets/. // 每个 sticker/底图的图片字节 ``` - `document.elements[]` 中 `type == "sticker"` 的元素通过 `assetId` 引用包内临时 ID, 导入后由 wordcloud 统一重映射为真实素材 ID。 - 名单快照可放 `manifest.meta`,仅记录,不影响还原。 ### GET /api/jobs/{job_id} 返回(与 v1 一致): ```json { "job_id": "...", "status": "queued|running|success|failed", "stage": "...", "progress_percent": 0, "message": "...", "created_at": "...", "updated_at": "...", "artifacts": {}, "error": "" } ``` ### GET /api/jobs/{job_id}/result 成功时返回产物地址: ```json { "job_id": "...", "status": "success", "image_url": "/api/jobs/{job_id}/files/png", "svg_url": "/api/jobs/{job_id}/files/svg", "svg_stroke_url": "/api/jobs/{job_id}/files/svg_stroke", "db_url": "/api/jobs/{job_id}/files/db", "metrics_url": "/api/jobs/{job_id}/files/metrics" } ``` ### GET /api/jobs/{job_id}/files/{kind} `kind` 支持 `png/svg/svg_stroke/db/metrics`。wxmp_backend 只消费 `png` 并把结果转存 COS。 ## 3. 状态语义 | status | 含义 | 小程序映射 | |---|---|---| | `queued` | 已入队,未开始 | `queued` | | `running` | 生成中 | `running` | | `success` | 完成 | `success` | | `failed` | 失败 | `failed` | 进度以 `progress_percent` 为准,`wxmp_backend` 原样透传;小程序轮询间隔 1-2 秒。 ## 4. 错误语义 - 4xx:参数错误,错误信息在 `detail` 或 `message`。 - `wcd_file` 非 `.wcd` / 非合法 Zip => 400。 - `manifest.format != "wordcloud-canvas"` 或 `version != 1` => 400。 - `name_list` 与 `wcd_file` 都缺失 => 400。 - 5xx:服务/任务异常,wxmp_backend 将任务标记 `failed` 并在超时后清理。 - wxmp_backend 适配层应设置请求超时(例如 30s),任务超时上限(例如 10 分钟)。 ## 5. 稳定性规则 - 上述端点的路径、字段名、状态枚举、分页/轮询语义冻结。 - `wcd_file` 为 v1.1 兼容扩展:对既有调用方完全向后兼容(纯新增可选字段)。 - wordcloud 内部重构、新增 canvas/assets/projects/templates 能力不影响本契约。 - 契约变更流程:定义 v2 -> 更新本文档 -> wxmp_backend 在 R4 分支升级适配器 -> 双版本并存一个发布周期。 ## 6. 集成要点 - `wxmp_backend` 负责把小程序文本名单转换为 `.xlsx` 再调用 `POST /api/jobs`(名单模式)。 - **`wxmp_backend` 负责在下单后把订单对应 `designData` 构造为 `.wcd` 再调用 `POST /api/jobs`(WCD 模式,`MODE=WCD`)**,见 `wechat_wc/docs/design-data-contract-v1.md`(数据结构)与 `wechat_wc/docs/routes/route-r4-upload-wordcloud.md` §3(派单流程)。 - `wxmp_backend` 保存 `job_id -> orderId/userId`(WCD 模式)或 `job_id -> userId`(名单模式)映射, 轮询与结果查询必须校验归属。 - 结果图由 wxmp_backend 下载并转存 COS,返回给小程序的是 COS 公网 URL。 - `WORDCLOUD_API_URL` 未配置时,下单派单返回结构化“未配置”错误(状态字面量 `not_configured`,见 `api-contract-v1.md` §8 的 `POST /api/orders/:id/dispatch`),不做假成功。 - **生产订单列表(wordcloud 侧运营查看,raw 消费可选)**:wordcloud 在 `POST /api/jobs` WCD 模式下从 `manifest.meta.orderNo` 登记生产订单,暴露 `GET /api/orders` 与 `GET /api/orders/{order_no}`。`wxmp_backend` 不消费该接口,仅供 wordcloud/运营侧查看 下单投递的生产任务与状态;`job_id → orderNo` 仍以 `wxmp_backend` 侧 `CustomizationTask` 为准。 - wordcloud 若对外暴露公网,需要加访问 token 或网络白名单,防止被直接刷任务。