尧图网站设计 尧图网站设计YAOTU DESIGN
ARTICLE DETAIL

资讯详情

深耕网站设计与一线实操的经验洞察。

x402-hono 深度解析:在 Hono 应用中接入 x402 支付协议的 HTTP 402 付费墙中间件

x402-hono 深度解析:在 Hono 应用中接入 x402 支付协议的 HTTP 402 付费墙中间件 x402-hono 深度解析在 Hono 应用中接入 x402 支付协议的 HTTP 402 付费墙中间件【免费下载链接】x402A payments protocol for the internet. Built on HTTP.项目地址: https://gitcode.com/GitHub_Trending/x4/x402x402-hono是 x402 支付协议x402 v1针对 Hono 框架的官方中间件集成包它让开发者只需几行代码即可在任意 Hono 路由上挂起基于 USDC 的“按次付费”付费墙未支付请求收到 HTTP 402 响应携带X-PAYMENT请求头的合法支付则放行并按链上签名结算。阅读本文后你将掌握paymentMiddleware的完整参数体系、内置 Paywall 的渲染条件、可选的 Coinbase Onramp 集成步骤以及中间件从路由匹配、支付校验到结算回头的完整内部调用链并能读懂其单元测试如何固化这套行为。需要说明的是该包在 package.json 中标注的版本为 1.2.0位于legacy目录下README 明确声明它实现的是x402 v1 协议、已弃用、仅接受安全补丁生产项目应迁移到 v2 版本x402/hono、x402/core等迁移方法可参考仓库内的 Migration guide: v1 to v2。安装与快速上手安装npm install x402-hono包的 npm 名称为x402-hono见 package.json同时提供 ESM./dist/esm与 CJS./dist/cjs两种入口并额外导出./session-token子路径入口供 Onramp 集成使用。最小可用示例README 的 Quick Start 是可直接复制运行的最小集成覆盖“声明收费路由 → 实现业务路由 → 启动服务”三步import { Hono } from hono; import { paymentMiddleware, Network } from x402-hono; const app new Hono(); // Configure the payment middleware app.use(paymentMiddleware( 0xYourAddress, { /protected-route: { price: $0.10, network: base-sepolia, config: { description: Access to premium content, } } } )); // Implement your route app.get(/protected-route, (c) { return c.json({ message: This content is behind a paywall }); }); serve({ fetch: app.fetch, port: 3000 });启动后任何人直接访问/protected-route都会得到 402只有携带合法X-PAYMENT头的请求才能拿到 JSON 响应。paymentMiddleware 的四个参数paymentMiddleware的函数签名定义在 src/index.tsexport function paymentMiddleware( payTo: Address | SolanaAddress, routes: RoutesConfig, facilitator?: FacilitatorConfig, paywall?: PaywallConfig, )参数类型说明payToEVM 地址0x${string}或 Solana 地址收款地址。EVM 地址经viem的getAddress做校验和规范化solana/kit的SolanaAddress同样受支持routesRoutesConfig受保护路由及其定价配置见下文facilitatorFacilitatorConfig可选x402 结算服务Facilitator地址与鉴权头paywallPaywallConfig可选内置 Paywall 的展示与 Onramp 配置中间件初始化时会通过useFacilitator(facilitator)预先生成verify/settle/supported三个 Facilitator 客户端方法并用computeRoutePatterns(routes)把所有路由模式预编译成正则表达式避免每个请求重复编译。路由配置 RoutesConfig路由表的类型定义在 x402 底层包的类型文件type RoutesConfig Recordstring, Price | RouteConfig; interface RouteConfig { price: Price; // Price in USD or token amount network: Network; // 网络名如 base / base-sepolia / solana config?: PaymentMiddlewareConfig; }两个实用特性值得注意简写形式RoutesConfig的 value 允许直接是一个Price价格字符串/数字等价于只写了price的路由配置index.test.ts 中 computeRoutePatterns 的 mock 实现清晰展示了这种归一化逻辑。路径模式支持*通配与[...]路径参数例如/weather/*key 里还可以带 HTTP 动词前缀如GET /weather未指定动词时默认为*匹配所有方法——这一点同样体现在测试对路由匹配 mock 的处理中index.test.ts#L45-L71。price支持多种形式Price Money | ERC20TokenAmount | SPLTokenAmount美元字符串如$0.10、数字如0.01或指定资产最小单位的对象。中间件内部调用processPriceToAtomicAmount(price, network)将其换算成链上最小单位例如$0.001在 USDC6 位小数下会得到maxAmountRequired: 1000——这正是 index.test.ts 中断言的accepts数组内容。支持的网络README 示例里写的是base or base-sepolia但从 网络定义源码 看v1 实际支持的Network枚举远不止这两个。EVM 网络SupportedEVMNetworksbase、base-sepolia、avalanche、avalanche-fuji、polygon、polygon-amoy、iotex、sei、sei-testnet、abstract、abstract-testnet、peaq、story、educhain、skale-base-sepoliaSVM 网络SupportedSVMNetworkssolana、solana-devnet。配置不支持的网络时中间件会直接抛出Unsupported network: name有对应的测试用例固化该行为。EVM 与 Solana 构建 paymentRequirements 的差异源码 index.ts#L129-L203EVM 网络scheme固定为exact资产默认取该网络的 USDC 合约地址maxTimeoutSeconds缺省为300并在extra字段携带 USDC 的 EIP-712 域信息name/version供客户端生成 ERC-20 Permit 签名。测试中断言的accepts条目中可以看到asset: 0x036CbD53842c5426634e7929541eC2318f3dCF7eBase Sepolia USDC与extra: { name: USDC, version: 2 }。Solana 网络中间件会先调用 Facilitator 的supported()接口在返回的kinds中找到与当前networkexactscheme 匹配的条目并取出extra.feePayer拿不到 feePayer 时直接抛错The facilitator did not provide a fee payer for network: ...。maxTimeoutSeconds缺省为60mimeType缺省为空串。相关行为由 solana-devnet / solana 的两组 402 断言测试 覆盖。每路由支付配置 PaymentMiddlewareConfigREADME 列出的字段与 类型定义一致后者额外包含inputSchema与errorMessagesinterface PaymentMiddlewareConfig { description?: string; // 支付描述写入 402 响应的 paymentRequirements mimeType?: string; // 资源 MIME 类型EVM 下默认 application/json maxTimeoutSeconds?: number; // 支付有效窗口源码默认EVM 300 / SVM 60 inputSchema?: object; // HTTP 请求结构描述合并进 outputSchema.input outputSchema?: Recordstring, any; // 响应的 JSON Schema discoverable?: boolean; // 是否对外可发现默认 true customPaywallHtml?: string; // 完全自定义的付费墙 HTML resource?: string; // 资源 URL缺省为当前请求 URL反代下按 X-Forwarded-* 头重建 errorMessages?: { paymentRequired?: string; invalidPayment?: string; noMatchingRequirements?: string; verificationFailed?: string; settlementFailed?: string; }; }几点实现细节resource未显式指定时中间件会检查X-Forwarded-Proto与X-Forwarded-Host头两者都存在反向代理场景则用它们重建资源 URL否则退回c.req.urlindex.ts#L113-L127。description/mimeType/inputSchema/outputSchema最终都会打包进outputSchema: { input: {...}, output: ... }结构随 402 响应一起返回供 x402 客户端以及 AI Agent 等自动付费方机器可读地理解资源。errorMessages允许为五个失败阶段分别定制报错文案五组对应的单元测试逐条验证了自定义文案会覆盖默认错误。Facilitator 配置type FacilitatorConfig { url: string; // x402 facilitator 服务地址 createAuthHeaders?: CreateHeaders; // 可选为 verify/settle 请求生成鉴权头 };FacilitatorConfig定义于 middleware.ts#L8-L11。不传facilitator时使用公共测试网 Facilitatorhttps://x402.org/facilitator常量DEFAULT_FACILITATOR_URL见 useFacilitator.ts#L17。createAuthHeaders的返回结构要求按用途分桶提供头useFacilitator.ts#L19-L24type CreateHeaders () Promise{ verify: Recordstring, string; settle: Recordstring, string; supported: Recordstring, string; list?: Recordstring, string; };useFacilitator内部会向url/verifyPOST、url/settlePOST、url/supportedGET发起请求请求体携带x402Version、paymentPayload与paymentRequirements。若配置了createAuthHeaders则按verify/settle/supported分桶合并到各自请求头上——这意味着你可以为验证和结算使用不同的凭据。中间件核心流程从 402 到结算理解 paymentMiddleware 主体 的执行顺序等于理解了整个 v1 HTTP 支付协议的服务端一侧路由匹配取method与c.req.path用预编译的routePatterns调用findMatchingRoute不匹配则直接next()放行零开销。构建 paymentRequirements按上文 EVM / SVM 分支生成scheme: exact的支付要求数组。无X-PAYMENT头 → 返回 402。这里区分两类客户端浏览器Accept含text/html且User-Agent含Mozilla渲染 Paywall HTML 并以 402 返回金额按美元价格或链上最小单位换算展示testnet: network base-sepolia决定测试网标识API / 客户端返回 JSON 402{ error: X-PAYMENT header is required, accepts: [ { scheme: exact, network: base-sepolia, maxAmountRequired: 1000, payTo: 0x..., asset: 0x..., maxTimeoutSeconds: 300, ... } ], x402Version: 1 }测试 should return 402 with payment requirements when no payment header is present 断言了该响应结构浏览器分支则由 should return HTML paywall for browser requests 覆盖断言c.html以 402 被调用。解码支付头调用exact.evm.decodePayment(payment)将 Base64 编码的X-PAYMENT头还原为PaymentPayload并打上x402Version: 1。解码失败malformed header返回 402 invalidPayment错误。需要注意从源码结构看v1 中间件对所有网络包括 Solana 路由都使用 EVM 的decodePayment解析支付头这是 v1 的实现现状。匹配支付要求findMatchingPaymentRequirements(paymentRequirements, decodedPayment)找到与支付载荷网络/资产匹配的 requirement匹配不上返回 402 noMatchingRequirements。验证调用 FacilitatorverifyisValid false返回 402 并附带payer与失败原因异常如 Facilitator 连接失败同样落入 402 分支错误文案可用errorMessages.verificationFailed定制。放行业务await next()执行你的路由处理函数。结算与响应这里有两个关键防御——业务响应状态码≥ 400 时不做结算服务未成功交付则不扣款直接返回原响应状态码 400 时调用 Facilitatorsettle成功后把交易回执写入响应头X-PAYMENT-RESPONSE由settleResponseHeader生成结算失败则降级为 402 响应。源码注释解释了为何要先await next()再结算Hono 中间件无法在响应发出后再追加头因此结算必须在构造最终响应之前完成index.ts#L326-L334。这一完整路径402 拒绝 → 验证通过放行 → 结算写头 → 各失败分支的 402都有对应测试用例should verify payment and proceed if valid、should return 402 if payment verification fails、should handle settlement after response 等。内置 Paywall浏览器用户的支付入口当检测为浏览器请求时中间件调用getPaywallHtml生成付费墙页面。Paywall 组件位于 x402 底层包 paywall 目录其 README 说明了它的能力边界自动完成钱包连接、网络切换、余额检查与支付处理支持 Coinbase Smart Wallet、Coinbase EOA、MetaMask、Rabby、Trust Wallet、Frame以及 Phantom、Backpack 等符合 wallet-standard 的 Solana 钱包多链感知根据可用支付要求自动选择 Base / Base Sepolia / Solana / Solana Devnet 中最佳的一条并渲染对应钱包流程无需额外配置cdpClientKey为可选项启用后使用 Coinbase 托管 RPCEnhanced RPC改善连接性能Solana 流程运行时通过 Wallet Standard 发现已安装钱包仅在选中 Solana 支付要求时才请求solana:signTransaction权限。PaywallConfig四个字段类型见 middleware.ts#L13-L18type PaywallConfig { cdpClientKey?: string; // CDP Client API Key用于增强 RPC appName?: string; // 钱包选择弹窗中展示的应用名paywall 默认 Dapp appLogo?: string; // 钱包选择弹窗中的 Logo sessionTokenEndpoint?: string; // Onramp session token API 路径 };其中sessionTokenEndpoint直接决定付费墙是否显示 “Get more USDC” 充值按钮未配置时按钮隐藏。可选集成Coinbase OnrampOnramp 集成完全可选——没有它付费墙照常工作。它的作用是让钱包余额不足的用户直接从付费墙跳转 Coinbase Onramp 购买 USDC。README 给出五步配置下面逐一对应到实现。第 1 步创建 session token 路由import { Hono } from hono; import { POST } from x402-hono/session-token; const app new Hono(); app.post(/api/x402/session-token, POST);这个POST处理函数来自 session-token.ts其内部实现值得细看从环境变量读取CDP_API_KEY_ID/CDP_API_KEY_SECRET缺失时返回 500Missing CDP API credentials——这正是 README 故障排查第一条的出处请求体必须是{ addresses: [{ address, blockchains? }], assets? }addresses为空数组或缺失时返回 400addresses is required and must be a non-empty arrayblockchains缺省为[base]用coinbase/cdp-sdk的generateJwt以 Secret API Key 生成请求级 JWThost 为api.developer.coinbase.compath 为/onramp/v1/token随后携带该 JWT 调用 Coinbase Onramp 的 token 接口上游返回非 2xx 时原样透传状态码400/401/500与Failed to generate session token错误。第 2 步告知 Paywall 端点位置app.use(paymentMiddleware( payTo, routes, facilitator, { sessionTokenEndpoint: path/to/session-token-route, } ));路由注册路径与sessionTokenEndpoint必须完全一致例如配置/api/custom/onramp就要app.post(/api/custom/onramp, POST)不一致时 Paywall 前端请求会 404表现为 README 故障排查中的 “API route not found”。第 34 步准备 CDP 凭据并开启安全初始化在 CDP Portal 为你的项目创建 Secret API Key注意Onramp 需要的是Secret API Keys不是 Client API Keys——用错密钥类型是 “Missing CDP API credentials” 之外的另一类常见坑然后在 CDP Portal 的 Payments → Onramp Offramp 页面将 “Enforce secure initialization” 开关置为 Enabled。第 5 步设置环境变量# .env CDP_API_KEY_IDyour_secret_api_key_id_here CDP_API_KEY_SECRETyour_secret_api_key_secret_heresession-token.ts通过process.env读取这两个值session-token.ts#L20-L29因此必须在服务端运行环境中可用。Onramp 工作机制README 的 “How Onramp Works”1你的后端用 CDP API 安全地生成 session token2用户被携带 session token 重定向到 Coinbase Onramp3钱包地址与 app id 从不暴露在 URL 中——这正是 Secure Initialization 的设计目的。测试视角如何验证中间件行为如果你需要在自己的项目中复刻这套保障index.test.ts 是一个现成的行为清单该文件超过 1500 行mock 掉x402/verify与x402/paywall后它验证了 402 响应结构含accepts、x402Version: 1、Solana 网络要求extra.feePayer存在、缺失 feePayer 与不支持网络的抛错、五类自定义错误文案、浏览器收到 HTML 付费墙、验证失败/抛错的 402 降级以及验证通过后next()被调用、结算失败的 402 分支。session-token.test.ts 则覆盖了 Onramp 端点的凭据缺失、参数校验与上游错误透传场景。结语版本定位与迁移x402-hono的价值在于展示了 v1 时代 x402 协议在 Web 框架中的完整落地形态路由级定价、Facilitator 校验/结算分离、浏览器付费墙与 Onramp 充值闭环全部压缩在一个 Hono 中间件里。但它的定位已明确——README 顶部的弃用声明指出该包仅接受安全补丁新的 Hono 集成应使用 v2 体系x402/hono、x402/core、x402/evm等。本仓库的 typescript/packages/http/hono 即对应 v2 的 Hono 适配包如需从 v1 迁移可对照 迁移指南 处理协议字段与包名变化。【免费下载链接】x402A payments protocol for the internet. Built on HTTP.项目地址: https://gitcode.com/GitHub_Trending/x4/x402创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考
返回列表