x402 Fastify 支付中间件实战:用 HTTP 402 协议为 Fastify API 接入按次付费墙
2026/9/17 3:22:00 网站建设 项目流程

x402 Fastify 支付中间件实战:用 HTTP 402 协议为 Fastify API 接入按次付费墙

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

导读

本文基于 x402 仓库中的 examples/typescript/servers/fastify/README.md 及其配套源码,完整讲解如何用@x402/fastify中间件为 Fastify 服务端接入 x402 支付协议,实现「付费后才能访问 API 端点」的 HTTP 402 按量付费墙。读完本文,你将掌握paymentMiddleware的路由配置方法、x402ResourceServerExactEvmScheme/ExactSvmScheme的注册方式、HTTPFacilitatorClient的对接要点,以及402 Payment Required/PAYMENT-REQUIRED/PAYMENT-RESPONSE头部的完整交互格式,并能在本地把示例服务器与 Fetch、Axios 示例客户端跑通。

示例服务器概览:一个付费的天气 API

示例服务器位于 examples/typescript/servers/fastify,它基于 Fastify(v5,见 package.json)构建,仅暴露一个示例端点GET /weather。访问该端点需要支付0.001 USDC,并支持两条可选支付网络:

  • Base Sepoliaeip155:84532),使用 EVM 精确支付方案;
  • Solana Devnetsolana:EtWTRABZaYq6iMfeYKouRu166VU2xqa1),使用 SVM 精确支付方案。

支付成功后,端点返回一份简单的天气报告:{"report":{"weather":"sunny","temperature":70}}。服务器的监听端口固定为4021(与 HTTP 状态码 402 呼应),具体见 index.ts。

前置条件

运行该示例需要:

  • Node.js v20+(建议通过 nvm 安装);
  • pnpm v10(workspace 安装与构建依赖 pnpm);
  • 有效的 EVM 与 SVM 收款地址(分别对应EVM_ADDRESSSVM_ADDRESS);
  • 支持目标支付网络的 facilitator 服务 URL

需要说明的是:x402 协议中,facilitator 负责在链上验证并结算支付。示例服务器本身不直接连接链上 RPC 结算,而是把验证与结算委托给 facilitator 完成,因此必须配置一个可用的 facilitator 端点(FACILITATOR_URL)。

环境变量与启动流程

1. 配置环境变量

示例目录下提供了.env-local模板,先复制为.env

cp .env-local .env

然后填入三个必填环境变量:

变量说明
FACILITATOR_URLFacilitator 服务端点 URL,负责支付验证与链上结算
EVM_ADDRESS接收 EVM 支付的以太坊地址(0x前缀)
SVM_ADDRESS接收 Solana 支付的地址

从 index.ts 的源码可以看出,这三个变量缺一不可:缺失时程序会打印Missing required environment variables❌ FACILITATOR_URL environment variable is required并直接process.exit(1)。此外,index.ts通过dotenvconfig()在模块加载时自动加载.env,因此启动前务必完成第一步。

2. 安装并构建全部包

示例属于 TypeScript examples 的 pnpm workspace,需要先回到 examples 根目录安装并构建所有依赖包(包括@x402/core@x402/fastify@x402/evm@x402/svm@x402/extensions,见 package.json):

cd ../../ pnpm install && pnpm build cd servers/fastify

3. 启动服务器

pnpm dev

dev脚本使用tsx index.ts直接运行 TypeScript(见 package.json),无需先编译。启动成功后终端会输出Server listening at http://...:4021

核心代码逐行拆解

完整示例代码见 index.ts,其骨架如下:

import { config } from "dotenv"; import Fastify from "fastify"; import { paymentMiddleware, x402ResourceServer } from "@x402/fastify"; import { ExactEvmScheme } from "@x402/evm/exact/server"; import { ExactSvmScheme } from "@x402/svm/exact/server"; import { HTTPFacilitatorClient } from "@x402/core/server"; config(); const evmAddress = process.env.EVM_ADDRESS as `0x${string}`; const svmAddress = process.env.SVM_ADDRESS; const facilitatorUrl = process.env.FACILITATOR_URL; // ... 环境变量校验 ... const facilitatorClient = new HTTPFacilitatorClient({ url: facilitatorUrl }); const app = Fastify(); paymentMiddleware( app, { "GET /weather": { accepts: [ { scheme: "exact", price: "$0.001", network: "eip155:84532", payTo: evmAddress, }, { scheme: "exact", price: "$0.001", network: "solana:EtWTRABZaYq6iMfeYKouRu166VU2xqa1", payTo: svmAddress, }, ], description: "Weather data", mimeType: "application/json", }, }, new x402ResourceServer(facilitatorClient) .register("eip155:84532", new ExactEvmScheme()) .register("solana:EtWTRABZaYq6iMfeYKouRu166VU2xqa1", new ExactSvmScheme()), ); app.get("/weather", async () => { return { report: { weather: "sunny", temperature: 70 }, }; }); app.listen({ port: 4021 }, (err, address) => { /* ... */ });

代码由三部分构成:

  1. HTTPFacilitatorClient(来自@x402/core/server,实现见 httpFacilitatorClient.ts):封装对 facilitator 的 HTTP 通信,仅需传入url
  2. paymentMiddleware(app, routes, resourceServer):注册路由支付配置并注入支付处理逻辑。
  3. x402ResourceServer:以链式register(network, schemeServer)注册各网络的支付方案服务端实现——ExactEvmSchemeExactSvmScheme分别对应 EVM/SVM 的 exact 精确支付方案(服务端实现见 mechanisms/evm/src/exact/server/scheme.ts 与 mechanisms/svm/src/exact/server/scheme.ts)。

注意:原 README 中的示意代码只注册了 EVM 方案,而仓库中真实的 index.ts 同时注册了 EVM 与 SVM 两条链,并以accepts数组的形式为/weather端点声明了两种可接受的支付方式,属于更完整的多网络写法。

路由配置结构(RoutesConfig)

paymentMiddleware的第二个参数是一个以"METHOD /path"为键的路由配置对象,键必须包含 HTTP 方法与路径。单个端点的配置字段如下:

字段类型说明
accepts对象或数组可接受的支付方式;传数组表示支持多条网络/多种定价
scheme字符串支付方案,如"exact"(精确支付,对应 upto 的"上限支付"方案)
price字符串人类可读价格,如"$0.001",由中间件解析为对应资产的原子单位
network字符串CAIP-2 网络标识,如eip155:84532solana:EtWTRABZaYq6iMfeYKouRu166VU2xqa1
payTo字符串收款地址(EVM 为0x开头,SVM 为 Base58 地址)
description字符串资源描述,会进入支付要求(payment requirements)展示给客户端
mimeType字符串资源 MIME 类型,如application/json

中间件底层如何工作

paymentMiddleware的真正实现位于 typescript/packages/http/fastify/src/index.ts:它内部构造一个x402HTTPResourceServer,随后通过paymentMiddlewareFromHTTPServer在 Fastify 实例上注册两个核心钩子(见同文件 index.ts):

  • onRequest钩子:把 Fastify 请求包装为FastifyAdapter,判断路径是否需要支付(requiresPayment);若需要,调用processHTTPRequest校验支付头(payment-signaturex-payment)。校验失败返回 402 及支付要求;校验通过则把支付上下文挂到request.x402Context,放行到业务路由。
  • onSend钩子:在响应发送前调用processSettlement完成链上结算,成功后在响应头写入PAYMENT-RESPONSE;若结算失败则改写响应为 402。对未受保护的路由或 4xx/5xx 响应则跳过结算。

其中FastifyAdapter实现了@x402/coreHTTPAdapter接口,负责屏蔽框架差异(头部大小写归一化、URL/路径/查询参数提取、body 获取等),源码见 adapter.ts,其行为由 adapter.test.ts 中的单元测试覆盖,例如getHeader大小写不敏感、getPath会去掉查询串、getUrl拼接protocol://host + url等。

用示例客户端验证付费流程

示例服务器配套了 Fetch 与 Axios 两种客户端,分别位于 examples/typescript/clients/fetch 与 examples/typescript/clients/axios。在各自目录下确认.env已配置后运行:

cd ../clients/fetch pnpm dev
cd ../clients/axios pnpm dev

这些客户端会完整演示 x402 协议的三个标准步骤:

  1. 首次请求:不带支付信息访问受保护端点,收到402 Payment Required与支付要求;
  2. 处理支付要求:客户端解析支付要求,签名并构造支付 token(通过 Permit2 等机制授权支付);
  3. 二次请求:携带支付 token 再次访问,拿到 200 响应与真实业务数据。

这也是 x402「先要价、后付款、再放行」的 HTTP 原生交互模型,客户端与服务器之间不依赖任何私有 SDK 约定。

响应格式详解

未支付:402 Payment Required

未携带有效支付信息时,服务器返回:

HTTP/1.1 402 Payment Required Content-Type: application/json; charset=utf-8 PAYMENT-REQUIRED: <base64-encoded JSON> {}

其中PAYMENT-REQUIRED头包含 base64 编码的支付要求 JSON,结构如下(示例来自 README,金额已换算为原子单位):

{ "x402Version": 2, "error": "Payment required", "resource": { "url": "http://localhost:4021/weather", "description": "Weather data", "mimeType": "application/json" }, "accepts": [ { "scheme": "exact", "network": "eip155:84532", "amount": "1000", "asset": "0x036CbD53842c5426634e7929541eC2318f3dCF7e", "payTo": "0x1c47E9C085c2B7458F5b6C16cCBD65A65255a9f6", "maxTimeoutSeconds": 300, "extra": { "name": "USDC", "version": "2", "resourceUrl": "http://localhost:4021/weather" } }, { "scheme": "exact", "network": "solana:EtWTRABZaYq6iMfeYKouRu166VU2xqa1", "amount": "1000", "asset": "4zMMC9srt5Ri5X14GAgXhaHii3GnPAEERYPJgZJDncDU", "payTo": "FV6JPj6Fy12HG8SYStyHdcecXYmV1oeWERAokrh4GQ1n", "maxTimeoutSeconds": 300, "extra": { "feePayer": "...", "resourceUrl": "http://localhost:4021/weather" } } ] }

关键点:

  • 金额使用原子单位。例如amount: "1000"表示 0.001 USDC(USDC 为 6 位小数,1000 / 10^6 = 0.001)。这是price: "$0.001"被方案服务端解析后的结果,开发者对接时切勿把原子单位当作小数直接使用。
  • accepts是数组,对应配置中的多网络accepts,客户端可任选其一完成支付。
  • asset为代币合约地址(EVM)或代币 Mint 地址(SVM),payTo为收款方。
  • maxTimeoutSeconds: 300表示支付有效期上限。
  • extra中携带协议内部元数据(如资源 URL、SVM 的feePayer),客户端应原样回传。

支付成功:200 OK

HTTP/1.1 200 OK Content-Type: application/json; charset=utf-8 PAYMENT-RESPONSE: <base64-encoded JSON> {"report":{"weather":"sunny","temperature":70}}

PAYMENT-RESPONSE头包含 base64 编码的结算详情 JSON:

{ "success": true, "transaction": "0x...", "network": "eip155:84532", "payer": "0x...", "requirements": { "scheme": "exact", "network": "eip155:84532", "amount": "1000", "asset": "0x036CbD53842c5426634e7929541eC2318f3dCF7e", "payTo": "0x...", "maxTimeoutSeconds": 300, "extra": { "name": "USDC", "version": "2", "resourceUrl": "http://localhost:4021/weather" } } }

transaction为链上交易哈希,network为实际结算网络,requirements回显了本次支付实际采用的要求(用于对账与审计)。

扩展示例:增加更多付费端点

新增付费端点的模式非常固定:先扩展paymentMiddleware的路由配置,再像普通 Fastify 路由一样定义业务逻辑:

// 1. 在中间件中声明新端点的支付要求 paymentMiddleware( app, { "GET /your-endpoint": { accepts: { scheme: "exact", price: "$0.10", network: "eip155:84532", payTo: evmAddress, }, description: "Your endpoint description", mimeType: "application/json", }, }, resourceServer, ); // 2. 按常规方式实现业务路由 app.get("/your-endpoint", async () => { return { // Your response data }; });

路径键同样支持通配符等 Fastify 风格的匹配模式(@x402/fastify包 README 中即展示了"GET /api/premium/*"这类多路由配置,见 typescript/packages/http/fastify/README.md)。

网络标识采用 CAIP-2 格式

network字段遵循 CAIP-2 链标识规范,常用示例:

网络标识对应网络
eip155:84532Base Sepolia(测试网)
eip155:8453Base Mainnet(主网)
solana:EtWTRABZaYq6iMfeYKouRu166VU2xqa1Solana Devnet(测试网)
solana:5eykt4UsFv8P8NJdTREpY1vzqKqZKvdpSolana Mainnet(主网)

x402ResourceServer 配置

x402ResourceServer采用链式 builder 模式注册各网络的支付方案服务端,声明每个网络应如何被处理:

const resourceServer = new x402ResourceServer(facilitatorClient) .register("eip155:*", new ExactEvmScheme()) // 匹配所有 EVM 链 .register("solana:*", new ExactSvmScheme()); // 匹配所有 SVM 链
  • register的第一个参数是网络标识,支持*通配符批量匹配同一体系的所有链(如eip155:*),示例服务器则使用了精确匹配(eip155:84532);
  • 第二个参数是SchemeNetworkServer实现,本示例用到的是 exact(精确支付)方案。

paymentMiddleware(传入预构建的 resourceServer)外,@x402/fastify还提供两个同族 API(见 typescript/packages/http/fastify/src/index.ts):

  • paymentMiddlewareFromHTTPServer(app, httpServer, ...):直接传入预配置的x402HTTPResourceServer,适合需要定制 HTTP 层钩子的场景;
  • paymentMiddlewareFromConfig(app, routes, facilitatorClients, schemes, ...):由中间件内部创建 resourceServer,仅需传入 facilitator 客户端与方案注册数组,适合快速上手。

三者共享可选的paywallConfigpaywall(自定义支付页 Provider)与syncFacilitatorOnStart(启动时是否同步 facilitator,默认true)参数。默认情况下,当浏览器(Accept: text/html)访问受保护端点时会返回一个内建的基础 HTML 支付说明页;如需完整的钱包连接与支付 UI,可安装@x402/paywall并传入paywallConfig(如{ appName, appLogo, testnet })。

Facilitator 配置

HTTPFacilitatorClient负责与 facilitator 服务通信,由 facilitator 在链上完成支付验证与结算:

const facilitatorClient = new HTTPFacilitatorClient({ url: facilitatorUrl }); // 或者传入多个 facilitator 以提升可用性 const facilitatorClient = [ new HTTPFacilitatorClient({ url: primaryFacilitatorUrl }), new HTTPFacilitatorClient({ url: backupFacilitatorUrl }), ];
  • 单个HTTPFacilitatorClient只需配置url
  • 传入数组即实现多 facilitator 冗余:x402ResourceServer会按顺序/策略轮询,主服务不可用时回退到备用服务;
  • 需要鉴权的自建 facilitator 还可以在构造时传入createAuthHeaders,为 verify 与 settle 请求分别生成请求头(参考 typescript/packages/http/fastify/README.md)。

下一步:进阶能力

本示例演示的是最基础的 exact 付费墙。仓库中的 examples/typescript/servers/advanced 提供了更丰富的进阶场景:

  • Bazaar discovery—— 让 API 可被发现(对接 Bazaar 市场发现机制);
  • Dynamic pricing—— 基于请求上下文动态定价;
  • Dynamic payTo—— 按请求把支付路由到不同收款方;
  • Lifecycle hooks—— 在 verify/settle 阶段注入自定义逻辑;
  • Custom tokens—— 接受自定义代币支付。

对应的实现细节可在 typescript/packages/extensions 的扩展包与 typescript/packages/mechanisms 的方案实现中找到;x402 协议本身的完整规范参见 specs/x402-specification-v2.md 与 specs/transports-v2/http.md。

小结

通过@x402/fastify,只需三步即可让 Fastify 端点变成按次付费资源:配置accepts支付要求、用x402ResourceServer.register()注册网络方案、通过HTTPFacilitatorClient对接 facilitator。整个支付协商过程完全构建在 HTTP 语义之上(402 状态码 +PAYMENT-REQUIRED/PAYMENT-RESPONSE头部),无需改动路由业务逻辑,客户端也只需遵循标准的三步交互即可完成付款访问。配合多网络accepts数组、通配符方案注册与多 facilitator 冗余,该中间件可以平滑支撑从测试网演示到主网生产的多链付费 API 场景。

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

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

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

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

立即咨询