CAPS 开放接口

把采购、预算、对账数据接进你自己的系统。只读 API + 事件推送,全程签名校验。 接入是申请制:提交申请 → 采购中心审核 → 发 Key。

认证限流与错误码接口 Webhook验签示例安全说明

一、认证

所有接口都要带 Key,两种写法等价:

X-API-Key: caps_xxxxxxxxxxxxxxxxxxxxxxxx
# 或
Authorization: Bearer caps_xxxxxxxxxxxxxxxxxxxxxxxx

Key 绑定了三样东西:权限范围(read:orders / read:catalog / read:budget / read:suppliers / read:recon)、 每分钟调用上限、可选的 IP 白名单。

Key 丢失请在系统里吊销并重新申请,我们不保存明文,无法找回。

二、限流与错误码

HTTP含义处理建议
401Key 无效或已吊销检查 Key,或重新申请
403权限不足 / IP 不在白名单看返回 detail,别重试
429超出每分钟调用上限退避重试(建议 60 秒后)
404资源不存在检查参数

三、接口

基础路径 https://ydcare.shop,全部 GET,返回 JSON。

1. 订单 read:orders

GET /open/v1/orders?status=&limit=50

{
  "count": 2,
  "data": [{
    "no": "CAPS20261112001", "status": "approved", "amount": 199.0,
    "created_at": "2026-11-12 10:21:33", "updated_at": "2026-11-12",
    "item_name": "维达 细韧小雏菊抽纸100抽3连包", "dept": "健康产品部",
    "supplier": "臻哒旺", "tracking_no": "SF1234567890",
    "expense_type": "行政费用"
  }]
}

2. 商品 read:catalog

GET /open/v1/catalog?q=抽纸&limit=100

{"count":1,"data":[{"id":"YZ5721376569","name":"维达 抽纸 130抽","spec":"130抽×10包",
  "unit":"箱","price":69.9,"cost":59.0,"category":"清洁与消杀","supplier":"臻哒旺"}]}

3. 预算 read:budget

GET /open/v1/budgets?year=2027

{"year":"2027","data":[{"dept_id":"RD","dept":"研发部","budget":470000.0,
  "used":128300.5,"remaining":341699.5,"usage_pct":27.3}]}

4. 供应商 read:suppliers

GET /open/v1/suppliers 手机号已脱敏(139****1263)。

5. 对账 read:recon

GET /open/v1/recon?month=2026-11

{"month":"2026-11","data":[{"supplier":"家化","n":13,"amount":1319.59,"no_invoice":2}]}

四、Webhook 事件推送

在系统「开放平台」里登记你的 https 回调地址,勾选事件。我们会在状态变化时 POST:

事件触发时机
order.approved订单审批通过
order.paid完成付款
order.shipped已发货(带快递信息)
order.received收货完成
oa.received每刻有新采购申请同步进来
recon.closed某供应商某月对账关账

请求头:

X-CAPS-Event: order.approved
X-CAPS-Timestamp: 1794421331
X-CAPS-Signature: 742de30f...(HMAC-SHA256 十六进制)
Content-Type: application/json

请求体:

{"event":"order.approved","sent_at":"2026-11-12 10:21:33",
 "data":{"no":"CAPS20261112001","amount":199.0,"item":"维达抽纸","dept":"健康产品部"}}

失败会按 1 分钟、5 分钟、30 分钟重试三次;连续失败请检查你的地址与验签逻辑。 你的处理必须幂等——同一事件可能重复到达。

五、验签示例

Python

import hmac, hashlib
from flask import Flask, request, abort

SECRET = "whsec_你的密钥"
app = Flask(__name__)

@app.post("/caps/hook")
def hook():
    ts = request.headers.get("X-CAPS-Timestamp", "")
    sig = request.headers.get("X-CAPS-Signature", "")
    body = request.get_data(as_text=True)
    expect = hmac.new(SECRET.encode(), f"{ts}.{body}".encode(), hashlib.sha256).hexdigest()
    if not hmac.compare_digest(expect, sig):
        abort(401)
    # 可选:检查时间戳新鲜度(5 分钟内)
    print(request.json)
    return {"ok": True}

Node.js

const crypto = require("crypto");
const SECRET = "whsec_你的密钥";

app.post("/caps/hook", express.text({type: "*/*"}), (req, res) => {
  const ts = req.get("X-CAPS-Timestamp") || "";
  const sig = req.get("X-CAPS-Signature") || "";
  const expect = crypto.createHmac("sha256", SECRET)
    .update(`${ts}.${req.body}`).digest("hex");
  const ok = expect.length === sig.length &&
    crypto.timingSafeEqual(Buffer.from(expect), Buffer.from(sig));
  if (!ok) return res.status(401).end();
  console.log(JSON.parse(req.body));
  res.json({ok: true});
});

六、安全说明

想接入?

提交申请后,采购中心会在 2 个工作日内联系你。通过审核才会发放 Key。

提交接入申请