从一次 API 调用到独立验签
按顺序完成 Request ID 提取、在线查询、证据下载和离线验签。真实日志同步可能需要几分钟。
完成后可以核对的内容
✓ Q-API 记录了指定 Request ID
✓ New API 记录了 OAuth 渠道选择
✓ 请求模型与实际转发模型
✓ 输入、缓存输入和输出 Token 计量
✓ Ed25519 签名与载荷哈希一致
✓ 证据记录进入链式 Merkle 检查点
第 1 步:发送最小检测请求
使用较短提示词即可。加上 -i 保留响应头。
curl -i https://aiapi.qhunliv13.online/v1/chat/completions \
-H "Authorization: Bearer sk-您的API密钥" \
-H "Content-Type: application/json" \
-d '{
"model": "gpt-5.6-sol",
"messages": [{"role": "user", "content": "Reply with OK only."}],
"max_tokens": 8
}'
保存响应头中的
X-QAPI-Request-ID。响应还会给出 X-QAPI-Trace-URL,可直接打开对应查询页。
第 2 步:在线查询请求证据
- 打开 请求可信验证。
- 粘贴完整 Request ID,然后点击“查询”。
- 等待系统同步真实日志并生成证据;繁忙时可能需要几分钟。
- 核对请求模型、实际转发模型、OAuth 渠道槽位、Token 数和时间。
- 点击“本地一键验签”,浏览器会在本机验证签名和哈希。
第 3 步:下载并阅读证据包
在查询结果中点击“下载证据包”,得到 qapi-evidence-REQUEST_ID.json。
| 字段 | 用途 | 核对重点 |
|---|---|---|
record | 冻结后的脱敏请求记录 | Request ID、模型、渠道、Token |
record_attestation | Q-API Ed25519 签名 | 载荷 SHA-256 与签名 |
merkle_proof | 检查点包含证明 | leaf、root 和记录哈希 |
checkpoint | 链式检查点 | 当前 root 与 previous root |
verified_scope | 本次已验证范围 | 逐项与页面结果对照 |
第 4 步:命令行离线验签
在项目目录执行;验证过程只读取本地 JSON。
python -m aiapi.verify_evidence qapi-evidence-REQUEST_ID.json
成功时会依次显示:
[PASS] Q-API record signature [PASS] Merkle inclusion proof [PASS] Checkpoint signature and root Evidence level: L2 Verified scope: signed record, routing evidence, and checkpoint integrity.
第 5 步:手动复算载荷哈希
需要独立复核时,按 JSON 键名排序并使用紧凑分隔符序列化,然后计算 SHA-256。
import hashlib, json
bundle = json.load(open("qapi-evidence-REQUEST_ID.json", encoding="utf-8"))
payload = json.dumps(
bundle["record"],
ensure_ascii=False,
sort_keys=True,
separators=(",", ":")
).encode("utf-8")
digest = hashlib.sha256(payload).hexdigest()
print("计算值:", digest)
print("签名值:", bundle["record_attestation"]["payload_sha256"])
assert digest == bundle["record_attestation"]["payload_sha256"]
结果判读
| 结果 | 含义 | 下一步 |
|---|---|---|
| PASS | 签名、哈希或检查点核对一致 | 继续核对下一项 |
| INFO | 附加见证信息或状态提示 | 结合证据包字段阅读 |
| FAIL | 文件内容、签名或检查点不一致 | 重新下载原始证据包并复核来源 |
| 未找到记录 | 日志尚未同步或 Request ID 输入不完整 | 等待几分钟后使用完整 ID 重试 |
常见问题排查
查询一直显示核查中:保留当前页面,等待日志分页同步完成后重新点击查询。
浏览器不支持本地验签:下载证据包,使用上面的 Python 离线验证命令。
Request ID 被截断:从原始响应头复制完整值。
模型字段不一致:在证据包中对照 model_name、forwarded_model 和 model_mapping。
需要保存审计材料:同时保存原始响应头、证据包、验证器输出和验证时间。