BotPay Facilitator(撮合器)
欢迎使用 BotPay Facilitator!该 Cloudflare Worker 提供一个安全的 API,用于在以太坊上通过 x402 协议撮合与处理支付。开始使用前,请先通过我们的账户管理门户获取 API key 与 secret。
API Key 管理
通过 Portal UI 管理 API key 与配额 —— 在 /register 注册你的 Botpay facilitator 账户,并访问 /login 登录页面进入 API key 管理控制台。
Portal 支持通过 x402 支付来增加配额或获取新的 API key。用户可以通过支付为 API key 充值补充配额。
Facilitator API(接口)
POST /verify
验证一笔支付交易。Facilitator 通过 x402 Node 包的实现,接受使用标准 x402 结构(PaymentPayload 与 PaymentRequirements)的请求 —— 详见 x402 包文档。
响应(Verify):
{
"isValid": true,
"invalidReason": null,
"payer": "0xPayerAddress"
}
POST /settle
使用 x402 的 payment payload 与 requirements 对已验证的支付进行结算。
请求体:
{
"paymentPayload": { ... },
"paymentRequirements": { ... }
}
(使用与 /verify 请求相同的结构 —— 参考上面的 EVM/SVM 示例。)
响应(Settle):
{
"success": true,
"transaction": "0xTransactionHash",
"network": "base",
"payer": "0xPayerAddress"
}
备注:
- 失败时
success将为false,并且errorReason可能提示原因(例如insufficient_funds、invalid_payment等)。 - verify 与 settle 两个操作每次调用都会消耗 1 点 API 配额。
认证(Authentication)
所有 facilitator API 请求都需要使用 HMAC 签名进行认证。你需要:
- API Key ID(通过
X-API-Key请求头传递) - 对应的 secret key(用于签名,绝不会在请求中发送)
HMAC 签名(HMAC Signing)
请求使用 HMAC-SHA256 签名。Facilitator 采用“仅签名 Header”的方案,并使用时间戳来防止重放与篡改。
必需请求头:
X-API-Key: 你的 API key IDX-Timestamp: Unix epoch 秒(整数)X-Signature: Hex 编码的 HMAC-SHA256 签名
待签名字符串:
{timestamp}\n{method}\n{path}
其中:
timestamp为X-Timestamp的值(秒)method为大写 HTTP 方法(例如POST)path为请求路径与 query(例如/facilitator/verify或/facilitator/verify?foo=1)
HMAC key:
服务端将 hashed_secret 存为 hex(SHA-256(secret))。要计算签名,你应:
- 计算
key = SHA256(secret),并使用key的原始字节作为 HMAC key - 计算
signature = hex(HMAC-SHA256(key, stringToSign))
时间窗口(Timestamp window):
服务端允许的时间偏移窗口由 SIGNATURE_WINDOW_SECONDS 控制(默认 300 秒)。
示例(Node.js):
const crypto = require('crypto');
function buildSignedHeaders(apiKeyId, secret, method, path = '') {
const timestamp = Math.floor(Date.now() / 1000).toString();
const stringToSign = `${timestamp}\n${method.toUpperCase()}\n${path}`;
const key = crypto.createHash('sha256').update(secret).digest(); // raw bytes
const signature = crypto.createHmac('sha256', key).update(stringToSign).digest('hex');
const headers = {
'Content-Type': 'application/json',
'X-API-Key': apiKeyId,
'X-Timestamp': timestamp,
'X-Signature': signature,
};
return headers;
}
// Usage example
const headers = buildSignedHeaders('your-api-key-id', 'your-secret', 'POST', '/facilitator/verify');
const body = JSON.stringify({ paymentPayload: {...}, paymentRequirements: {...} });
fetch('https://your-facilitator.com/facilitator/verify', { method: 'POST', headers, body });
客户端示例(Client Examples)
JavaScript 客户端
// Node client: create an x402 payment (using `x402`), sign it with your EVM signer, then POST to the facilitator
const crypto = require('crypto');
const { createAndSignPayment } = require('x402'); // builds canonical paymentPayloads
// Example helper to build HMAC headers matching the facilitator
function buildSignedHeaders(apiKeyId, secret, method, path = '') {
const timestamp = Math.floor(Date.now() / 1000).toString();
const stringToSign = `${timestamp}\n${method.toUpperCase()}\n${path}`;
const key = crypto.createHash('sha256').update(secret).digest(); // raw bytes
const signature = crypto.createHmac('sha256', key).update(stringToSign).digest('hex');
const headers = {
'Content-Type': 'application/json',
'X-API-Key': apiKeyId,
'X-Timestamp': timestamp,
'X-Signature': signature,
};
return headers;
}
// Usage example (pseudo-code — replace signer with your viem wallet client or other signer)
async function verifyPayment(apiKeyId, secret, signer, paymentRequirements) {
// Build and sign a canonical x402 paymentPayload using your signer
const paymentPayload = await createAndSignPayment(signer, {
x402Version: 1,
scheme: 'exact',
network: paymentRequirements.network,
payload: {
// For exact EVM payments, create authorization; createAndSignPayment will sign it
authorization: {
from: '0xSenderAddress',
to: paymentRequirements.payTo,
value: paymentRequirements.maxAmountRequired,
validAfter: '0',
validBefore: `${Math.floor(Date.now() / 1000) + 3600}`,
nonce: '0x...'
}
}
}, paymentRequirements);
const body = JSON.stringify({ paymentPayload, paymentRequirements });
const headers = buildSignedHeaders(apiKeyId, secret, 'POST', '/facilitator/verify', body);
const res = await fetch('https://botpay-facilitator.alexwlex143.workers.dev/facilitator/verify', { method: 'POST', headers, body });
return res.json();
}
配额管理(Quota Management)
- 每个 API key 都有配额上限
- verify 与 settle 操作每次各消耗 1 点配额
- 通过
/api-keys端点查看剩余配额 - 通过
/add-quota端点增加配额
错误处理(Error Handling)
API 返回标准 HTTP 状态码:
200: 成功400: 请求错误(Bad Request)401: 未授权(签名无效)403: 禁止(配额超限)500: 服务端内部错误(Internal Server Error)
错误响应会返回 JSON,包含 success: false 与错误信息。
安全最佳实践(Security Best Practices)
- 永远不要分享你的 secret key
- 所有请求都使用 HTTPS
- 如有需要,可在你侧校验签名
- 监控配额使用情况
- 定期轮换 API key
参考(References)
- x402(package) — Payment payload/requirements 结构与 facilitator 辅助方法:https://www.npmjs.com/package/x402
- x402-hono — 用于 x402 集成的 Hono 中间件与辅助工具:https://www.npmjs.com/package/x402-hono
- viem — EVM 签名工具与
verifyTypedData:https://www.npmjs.com/package/viem - @coinbase/cdp-sdk — 用于为 CDP facilitator 集成生成 CDP JWT:https://www.npmjs.com/package/@coinbase/cdp-sdk
- 本地实现:
src/facilitatorCore.js— verify/settle 核心路由与认证中间件src/utils/x402-hono-utils.js— 为 verify 与 settle 操作构建 CDP JWT 请求头