Logo拍图猫文档
Logo拍图猫文档
首页拍图猫是什么如何出图积分API 参考
开发者中心
快速开始密钥管理权限图片下载错误格式限额图片包拉取发布通知
开发者中心

发布通知

发布后主动通知你的地址,签名验证与重试规则

不想轮询图片包拉取接口,可以填一个接收地址:店主在网页上点「发布」、真的产生了新版本之后,拍图猫往这个地址 POST 一条消息。消息只带这一版的基本信息,不带图片和文字 —— 收到后用带 documents:read 权限的密钥去 GET /api/v1/image-pack-publications/<id> 拉内容。

设置在「开发者中心 → 发布通知」:填地址(只收 https://)、打开开关、抄走签名密钥。页面上的「发送测试通知」会立刻发一条 ping,用来确认地址通、验签对。

什么时候发

情况发不发
点「发布」,版本号加一发
同一把 Idempotency-Key 重复提交,没有产生新版本不发
发布被拒(草稿有未保存修改、缺图、空包)不发
开关关着,或地址为空不发

请求

POST <你的地址>
Content-Type: application/json
User-Agent: paitumao-webhook/1
X-Paitumao-Event: image_pack.published
X-Paitumao-Delivery: 7f5b0c9e-…
X-Paitumao-Timestamp: 1757600000
X-Paitumao-Signature: v1=3f1a…
{
  "event": "image_pack.published",
  "publication": {
    "id": 42,
    "pack_id": "pk_xxxxxxxx",
    "version": 3,
    "style_code": "QS-2601",
    "published_at": 1757600000000
  }
}
请求头说明
X-Paitumao-Eventimage_pack.published,或测试按钮发的 ping
X-Paitumao-Delivery这一次投递的 id。重试时不变,按它去重
X-Paitumao-Timestamp发送时刻,Unix 秒。重试时刷新
X-Paitumao-Signaturev1= + 十六进制 HMAC-SHA256,见下

ping 的请求体只有 {"event":"ping"},没有 publication。

字段含义和拉取接口一致:id 是拉内容用的记录 id,pack_id 判同一件商品,style_code 只是展示。

验签

签名密钥在「开发者中心 → 发布通知」页面上,whsec_ 开头。算法:

  1. 取请求头 X-Paitumao-Timestamp 的值 ts 和原始请求体 body(不要先 parse 再序列化,字节要一模一样)
  2. 用密钥算 HMAC-SHA256(secret, ts + "." + body),十六进制
  3. 和 X-Paitumao-Signature 里 v1= 后面的值做常数时间比较
  4. ts 和当前时间相差超过 5 分钟就拒绝 —— 防重放

Node.js 参考实现:

import { createHmac, timingSafeEqual } from 'node:crypto';

function verify(secret, headers, rawBody) {
  const ts = headers['x-paitumao-timestamp'];
  const sig = headers['x-paitumao-signature'] ?? '';
  if (Math.abs(Date.now() / 1000 - Number(ts)) > 300) return false;
  const expected = Buffer.from(
    createHmac('sha256', secret).update(`${ts}.${rawBody}`).digest('hex'),
    'hex'
  );
  for (const part of sig.split(',')) {
    const [v, hex] = part.trim().split('=');
    if (v !== 'v1' || !hex) continue;
    const given = Buffer.from(hex, 'hex');
    if (given.length === expected.length && timingSafeEqual(given, expected)) {
      return true;
    }
  }
  return false;
}

验不过就回 401 并丢弃。密钥泄露了就在页面上「重新生成」:旧密钥立即作废,之后的通知全用新密钥签。

超时与重试

  • 单次请求 8 秒超时。你的接收端只需要「验签、记下 id、回 2xx」,拉内容放到之后做,不要在响应之前去拉。
  • 非 2xx、连不上、超时都算失败,之后再试两次(间隔 2 秒、10 秒),三次都失败就放弃。
  • 放弃不补发。你的系统本来就要按增量拉取的契约兜底:通知只是让你早一点拉,不是唯一来源。
  • 重试的 X-Paitumao-Delivery 不变,X-Paitumao-Timestamp 和签名重新算。同一条通知可能收到两次,按 delivery id 或 (pack_id, version) 去重。
  • 通知在发布之后的后台发,发不出去不影响发布本身;结果显示在设置页「上次投递」。

地址要求

  • 只收 https://,不跟随重定向(3xx 算失败)。
  • 不收 localhost、内网主机名、IP 字面量 —— 拍图猫的服务器够不到它们。本机调试用一条公网可达的隧道(如 cloudflared tunnel --url)。
  • 地址里不能带用户名密码。

图片包拉取

增量拉取已发布的图片包

目录

什么时候发请求验签超时与重试地址要求