AI盒绘开放平台开发者中心
欢迎接入 AI盒绘开放平台!我们为第三方合作企业系统提供无缝集成方案。您的终端用户可凭免登凭据直达全功能 AI 包装设计工作台,设计完成后通过异步 Webhook 文件流将高清图像回传至贵司系统,实现安全、隔离、一对一的用户设计闭环。
企业用户一对一隔离
通过 company_id 物理强隔离,外部用户账号无缝映射为系统内部唯一实体。
Ticket 一次性即焚免登
服务端 5 分钟短时票据申请,前端首屏自动兑换 RS256 JWT 写入登录 Cookie,防重放更安全。
Webhook 文件流直推
用户点击“完成编辑”,合成图像二进制流与用户 ID 自动异步推送至合作方系统。
02 第三方企业用户免登认证 (Ticket 换票)
避免在前端 URL 暴露长期有效的主站 JWT。合作方服务端通过凭据预先申请 Ticket,用户带 Ticket 访问编辑器完成自动认证。
向 AI盒绘开放平台申请接入资质,平台为贵司分配唯一的 company_id、app_key 与 app_secret。注意:AppSecret 属于绝密凭证,严格保存在贵司服务器,绝不通过网络传输!
在引导用户打开设计器之前,贵司服务端基于参数字典序与 AppSecret 计算 HMAC-SHA256 签名,携带时间戳与随机防重放串请求接口,换取 5 分钟有效的一次性 ticket。
1. 收集非空请求参数:appKey, timestamp (秒), nonce (随机防重放字符串), externalUserId (以及可选的 nickname, avatarUrl)。
2. 将所有非空参数按 Key 进行 ASCII 升序排序,以 key=value 形式用 & 拼接待签名串:
stringToSign = "appKey=test_partner_key&externalUserId=u_10086&nickname=张三&nonce=d7a9e14c×tamp=1726589000"
3. 使用 AppSecret 作为密钥对待签名串执行 HmacSHA256 运算,输出 64 位小写十六进制字符串(Hex)作为签名值放于请求头 X-Open-Signature。
安全认证请求头 (Headers)
| Header 名称 | 类型 | 必填 | 说明 |
|---|---|---|---|
| X-Open-App-Key | String | 是 | 平台分配的企业应用公开 AppKey 标识 |
| X-Open-Timestamp | Long | 是 | 当前 Unix 时间戳 (10位秒级),服务端校验有效窗口 ±300 秒 |
| X-Open-Nonce | String | 是 | 随机防重放字符串 (UUID 或 16~32 位随机码),5分钟内原子唯一 |
| X-Open-Signature | String | 是 | 基于 AppSecret 与字典序待签名串计算出的 HMAC-SHA256 十六进制签名 (小写) |
| Content-Type | String | 是 | 固定传 application/json |
请求体 (Request Body)
{
"externalUserId": "corp_u_10086", // 必填:贵司内部的用户唯一ID (字符串)
"nickname": "张经理", // 选填:用户昵称
"avatarUrl": "https://cdn.corp.com/u.png" // 选填:用户头像
}
响应体 (Response Body)
{
"code": 200,
"message": "操作成功",
"data": {
"ticket": "8c3b7f1e4a9d4e5f8a1c2b3d4e5f6a7b", // 一次性换票凭据
"expiresIn": 300 // 有效期:300 秒 (5分钟)
}
}
03 交互时序全景流程
涵盖“申请 Ticket 换票 -> 打开设计器 -> 前端静默兑换 JWT -> 设计与 Webhook 导出回传”的完整生命周期。
┌──────────────┐ ┌────────────────┐ ┌────────────────┐ ┌───────────────┐
│ 第三方服务端 │ │ 第三方前端/APP │ │ AI盒绘开放网关 │ │ 编辑器前端/画布│
└──────┬───────┘ └───────┬────────┘ └───────┬────────┘ └───────┬───────┘
│ │ │ │
│ 1. 申请免登换票 (HMAC签名)│ │ │
│ POST /open/auth/ticket │ │ │
│ (Header: Key/Sign/Nonce) │ │ │
├─────────────────────────────────────────────────────►│ │
│ 2. 返回 ticket (5分钟有效)│ │ │
│◄─────────────────────────────────────────────────────┤ │
│ │ │ │
│ 3. 将 ticket 传给其前端 │ │ │
├─────────────────────────►│ │ │
│ │ 4. 打开编辑器页面 (带 ticket & image_url) │
│ │ GET /aidesign/editor?ticket=xxxx&image_url=... │
│ ├──────────────────────────►│ (网关检测到ticket放通) │
│ │ ├──────────────────────────►│
│ │ │ │ 5. 首屏加载
│ │ │ │ 6. 异步兑换:
│ │ │ POST /open/auth/ │ exchange-token
│ │ │◄──────────────────────────┤
│ │ │ 7. Redis 销毁 ticket 即焚 │
│ │ │ 8. 颁发 RS256 JWT Token │
│ │ ├──────────────────────────►│
│ │ │ │ 9. 写入 Cookie
│ │ │ │ hyj-Token
│ │ │ │ 10. 清洗 URL ticket
│ │ │ │
│ │ │ 11. 正常操作/自动云端同步 │
│ │ │◄──────────────────────────┤
│ │ │ (Cookie 自动携带,秒级验签) │
│ │ │ │
│ │ │ 12. 用户点击“完成编辑” │
│ 13. POST multipart/form-data 文件流直推 Webhook 接口 │ │
│◄─────────────────────────────────────────────────────┼───────────────────────────┤
│ 14. 返回 HTTP 200 OK 确认接收 │ │
├─────────────────────────────────────────────────────►│ │
│ │ │ │ 15. 关闭弹窗/页面
04 跳转编辑器对接规范 (URL Parameters)
获得换票凭据后,直接通过浏览器窗口打开指定 URL 即可进入全功能纯编辑器画布。
| 参数名 (Key) | 类型 | 是否必填 | 说明与示例 |
|---|---|---|---|
| ticket | String | 推荐 | 由贵司服务端提前调接口获取的一次性免登换票凭据。首屏自动换取 JWT 写入 Cookie,防止 URL 泄露长期 Token。 |
| image_url | String (URL) | 可选 |
待编辑的底图远程 HTTP/HTTPS 地址。必须进行标准 encodeURIComponent 编码。
|
| title | String | 可选 | 设计项目的初始标题(如“2026月饼礼盒包装正面”)。 |
| source | String | 可选 |
来源渠道标识(如 open_platform)。
|
https://1packify.com/aidesign/editor?ticket=8c3b7f1e4a9d4e5f8a1c2b3d4e5f6a7b&image_url=https%3A%2F%2Fcdn.example.com%2Fpack_front.png&title=%E6%96%B0%E5%8C%85%E8%A3%85%E8%AE%BE%E8%AE%A1
05 完成编辑 Webhook 接收规范 (Webhook Contract)
用户在编辑器中设计完毕后,点击右上角“导出”->“完成编辑”。系统将直接合成高分辨率图像二进制文件流,POST 推送到预先配置的 Webhook 回调接口。
multipart/form-data
| 表单字段名 (Key) | 类型 | 说明 |
|---|---|---|
| file | Binary File (Blob) | 导出生成的合成图像二进制文件流 (PNG/JPEG) |
| userId | String | 对应系统内部的唯一用户 ID |
| projectId | String | 本次编辑画布关联的工程 Project ID |
| title | String | 导出作品的文件名称 |
06 多语言实战示例代码
提供主流后端语言实现“服务端申请 Ticket 换票”以及“服务端接收 Webhook 文件流”的生产级范式。
// 1. 服务端安全加签申请免登 Ticket
public static String hmacSha256Hex(String data, String key) throws Exception {
Mac mac = Mac.getInstance("HmacSHA256");
mac.init(new SecretKeySpec(key.getBytes(StandardCharsets.UTF_8), "HmacSHA256"));
byte[] hash = mac.doFinal(data.getBytes(StandardCharsets.UTF_8));
StringBuilder sb = new StringBuilder();
for (byte b : hash) sb.append(String.format("%02x", b));
return sb.toString();
}
public String getOpenEditorTicket(String externalUserId) throws Exception {
String appKey = "test_partner_key";
String appSecret = "test_partner_secret"; // 绝密凭证,严格保存在本地
long timestamp = System.currentTimeMillis() / 1000;
String nonce = UUID.randomUUID().toString().replace("-", "").substring(0, 16);
String nickname = "张经理";
// 1.1 参数字典序组装待签名串
Map<String, String> params = new TreeMap<>();
params.put("appKey", appKey);
params.put("timestamp", String.valueOf(timestamp));
params.put("nonce", nonce);
params.put("externalUserId", externalUserId);
params.put("nickname", nickname);
StringBuilder sb = new StringBuilder();
for (Map.Entry<String, String> entry : params.entrySet()) {
if (sb.length() > 0) sb.append("&");
sb.append(entry.getKey()).append("=").append(entry.getValue());
}
String stringToSign = sb.toString();
String signature = hmacSha256Hex(stringToSign, appSecret);
// 1.2 携带签名请求头申请 Ticket
RestTemplate restTemplate = new RestTemplate();
HttpHeaders headers = new HttpHeaders();
headers.set("X-Open-App-Key", appKey);
headers.set("X-Open-Timestamp", String.valueOf(timestamp));
headers.set("X-Open-Nonce", nonce);
headers.set("X-Open-Signature", signature);
headers.setContentType(MediaType.APPLICATION_JSON);
Map<String, Object> body = new HashMap<>();
body.put("externalUserId", externalUserId);
body.put("nickname", nickname);
HttpEntity<Map<String, Object>> entity = new HttpEntity<>(body, headers);
ResponseEntity<Map> resp = restTemplate.postForEntity(
"https://open.1packify.com/api/open/auth/ticket", entity, Map.class);
Map data = (Map) resp.getBody().get("data");
return (String) data.get("ticket");
}
// 2. 接收完成编辑 Webhook 文件流
@PostMapping("/api/webhook/aidesign/handleSave")
public ResponseEntity<Map<String, Object>> handleSave(
@RequestParam("file") MultipartFile file,
@RequestParam("userId") String userId,
@RequestParam("projectId") String projectId) throws IOException {
String filename = file.getOriginalFilename();
File dest = new File("/data/designs/" + userId + "_" + filename);
file.transferTo(dest);
return ResponseEntity.ok(Collections.singletonMap("code", 200));
}
07 在线参数生成调试台 (Interactive Playground)
在下方输入联调参数,即时生成符合编码标准的完整跳转 URL 并可一键体验。
08 接入演进与后续支持 (Roadmap)
我们正在持续扩充开放平台的生态连接能力,后续将陆续上线以下高阶特性:
基于 company_id 的用户一对一隔离与免登
支持通过 Ticket 方式进行无感静默认证,自动载入远程底图,并在完成编辑后触发 Webhook 文件流推送。
Iframe 嵌入式工作台与 PostMessage 双向通信
支持第三方系统直接以全屏或局部 Iframe 内嵌设计器,并通过 window.postMessage 实现实时事件与文件数据双向传递。