402 Payment Required,附带 accepts: [...] 字段列出可接受的链 / 资产 / 价格;客户端在本地签好一笔授权(EVM 上是 Permit2 / EIP-712,Solana 上是 SPL token transfer 授权),把 base64 后的 envelope 放进 PAYMENT-SIGNATURE 头重发。服务端验证后真正去链上结算,再返回业务结果。
Ace Data Cloud 的 X402 客户端直接调用目标 API,并以该请求实时返回的402 Payment Required和accepts作为价格与签名依据。Facilitator 的支付能力可在/.well-known/x402核验。
@acedatacloud/sdk 和 acedatacloud 都暴露了一个 paymentHandler 钩子:当 SDK 自己发出的请求收到 402 时,调用你注入的 handler 拿到 PAYMENT-SIGNATURE 头,再重发原请求。把 @acedatacloud/x402-client / acedatacloud-x402 配合 SDK,整个流程对业务代码完全透明——你只用 client.openai.chat.completions.create(...) ,看起来和 token 模式一模一样,但底层是按调用付费、不需要事先充值。
本文:
- 真实串了一遍 TS 端的「无 token + X402 handler 注入」链路(T12 验证)
- 列了 EVM / Solana 两套签名链路的差异
- 给出
viem私钥模式、浏览器钱包模式、PythonEVMAccountSigner模式三种适配 - 把
preferScheme/prefer_scheme这个容易踩坑的字段说清楚
一、协议总览(必看)
一次成功的 X402 调用涉及 3 个 HTTP RTT:PAYMENT-SIGNATURE 头。结构(节选):
x402Version: 2,并用 accepted 对象声明本次选择的 scheme 和 network(CAIP-2 标识)。
preferScheme / prefer_scheme 用来在服务端同时提供多种 scheme 时选偏好。如果服务端只暴露 exact,这个字段会被忽略;如果设了 upto 但服务端没暴露,会回退到第一个匹配项。
二、TypeScript:浏览器钱包 + 服务端 viem 两套用法
安装
createX402PaymentHandler 完整签名
(ctx) => Promise<{ headers: Record<string, string> }>,正好对得上 SDK 的 paymentHandler 钩子签名。
用法 1:浏览器(MetaMask / WalletConnect)
MaxUint256,写进链);第二次是 X402 envelope 的 EIP-712 签名(不上链,只是给 facilitator 验证)。后续调用只需要第二次签名,体验上是“点一次签名 → 拿结果”。
用法 2:Node 服务端 + viem 私钥(适合后端 / CLI)
@acedatacloud/x402-client 在 TS 端只接受 EIP-1193 provider——它不直接管私钥。在 Node / CLI 场景,标准做法是用 viem 把私钥包成 WalletClient,再走 @ethereumjs/util 或 viem 内部的 EIP-1193 适配。
如果觉得 viem 的 EIP-1193 适配不够稳,也可以走更底层的signEVMUptoPayment,自己把accepts → signed envelope → PAYMENT-SIGNATURE header这条路串起来,跳过 SDK 钩子;不过推荐还是首选createX402PaymentHandler,省得自己维护协议升级。
用法 3:Solana
exact scheme,所以 preferScheme 在 Solana 上不起作用。
三、Python:私钥模式
Python 的acedatacloud-x402 走的是直接拿私钥签名的路(没有 EIP-1193 抽象),更适合服务端 / 任务执行器。
安装
EVM(Base / Skale)
Solana
一次性 approve(仅 EVM 首次)
EVM Base 上 X402 走 Permit2,需要钱包对 USDC 给 Permit2 合约做一次MaxUint256 的 approve。acedatacloud-x402 内置了 approve_permit2:
四、真实运行验证
测试目标:TS SDK 不传 token,注入 X402 handler,能正常构造并发起请求(不消耗真链上 USDC 的轻量验证)。- 没有传
apiToken,SDK 构造不报错,证明 X402 模式确实是 token 的合法替代品。 createX402PaymentHandler返回的是函数(钩子),SDK 拿到后只在收到 402 时才会调。- 实际链上付费走通的端到端测试,因为涉及真实 USDC 扣款,没放进本教程;可以参考 X402 集成指南 里的 e2e 示例。
Python 端create_x402_payment_handler也做了相同的验证 —— 函数返回值是 callable,注入payment_handler=...时AceDataCloud(...)构造不报错。两边语义对齐。
五、和「Bearer token 模式」的对比
两种模式可以共存——同一个进程里,给不同
client 实例配不同认证方式即可。
六、常见陷阱
- chat 类必须
preferScheme=upto:用exact会让 facilitator 按maxAmountRequired(不是实际用量)扣 USDC。 - Node 端别传裸私钥给
createX402PaymentHandler:TS 包不接受{ privateKey },必须包成 EIP-1193 provider(推荐 viemWalletClient)。 - 首次调用是双签名:第一次签 Permit2 approve(上链、有 gas),第二次签 X402 envelope(不上链)。后续调用只剩第二次。
- Solana 没有 Permit2 概念:直接签 SPL token transfer 授权,不需要 approve;但目前 Solana 链上只支持
exact。 - 业务报错和支付错误区分:402 → handler 失败抛
X402SignError(具体类型按链不同);后续重发后业务接口的报错(401 / 422 / 5xx)仍然按普通 SDK 异常分类。 viem适配最稳的写法:evmProvider: walletClient as any会失去类型检查但兼容性最好;如果想保留类型,用 viem 的.transport.request单独包一层{ request }对象传进去。

