2026 年做 AI 服务的人都清楚一件事:API 变现的最后一米是支付。传统路径要过商户资质、类目审核、跨境结汇三道门,对个人开发者和小团队极不友好。x402 协议提供了另一种可能——HTTP 402 状态码复活了,Agent 之间用稳定币微支付,收款方只需要一个钱包地址,没有类目审核这回事。这篇文章记录我们把三条业务腿(提示词查询、视频解析、语料检索)按 x402 协议上线的全过程,包括 Express 路由、支付中间件、 facilitator 验收的四个实测坑,以及 Bazaar 目录竞品情报的副产品。所有金额以 $0.01/次为例,均为真实定价。

一、为什么是 x402
先看一个现实约束:某类业务(比如媒体解析工具)在传统支付服务商(MoR)的 AUP 里属于明文禁售类目——借已过关的其他业务店铺收款,一旦被查出,连累的是整个商户账户的冻结资金。这类”技术方案都通了、就是收不了钱”的死局,靠法币通道无解。
x402 的形态完全不同:
- 客户端(人或 Agent)请求付费资源 → 服务端返回
HTTP 402+ 付费要求头(价格、收款地址、网络、过期时间); - 客户端用钱包对该要求签名付款(Base 链 USDC 之类)→ 原样重试请求,附带
X-PAYMENT头; - 服务端把付款凭证交给 facilitator 结算上链 → 确认入账 → 返回 200 和资源内容。
收款方全程只暴露一个钱包地址。没有 KYC 类目、没有店铺审核、没有结算周期——链上收款天然免类目审核,这正是治 AUP 死穴的那条腿。风险形态也变了:从”账号被关”变成”私钥安全”,大额前人工核对地址/网络/金额即可。
二、服务端最小实现:三条设计规则
Express 实现(零重依赖,一个 .mjs 文件跑起服务),一周内三条腿复用同一份骨架,只改后端反代地址。踩出来的规则:
规则 1:路由参数用 [param] 不是 :param
x402 的路径匹配器(用于按 URL pattern 挂价格)用 Express v5 风格方括号:
// 正确:/x402/parse/[id]
// 错误:/x402/parse/:id —— 永不匹配,且**不报任何错**
第二条是最阴险的:价格挂不上,所有请求都 404 或裸 402 死循环,没有任何日志提示。上线前逐条自测 catalog 返回的 pattern 与真实路由是否一致。
规则 2:paymentMiddleware 必须在业务路由之前
app.use(x402().paymentMiddleware); // ← 先挂
app.get('/x402/parse/:id', handler); // ← 后挂业务
顺序反了,付费路由等于没保护。
规则 3:长 hex 别走 shell 环境变量
收款地址这种 42 位 hex,通过 export PAYTO=0x... 传参时被 shell/剪贴板链路混入 U+2026(省略号字符)截断污染——服务启动不报错,付出去的款进了黑洞。改成落文件读:
const payTo = fs.readFileSync(SECRET_DIR + '/.payto', 'utf8').trim();
凭据、地址、密钥,一律文件进、命令行不进(和上一篇 Matomo token 的教训同源)。

三、facilitator 验收:四个实测坑
服务端写完,用自测页做端到端付款验证。四个坑挨个踩:
坑 1:自测页报价禁止内嵌静态值
第一版自测页把 $0.01 写死在 HTML 里。后来把某端点调价到 $0.05,自测页仍按 $0.01 生成支付要求——facilitator 拒付,用户白签一次钱包,还以为是协议坏了。
正解:自测页打开时实时 fetch 生产端点的 402 响应头,从 X-PAYMENT-REQUIRED 里解码真实报价再生成付款请求。报价的单一事实来源只能是服务端。
坑 2:报价头里的 resource.url 是路由模板
402 头里 resource.url 字段是 /parse/:id 这种模板字面量,不是具体请求 URL。自测页把它原样塞进回放,paywall 校验 URL 不匹配直接拒。要从当前实际请求 URL 重建 resource 字段。
坑 3:自付测试里”余额没变”≠”没付款”
用自己钱包付给自己钱包(from == to)做链路验证,签名、广播、确认全过了,钱包 UI 显示余额纹丝不动——差点误判成付款失败重签一次。
x402 结算的本质是 EIP-3009 transferWithAuthorization,转账永远发生,只是 from==to 时净变化为零。判成交的唯一铁证是 Transfer 事件 + 服务端 200:
// eth_getLogs,topic0 = USDC Transfer 事件哈希
// ddf252ad1be2c89b69c2b068fc378daa952ba7f637c03875984d7c0dc6f785e0
对 payTo 地址查 Transfer 日志,from/to 双 pad 到同一地址、value 对得上,就是成交。余额、钱包 UI 都不算数。
坑 4:Bazaar 目录收录是小时级批处理
首笔成交后立刻去 x402 Bazaar(端点目录)搜自己的服务——0 命中。链上 tx 已确认(status=0x1),目录里就是找不到。查了 3000 条全量目录后接受现实:目录收录按小时级批处理,不是即时的。别把”目录没收录”当成”服务没上线”来报警。
四、部署形态:三条腿共用一套模式
| 腿 | 服务 | 端口 | 入口 |
|---|---|---|---|
| 提示词查询 | x402-prompt | 9100 | nginx location ^~ /x402/ 反代 |
| 视频解析 | x402-video | 9101 | 独立 vhost 片段插入 |
| 语料检索 | x402-corpus | 9102 | 面板 extension 目录 conf |
统一要点:
- systemd
Restart=always+MemoryMax限额,node 服务本体保持无状态; - nginx 反代处加
Cache-Control: no-store——付费头绝不能被边缘缓存,否则 A 用户的付款要求头被 B 用户拿去付一个过期报价; - 限速放在上游业务端(按访客 IP 分桶,XFF 透传真实 IP),x402 层只管收钱;
- 每条腿配一个”成交增量哨兵”:状态文件记下已报事件数,只在链上出现新 Transfer 时播报(老订单绝不重复报),把收款信号接到值班通道。

五、副产品:把竞品目录全量拉下来看
Bazaar 是公开目录。一次性脚本拉全量(实测 19,080 个端点),做了一张竞品分布表,得到三条可直接抄的打法:
- 端点数即货架:头部供给方不是单价高,而是把同一个能力拆成几十个粒度不同的端点——买”一次查询”的人远比买”订阅”的人多;
- Use-when 文案:好端点的描述全部是”当你需要 X 时用我”的意图句式,而不是功能罗列——Agent 是按意图选服务的,不是按介绍页;
- 价格带:微服务集中在 $0.001–$0.10,$0.01 是心理甜点位。
新腿定价直接参考这个分布定在 $0.01/次——先跑起来,让真实成交说话。
六、给 Agent 开发者的一句话
x402 目前最大的限制不是技术,是流量来源还主要是其他 Agent。对你的服务做 API 化改造(可寻址的资源、清晰的 catalog、按次计价的粒度),无论来的是人还是爬虫还是 Agent,路都提前修好了。收款这件事,第一次跑通 $0.01 的意义不在钱,在于证明整个闭环——报价、签名、结算、供货——在没有支付服务商参与的情况下也能自己转起来。
| 检查项 | 上线前必测 |
|---|---|
| catalog 返回的 pattern 与实际路由逐条一致 | 防 [param] 陷阱 |
| 自测页报价实时来自生产 402 头 | 防静态值过期 |
| 成交判定 = Transfer 事件 + 服务端 200 | 防 from==to 误判 |
| 反代 no-store | 防付款头被缓存 |
| Bazaar 收录按小时等 | 防误报警 |




