浏览 AI使用教程

API 接口对接流程:先核对认证、请求、响应和错误格式

API 对接不要从复制成功响应开始。认证方式、请求头、字段类型、错误结构和最小可运行请求,才是双方能否联通的基础。

沿完整工作流推进

前一阶段的可检查结果,是下一阶段的输入;中间证据不足时停在当前阶段。

  1. 01先遇到 401、再遇到 422,问题其实出在两层
  2. 02先确认这次任务的起点、边界和交付
  3. 03从“认证与环境”走到“测试分页、超时和重试”
  4. 04只处理创建订单,不切换成订单查询
  5. 05完成后的API 契约核对表与最小请求
沿同一任务走到交付

先遇到 401、再遇到 422,问题其实出在两层

教学场景:阅读一个订单创建契约,先在本机模拟接口上复现201、401、422与幂等重试,再把相同检查方法用于已获授权的供应商沙盒。

完整本机模拟仅服务教学;下面预期结果不标为供应商实测。

  • 请求方法与地址全篇一致
  • 状态码、响应体与请求标识一起保存
  • 区分本地模拟与真实供应商验证
本例材料

先确认这次任务的起点、边界和交付

需要确认本例内容
现有材料Node.js 20+、PowerShell 7+;本机接口固定为 POST http://127.0.0.1:3210/v1/orders,Bearer lesson 为公开演示标记;body含sku与正整数quantity。
不能越过的边界模拟接口只监听127.0.0.1,不发送真实订单、不用真实凭证。模拟响应说明契约判断方法,不证明任何供应商API兼容或可用。
要交付的结果API 契约核对表与最小请求
处理记录

从“认证与环境”走到“测试分页、超时和重试”

当前阶段实际处理
认证与环境区分测试和生产端点、密钥类型、scope、请求头和轮换方式,不把密钥写进源码。
最小成功请求只带必填字段运行一次,保存脱敏请求、响应、状态码、请求 ID 和时间。
建立请求响应模型逐字段记录类型、必填、枚举、默认、空值和版本兼容,未知字段保持向前兼容。
按状态码处理错误区分用户输入、认证、权限、资源、限流和服务端错误,保留上游原始信息供诊断。
测试分页、超时和重试验证终止条件、幂等性、退避和取消,不对所有失败无限重试。
本例接口契约

只处理创建订单,不切换成订单查询

项约定检查
认证Authorization: Bearer lesson缺失或不符返回401
bodysku为非空字符串;quantity为正整数quantity=0返回422
幂等Idempotency-Key必填;相同键绑定相同body同键同体返回原订单;同键异体409
输出id、sku、quantity首次201;重复200;x-request-id用于串联
分页本端点无分页不要把列表游标要求套在创建端点
可运行输入

保存为 order-demo.mjs 并在一个终端运行

Node.js 20+

node order-demo.mjs

import http from 'node:http';
import { randomUUID } from 'node:crypto';
const records = new Map();
const server = http.createServer(async (req, res) => {
  const send = (status, body) => {
    res.writeHead(status, {'content-type':'application/json', 'x-request-id':randomUUID()});
    res.end(JSON.stringify(body));
  };
  if (req.method !== 'POST' || req.url !== '/v1/orders') return send(404, {error:'route_not_found'});
  if (req.headers.authorization !== 'Bearer lesson') return send(401, {error:'unauthorized'});
  const key = req.headers['idempotency-key'];
  if (!key) return send(400, {error:'missing_idempotency_key'});
  let body;
  try { let text = ''; for await (const part of req) text += part; body = JSON.parse(text); }
  catch { return send(400, {error:'invalid_json'}); }
  if (!body || typeof body.sku !== 'string' || !body.sku.trim() || !Number.isInteger(body.quantity) || body.quantity < 1)
    return send(422, {error:'invalid_order'});
  const fingerprint = JSON.stringify({sku:body.sku, quantity:body.quantity});
  const previous = records.get(key);
  if (previous) return previous.fingerprint === fingerprint
    ? send(200, previous.order) : send(409, {error:'idempotency_conflict'});
  const order = {id:randomUUID(), sku:body.sku, quantity:body.quantity};
  records.set(key, {fingerprint, order}); send(201, order);
});
server.listen(3210, '127.0.0.1', () => console.log('POST http://127.0.0.1:3210/v1/orders'));

Ctrl+C停止模拟服务。记录仅在内存中,重启会清空;它不实现生产鉴权、持久化或配额。

最小请求

在另一个 PowerShell 7 终端保留原始响应

PowerShell 7+

POST创建和重复请求

$headers = @{ Authorization = 'Bearer lesson'; 'Idempotency-Key' = 'lesson-order-1' }
$body = @{ sku = 'A-17'; quantity = 2 } | ConvertTo-Json -Compress
$response = Invoke-WebRequest -Uri 'http://127.0.0.1:3210/v1/orders' -Method Post -Headers $headers -ContentType 'application/json' -Body $body -SkipHttpErrorCheck
$response.StatusCode
$response.Headers['x-request-id']
$response.Content
# 原样再次执行 Invoke-WebRequest:预期200,订单id不变。
# 使用同一键,把quantity改为3:预期409。
# 删除Authorization:预期401;新键且quantity=0:预期422。

-SkipHttpErrorCheck是PowerShell 7参数;Windows PowerShell 5.1请换用pwsh运行本练习。真实接口应采用服务明确的认证、路径和幂等语义,不能直接替换域名猜测。

预期结果

完成后的API 契约核对表与最小请求

预期首次合法请求201;同一Idempotency-Key和相同body重发为200且id不变;同键不同body为409;缺认证401;quantity为0时422。需实际保存本机响应后才将对应项标为通过。

常见失败

为什么“最小请求成功,前端接入仍失败”还不能交付

最小请求成功,前端接入仍失败

原因
浏览器请求在 CORS、代理或序列化层改变
怎么改
对比实际网络请求与成功 curl,逐字段检查头、正文和环境
验收方式

API 契约核对表与最小请求通过哪些检查才算完成

进一步核对

后端与数据:参考资料与核对入口