跳转到主要内容
学习指南为您的AI代理添加支付
指南

如何将支付添加到您的AI代理。

10 minutes
简短答案

使用 @blockchain0x/node(或 Python 客户端)中的 createClient 创建一个代理,使用 payments.create 发送 USDC 支付,并使用 webhooks.verify 验证签名的 webhook。支出控制在仪表板中设置,并通过 API 只读。代理从不直接接触私钥。从注册到在 Base 上进行第一次 USDC 支付不超过十分钟,使用 TypeScript 或 Python。

先决条件

在您开始之前。

  • 一个 Blockchain0x 账户 (免费注册)。
  • 来自仪表板的 API 密钥(使用 sk_test_ 密钥进行本指南;稍后您将切换到 sk_live_)。
  • 在您的代理运行时中使用Node.js 20+或Python 3.11+。
  • 基于任何框架构建的代理 - LangChain、CrewAI、AutoGen、LlamaIndex、OpenAI Agents SDK、MCP 或普通 SDK 代码。说明与框架无关。
  • 一个可从公共互联网访问的 HTTPS 端点以接收 webhook(ngrok 或部署预览适合开发)。
第1步,共5步

创建代理个人资料。

代理档案是您代理发送或接收的每笔支付背后的可寻址身份。它包含钱包地址、公共页面、验证徽章和(稍后)支出政策。每个逻辑代理创建一个。

TypeScript
import { createClient } from "@blockchain0x/node";

const client = createClient({ apiKey: process.env.BLOCKCHAIN0X_API_KEY! }); // sk_test_ / sk_live_

const agent = await client.agents.create({ name: "research-bot" });

console.log(agent.id); // "agt_..."
// Public page: https://wallet.blockchain0x.com/a/{slug}
Python
from blockchain0x import Client

client = Client()  # reads BLOCKCHAIN0X_API_KEY from the environment

agent = client.agents.create(body={"name": "research-bot"})

print(agent["id"])  # "agt_..."
# Public page: https://wallet.blockchain0x.com/a/{slug}

After this call, the agent has a public page at https://wallet.blockchain0x.com/a/<slug> that any counterparty (human or agent) can hover for verification info. See the agent payment identity glossary entry for what that page exposes.

第2步,共5步

发送付款。

payments.create sends USDC from the agent wallet. amountWei is base units (USDC has 6 decimals), so 0.01 USDC is the string "10000". The SDK auto-stamps an Idempotency-Key, and the call can return 503 until the chain adapter is wired for your network. To RECEIVE instead, settle an invoice you created in the dashboard with paymentRequests.settle - see the payment API page.

TypeScript
// Send a USDC payment from the agent wallet. amountWei is base units
// (USDC has 6 decimals): "10000" is 0.01 USDC. payments.create auto-stamps an
// Idempotency-Key and can return 503 until the chain adapter is wired.
const tx = await client.payments.create({
  agentId: agent.id,
  to: "0xRecipient",
  amountWei: "10000",
});

console.log(tx); // the submitted transfer
Python
# amountWei is USDC base units (6 decimals): "10000" is 0.01 USDC.
tx = client.payments.create(body={
    "agentId": agent["id"],
    "to": "0xRecipient",
    "amountWei": "10000",
})

print(tx)  # the submitted transfer
第3步,共5步

处理Webhook。

Webhook 是您了解付款结算的方式。在 Node 中,@blockchain0x/node 的 webhooks.verify 进行 HMAC 检查并返回一个区分的联合;在其他语言中,对原始主体计算相同的 HMAC。根据事件类型分支(入站的 payment.received),快速响应 2xx,并将任何更重的内容排队在 2xx 后,以便交付不会超时。

TypeScript (Express)
import express from "express";
import { webhooks } from "@blockchain0x/node";

const app = express();
// Capture the RAW body. The HMAC is over the exact bytes on the wire.
app.use(express.raw({ type: "application/json" }));

app.post("/webhooks/payment", (req, res) => {
  const result = webhooks.verify({
    headers: req.headers,
    rawBody: req.body, // Buffer, raw bytes
    secret: process.env.BLOCKCHAIN0X_WEBHOOK_SECRET!,
  });
  if (!result.ok) return res.status(400).json({ code: result.code });

  if (result.eventType === "payment.received") {
    // USDC landed - deliver the work, fulfil the order, etc.
    void deliver(result.eventId);
  }
  res.status(200).send("ok");
});
Python(Flask)
import hmac, hashlib, os, time
from flask import Flask, request, abort

app = Flask(__name__)
SECRET = os.environ["BLOCKCHAIN0X_WEBHOOK_SECRET"].encode()

@app.post("/webhooks/payment")
def webhook():
    raw = request.get_data()  # RAW bytes - do not parse first
    sig = request.headers.get("X-Blockchain0x-Signature", "")
    ts = request.headers.get("X-Blockchain0x-Timestamp", "")
    parts = dict(p.split("=", 1) for p in sig.split(",") if "=" in p)
    t, v1 = parts.get("t", ts), parts.get("v1", sig)
    want = hmac.new(SECRET, t.encode() + b"." + raw, hashlib.sha256).hexdigest()
    if not hmac.compare_digest(want, v1) or abs(time.time() - int(t)) > 300:
        abort(401)
    if request.headers.get("X-Blockchain0x-Event-Type") == "payment.received":
        deliver(request.get_json())  # USDC landed
    return ("ok", 200)
第4步,共5步

在仪表板中设置支出控制。

如果您的代理仅接收,您可以跳过此步骤。如果它还支付,请在仪表板中设置支出权限 - 每个周期的津贴和每笔交易的上限。它在每次支付时由后端强制执行,因此它以代理端规则无法做到的方式存活下来。没有API或SDK调用可以更改权限(代理自己的密钥无法扩大其限制);API是只读的,因此您的代码可以获取当前值以进行显示或规划。

读取 (curl)
curl https://api.blockchain0x.com/v1/agents/agt_123/spend-permissions \
  -H "Authorization: Bearer $BLOCKCHAIN0X_API_KEY"
响应
{
  "allowance_wei": "5000000",
  "per_tx_wei": "1000000",
  "period_seconds": 86400,
  "revoked_at": null
}
第5步,共5步

在Base Sepolia上测试整个流程。

在切换到sk_live_密钥之前,使用sk_test_运行完整的端到端路径。测试密钥将所有内容保留在Base Sepolia上,您可以从公共水龙头为钱包提供资金,并且响应形状与实时匹配。密钥前缀选择网络,因此测试密钥无法移动主网资金。

演练三种场景:一个正常路径的支付触发 payment.received,一个错过的交付(将 webhook 指向一个死 URL,然后通过 transactions.get 获取交易进行对账),以及一个 webhook 重试(第一次返回 500,第二次返回 200,并确认您的处理程序是幂等的)。当所有三个测试通过时,交换密钥并发布。

常见陷阱

五个让团队损失一周的错误。

跳过Webhook签名验证

如果您将任何POST请求到/webhooks/payment视为权威,攻击者可以伪造虚假的支付事件并欺骗您的代理免费交付工作。始终使用Webhook密钥进行HMAC验证,使用恒定时间比较。第一次妥协几乎总是缺少验证。

假设有一个单独的确认事件

已发布的事件是 payment.received、payment.sent、wallet.deployed 和 webhook.test - 没有单独的确认事件。当转账在区块中时,payment.received 被触发。对于大多数工作,这就是您交付的信号。对于昂贵或不可逆的操作,使用 transactions.get 轮询交易并在采取行动之前应用您自己的确认阈值;不要等待不存在的事件。

Webhook 处理程序没有幂等性

Webhook在非2xx响应时重试,并且在负载下同一事件将多次到达。您的处理程序必须是幂等的:保持一个小表,记录您已经处理过的事件ID,并跳过重复项。否则,瞬时故障将交付相同的工作两次,您将花费数小时调试双重履行。

混合测试和实时 API 密钥

测试密钥(sk_test_)命中沙箱并使用Base Sepolia;实时密钥(sk_live_)命中生产并使用Base主网。在环境配置中混合使用它们是大多数'在开发中有效,在生产中失败'问题的原因。如果您的运行时环境和密钥前缀不匹配,则在启动时硬失败。

将缺失的 webhook 视为失败的付款

没有失败事件,并且可能会错过 webhook(您的端点宕机,交付被丢弃)。不要让代理卡在“等待资金”的循环中。进行对账:使用 transactions.get 获取交易以了解实际状态,并对任何等待流程设置超时,以便被放弃的付款释放持有的资源,而不是永远挂起。

下一步

一旦您有了第一次付款。

在基本支付正常工作的情况下,最有价值的后续工作是支出控制(以便代理无法随意使用预算)、webhook 的稳健性(以便支付在负载下不会悄然丢失)和身份验证(以便对方信任代理的公共页面)。

完整API参考在docs.blockchain0x.com。相同API的产品表面:支付API

最后审查时间:2026-05-15。根据 CC BY 4.0 发布。

一次POST,您的代理正在获得报酬。

免费开始。包含测试密钥。首次支付在十分钟内确认。