--- name: agent-payment-x402 description: 将 x402 支付执行添加到 AI 代理中,具备每任务预算、支出控制和非托管钱包。通过 agentwallet-sdk 支持 Base,通过 OKX Payments / OKX 代理支付协议支持 X Layer,并通过上游 x402 包与基于结算器的结算支持 Solana 及多网络 EVM。 origin: community --- # 代理支付执行 (x402) 让 AI 代理能够进行策略门控的支付并内置支出控制。使用 x402 HTTP 支付协议和 MCP 工具,使代理能够为外部服务、API 或其他代理付费,无托管风险。 ## 使用场景 适用于:代理需要支付 API 调用、购买服务、与其他代理结算、强制执行每任务支出限额,或管理非托管钱包。与 cost-aware-llm-pipeline 和 security-review 技能自然搭配。 ## 决策树 根据代理是购买对付费 API 的访问权,还是向他人收费,选择集成路径: | 需求 | 推荐路径 | |------|------------------| | 代理为 Base 或其他 agentwallet 支持链上的 402 门控 API 付费 | 使用 `agentwallet-sdk` 作为 MCP 支付服务器,并配置严格的支出策略 | | 代理为 X Layer 上的 402 门控 API 付费 | 使用 `okx/onchainos-skills` 中的 OKX 代理支付协议;`okx-x402-payment` 是已弃用的旧别名 | | 代理为 Solana 或其他 x402 v2 网络上的 402 门控 API 付费 | 用上游的 `@x402/fetch` 或 `@x402/axios` 包包装代理的 HTTP 客户端并注册 EVM/SVM 方案;由资源服务器的结算器验证和结算 | | API 在 Solana 或多个网络上向代理收费(TypeScript、Python 或 Go) | 使用来自 `x402-foundation/x402` 的上游 x402 中间件 —— TypeScript 用 `@x402/express`、`@x402/hono`、`@x402/next` 或 `@x402/fastify`,Python 用 `x402`,Go 用 `github.com/x402-foundation/x402/go/v2` | | TypeScript API 向代理收费 | 使用面向 Express、Hono、Fastify 或 Next.js 的 OKX Payments TypeScript 卖家 SDK 文档 | | Go API 向代理收费 | 使用面向 Gin、Echo 或 `net/http` 的 OKX Payments Go 卖家 SDK 文档 | | Rust API 向代理收费 | 使用面向 Axum 的 OKX Payments Rust 卖家 SDK 文档 | | Java API 向代理收费 | 使用面向 Spring Boot 2/3、Java EE 或 Jakarta 的 OKX Payments Java 卖家 SDK 文档 | | Python API 向代理收费 | 实现前先检查当前 OKX Payments 仓库;可能尚无 Python 卖家指南 | ## 支持的网络 - `agentwallet-sdk`:在生产使用前,通过包文档确认当前网络覆盖范围。Base Sepolia 是最安全的开发默认值;Base 主网是原始技能所述的生产路径。 - OKX Payments / X Layer:当前卖家文档面向 X Layer(`eip155:196`)和 USDT0 结算。由于支付包和结算器行为可能快速变化,生成生产代码前请获取当前 SDK 文档。 - 上游 x402 包:设计上即多网络 —— 一条路由可以同时提供 Base 和 Solana,由买方选择。包默认使用 `x402.org` 结算器,它仅限测试网(Base Sepolia `eip155:84532`、Solana 开发网 `solana:EtWTRABZaYq6iMfeYKouRu166VU2xqa1`,以及 Stellar、Aptos、Hedera、XRPL 测试网),不适用于主网路由。主网(Solana 为 `solana:5eykt4UsFv8P8NJdTREpY1vzqKqZKvdp`)请选择自结算、自行运行结算器,或从上游结算器列表中挑选托管方案——参见选项 C 中的结算器对比。生产前请在结算器的 `/supported` 端点确认实时覆盖范围,而不要在此硬编码。 ## 工作原理 ### x402 协议 x402 将 HTTP 402(需要付款)扩展为机器可协商的流程。当服务器返回 `402` 时,代理的支付工具会协商价格、检查预算、签署交易,并仅在编排器设定的策略与确认边界内重试。 ### 支出控制 每次支付工具调用都会强制执行 `SpendingPolicy`: - **每任务预算** — 单次代理操作的最大支出 - **每会话预算** — 整个会话的累计限额 - **白名单接收方** — 限制代理可支付的地址/服务 - **速率限制** — 每分钟/小时的最大交易数 ### 非托管钱包 代理通过 ERC-4337 智能账户持有自己的密钥。编排器在委托前设置策略;代理只能在限定范围内支出。无资金池,无托管风险。 ## MCP 集成 支付层暴露标准 MCP 工具,可无缝接入任何 Claude Code 或代理框架设置。 > **安全提示**:务必锁定包版本。此工具管理私钥——未锁定的 `npx` 安装会引入供应链风险。 ### 选项 A:agentwallet-sdk(Base / 多链) ```json { "mcpServers": { "agentpay": { "command": "npx", "args": ["agentwallet-sdk@6.0.0"] } } } ``` ### 可用工具(代理可调用) | 工具 | 用途 | |------|---------| | `get_balance` | 检查代理钱包余额 | | `send_payment` | 向地址或 ENS 发送付款 | | `check_spending` | 查询剩余预算 | | `list_transactions` | 所有付款的审计追踪 | > **注意**:支出策略由**编排器**在委托给代理之前设置——而非代理本身。这可防止代理自行提高支出限额。通过编排层或任务前钩子中的 `set_policy` 配置策略,切勿将其作为代理可调用工具。 ### 选项 B:OKX 代理支付协议(X Layer) 将此路径用于 X Layer x402、多方支付(MPP)、会话支付、收费和 A2A 收费流程。 对于买方代理流程: 1. 安装或引用当前的 `okx/onchainos-skills` 仓库。 2. 使用 `skills/okx-agent-payments-protocol/SKILL.md` 作为调度器。 3. 将 `skills/okx-x402-payment/SKILL.md` 视为已弃用的兼容别名,而非规范技能。 4. 在钱包状态检查或支付操作前要求明确的用户确认。不要将支付执行隐藏在通用工具调用之后。 对于卖方 API 流程,生成代码前先获取最新的语言专用指南: | 运行时 | 当前指南 | |---------|---------------| | TypeScript | `https://raw.githubusercontent.com/okx/payments/main/typescript/SELLER.md` | | Go | `https://raw.githubusercontent.com/okx/payments/main/go/x402/SELLER.md` | | Rust | `https://raw.githubusercontent.com/okx/payments/main/rust/x402/SELLER.md` | | Java | `https://raw.githubusercontent.com/okx/payments/main/java/SELLER.md` | 不要在未检查当前 OKX 仓库的情况下复制旧文档中的示例。当前 OKX 指南使用 `okx-agent-payments-protocol` 作为调度器,且 Java 卖家文档现已可用。 ### 选项 C:上游 x402 包(Solana + Base/EVM) 当代理在 Solana、Base 或上游协议实现支持的其他网络上付费(或你的 API 收费)时,使用此路径。位于 [`x402-foundation/x402`](https://github.com/x402-foundation/x402) 的规范 x402 monorepo 正在积极维护,并直接发布客户端和中间件包。与选项 A 和 B 不同,这不是独立的 MCP 服务器——你包装代理自己的 HTTP 客户端,由资源服务器选择的结算器验证并结算。 对于买方代理流程: 1. 从维护中的 [`examples/typescript/clients`](https://github.com/x402-foundation/x402/tree/main/examples/typescript/clients) 示例(fetch、axios、MCP)开始,而不是复制旧文档中的片段。 2. 在签署或提交第一笔付费请求之前要求明确的用户确认,与选项 B 对 OKX 流程的要求完全一致。不要将支付执行隐藏在通用工具调用之后。 3. 锁定包版本(例如 `@x402/fetch@2.22.0`);上游所有包以相同步调发布版本。 4. 用注册到客户端的 `PaymentPolicy` 强制预算,使检查在每次调用时都针对服务器的真实挑战运行。与你自己传入的数字比较的预算不能证明任何事——金额、资产和网络都来自服务器,因此必须在签名产生之前全部验证。 5. 在收款方和预算策略之外,单独配置精确的资源来源白名单。下方所有支付 fetch 均拒绝重定向。会话确认应明确列出允许的来源、网络、资产、收款方和以可读单位表示的支出上限;并发调用共享一次确认结果。客户端和策略只能由编排器持有。 ```typescript import { x402Client, wrapFetchWithPayment } from "@x402/fetch"; import { ExactEvmScheme } from "@x402/evm/exact/client"; import { ExactSvmScheme } from "@x402/svm/exact/client"; import { privateKeyToAccount } from "viem/accounts"; import { createKeyPairSignerFromBytes } from "@solana/kit"; import { base58 } from "@scure/base"; // Signer keys belong to the ORCHESTRATOR's env — never hardcoded, never agent-writable. const evmKey = process.env.EVM_PRIVATE_KEY as `0x${string}`; const svmKey = process.env.SVM_PRIVATE_KEY; if (!evmKey || !svmKey) { throw new Error("Signer keys are not set — refusing to start payment client"); } // One client, both network families: the buyer pays whichever chain the 402 offers. const client = new x402Client(); client.register("eip155:*", new ExactEvmScheme(privateKeyToAccount(evmKey))); client.register("solana:*", new ExactSvmScheme(await createKeyPairSignerFromBytes(base58.decode(svmKey)))); // A PaymentPolicy filters the SERVER's payment requirements before any // signature is created. Returning an empty array means "nothing here is // acceptable" and the client refuses to pay rather than falling back. const ALLOWED_NETWORKS = new Set([ "solana:5eykt4UsFv8P8NJdTREpY1vzqKqZKvdp", // Solana mainnet "eip155:8453", // Base ]); const MAX_AMOUNT = 10_000n; // atomic units, 6-decimal USDC: 0.01 USDC per call const SESSION_CAP = 50_000n; // 0.05 USDC across the whole session // EVM addresses are case-insensitive, so compare them lowercased. Solana // addresses are base58 and ARE case-sensitive — never lowercase those, or a // different account could slip through. const normalizeAddress = (a: string) => (a.startsWith("0x") ? a.toLowerCase() : a); const ALLOWED_ASSETS = new Set( [ "EPjFWdd5AufqSSqeM2qN1xzybapC8G4wEGGkZwyTDt1v", // USDC, Solana mainnet "0x833589fCD6eDb6E08f4c7C32D4f71b54bdA02913", // USDC, Base ].map(normalizeAddress), ); // Who you are willing to pay. Without this, any 402 an agent happens to hit // can name its own recipient. const ALLOWED_PAY_TO = new Set( ["7pr7NCaQRz5PEhPy7BAeB3Z72TVkiShhjRyVCN5DA6yC"].map(normalizeAddress), ); client.registerPolicy((_x402Version, requirements) => requirements.filter(r => { if (!ALLOWED_NETWORKS.has(r.network)) return false; // wrong chain if (!ALLOWED_ASSETS.has(normalizeAddress(r.asset))) return false; // wrong token if (!ALLOWED_PAY_TO.has(normalizeAddress(r.payTo))) return false; // wrong recipient try { const amount = BigInt(r.amount); return amount >= 0n && amount <= MAX_AMOUNT; // over budget / negative } catch { return false; // unparseable amount } }), ); // The policy sees one challenge at a time, so it cannot enforce a session // total or ask a human anything. Keep the payment-enabled client private and // route every paid call through the payOnce boundary below. // Supply this from your harness — a real prompt, never a stub that returns true. declare function confirmWithUser(prompt: string): Promise; // Resource authorization is independent of recipient and budget policy. // The ORCHESTRATOR supplies exact approved HTTPS origins before delegation; // never populate this set from a server challenge or agent-controlled input. const ALLOWED_ORIGINS = new Set(["https://api.example.com"]); function requireAllowedOrigin(url: string): void { const parsed = new URL(url); if (!ALLOWED_ORIGINS.has(parsed.origin) || parsed.username || parsed.password) { throw new Error("Resource origin is not authorized"); } } // Both approved assets above are 6-decimal USDC. Update this trusted formatting // policy along with the asset allowlist if you support other assets/decimals. const USDC_SCALE = 1_000_000n; const humanUSDC = (amount: bigint) => `${amount / USDC_SCALE}.${(amount % USDC_SCALE).toString().padStart(6, "0").replace(/0+$/, "") || "0"} USDC`; let sessionSpent = 0n; let sessionApproval: Promise | undefined; async function payOnce(url: string, init?: RequestInit): Promise { requireAllowedOrigin(url); // Before reservation, prompt, fetch, or signature. // Reserve the worst case the policy allows. Settlement responses do not // carry an amount, so counting MAX_AMOUNT per call is a deliberate // over-estimate — it can stop early, never late. Reserve before any await, // so concurrent calls cannot all pass the check. if (sessionSpent + MAX_AMOUNT > SESSION_CAP) { throw new Error("Session budget exhausted — blocked"); } sessionSpent += MAX_AMOUNT; // Release the reservation only when no signed payment left this process: // a declined or failed prompt, a challenge the policy rejected, or a free // response. Once a signed request is sent it may settle, so keep it counted. let signedRequestSent = false; const trackingFetch: typeof fetch = async (input, reqInit) => { // Override caller options on BOTH the challenge and signed retry. Native // fetch refuses redirects, so an unauthorized host cannot return a 402 // or receive a payment header via an automatic redirect. const req = new Request(input, { ...reqInit, redirect: "error" }); requireAllowedOrigin(req.url); if (req.headers.has("PAYMENT-SIGNATURE") || req.headers.has("X-PAYMENT")) { signedRequestSent = true; } const response = await fetch(req); // Also fail closed for adapters that expose a redirect response instead. if (response.redirected || (response.status >= 300 && response.status < 400)) { throw new Error("Paid request redirects are blocked"); } return response; }; try { // Install one promise before awaiting the prompt. Concurrent calls share // the same decision, including a decline or failure; never auto-reprompt. sessionApproval ??= Promise.resolve().then(() => confirmWithUser( `Allow paid requests to origins: ${[...ALLOWED_ORIGINS].join(", ")}? ` + `Networks: ${[...ALLOWED_NETWORKS].join(", ")}. ` + `Assets: ${[...ALLOWED_ASSETS].join(", ")} (6-decimal USDC). ` + `Recipients (payTo): ${[...ALLOWED_PAY_TO].join(", ")}. ` + `Per-call cap: ${humanUSDC(MAX_AMOUNT)}; session cap: ${humanUSDC(SESSION_CAP)}.`, )); if (!await sessionApproval) { throw new Error("User declined: no payment attempted"); } return await wrapFetchWithPayment(trackingFetch, client)(url, init); } finally { if (!signedRequestSent) sessionSpent -= MAX_AMOUNT; } } const res = await payOnce("https://api.example.com/data", { method: "GET" }); ``` 注册该策略后,超预算金额、非预期代币或未注册的链都会故障关闭——所有候选项都被过滤掉,`createPaymentPayload` 会抛出异常而不是签名。开发网 USDC 是 `4zMMC9srt5Ri5X14GAgXhaHii3GnPAEERYPJgZJDncDU`;仅在开发时把它加入 `ALLOWED_ASSETS`。对策略做对抗性测试——分别喂入要求 `5000000` 原子单位的挑战、报价另一种铸币地址的挑战,以及你从未注册的链上的挑战,并断言它们都不会产生签名。在 exact-SVM 方案中,结算器是交易费用支付方,因此买方钱包只需持有 USDC——无需 SOL 支付 gas。 **结算器选择。** 结算器代表资源服务器执行验证和结算,因此这是资源服务器的决定,而非买方的决定。按委托信任由少到多排列: | 选项 | 适用场景 | |--------|--------------| | [进程内自结算](https://github.com/x402-foundation/x402/tree/main/examples/typescript/servers/self-facilitation) | 你不希望结算路径中有第三方,且能自行持有密钥和 RPC 访问 | | 自行运行结算器 | 你想要同样的控制力,但在多个服务间共享 | | [`x402.org` 结算器](https://x402.org/facilitator) | 开发与测试网——它是包的默认值,无需配置,上游明确说明它不适用于主网路由 | | 托管的生产结算器 | 你希望获得主网覆盖而不必自己运维基础设施 | 选择托管方案时,请从上游文档的[结算器列表](https://docs.x402.org/dev-tools/facilitators)中挑选,而不是照搬这里的名字——该列表有人维护、并不详尽,且覆盖范围会变化。撰写时它包含 Coinbase 的 CDP(对每笔交易执行 KYT/OFAC 筛查)、PayAI、Corbits、Dexter、Solvador 等,其中若干同时覆盖 EVM 与 Solana 主网。无论选择哪一个,上线前都要在其 `/supported` 端点确认实时覆盖范围,并在新增网络时重新确认。 > **披露**:本节由参与 PayAI(所列结算器之一)的人贡献。它只是若干选项之一,上面的自托管与上游默认路径是有意排在前面的。 **卖方侧(API 向代理收费)。** 使用上游中间件;一条路由可以同时提供 Base 和 Solana(可运行版本参见 [`examples/typescript/servers`](https://github.com/x402-foundation/x402/tree/main/examples/typescript/servers)): | 运行时 | 包 | |---------|---------| | Express / Hono / Next.js / Fastify | `@x402/express@2.22.0`、`@x402/hono@2.22.0`、`@x402/next@2.22.0`、`@x402/fastify@2.22.0` | | Python(FastAPI、Flask) | PyPI 上的 `x402` | | Go(Gin、Echo、`net/http`) | `github.com/x402-foundation/x402/go/v2` | **Solana 卖方:`payTo` 地址需要先有其规范代币账户。** exact-SVM 客户端用 `findAssociatedTokenPda` 为 `payTo` 推导*关联代币账户*(ATA)并转账到那里,但不会创建它。如果那个确切账户不存在,结算会在模拟阶段失败,402 返回 `transaction_simulation_failed`,看起来像客户端 bug,实际是收款方账户缺失。要检查推导出的地址本身——扫描该所有者的代币账户并不等价,因为同一铸币地址下的非规范辅助账户会让检查通过,而客户端真正要用的 ATA 仍然不存在: ```typescript import { findAssociatedTokenPda, TOKEN_PROGRAM_ADDRESS } from "@solana-program/token"; const [ata] = await findAssociatedTokenPda({ mint: "EPjFWdd5AufqSSqeM2qN1xzybapC8G4wEGGkZwyTDt1v", // USDC mainnet owner: payToAddress, tokenProgram: TOKEN_PROGRAM_ADDRESS, // TOKEN_2022_PROGRAM_ADDRESS for Token-2022 mints }); ``` 然后确认该确切地址存在——`value: null` 表示不存在,向它结算将会失败: ```bash curl -s https://api.mainnet-beta.solana.com -X POST -H 'Content-Type: application/json' \ -d '{"jsonrpc":"2.0","id":1,"method":"getAccountInfo", "params":["",{"encoding":"base64"}]}' \ | jq '.result.value != null' ``` 创建方式(由创建者支付少量租金,而非付款方): - 在代码中,将 `@solana-program/token` 的 `getCreateAssociatedTokenIdempotentInstruction` 加入你的开通流程——幂等版本可安全重复执行,也是唯一确定性的方式。 - 用 spl-token CLI:`spl-token create-account --owner `。 - 向 `payTo` 转账该代币也可以,但仅当发送方包含创建指令时——钱包和 `spl-token transfer --fund-recipient` 会包含;对缺失 ATA 的裸 `transferChecked` 会像结算一样失败。 这个问题在向新开通的钱包或托管钱包付款时最容易出现,这类钱包往往还没有该资产的 ATA。 **发现。** 实现 x402 集市扩展的结算器会公开 `/discovery/resources` 端点——可在 `https://api.cdp.coinbase.com/platform/v2/x402/discovery/resources` 查询 CDP 目录,在 `https://facilitator.payai.network/discovery/resources` 查询 PayAI 目录。对于 Solana 可付费服务,还有 Solana 基金会的精选目录 [pay.sh](https://pay.sh)。 ## 示例 ### MCP 客户端中的预算执行 在构建调用 agentpay MCP 服务器的编排器时,在分派付费工具调用前强制执行预算。 > **前提条件**:在添加 MCP 配置前安装包——`npx` 不带 `-y` 会在非交互环境中提示确认,导致服务器挂起:`npm install -g agentwallet-sdk@6.0.0` ```typescript import { Client } from "@modelcontextprotocol/sdk/client/index.js"; import { StdioClientTransport } from "@modelcontextprotocol/sdk/client/stdio.js"; async function main() { // 1. Validate credentials before constructing the transport. // A missing key must fail immediately — never let the subprocess start without auth. const walletKey = process.env.WALLET_PRIVATE_KEY; if (!walletKey) { throw new Error("WALLET_PRIVATE_KEY is not set — refusing to start payment server"); } // Connect to the agentpay MCP server via stdio transport. // Whitelist only the env vars the server needs — never forward all of process.env // to a third-party subprocess that manages private keys. const transport = new StdioClientTransport({ command: "npx", args: ["agentwallet-sdk@6.0.0"], env: { PATH: process.env.PATH ?? "", NODE_ENV: process.env.NODE_ENV ?? "production", WALLET_PRIVATE_KEY: walletKey, }, }); const agentpay = new Client({ name: "orchestrator", version: "1.0.0" }); await agentpay.connect(transport); // 2. Set spending policy before delegating to the agent. // Always verify success — a silent failure means no controls are active. const policyResult = await agentpay.callTool({ name: "set_policy", arguments: { per_task_budget: 0.50, per_session_budget: 5.00, allowlisted_recipients: ["api.example.com"], }, }); if (policyResult.isError) { throw new Error( `Failed to set spending policy — do not delegate: ${JSON.stringify(policyResult.content)}` ); } // 3. Use preToolCheck before any paid action await preToolCheck(agentpay, 0.01); } // Pre-tool hook: fail-closed budget enforcement with four distinct error paths. async function preToolCheck(agentpay: Client, apiCost: number): Promise { // Path 1: Reject invalid input (NaN/Infinity bypass the < comparison) if (!Number.isFinite(apiCost) || apiCost < 0) { throw new Error(`Invalid apiCost: ${apiCost} — action blocked`); } // Path 2: Transport/connectivity failure let result; try { result = await agentpay.callTool({ name: "check_spending" }); } catch (err) { throw new Error(`Payment service unreachable — action blocked: ${err}`); } // Path 3: Tool returned an error (e.g., auth failure, wallet not initialised) if (result.isError) { throw new Error( `check_spending failed — action blocked: ${JSON.stringify(result.content)}` ); } // Path 4: Parse and validate the response shape let remaining: number; try { const parsed = JSON.parse( (result.content as Array<{ text: string }>)[0].text ); if (!Number.isFinite(parsed?.remaining)) { throw new TypeError("missing or non-finite 'remaining' field"); } remaining = parsed.remaining; } catch (err) { throw new Error( `check_spending returned unexpected format — action blocked: ${err}` ); } // Path 5: Budget exceeded if (remaining < apiCost) { throw new Error( `Budget exceeded: need $${apiCost} but only $${remaining} remaining` ); } } main().catch((err) => { console.error(err); process.exitCode = 1; }); ``` ## 最佳实践 - **委托前设置预算**:生成子代理时,通过编排层附加 SpendingPolicy。切勿让代理拥有无限支出权限。 - **锁定依赖项**:始终在 MCP 配置中指定确切版本(例如 `agentwallet-sdk@6.0.0`)。部署到生产环境前验证包完整性。 - **审计追踪**:在任务后钩子中使用 `list_transactions` 记录支出内容和原因。 - **故障关闭**:如果支付工具不可达,阻止付费操作——不要回退到无计量访问。 - **配合 security-review**:支付工具是高权限操作。应用与 shell 访问相同的审查标准。 - **先在测试网测试**:开发时使用 Base Sepolia;生产环境切换到 Base 主网。在 Solana 上,先针对 Solana 开发网(`solana:EtWTRABZaYq6iMfeYKouRu166VU2xqa1`)和免费的 x402.org 结算器开发,再转到主网的生产结算器。 - **在 Solana 上注入 USDC 而非 SOL**:exact-SVM 方案让结算器成为交易费用支付方,因此没有 SOL 的钱包也能付费。签署前将每个挑战的 `asset` 与预期的 USDC 铸币地址核对(主网 `EPjFWdd5AufqSSqeM2qN1xzybapC8G4wEGGkZwyTDt1v`,开发网 `4zMMC9srt5Ri5X14GAgXhaHii3GnPAEERYPJgZJDncDU`)——一个会支付任意资产的包装客户端是预算上的漏洞。 ## 生产参考 - **npm**:[`agentwallet-sdk`](https://www.npmjs.com/package/agentwallet-sdk) - **合并到 NVIDIA NeMo Agent Toolkit**:[PR #17](https://github.com/NVIDIA/NeMo-Agent-Toolkit-Examples/pull/17) — 面向 NVIDIA 代理示例的 x402 支付工具 - **协议规范**:[x402.org](https://x402.org) - **OKX Payments SDK**:[`okx/payments`](https://github.com/okx/payments) — 面向 X Layer x402 的 TypeScript、Go、Rust 和 Java 卖家集成 - **OKX 代理支付协议技能**:[`okx/onchainos-skills`](https://github.com/okx/onchainos-skills/tree/main/skills/okx-agent-payments-protocol) - **OKX Payments 概览**:[web3.okx.com/onchainos/dev-docs/payments/overview](https://web3.okx.com/onchainos/dev-docs/payments/overview) - **上游 x402 monorepo**:[`x402-foundation/x402`](https://github.com/x402-foundation/x402) — TypeScript、Python 和 Go 实现,以及维护中的客户端和服务器示例 - **x402 文档**:[docs.x402.org](https://docs.x402.org);生产结算器列表位于 [docs.x402.org/dev-tools/facilitators](https://docs.x402.org/dev-tools/facilitators) - **`@x402` 包**:[npmjs.com/org/x402](https://www.npmjs.com/org/x402) — `@x402/fetch`、`@x402/axios`、`@x402/express`、`@x402/hono`、`@x402/next`、`@x402/fastify`、`@x402/evm`、`@x402/svm` - **结算器**:[自结算示例](https://github.com/x402-foundation/x402/tree/main/examples/typescript/servers/self-facilitation)(无第三方)、[x402.org 结算器](https://x402.org/facilitator)(测试网默认)、以及有人维护的[生产列表](https://docs.x402.org/dev-tools/facilitators) - **发现**:CDP 与 PayAI 集市位于 `/discovery/resources`;Solana 可付费服务见 [pay.sh](https://pay.sh)