博客 AI / Agent Payments

Agent Payments Protocol(AP2)是什麼?2026 AI Agent 自動支付、JSON API 與智慧交易完整解析

你在接 AI Agent 电商或自动采购时,文档里会同时冒出 A2A、MCP,以及一套叫 AP2 的支付协议。前两者管「怎么对话、怎么调工具」,AP2 管「凭什么替用户付钱」。

Agent Payments Protocol(AP2)是 Google 于 2025 年 9 月与 60 多家支付和科技公司一起发布的开放协议,用来给「Agent 替用户付钱」这件事补上可验证的授权、真实意图和事后追责。2026 年的实现稿(v0.2)把交易拆成两张可验证凭证:Checkout Mandate 和 Payment Mandate,载荷是 JSON,封装多用 SD-JWT。

本文将说明:

先記住這一點:AP2 不是又一套结账 UI,也不是替代 Stripe 的支付网关。它是 Agent 支付的信任层:用密码学签名的 Mandate 证明「用户允许这笔交易」。下面按「为什么需要 → 角色 → Mandate JSON → 两种模式 → Schema 校验 → 和 A2A/MCP 怎么叠」拆开。

AP2 是什么

Google Cloud 公告把 AP2 定义成一套支付无关的开放协议:用户、商户、支付机构用同一种语言完成 Agent 发起的交易。它可以作为Agent2Agent (A2A)Model Context Protocol (MCP)的支付扩展,不替代两者。

2026 年公开规范见AP2 Specification v0.2,参考实现在google-agentic-commerce/AP2

核心对象不是「订单表单」,而是Mandate(授权书):一份防篡改、可验证的数字合同,证明用户给了 Agent 某次购买或某类约束下的购买权限。规范要求 Mandate 用SD-JWT这类可验证数字凭证封装,而不是裸 JSON POST。

发布时的产品叙事用过 Intent Mandate / Cart Mandate / Payment Mandate 三张凭证。当前 v0.2 实现稿收敛成两张,并区分开放(open)与封闭(closed):

概念 v0.2 对应 证明什么
Intent / 开放约束 Open Checkout / Open Payment Mandate 用户预先批准的预算、商户范围、有效期
Cart / 封闭结账 Closed Checkout Mandate 这张购物车的商品、价格、商户签名 Checkout JWT
Payment Closed Payment Mandate 为这一笔 Checkout 付款的金额、收款方、支付工具

读老文章时不要被三套名词卡住:产品层讲「意图 → 购物车 → 付款」,实现层就是开放约束 + 封闭 Checkout/Payment。

为什么 Agent 支付需要新协议

传统电商默认「人在可信页面点购买」。Agent 一旦能自己下单,旧假设破了。AP2 要回答三件事:

只靠 prompt「帮我买票」没有密码学边界。模型可能改数量、换商户、重复提交。AP2 把「用户签过的约束」和「Agent 组装的封闭订单」绑在一起,验证必须在确定性代码里做,不能再丢回 LLM 判断。

支付方式本身仍走卡组、银行或稳定币轨道。AP2 不管清算,只管「这笔 Agent 交易有没有被授权」。加密货币方向有 A2A x402 扩展,和 Coinbase、Ethereum Foundation、MetaMask 等一起做 Agent 加密支付。

五种角色:谁签、谁验、谁收款

规范定义五个角色。一个主体可以兼任,但验证规则按角色叠加:

角色 英文 做什么 是否允许 Agent 化
购物 Agent Shopping Agent 发现商品、组结账、发起购买 预期是 Agent
凭证提供方 Credential Provider 核发支付凭证,确认 Agent 有权使用该凭证 可以是,也可以不是
商户 Merchant 提供并完成 Checkout,核库存与价格 可以是,也可以不是
商户收单方 Merchant Payment Processor 处理付款,确认凭证绑定了这一笔 Checkout 可以是,也可以不是
可信界面 Trusted Surface 向用户展示意图并收集签名 必须不是 Agent

关键约束:Trusted Surface 必须是非 Agent 的确定性界面。用户签名不能交给另一个 LLM 去「转述」。Shopping Agent 可以是非确定性的,所以它发出的内容默认不可信,必须靠 Mandate 的签名和哈希来钉死。

Mandate:Checkout 与 Payment

v0.2 只定义两类 Mandate。购物 Agent 组好任务后,通过可信界面拿到签名,再分别交给商户和支付链路。

Checkout Mandate

给商户看:Shopping Agent 被授权购买它组装的那一笔 Checkout。商户必须先给出自己签名的 Checkout JWT;封闭 Checkout Mandate 用该 JWT 的密码学哈希(checkout_hash)绑死,防止 Agent 改完价格再拿旧授权去结账。

商户接受或拒绝后,必须返回 Checkout Receipt。

Payment Mandate

给凭证提供方、卡组和收单方看:Shopping Agent 被授权为这一笔Checkout 付款。绑定方式是 Checkout JWT 的密码学哈希。规范要求 Checkout JWT 用 ECDSA 这类非确定性签名,不要用 Ed25519,以免彩虹表攻击。

收单方接受或拒绝后,必须返回签名的 Payment Receipt,回给 Agent、凭证提供方,必要时回给卡组。争议时把 Checkout / Payment 的 Mandate 和 Receipt 拼在一起,就是证据包。

两种模式:人在场 vs 自主代付

验证方最终都收到封闭的 Checkout 和 Payment Mandate。差别只在封闭凭证是谁签的、开放约束怎么核。

  1. 1
    Human Present(直接 / 人在场)

    用户在可信界面看到封闭购物车,亲自签名。验证方核的是用户凭证或 Agent Provider 信任列表上的用户签名。

  2. 2
    Human Not Present(自主 / 人不在场)

    用户先签开放 Mandate:金额区间、允许的商户、有效期,并带上 Agent 公钥(cnf 声明)。条件满足后,Agent 用自己的密钥签封闭单;验证方必须核对封闭单落在开放约束内。

自主模式还有两条硬规则:同一张开放 Mandate 在上一笔被拒绝之前,不能再拿去签另一笔封闭单;出示开放 Mandate 时只披露验证封闭单所需的字段,保护用户隐私。

典型场景:票开售瞬间代抢、缺货补货自动下单、旅行预算内同时订机票和酒店。这些都是「约束先签、成交后补封闭单」,不是给 Agent 一张无限额信用卡。

JSON API:字段、vct 与 Schema

开发者接触 AP2,日常就是 JSON。官方 SDK 把规范对象放在code/sdk/python/ap2/schemas/,并用 Pydantic 生成模型。你调试时先当普通 JSON 对象看,再谈 SD-JWT 封装。

每张 Mandate 用vct声明类型和版本,例如mandate.payment.1mandate.checkout.open.1。实现必须精确匹配整串,包括数字后缀;不兼容的改版会换成.2

下面是规范里封闭 Payment Mandate 的业务载荷形态(金额单位依实现,示例用最小货币单位):

封闭 Payment Mandate 载荷(示意,基于 AP2 v0.2)
{
  "vct": "mandate.payment.1",
  "transaction_id": "NivWhuqfzcvZNapvIEJ2-3tsdQLkiuIcye2g46WVgX8",
  "payee": {
    "id": "merchant_1",
    "name": "Demo Merchant",
    "website": "https://demo-merchant.example"
  },
  "payment_amount": {
    "amount": 19900,
    "currency": "USD"
  },
  "payment_instrument": {
    "id": "stub",
    "type": "card",
    "description": "Card ••••4242"
  }
}

开放 Payment Mandate 不写死某一笔,而是写约束:

开放 Payment Mandate 约束(示意)
{
  "vct": "mandate.payment.open.1",
  "cnf": {
    "jwk": {
      "kty": "EC",
      "crv": "P-256",
      "x": "QpSyxPQHy38xckypDr54gZ3T42zj9iLtV4koyb5U27c",
      "y": "37HLd7JJinxjJIn8J7HijssoeclbfhdW-gUL7feI9lw"
    }
  },
  "exp": 1781203600,
  "constraints": [
    {
      "type": "mandate.payment.allowed_payees",
      "allowed": [{ "id": "merchant_1" }]
    },
    {
      "type": "mandate.payment.amount_range",
      "currency": "USD",
      "min": 10000,
      "max": 40000
    }
  ]
}

传输时它们不是裸 JSON,而是 SD-JWT:可选择披露 + 密钥绑定。业务层调试时,你仍然先把披露还原成上面这种 JSON,再校验字段和约束。

对应的 JSON Schema 应至少锁住vcttransaction_idpayeepayment_amount和支付工具类型,避免模型漏字段或把金额写成字符串:

Payment Mandate 业务字段 JSON Schema(调试用精简版)
{
  "$schema": "https://json-schema.org/draft/2020-12/schema",
  "$id": "https://jsonnote.com/schemas/ap2-payment-mandate-debug.json",
  "title": "AP2 Closed Payment Mandate (debug)",
  "type": "object",
  "additionalProperties": false,
  "required": ["vct", "transaction_id", "payee", "payment_amount", "payment_instrument"],
  "properties": {
    "vct": {
      "type": "string",
      "const": "mandate.payment.1"
    },
    "transaction_id": {
      "type": "string",
      "minLength": 16
    },
    "payee": {
      "type": "object",
      "required": ["id", "name"],
      "properties": {
        "id": { "type": "string", "minLength": 1 },
        "name": { "type": "string", "minLength": 1 },
        "website": { "type": "string", "format": "uri" }
      }
    },
    "payment_amount": {
      "type": "object",
      "required": ["amount", "currency"],
      "properties": {
        "amount": { "type": "integer", "minimum": 1 },
        "currency": { "type": "string", "pattern": "^[A-Z]{3}$" }
      }
    },
    "payment_instrument": {
      "type": "object",
      "required": ["id", "type"],
      "properties": {
        "id": { "type": "string" },
        "type": {
          "type": "string",
          "enum": ["card", "bank_transfer", "stablecoin"]
        },
        "description": { "type": "string" }
      }
    }
  }
}

生产环境请以官方仓库里的 canonical schema 为准。上面这份是调试精简版,方便贴进 JSONNote 做本地校验,不能替代规范里的完整字段和选择性披露标注。

实际示例:校验 Payment Mandate

Agent 侧常见失败不是验签失败,而是 JSON 先坏了:

业务层先 parse,再按 schema validate,最后才做 SD-JWT 验签和约束求值:

先校验 JSON 结构,再谈验签
import json
from jsonschema import validate, ValidationError

PAYMENT_MANDATE_SCHEMA = {
    "type": "object",
    "required": ["vct", "transaction_id", "payee", "payment_amount"],
    "properties": {
        "vct": {"type": "string", "const": "mandate.payment.1"},
        "transaction_id": {"type": "string", "minLength": 16},
        "payee": {
            "type": "object",
            "required": ["id", "name"],
            "properties": {
                "id": {"type": "string"},
                "name": {"type": "string"},
            },
        },
        "payment_amount": {
            "type": "object",
            "required": ["amount", "currency"],
            "properties": {
                "amount": {"type": "integer", "minimum": 1},
                "currency": {"type": "string", "pattern": "^[A-Z]{3}$"},
            },
        },
    },
    "additionalProperties": True,
}

def parse_payment_mandate(raw: str) -> dict:
    try:
        data = json.loads(raw)
    except json.JSONDecodeError as e:
        raise ValueError(f"invalid mandate JSON: {e}") from e
    try:
        validate(instance=data, schema=PAYMENT_MANDATE_SCHEMA)
    except ValidationError as e:
        raise ValueError(f"mandate schema failed: {e.message}") from e
    return data

# 用法:先过结构,再拿 transaction_id 去对 Checkout JWT 的哈希
mandate = parse_payment_mandate(disclosed_payload)
assert mandate["transaction_id"] == checkout_hash

这和 Agent 里校验tool_calls[].function.arguments是同一套纪律:先保证是合法 JSON,再保证符合契约,最后才执行副作用。见AI Agent 与 JSON Schema

智能交易的完整链路可以看成:

  1. 1
    用户签约束或当场签封闭单

    可信界面出 Mandate,Agent 不得自己「补签」用户意图。

  2. 2
    商户签发 Checkout JWT

    价格、库存、优惠以商户签名为准,Agent 不能改完再假装同一笔。

  3. 3
    封闭 Mandate 绑定 checkout_hash

    Payment Mandate 的 transaction_id 必须等于该哈希。

  4. 4
    各方验签并回 Receipt

    失败返回带错误的 Receipt JWT,成功才进入真正的收单或推送资金。

AP2 vs 传统支付 / A2A / MCP

解决什么 典型对象 和 AP2 的关系
传统支付 API 扣款、退款、令牌化卡号 PaymentIntent、capture AP2 不替代清算;Payment Mandate 证明「可以去调这些 API」
A2A Agent 与 Agent 互操作 任务、消息、能力发现 AP2 可作为 A2A 的支付扩展;另有 x402 走加密货币
MCP Agent 调外部工具 inputSchema / outputSchema 工具契约描述参数;付钱仍要 AP2 Mandate
UCP 等商务协议 目录、改价、结账会话 Checkout 对象 AP2 明确兼容,自身不管商品浏览
JSON Schema 结构契约 type / required / enum Mandate 和工具参数都靠它;验签之前先过结构

一句话:MCP 让 Agent 会用工具,A2A 让 Agent 会协作,AP2 让 Agent 在被允许的范围内会付钱。三者叠在一起才是 2026 年的智能交易栈。MCP 工具契约怎么写,见AI Agent 与 JSON Schema;模型怎么稳定吐 JSON,见2026 Structured Output

用 JSONNote 调试 AP2 JSON

接 AP2 时最慢的往往不是密码学,而是对 payload。Mandate、Checkout JWT 声明、Receipt、约束数组都是 JSON。JSONNote 在浏览器本地跑,原始交易数据不上传:

  1. 1
    先看结构对不对

    把披露还原后的 Mandate 贴进JSON 格式化,先排除缺逗号、尾逗号、半截 JWT。

  2. 2
    用 Schema 卡住字段

    把上面的调试 Schema 和实例一起放进JSON Schema,立刻看到缺字段、类型错、enum 越界。

  3. 3
    对比两笔交易

    开放约束 vs 封闭单、或两次 Agent 组装结果,用JSON Diff看哪些字段被改过。

  4. 4
    本地分享调试样本

    不要把真实卡号或私钥放进链接。用Hash 分享只传脱敏后的样例 JSON,数据留在 URL fragment,不上传服务器。

常見問題

AP2 和 A2A、MCP 是什麼關係?

A2A 负责 Agent 之间怎么对话,MCP 负责 Agent 怎么调外部工具。AP2 只解决「谁授权这笔钱、凭什么付、事后怎么举证」。它可以作为 A2A / MCP 的支付扩展,不替代两者。

AP2 只支援信用卡嗎?

不是。AP2 对支付工具不可知:卡、银行转账、稳定币都可以,用 Payment Instrument 的 type 区分。加密货币场景还有 A2A x402 扩展。

自主代付是不是 Agent 可以隨便花錢?

不是。自主模式先由用户在可信界面签署开放 Mandate,写明金额上限、商户范围、有效期和 Agent 公钥。Agent 只能签符合这些约束的封闭 Mandate,验证方必须核对约束。

開發 AP2 為什麼還要校驗 JSON Schema?

Mandate 在传输层是 SD-JWT,业务层看到的仍是 JSON 对象。字段名、金额单位、vct 版本写错,验签还没开始就会失败。先用 JSON Schema 拦住结构错误,再做密码学验证。

公告裡的 Intent / Cart Mandate 還算數嗎?

产品叙事仍是「意图 → 购物车 → 付款」。实现时请以当前规范的 Checkout / Payment Mandate(含 open / closed)和官方 schema 为准,不要自己发明第三套字段名。

總結

2026 年 Agent 要自动支付,缺的不是又一个 checkout 按钮,而是可验证的授权。

AP2 用签名 Mandate 把用户意图钉在 JSON 契约上;Checkout 钉住买什么,Payment 钉住付多少、付给谁。

人在场就签封闭单,人不在场就先签约束再让 Agent 补封闭单。结构先用 JSON Schema 校验,再验 SD-JWT。调试 payload 时用 JSONNote 本地格式化、校验和 Diff——密钥和真实支付凭证不要离开你的机器。

← 返回博客