CAPS 开放接口
把采购、预算、对账数据接进你自己的系统。只读 API + 事件推送,全程签名校验。 接入是申请制:提交申请 → 采购中心审核 → 发 Key。
一、认证
所有接口都要带 Key,两种写法等价:
X-API-Key: caps_xxxxxxxxxxxxxxxxxxxxxxxx
# 或
Authorization: Bearer caps_xxxxxxxxxxxxxxxxxxxxxxxx
Key 绑定了三样东西:权限范围(read:orders / read:catalog / read:budget / read:suppliers / read:recon)、 每分钟调用上限、可选的 IP 白名单。
Key 丢失请在系统里吊销并重新申请,我们不保存明文,无法找回。
二、限流与错误码
| HTTP | 含义 | 处理建议 |
|---|---|---|
| 401 | Key 无效或已吊销 | 检查 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});
});
六、安全说明
- Key 只存哈希,明文仅创建时可见;我们不记录你们的调用明细内容
- 手机等敏感字段默认脱敏;需要完整信息请走线下授权
- 所有管理动作(发 Key、吊销、改权限)都进变更记录,可倒查
- 建议你们的回调地址做 IP 白名单,并校验时间戳防重放
- 接入需审核:申请里写清用途,通过后会有人跟你确认对接方式
想接入?
提交申请后,采购中心会在 2 个工作日内联系你。通过审核才会发放 Key。
提交接入申请