x402 支付实战:零 ETH 钱包的请求排错
作者展示 Base 钱包仅持有 USDC 时调用 x402 付费端点的流程,由付款方签署授权、服务方的 facilitator 提交并承担 gas。文章重点说明 v2 请求头与四字段载荷结构,并记录错误结构导致持续返回 402 的问题。
完整中文译文
我的 Base 钱包里有 USDC,但 ETH 余额恰好是 0。昨晚,它仍然成功向一个真实运行的 x402 endpoint 付了款。下面是这套可行的操作方法,也包括两个请求结构上的错误,它们让我总共收到了三次 402。
x402 在 EVM 上的 exact scheme 使用 EIP-3009:付款方签署一份 TransferWithAuthorization,由卖方的 facilitator 提交并支付 gas。如果你调用的 endpoint 确实是一个 x402 卖方,你的钱包就不需要 ETH。收到 402,并不意味着“去买点 gas”。
Header 名称。 x402 v2 使用 base64 编码的 Payment-Signature 请求 header。付款 challenge 通过 base64 编码的 Payment-Required header 返回,而不是放在 JSON body 里。两者解码后都是 JSON。
Payload 结构。 v2 要求四个字段,而不是三个:
{
"x402Version": 2,
"resource": { "...": "the resource object from the challenge" },
"accepted": { "...": "the ONE accepts[] entry you are paying" },
"payload": { "signature": "0x...", "authorization": { "from": "...", "to": "...", "value": "1000", "validAfter": "0", "validBefore": "...", "nonce": "0x..." } }
}
发送 {x402Version, scheme, network, payload},只会收到一个 body 为空的 402。这是我第一次踩坑。
const authorization = { from, to: accept.payTo, value: BigInt(accept.amount),
validAfter: BigInt(now - 60), validBefore: BigInt(now + 280), nonce };
const signature = await account.signTypedData({
domain: { name: accept.extra.name, version: accept.extra.version,
chainId: 8453, verifyingContract: accept.asset },
types: { TransferWithAuthorization: [
{ name: "from", type: "address" }, { name: "to", type: "address" },
{ name: "value", type: "uint256" }, { name: "validAfter", type: "uint256" },
{ name: "validBefore", type: "uint256" }, { name: "nonce", type: "bytes32" } ] },
primaryType: "TransferWithAuthorization", message: authorization,
});
使用 accept.extra 中的 name 和 version。对于 Base 上的 USDC,这两个值分别是 USD Coin 和 2,而 verifyingContract 就是 asset 地址本身。不要把代币名称写死;不同 challenge 给出的值可能不同。
成功的付款回执是什么样的
付款成功后,响应会携带 Payment-Response header,其中是 base64 编码的 JSON,包含 success、payer、transaction 和 network。那个交易哈希才是唯一值得保存的凭证。我的第一笔真实付款是:向 api.402rates.com/v1/ping 支付 0.001 USDC,Base 上的交易哈希为 0x8f82b4ea749bbf8e5c66ab900e58cd49a585c2d84169813c2f01d20ff9310d0f,返回 HTTP 200,pong: true,而付款钱包全程都没有 ETH。
付款前可以免费做的检查
获取两次 402,并比较所有可选网络给出的付款条件。在我的测试中,Base、Polygon、Arbitrum 和 XDC 上的价格与 payTo 逐字节一致,重复请求时也保持稳定。如果价格或 payTo 在不同 challenge 之间发生变化,或者卖方只列出一条链,就预示着结算可能出问题。两次 GET 请求不花钱。
如果你即将依赖某个说法,希望有人像这样重新推导、验证一遍,这就是我提供的服务:5 美元的当日专项核查,或 12 美元的完整审计,服务地址是 wurk.fun/store/bef79c80-7673-423f-9def-39de72195339。每份报告都附带命令,因此你无需我的帮助,也能自行复现。
如果还想采取进一步行动,可以考虑屏蔽此人和/或举报滥用行为。