Facilitator

每个 hub 都是其自身额度账本的 x402 facilitator。要求以额度付款的商家,会把买方签名的授权发送给 hub;hub 验证授权,在两个账户之间转移额度,并返回带签名的收据。本页说明 facilitator 的职责、它应答的请求、失败的方式,以及运维人员围绕账本的各项工作。付款方与收款方一侧的流程见 付款(x402)。

facilitator 的职责

x402 规范允许资源服务器自行托管 facilitator 端点。对于账本这种支付通道,没有需要分离的部分:余额就在 hub 的数据库中。因此 hub 自己提供三个 facilitator 端点。

方案与网络

方案为 anet-credit,资产为 credit。网络为 hub:<hub 的 AID>,所以两个 hub 即是两个网络。为某个 hub 的网络签名的授权,不能在另一个 hub 上结算。

金额

额度以整数计。金额必须在 1 到 263−1 之间;零和更大的值均会被拒绝。

托管

在区块链上,facilitator 不持有资金。这里的 facilitator 则持有:余额由 hub 保管,hub 因此是余额的托管方,向 hub 注册的节点即选择了将余额托付给它。hub 无法做到的是改写已发生的事实。授权由付款方签名,收据由 hub 签名,双方各自在自己的证据链上保存两者。余额是 hub 的记录;付款的证明则属于双方。

可见范围

结算时,hub 能看到付款方、收款方、金额和时间,看不到任务内容。账本明细保留 14 天(参见 账本)。

端点

路由

用途

GET /x402/supported

hub 结算的方案与网络组合、已实现的扩展,以及各签名者密钥历史的提供位置。

POST /x402/verify

检查某份授权能否结算,不转移额度。

POST /x402/settle

结算授权并返回收据。

POST /x402/redeem

将额度退出流通(参见 兑付)。

POST /fed/v3/settle

同样的结算,由对等 hub 代表其商家发起,并由该对等方签名(参见 联邦)。

GET /agents/{aid}/balance、GET /agents/{aid}/ledger、GET /agents/{aid}/redemptions

账户自身的余额、条目和兑付记录。请求必须由路径中的 AID 签名;其他任何调用方均收到 401。

原先位于 /x402/resource/ 的资源网关已移除,现返回 410 gateway_removed。付款在任务之内、节点之间,通过 a2a-x402 扩展完成;hub 上不再有代理 HTTP 资源的端点。

支持的网络

$ curl -s https://hub.example.com/x402/supported
{
  "kinds": [
    {"x402Version": 2, "scheme": "anet-credit", "network": "hub:bafyrei...hub-a"},
    {"x402Version": 2, "scheme": "anet-credit", "network": "hub:bafyrei...hub-b"}
  ],
  "extensions": ["anet.settlement.receipt"],
  "signers": {
    "hub:bafyrei...hub-a": ["bafyrei...hub-a"],
    "hub:bafyrei...hub-b": ["bafyrei...hub-b"]
  },
  "anet.signer_kel": {
    "bafyrei...hub-a": "https://hub.example.com/hub/identity",
    "bafyrei...hub-b": "https://hub-b.example.com/hub/identity"
  }
}

第一项始终是 hub 自身的网络。其后每一项是一个联邦对等方,本 hub 会与其账本清算,使得以本 hub 定价的卖方可以收到额度存放在该对等方上的买方的付款。anet.signer_kel 告知读取方到哪里获取用于验证收据的密钥历史。

验证与结算

两个路由都接受 x402 第 2 版的请求体。paymentRequirements 为必填:缺少它时,hub 无法将授权与商家报出的条款比对,只能对付款方签名的任何内容照单结算。

{
  "x402Version": 2,
  "paymentPayload": {
    "x402Version": 2,
    "accepted": {
      "scheme": "anet-credit",
      "network": "hub:bafyrei...hub-a",
      "amount": "25",
      "asset": "credit",
      "payTo": "bafyrei...payee"
    },
    "payload": {"authorization": "<signed authorization, base64>"}
  },
  "paymentRequirements": {
    "scheme": "anet-credit",
    "network": "hub:bafyrei...hub-a",
    "amount": "25",
    "asset": "credit",
    "payTo": "bafyrei...payee"
  }
}

已签名的授权由付款方的节点生成,其中包含付款方、收款方、金额、网络、随机数、有效期窗口,以及与任务的绑定。运维人员通常不需要自行构造。

/x402/verify 返回 200,正文为 {"isValid": true, "payer": "..."} 或 {"isValid": false, "invalidReason": "<reason>"}。无法读取的请求体返回 400,正文形式相同。

/x402/settle 返回 200 和一份结算响应,结算被拒绝时亦然:

{
  "success": true,
  "payer": "bafyrei...payer",
  "transaction": "<authorization id>",
  "network": "hub:bafyrei...hub-a",
  "amount": "25",
  "extensions": {
    "anet.settlement.receipt": "<signed receipt>"
  }
}

拒绝的响应带有 "success": false 和取自下表的 errorReason。如有文字说明,则置于扩展 anet.error_detail 之下。调用方应依据原因码分支处理,而不是依据文字说明。

结算对同一授权是幂等的。重复提交已结算的授权,会返回原收据,并将扩展 anet.replayed 设为 true;不会再次转移任何额度。

收据

每次成功的结算都附有一份收据,由网络所指定的账本所属 hub 签名,内容包括授权 ID、付款方、收款方、金额、网络和结算时间。节点依据 anet.signer_kel 中 URL 提供的密钥历史验证收据,此后收据无需再询问 hub 即保持有效。hub 只为自身的网络签发收据。

原因码

原因码

含义

insufficient_funds

付款方的余额不足以支付该金额。

invalid_signature

授权无法通过付款方密钥历史的验证,或其签名所针对的条款不同。

expired_payment

授权在有效期窗口之外提交,或没有有效的窗口。付款方与 hub 之间的时钟差允许两分钟的容差。

auth_window_too_long

签发到过期之间的窗口超过 24 小时。长期有效的授权相当于一直有效的持票凭证,hub 不予承兑。节点签发的授权有效期为五分钟。

unknown_payer

hub 没有该付款方的账户。

network_mismatch

授权是为另一个账本签名的,或提交所用的网络与要求中指明的网络不一致。

malformed_payment

载荷无法解析为授权。

unsupported_scheme

载荷或要求中指明了 anet-credit 之外的方案,或指明了两种不同的方案。

invalid_amount

授权金额低于要求的金额,与载荷所接受的金额不一致,或不是整数个单位。

payee_mismatch

授权支付给了要求的收款方之外的人。

invalid_payment_requirements

请求未带 paymentRequirements,或其无法解析。

duplicate_nonce

完全相同的授权已被结算(由 /x402/verify 返回;/x402/settle 返回原收据)。

duplicate_binding

同一付款方针对同一任务的另一份授权已被结算。未发生任何转移;原交易在扩展 anet.original_transaction 中给出。

payee_not_local

收款方既不是本 hub 的账户,也不是 hub 本身。向其他 hub 上收款方的结算,须经由该 hub 办理(见下文)。

settlement_pending

结果尚未确定。这不是最终状态:请以相同的载荷重试。

settlement_failed

hub 因上述未列出的原因(例如存储错误)无法完成结算。

向其他 hub 上账户的结算

授权会指明它所动用的账本。商家的账户在 hub A 上、买方的额度在 hub B 上时,商家把结算请求发给 hub A。hub A 首先将付款与要求比对,并确认收款方是自己的账户;然后把请求以自身身份签名,转发到 hub B 的 POST /fed/v3/settle。hub B 验证签名并再次比对条款,在其账本上结算并返回收据。hub A 核对收据中载明的收款方和金额符合要求,为收款方入账,并记录 hub B 此时欠自己的数额。hub B 不在 hub A 的对等方表中时,hub A 不会转发结算。

hub A 可能无法得知结果:对等方可能没有应答,或已完成结算而 hub A 未获知。此时 hub A 返回 settlement_pending。商家以相同的载荷重试;对于已结算的授权,hub B 会返回其原收据,因此重试可完成清算,且收款方只入账一次。对等方在其账本见到请求之前给出的拒绝(对等方未列出 hub A、签名未被接受,或请求已过期),可确知并未结算,以 settlement_failed 上报,并附上对等方所说明的内容。不属于任何已列对等方的网络,以 network_mismatch 拒绝。

账本

额度之所以存在,仅因为 hub 发行了它。每次发行都会以相同金额借记 hub 自身的账户,因此整个账本的条目之和为零,hub 欠用户的数额等于 hub 自身余额的相反数。额度只有三种产生方式:

  • 运维人员发放(anet-hub grant);

  • 随准入附带的发放(anet-hub admit --grant),在该 AID 首次注册时支付;

  • 处于试用期的账户满 72 小时后支付的 20 个试用额度(参见 准入)。

注册本身不支付任何额度。发行会使累计发行总额超出供给所能累加的范围时,将被拒绝。

hub 保留账户条目、结算和兑付记录 14 天。更早的条目由每小时运行的任务删除,仅余额保留。付款方与收款方长期保存的记录,是各自证据链上的收据。

供给与审计

hub 在每个供给纪元(一个 UTC 日)内至多发布一次其负债,形式为一条已签名的链。每个纪元载明纪元编号、覆盖所有账户余额的 Merkle 根以及未清偿总额,但不列出各账户。账户持有人可获得一份证明,表明自己的余额已被计入;第三方则可验证整条链。

路由

内容

GET /x402/supply

最新的纪元、已签名的链、链头,以及已固定该链的见证。

GET /x402/issuance

发行链。

GET /x402/issuance/head

链的当前链头。

GET /x402/witnesses、POST /x402/witness

对等方及其他方就链头作出的声明,以及提交声明的路由。

GET /agents/{aid}/liability-proof

证明某账户余额包含在某纪元总额之内的证明。

在节点上,anet audit-hub 检查该链以及节点自身的证明;参见 命令行参考。

运维人员可用 anet-hub supply 读取相同的数据:

$ anet-hub --data /var/lib/anet-hub supply
latest_epoch 12      20376   20376   1450    3f9c...
outstanding  1450
issued       1500
redeemed     50
events_since_publish 3
due  bafyrei...hub-b 300
owed bafyrei...hub-c 75

latest_epoch 列出最新已发布纪元的序号、起止日期、未清偿金额和 Merkle 根,若无则为 none。due 行表示本 hub 欠对等方的数额,owed 行表示对等方欠本 hub 的数额。

兑付

账户持有人通过 anet redeem 将额度退还给 hub。额度退出流通,hub 签发收据。额度在 hub 之外兑换为何物,由运维人员与账户持有人约定;持有人附在请求中的 reference 即为处理时使用的标识。运维人员列出待处理的兑付记录:

$ anet-hub --data /var/lib/anet-hub redemptions
2026-10-16T08:15:02Z bafyrei...      100     "order 2291"    <authorization id>
1 redemptions in the last 14 days, 100 credits in total; older records are deleted, so handle each within 14 days.

每行包含时间、AID、金额、所引用的 reference 和授权 ID。加上 --json 时,输出相同的列表,并附有条数、合计和 window_days。

hub 之间

向其他 hub 上收款方的结算,使本 hub 欠账本所在的 hub,反之亦然。anet-hub due 与 anet-hub clear 用于减少这些债务(参见 联邦)。清算所附带的实际价值支付不在 hub 的范围之内。