作者:Beosin
随着AI Agent和自动化客户端自主执行任务的需求爆发,机器与机器之间如何在没有人类干预的情况下完成支付,正成为一个亟待解决的基础设施问题,传统的支付接口难以适应高频、动态、跨平台的机器间交易场景。
为此,Stripe与Tempo联合推出了专为机器间支付设计的开放协议Machine Payments Protocol(MPP),旨在让客户端和服务端在自动化流程中,无缝完成价格协商、支付方式选择、凭证提交与交易结算。本文将从MPP协议机制、与x402的对比、生态现状三个维度,解析MPP的协议设计与现实进展。
MPP协议解析
MPP借用了 HTTP 里开发者已经熟悉的 challenge-response 结构,把支付自然嵌进网络请求的生命周期里,通过Stripe的支付渠道或Tempo等区块链完成交易。整个流程遵循一种基于标准 HTTP headers 的挑战-响应模式:
1. 客户端向付费 endpoint 发送一个普通 HTTP 请求(如GET)
2. 服务器返回一个支付挑战(challenge):402 Payment Required 和 WWW-Authenticate: Payment 标头。该标头告诉客户端当前支持接受的货币、价格、收款地址以及可用的支付方式
3. 客户端选择一种支付方式并完成支付(稳定币转账、银行卡支付等)
4. 客户端重新发送原始请求,并带上Authorization: Payment标头的支付凭证(credential)
5. 服务器验证支付并返回带有 Payment-Receipt 标头的响应
https://mpp.dev/protocol
整个流程中有两个重要概念:支付挑战与支付凭证。支付挑战是服务器发出的具体支付要求,其内容结构如下所示:
WWW-Authenticate: Payment id="qB3wErTyU7iOpAsD9fGhJk",
realm="mpp.dev",
method="tempo",
intent="charge",
expires="2025-01-15T12:05:00Z",
opaque="eyJyb3V0ZSI6Ii92MS9zZWFyY2gifQ",
request="eyJhbW91bnQiOiIxMDAwIiwiY3VycmVuY3kiOiJ1c2QifQ"
intent参数目前分为charge、subscription、session三类,以Tempo区块链为例:
request参数是base64url 编码的JSON字符串,由客户端解码获得支付方式的详细信息,如
{
"amount": "1000",
"currency": "usd",
"recipient": "0xf39Fd6e51aad88F6F4ce6aB8827279cffFb92266"
}
支付凭证用于证明您已付款或授权付款,其内容也是base64url 编码的JSON字符串:
Authorization: Payment eyJjaGFsbGVuZ2UiOnsiaWQiOiJxQjN3RXJUeVU3aU9wQXNEOWZHaEprIiwi...
解码后内容包含原来的支付挑战、特定的付款方式和付款证明、付款人身份信息(地址、DID、账户ID)
{
"challenge": {
"expires": "2025-01-15T12:05:00Z",
"id": "qB3wErTyU7iOpAsD9fGhJk",
"intent": "charge",
"method": "tempo",
"opaque": "eyJyb3V0ZSI6Ii92MS9zZWFyY2gifQ",
"realm": "mpp.dev",
"request": "eyJhbW91bnQiOiIxMDAwIi4uLn0",
},
"payload": {
"signature": "0xabc123...",
"type": "transaction"
},
"source": "did:pkh:eip155:4217:0x1234567890abcdef..."
}
以MPP的 TypeScript SDK为例,其具体实践如下:
服务器部分
1. 创建处理支付请求的服务器端点
import crypto from 'crypto';
import Stripe from 'stripe';
// 'stripe' here is the mppx payment method factory, not the Stripe Node SDK
import { Mppx, stripe as mppStripe, tempo } from 'mppx/server';
// Tempo testnet token contract address for pathUSD (testnet USDC).
const PATH_USD = '0x20c0000000000000000000000000000000000000';
const mppSecretKey = crypto.randomBytes(32).toString('base64');
const stripeClient = new Stripe(process.env.STRIPE_SECRET_KEY!, {
apiVersion: '2026-03-04.preview',
});
export async function handler(request: Request) {
const recipientAddress = await createPayToAddress(request);
const mppx = Mppx.create({
methods: [
tempo.charge({
currency: PATH_USD,
recipient: recipientAddress,
testnet: true,
}),
mppStripe.charge({
client: stripeClient,
networkId: process.env.STRIPE_PROFILE_ID!,
paymentMethodTypes: ['card', 'link'],
}),
],
secretKey: mppSecretKey,
});
const response = await Mppx.compose(
mppx.tempo.charge({ amount: '0.01', recipient: recipientAddress }),
mppx.stripe.charge({ amount: '0.50', currency: 'usd' }),
)(request);
if (response.status === 402) return response.challenge;
return response.withReceipt(Response.json({ data: '...' }));
}
2. 创建一个支付意图(PaymentIntent)用于接收稳定币/加密货币支付,当客户端发起请求后,createPayToAddress会返回一个加密货币存款地址,客户端将收到该地址并用于支付。
import Stripe from 'stripe';
import { Credential } from 'mppx';
import NodeCache from 'node-cache';
const paymentCache = new NodeCache({ stdTTL: 300, checkperiod: 60 });
async function createPayToAddress(request: Request): Promise<`0x${string}`> {
const authHeader = request.headers.get('authorization');
if (authHeader && Credential.extractPaymentScheme(authHeader)) {
const credential = Credential.fromRequest(request);
const toAddress = credential.challenge.request.recipient as `0x${string}`;
if (!toAddress) {
throw new Error(
'PaymentIntent did not return expected crypto deposit details'
);
}
if (!paymentCache.has(toAddress)) {
throw new Error('Invalid payTo address: not found in server cache');
}
return toAddress;
}
const decimals = 6;
const amountInCents = Number(10000) / 10 ** (decimals - 2);
const paymentIntent = await stripe.paymentIntents.create({
amount: amountInCents,
currency: 'usd',
payment_method_types: ['crypto'],
payment_method_data: {
type: 'crypto',
},
payment_method_options: {
crypto: {
mode: 'deposit',
deposit_options: {
networks: ['tempo'],
},
} as Stripe.PaymentIntentCreateParams.PaymentMethodOptions.Crypto,
},
confirm: true,
});
if (
!paymentIntent.next_action ||
!('crypto_display_details' in paymentIntent.next_action)
) {
throw new Error(
'PaymentIntent did not return expected crypto deposit details'
);
}
const depositDetails = paymentIntent.next_action
.crypto_display_details as unknown as {
deposit_addresses?: Record<string, { address?: string }>;
};
const payToAddress = depositDetails.deposit_addresses?.tempo?.address;
if (!payToAddress) {
throw new Error(
'PaymentIntent did not return expected crypto deposit details'
);
}
console.log(
`Created PaymentIntent ${paymentIntent.id} for $${(
amountInCents / 100
).toFixed(2)} -> ${payToAddress}`
);
paymentCache.set(payToAddress, true);
return payToAddress as `0x${string}`;
}
客户端部分
创建Tempo/其它用于付款的账户
import { Mppx, tempo } from 'mppx/client'
const provider = Provider.create({ mpp: false }) // Avoid double 402 handling; mppx is configured below.
await provider.request({ method: 'wallet_connect' })
在此基础上,创建支付处理程序
import { Provider } from 'accounts'
Mppx.create({
methods: [tempo({
account: provider.getAccount({ signable: true }),
getClient: provider.getClient,
})],
})
使用fetch请求资源
const response = await fetch('https://mpp.dev/api/ping/paid')
MPP与x402的差异
2025年5月Coinbase推出了x402协议,利用402 Payment Required实现了稳定币支付协议,其流程与MPP非常类似:客户端请求资源->服务器返回带有支付头的 HTTP 402->客户端签署一个稳定币转账并带着支付签名重试->Facilitator 在链上验证结算->服务器返回 HTTP 200。
x402协议对于稳定币支付来说是突破性的,协议非常简洁,开发者可以快速接入。但x402没有法定货币支付的渠道,企业级Agent无法通过x402协议使用公司信用卡支付各类API的费用。而Stripe通过MPP协议填补了以上法币通道的空白,其支付方式已包括Tempo、EVM、Solana、Stellar、Lightning、Stripe、银行卡,并且针对不同场景设计了不同的支付规范:Charge、Session、Discovery、JSON-RPC/MCP transport。概括地说,x402 是互联网的链上稳定币支付标准,MPP 是一个更为通用的 HTTP 支付标准:
MPP 生态发展现状
根据官方注册表(MPP Service Registry)统计,MPP 共收录 137 个服务(其中一个服务可同时属于多个类别)和1439个endpoint。其中 128 个服务只支持 Tempo 支付, 2 个服务只支持 Stripe 支付, 7 个服务同时支持 Tempo 和 Stripe 支付。
*注:MPP 协议文档支持的支付方法不止这两种,还支持lightning、evm、card、solana等支付方式,但这份官方服务注册表当前只收录了 Tempo 与 Stripe 这两类支付服务。
从 endpoint 看,注册表里 1261 个 endpoint 标有价格或动态价格,其中 1068 个是固定价格,193 个是动态价格,另有 178 个没有显式价格或可视为免费/未定价。固定价格的中位数是 $0.02/request,平均值约 $0.139/request,最高固定价格是 StablePhone 的购买手机号 endpoint,$20/request。
在 intent 的使用上:129 个服务使用 charge,8 个服务使用 session。session 服务包括 Anthropic、Dune、Google Gemini、Modal、OpenRouter、Alchemy、Conduit、Tempo RPC这类高频、多次调用、用量动态变化的服务里,而普通数据服务更适合一次请求一次 charge。
分类上,已注册的服务分布偏向 Agent 可消费的数据与工具 API:
data source: https://raw.githubusercontent.com/tempoxyz/mpp/main/schemas/services.ts
第三方数据平台MPPscan收录了超过3700个MPP服务器,根据其统计数据,MPP总交易笔数超过110万,交易量约为14万美元,平均每笔交易金额约0.127美元。
由于x402协议相比MPP协议早推出约8个月,我们只选取过往30日MPP协议与x402协议的数据(未包含MPP非区块链支付渠道的数据)进行对比,如下图所示:
x402协议在当前阶段的整体采用规模明显高于 MPP协议,近30日,x402 的总交易笔数是MPP协议的10.6倍,总交易金额是后者的20.2倍。从协议定位上,x402 更强调轻量、开放和快速接入,更容易先做大交易规模;而 MPP 更强调多支付方式和支付系统完整性,在当前生态发展和场景验证的初期与x402协议存在规模差异。
结语
MPP将支付逻辑深度嵌入HTTP请求的生命周期,通过开发者熟悉的挑战-响应模式,降低了接入机器支付的门槛。相比Coinbase的x402协议,MPP在支付方式上更为多元(覆盖稳定币、银行卡、闪电网络等),在结算模式上支持一次性扣费、会话级按量结算和订阅服务,并借助Stripe的法币通道和Tempo的链上合规控制,为不同规模的企业级应用提供了更完整的支付框架。
未来,MPP能否成为AI Agent经济的通用支付协议,取决于是否有更多服务提供方注册并实际启用多种支付方式。在区块链支付渠道的交易数据,x402协议目前大幅领先。MPP虽然通过Tempo、Stripe等平台提供更为完善的支付渠道,但其支付规模和开发者采用率仍需时间验证。



