x402 Python SDK 实战指南:基于 httpx 的异步 402 支付请求与 EVM/SVM 双链支持
2026/9/17 23:26:33 网站建设 项目流程

x402 Python SDK 实战指南:基于 httpx 的异步 402 支付请求与 EVM/SVM 双链支持

【免费下载链接】x402A payments protocol for the internet. Built on HTTP.项目地址: https://gitcode.com/GitHub_Trending/x4/x402

本文基于 x402 仓库中的官方示例 examples/python/clients/httpx/README.md,讲解如何使用 x402 v2 Python SDK 的 httpx 异步客户端访问受 402(Payment Required)保护的 API 端点。读完后你将能够:配置并运行一个支持以太坊(EVM)与 Solana(SVM)两种链上支付的客户端、理解 SDK 在底层 Transport 层自动拦截 402、签名并携带支付头重发的完整机制,以及如何从响应头中解析出结算确认(Settlement)信息。

1. 示例定位与目录结构

该示例位于examples/python/clients/httpx/,是 x402 Python SDK 系列客户端示例之一(同目录下还有 requests 同步客户端示例 等)。它演示的核心场景是:httpx 是异步 HTTP 客户端,SDK 为其提供了带支付能力的x402HttpxClient,让调用方对 402 协议完全无感

examples/python/clients/httpx/ ├── .env-local # 环境变量模板(私钥、服务器地址、端点路径) ├── main.py # 示例主程序 ├── pyproject.toml # uv 项目配置 ├── uv.lock # 依赖锁定文件 └── README.md # 本文对应的原始文档

依赖声明见 pyproject.toml:要求Python >= 3.10,依赖python-dotenvx402[httpx,evm,svm]。其中x402通过 uv 的本地路径源以可编辑(editable)模式指向仓库内的 SDK 源码python/x402,因此该示例天然跟随仓库内 SDK 的最新状态:

[project] name = "x402-httpx-example" requires-python = ">=3.10" dependencies = [ "python-dotenv>=1.0.0", "x402[httpx,evm,svm]", ] [tool.uv.sources] x402 = { path = "../../../../python/x402", editable = true }

[httpx,evm,svm]是三个可选依赖组(extra):httpx提供异步传输封装,evm/svm分别提供两条链的支付机制(scheme)与签名器。

2. 环境准备

2.1 配置环境变量

仓库提供了模板文件 .env-local,复制为.env并填入私钥:

cp .env-local .env

.env-local的默认内容为:

EVM_PRIVATE_KEY= SVM_PRIVATE_KEY= RESOURCE_SERVER_URL=http://localhost:4021 ENDPOINT_PATH=/weather
变量说明
EVM_PRIVATE_KEYEVM 链私钥(带或不带0x前缀均可)
SVM_PRIVATE_KEYSolana 私钥(base58 编码)
RESOURCE_SERVER_URL受 x402 保护的服务器基地址(默认模板为http://localhost:4021
ENDPOINT_PATH受保护端点的路径(默认模板为/weather

注意:EVM_PRIVATE_KEYSVM_PRIVATE_KEY至少提供其一。这一点在 main.py 的validate_environment()中得到了代码级印证(L22-L49):函数依次读取四个环境变量,若两个私钥均为空、或服务器地址/端点路径缺失,则打印缺失项并以sys.exit(1)终止。

2.2 安装依赖并运行

# 安装依赖(uv 会自动读取 pyproject.toml 中的本地路径源) uv sync # 运行示例 uv run python main.py

运行效果:客户端向{RESOURCE_SERVER_URL}{ENDPOINT_PATH}发起 GET 请求;若服务器返回 402,SDK 自动完成支付并返回成功响应,同时打印响应状态码、响应体以及从响应头解码出的SettleResponseJSON。

3. 完整支付流程:main.py 逐段解析

main.py 是官方文档“Code Overview”一节的完整可运行版本,整体流程分四步。

3.1 第一步:创建 x402 支付客户端

from x402 import x402Client client = x402Client()

x402Client是 v2 SDK 的异步客户端核心,本身不感知 HTTP,只负责:按网络注册支付机制(scheme)、在收到 402 时选择合适的机制创建并签名支付载荷(payment payload)。

3.2 第二步:注册 EVM 与 SVM 支付机制

from eth_account import Account from x402.mechanisms.evm import EthAccountSigner from x402.mechanisms.evm.exact.register import register_exact_evm_client from x402.mechanisms.svm import KeypairSigner from x402.mechanisms.svm.exact.register import register_exact_svm_client # 注册 EVM(以太坊系)支付 if evm_private_key: account = Account.from_key(evm_private_key) register_exact_evm_client(client, EthAccountSigner(account)) print(f"Initialized EVM account: {account.address}") # 注册 SVM(Solana 系)支付 if svm_private_key: svm_signer = KeypairSigner.from_base58(svm_private_key) register_exact_svm_client(client, svm_signer) print(f"Initialized SVM account: {svm_signer.address}")

签名器分别来自 python/x402/mechanisms/evm/signers.py 的EthAccountSigner(包装eth_account.Account)与 python/x402/mechanisms/svm/signers.py 的KeypairSigner(从 base58 私钥构造)。

两个register_*_client帮助函数值得展开。以 EVM 版 register_exact_evm_client 为例,其源码显示它一次做了三件事:

  1. 将传入的 signer 经_wrap_if_local_account归一化后,构造ExactEvmClientScheme
  2. 若未指定networks参数,则按eip155:*通配符注册 V2 机制——即该客户端可响应任意 EVM 网络(如eip155:8453Base、eip155:1主网等)的 exact 支付要求;若指定了具体网络则逐个注册;
  3. 同时为所有 V1 遗留网络注册ExactEvmSchemeV1,保证对旧版 x402 v1 服务器的向后兼容。

SVM 版 register_exact_svm_client 结构相同,只是 V2 通配符为solana:*,且多一个可选参数rpc_url用于指定自定义 RPC 端点。两个函数都支持policies参数注册支付策略,并在末尾返回 client 以支持链式调用。

3.3 第三步:发起请求,402 由 SDK 自动处理

from x402.http import x402HTTPClient from x402.http.clients import x402HttpxClient http_client = x402HTTPClient(client) # 用于事后解析支付响应头 url = f"{base_url}{endpoint_path}" async with x402HttpxClient(client) as http: response = await http.get(url) await response.aread() print(f"Response status: {response.status_code}") print(f"Response body: {response.text}")

对业务代码而言,x402HttpxClient就是一个普通的httpx.AsyncClientget/post/...用法不变,但返回的永远不是“原始的” 402——拦截、付费、重试全部发生在传输层。其底层实现见第 4 节。

3.4 第四步:提取支付结算确认

try: settle_response = http_client.get_payment_settle_response( lambda name: response.headers.get(name) ) print(f"\nPayment response: {settle_response.model_dump_json(indent=2)}") except ValueError: print("\nNo payment response header found")

get_payment_settle_response接收一个“按名称取响应头”的回调,内部依次检查PAYMENT-RESPONSE(V2)与X-PAYMENT-RESPONSE(V1)两个头,将 base64 解码为SettleResponse对象(含交易哈希/签名等结算凭据),见 python/x402/http/x402_http_client_base.py。若两个头都不存在则抛出ValueError,示例中据此优雅降级为“无支付响应头”提示——这对应了请求根本没有经过付费路径的情况(例如端点未受保护)。

4. 底层原理:Transport 层的 402 拦截与重发

为什么 SDK 选择 Transport 而非 httpx 的事件钩子(event hooks)?这是理解整个异步封装的关键设计决策。

httpx 的 request/response 事件钩子无法替换最终返回给调用方的 Response 对象,因此 SDK 实现了一个自定义异步传输 x402AsyncTransport:它继承httpx.AsyncBaseTransport,内部再包装一个默认AsyncHTTPTransport,在handle_async_request中拦截并改写响应。源码注释明确写道:“Unlike event hooks, transports can control the response returned.”。完整的处理链为:

  1. 透传非 402 响应response.status_code != 402时原样返回;
  2. 防止无限重试:检查请求扩展字段中的RETRY_KEY(值为"_x402_is_retry")。若当前请求已是重试请求仍收到 402(例如余额不足、签名被拒),直接把 402 交还给调用方,不再二次付费;
  3. 解析支付要求:调用get_payment_required_response(get_header, body)——优先读PAYMENT-REQUIRED头(V2 格式),头不存在时回退解析 JSON 响应体中x402Version == 1的 V1 格式,两者皆无则报ValueError(见 x402_http_client_base.py);
  4. 创建并签名支付载荷await self._client.create_payment_payload(payment_required)按网络匹配已注册的 scheme 完成签名;
  5. 编码支付头encode_payment_signature_header根据载荷版本选择头名——V2 用PAYMENT-SIGNATURE,V1 用X-PAYMENT,值为 base64 编码(见 x402_http_client_base.py 与 python/x402/http/utils.py);
  6. 克隆请求并重发:拷贝原请求的 method/url/content,更新头(含Access-Control-Expose-Headers: PAYMENT-RESPONSE,X-PAYMENT-RESPONSE,便于跨域场景下前端脚本读取结算头),在 extensions 中打上RETRY_KEY标记,然后经同一底层 transport 重发,返回重试后的响应;
  7. 错误归一化:任何处理过程中的异常都被包装为PaymentError抛出,调用方可捕获统一处理。

对应的测试位于 python/x402/tests/unit/http/clients/test_httpx.py,覆盖了 402 拦截、重试标记、异常分支等行为。

5. SDK 提供的四种 httpx 接入方式

x402HttpxClient(本示例采用)只是四种官方接入方式之一,全部定义在 python/x402/http/clients/httpx.py,总览文档见 python/x402/http/clients/README.md:

接入方式适用场景用法
x402HttpxClient最常用,继承httpx.AsyncClientasync with x402HttpxClient(client) as http: ...
x402_httpx_transport()已有httpx.AsyncClient构造逻辑,只替换 transporthttpx.AsyncClient(transport=x402_httpx_transport(client))
wrapHttpxWithPayment()一行创建带支付的客户端,可透传额外 httpx 参数async with wrapHttpxWithPayment(client) as http: ...
wrapHttpxWithPaymentFromConfig()不想手动 register,用x402ClientConfig声明式配置async with wrapHttpxWithPaymentFromConfig(config) as http: ...

其中FromConfig变体基于x402ClientConfig+SchemeRegistration声明方案与网络,例如注册ExactEvmScheme(signer=...)eip155:8453,适合配置驱动的部署形态。

两点需要注意:

  • 同步/异步必须匹配:httpx(异步)必须搭配异步的x402Clientrequests(同步)则搭配x402ClientSync。混用会抛出TypeError(见 clients README 的 “Sync/Async Matching” 一节)。
  • x402_httpx_hooks已废弃:SDK 保留了该函数仅用于 API 兼容,调用时会触发DeprecationWarning并返回空钩子(httpx.py),原因是 httpx 事件钩子无法改写响应。新代码应使用 transport 方式。

6. 运行验证与小结

在填好.env(至少一个私钥)后执行:

uv run python main.py

预期输出依次为:初始化信息(Initialized EVM account: 0x...Initialized SVM account: ...)、请求 URL、响应状态码与响应体(如/weather端点返回的天气文本),以及Payment response:后跟SettleResponse的 JSON(含链上结算凭据)。若服务器端点不受保护或响应中无支付头,则输出No payment response header found

总结本示例的技术要点:

  • 零侵入:业务代码只写await http.get(url),402 拦截、方案匹配、载荷签名、头编码、重试全部在 x402AsyncTransport 内闭环完成;
  • 双链支持:通过 register_exact_evm_client / register_exact_svm_client 注册eip155:*/solana:*通配方案,并同时兼容 V1 遗留网络;
  • 可验证的结算:用x402HTTPClient.get_payment_settle_responsePAYMENT-RESPONSE头还原结算确认,作为交易凭据存档或展示。

想进一步深入 SDK 全貌(服务器端中间件、facilitator、MCP 集成等),可继续阅读 python/x402/README.md 与同目录下的 requests 同步客户端示例。

【免费下载链接】x402A payments protocol for the internet. Built on HTTP.项目地址: https://gitcode.com/GitHub_Trending/x4/x402

创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考

需要专业的网站建设服务?

联系我们获取免费的网站建设咨询和方案报价,让我们帮助您实现业务目标

立即咨询