关于 cryptorefills-x402
cryptorefills-x402 是供 AI Agent 使用的技能,可通过 Cryptorefills 使用 USDC 购买数字商品,无需账户或 API 密钥。它支持 Base 和 Solana 支付流程,并提供支付证明校验及签名、支出保护措施。
主要功能
- 01浏览品牌与商品目录
- 02使用 USDC 下单
- 03选择 Base 或 Solana 结算
- 04验证签名支付要求
- 05跟踪订单交付
适用场景
- 01自主采购礼品卡
- 02开通旅行 eSIM
- 03发放程序化奖励
- 04进行注册表驱动的 Solana 支付
安装
复制下面的命令,在终端中运行。
npx skills add https:/ / github.com/ cryptorefills/ agents --skill cryptorefills-x402安装后在 Claude Code 中输入/cryptorefills-x402确认已加载。
包含的文件
除 SKILL.md 外,安装时一起下载的参考资料和脚本。
references/endpoints.mdprotocol.mdtroubleshooting.md详细介绍
Cryptorefills x402 — 自主 Agent 商务
为持有加密货币钱包的 AI Agent 提供完全自主的购买功能。无需账户、OAuth 或 API 密钥,只需稳定币和签名密钥。
基于 x402 protocol 构建,将 HTTP 402 Payment Required 作为机器间支付标准。支持两种结算通道:Base(Ethereum L2 上的 USDC,默认)和 Solana(Solana 主网上的 USDC SPL,可选)。
如需在人类指导下使用多种支付方式进行购买,请改用 cryptorefills-buy。 如需仅浏览目录,请改用 cryptorefills-catalog。
选择结算通道
| 结算通道 | 主机 | Phase-1 标头 | 钱包 | 资产 | 原生 Gas |
|---|---|---|---|---|---|
| Base(默认) | x402.cryptorefills.com | 无,或 X-Preferred-Network: base | 支持 EIP-712 的 EVM 钱包 | USDC 0x833589fCD6eDb6E08f4c7C32D4f71b54bdA02913,链 ID 8453 | 无 — Cryptorefills 负责中继 |
| Solana | x402.cryptorefills.com | X-Preferred-Network: solana | Solana 密钥对 | USDC SPL 铸币地址 EPjFWdd5AufqSSqeM2qN1xzybapC8G4wEGGkZwyTDt1v | 无 — CDP facilitator 支付 SOL |
| Solana(主机固定) | solana.x402.cryptorefills.com | 省略,或仅使用 solana | Solana 密钥对 | 同上 | 无 |
默认结算通道建议。 如果你的 Agent 在两种结算通道上都有钱包,且没有外部限制,请使用 Base — EIP-712 工具支持更广泛,支付窗口更长(约 15 分钟,Solana 约 60 秒),且与自 v1.0 起 EVM-only Agent 一直使用的合约完全一致。若 Agent 已在 Solana 上运行、需要避免使用 SOL,或注册表 / 市场(例如 pay-skills)要求默认使用 Solana 主网 402 挑战,则使用 Solana — 此时请使用 solana.x402.cryptorefills.com 主机,以固定结算通道,避免歧义。
何时启用
- Agent 在 Base 上拥有钱包(USDC、EIP-712),或在 Solana 上拥有钱包(USDC SPL,可对 v0 交易进行部分签名)
- 任务需要在没有人工支付交互的情况下自主购买
- 不希望设置账户、执行 OAuth 流程或管理 API 密钥
- 关键词:“用 USDC 购买”、“USDC SPL”、“自主购买”、“Agent 商务”、“x402 支付”、“程序化礼品卡”、“Solana mainnet-beta”、“partial-sign”、“VersionedTransaction”、“compute-budget”、“pay-skills registry”、“无需 SOL”、“无需 ETH”
- 使用场景:自动采购礼品卡、配置旅行 eSIM、程序化奖励、由注册表驱动的 Solana 支付
要求
Base 结算通道
| 要求 | 详情 |
|---|---|
| Base 上的 USDC | 链 ID 8453,合约 0x833589fCD6eDb6E08f4c7C32D4f71b54bdA02913 |
| EIP-712 签名 | 为 transferWithAuthorization(EIP-3009)签署类型化数据 |
| 用于 Gas 的 ETH | 不需要 — Cryptorefills 会在链上中继授权 |
| HTTP 客户端 | 标准 REST API 调用 |
| 账户 | 无需账户 |
Solana 结算通道
| 要求 | 详情 |
|---|---|
| Solana 主网上的 USDC SPL | 铸币地址 EPjFWdd5AufqSSqeM2qN1xzybapC8G4wEGGkZwyTDt1v,6 位小数 |
| Solana 密钥对 | 64 字节 Ed25519 密钥(Phantom / Solflare 导出格式均可) |
| Solana RPC 访问权限 | 用于获取最新的 recentBlockhash。默认使用 https://api.mainnet-beta.solana.com;任何可靠的 RPC 均可 |
| v0 交易签名 | 按照规范的 3 条指令结构构建 VersionedTransaction,并进行部分签名 — 参见 protocol.md |
| 用于 Gas 的 SOL | 不需要 — CDP facilitator 使用其资金池支付 SOL Gas |
| HTTP 客户端 | 标准 REST API 调用 |
| 账户 | 无需账户 |
支出保障措施
自主 Agent 使用真实资金消费时,需要严格的管控:
- 开始前设置每个会话的消费限额(默认:每个会话最高 $100,每笔交易最高 $50 — 只有用户明确要求时才提高限额)。
- 签名前核实 402 响应中的订单金额 — 切勿盲目签名。
- 每种支付通道使用专用钱包,其中只存放所需数量的稳定币。
- 切勿记录、暴露或分享钱包的私钥/密钥 — 使用环境变量或密钥管理器。
- 记录每笔交易:
order_id、产品、金额、钱包地址、支付通道、交易签名/哈希。 - 签名金额不得超过 402 响应中的
maxAmountRequired。 - 签名前验证 402 的真实性。
payTo是每个会话的存款钱包 — 清单中不会列出存款钱包,因此无法使用允许列表。相反,每个 402 都携带X-Payment-Required-Signature,这是由网关签名的 JWS(ES256)。使用清单中的attestation.keys/attestation.jwks_uri中的密钥验证它(与清单同源),并确保:iss== 你发送 POST 请求所用的源站,sid==X-Session-Id标头,pr_sha256== base64url(sha256(PAYMENT-REQUIRED标头的原样值)),pay_to/network== 解码后的accepts[0]值,exp为未来时间。**如果缺少该标头或任何检查未通过,请拒绝该 402,且不要签名。**完整操作步骤和verify402()代码片段:references/protocol.md→ 验证 402 证明。
Solana 特定要求:
payTo是 OWNER 公钥,绝不是 ATA。 根据(payTo, mint)推导收款方 ATA。若将payTo当作 ATA 来签署转账,操作会失败。- 部分签名之前,验证
extra.feePayer与 PAYMENT-REQUIRED 中的值一致 — 并将其用作交易的payerKey。 - 部分签名前立即重新获取
recentBlockhash。 有效时间约为 60 秒;网关将maxTimeoutSeconds限制为 60 以提示这一点。在 Solana 上,不要在阶段 1 和阶段 2 之间插入用户提示。 - 序列化之前,断言构建的交易恰好包含 3 条指令(compute-unit limit、compute-unit price、TransferChecked)。
- 使用 SPL
TransferChecked(标签0x0c),而不要使用Transfer(0x03)。 CDP 会以unknown_error拒绝普通Transfer。
一般要求:
- 礼品卡代码(
voucher_code)与现金类似 — 妥善保管,绝不公开分享或写入日志。 - 数字商品一经交付概不退款。
- 条款:https://www.cryptorefills.com/terms/
每个主机均通过 /.well-known/x402.json 提供清单,并包含 attestation 区块(签名密钥、jwks_uri、验证流程)。请从你在阶段 1 中使用的同一主机读取清单 — attestation 中的 iss 必须与该源站一致,且 jwks_uri 必须与该源站同源。
阶段 2 始终发送到与阶段 1 相同的主机。 X-Session-Id 对应的会话绑定到特定主机;跨主机 POST 请求可能导致会话查找失败。
核心工作流
GET /v1/brands → discover brands
GET /v1/catalog → get products and prices
POST /v1/orders → 402 + PAYMENT-REQUIRED + X-Session-Id + X-Payment-Required-Signature
↓ verify the attestation (JWS) — reject the 402 if it is missing or invalid
↓ sign (EIP-712 for Base, partial-sign v0 tx for Solana)
POST /v1/orders → submit with PAYMENT-SIGNATURE [+ X-Session-Id] → 200
GET /v1/orders/{id} → poll until delivered
两种支付通道的流程、REST 合约以及订单/交付模式完全相同。只有阶段 1 的标头选择、PAYMENT-REQUIRED 中的 extra 区块以及签名原语不同。
分步说明
1. 浏览品牌
GET /v1/brands?country_code=us
返回该国家/地区可用的品牌。每个条目都包含 brand_name、family、category、min、max。
国家代码使用 ISO 3166-1 Alpha-2 小写格式(us、it、br),无论支付通道为何。如果从目录或购买技能(使用大写格式)获取国家代码,请先将其转换为小写,再用于 x402 端点。
2. 获取目录
GET /v1/catalog?country_code=us&brand_name=Amazon.com
返回包含 product_id、is_range、currency、price_usdc,以及 denomination(固定面值)或 min_value/max_value(范围面值)的商品。
- 固定面值商品(
is_range: false):直接使用product_id。省略product_value。面值是以currency计价的denomination。 - 范围面值商品(
is_range: true):将items[].product_value设为所需金额,单位为品牌当地的currency(不是美元)。例如,购买一张面值 €5、currency: "EUR"的 Amazon.nl 礼品卡时,传入product_value: 5。402 响应会提供实际结算所需的 USDC 金额(通常为price_usdc加减少量价差)。
下单前:检查稳定币余额
下单前,请确认所选通道上的钱包有足够的稳定币:
- Base:在
0x833589fCD6eDb6E08f4c7C32D4f71b54bdA02913上调用balanceOf(walletAddress)。 - Solana:在发送方 ATA 上调用
getTokenAccountBalance—getAssociatedTokenAddress(mint=EPjF…WEGGkZwyTDt1v, owner=agent)。无需 SOL 余额。
目录中的 price_usdc 仅供参考;确切金额会在 402 响应中确认。
3. 创建订单 — 阶段 1(获取付款要求)
Base(默认):
curl -X POST https://x402.cryptorefills.com/v1/orders \
-H "Content-Type: application/json" \
-d '{
"email": "[email protected]",
"items": [{
"product_id": "abc123",
"beneficiary_account": "[email protected]",
"product_value": 25
}]
}'
# → HTTP 402 with PAYMENT-REQUIRED, X-Session-Id and X-Payment-Required-Signature headers
Solana(通过标头启用):
curl -X POST https://x402.cryptorefills.com/v1/orders \
-H "Content-Type: application/json" \
-H "X-Preferred-Network: solana" \
-d '<same body>'
Solana(固定主机):
curl -X POST https://solana.x402.cryptorefills.com/v1/orders \
-H "Content-Type: application/json" \
-d '<same body>'
范围面值商品必须提供 product_value;固定面值商品则省略。可选:添加 "callback_url": "https://...",以通过 webhook 接收交付通知,而不是轮询。
捕获以下三个响应标头:
PAYMENT-REQUIRED— 付款要求的 base64url 编码 JSON(各通道格式见下文)。X-Session-Id— UUID。在阶段 2 中原样回传(Solana 必需,Base 可选)。X-Payment-Required-Signature— 用于证明上述两个标头的 JWS(iss、sid、pr_sha256、pay_to、network、exp)。签名前先验证 — 参见references/protocol.md。缺少该标头应视为 402 失败。
PAYMENT-REQUIRED — Base 示例
{
"x402Version": 2,
"accepts": [{
"scheme": "exact",
"network": "eip155:8453",
"maxAmountRequired": "25000000",
"asset": "0x833589fCD6eDb6E08f4c7C32D4f71b54bdA02913",
"extra": { "name": "USD Coin", "version": "2", "decimals": 6 },
"payTo": "0x...",
"description": "$25.00 Amazon Gift Card"
}],
"expiresAt": 1830000000
}
与 Base 相比的 Solana 差异(完整 Solana 示例见 protocol.md)
| Base | Solana | |
|---|---|---|
network | eip155:8453 | solana:5eykt4UsFv8P8NJdTREpY1vzqKqZKvdp(完整 CAIP-2) |
asset | EVM 合约 | SPL 铸币地址,base58 编码(USDC 为 EPjF…WEGGkZwyTDt1v) |
extra | {name, version, decimals} | {feePayer} — 用作 payerKey |
payTo | 收款钱包 | 收款方 所有者 公钥(由 facilitator 端派生 ATA) |
expiresAt 时间窗口 | 约 15 分钟 | 约 60 秒 |
4. 签署付款
Base — EIP-712 / EIP-3009
为 transferWithAuthorization 签署类型化数据。
Domain:Base 上的 USDC 合约。
Types:TransferWithAuthorization(address from, address to, uint256 value, uint256 validAfter, uint256 validBefore, bytes32 nonce)。
| 字段 | 值 |
|---|---|
from | 你的钱包地址 |
to | 402 响应中的 payTo |
value | 402 响应中的 maxAmountRequired |
validAfter | 0 |
validBefore | 402 响应中的 expiresAt(Unix 秒) |
nonce | 随机 32 字节十六进制值 |
确切的 EIP-712 类型化数据结构见 references/protocol.md。
Solana — 部分签名 v0 交易
构建 v0 VersionedTransaction,且必须恰好包含 3 条指令,并按以下顺序排列:ComputeBudget 设置计算单位上限(200_000 units)→ ComputeBudget 设置价格(1000 microLamports)→ SPL createTransferCheckedInstruction(标签 0x0c,不是 Transfer 的 0x03)。使用 mint = asset、senderAta = getAssociatedTokenAddress(mint, signer)、recipientAta = getAssociatedTokenAddress(mint, payTo)(其中 payTo 是所有者)、payerKey = extra.feePayer,以及从 Solana RPC 获取的最新 recentBlockhash。使用 tx.sign([signer]) 进行部分签名 — 为 CDP 保留 feePayer 签名槽位。序列化后不超过 1232 字节。
完整步骤见 references/protocol.md。
5. 完成订单 — 阶段 2
使用 PAYMENT-SIGNATURE 重新 POST 相同的请求体。回传阶段 1 中的 X-Session-Id(Solana 必需)。
Base
curl -X POST https://x402.cryptorefills.com/v1/orders \
-H "Content-Type: application/json" \
-H "PAYMENT-SIGNATURE: <base64url-encoded JSON>" \
-d '<same body as phase 1>'
# → HTTP 200
PAYMENT-SIGNATURE 负载(然后对 JSON 进行 base64url 编码):
{
"x402Version": 2,
"scheme": "exact",
"network": "eip155:8453",
"payload": {
"signature": "0x...",
"authorization": {
"from": "0xYourWallet",
"to": "0xPayToAddress",
"value": "25000000",
"validAfter": "0",
"validBefore": "1830000000",
"nonce": "0xRandomBytes32"
}
}
}
Solana
curl -X POST https://x402.cryptorefills.com/v1/orders \
-H "Content-Type: application/json" \
-H "PAYMENT-SIGNATURE: <base64url-encoded JSON>" \
-H "X-Session-Id: <UUID from Phase 1 response>" \
-d '<same body as phase 1>'
# → HTTP 200
PAYMENT-SIGNATURE 载荷(对外层 JSON 进行 base64url 编码;内层 payload.transaction 为普通 base64):
{
"x402Version": 2,
"scheme": "exact",
"network": "solana:5eykt4UsFv8P8NJdTREpY1vzqKqZKvdp",
"payload": {
"transaction": "<plain-base64 of serialized v0 transaction>"
}
}
编码规则。 对于两种支付通道,外层
PAYMENT-SIGNATURE封装都使用 base64url 编码。只有 Solana 上的内层payload.transaction字段使用普通 base64(Solana 生态惯例;不透明地传递给支付协调方)。不要将两者统一处理。
服务端以 HTTP 200 响应:
{
"order_id": "cr_abc123",
"status": "processing",
"estimated_delivery_seconds": 60,
"poll_url": "/v1/orders/cr_abc123"
}
6. 跟踪交付状态
GET /v1/orders/{order_id}
每隔 5–10 秒轮询一次,直到 status 为 completed 或 failed。10 分钟后停止轮询,并报告订单可能卡住了——请通过 [email protected] 联系支持团队,并提供 order_id。
当 completed 时,deliveries 数组包含:
voucher_code— 礼品卡兑换码pin— 如有要求则提供 PINurl— 如适用则提供兑换 URLbrand_name、product_name— 购买的商品
示例:Solana 上的 €5 Amazon.nl 礼品卡
端到端验证各步骤的说明是否能够组合使用。真实数值,钱包地址已匿名化:
# 1. Discover Amazon.nl
curl 'https://x402.cryptorefills.com/v1/brands?country_code=nl' | jq '.[] | select(.family|test("Amazon"))'
# → {"brand_name":"Amazon.nl","family":"Amazon.nl","category":"e-commerce", ...}
# 2. Find a range product priced in EUR
curl 'https://x402.cryptorefills.com/v1/catalog?country_code=nl&brand_name=Amazon.nl' | jq '.[0]'
# → {"product_id":"amzn-nl-range","is_range":true,"currency":"EUR",
# "min_value":5,"max_value":500,"price_usdc":"5.42", ...}
# 1 EUR isn't offered (min is 5 EUR) — pick 5 EUR.
# 3. Phase 1 — opt into Solana
curl -i -X POST https://x402.cryptorefills.com/v1/orders \
-H "Content-Type: application/json" \
-H "X-Preferred-Network: solana" \
-d '{"email":"[email protected]",
"items":[{"product_id":"amzn-nl-range",
"beneficiary_account":"[email protected]",
"product_value":5}]}'
# → HTTP/1.1 402
# X-Session-Id: 3f9c1a8b-... ← capture, echo on Phase 2
# PAYMENT-REQUIRED: <base64url JSON> ← decode for accepts[0]
# X-Payment-Required-Signature: <JWS> ← verify first (protocol.md → Verifying the 402 attestation)
#
# accepts[0] decoded:
# network: solana:5eykt4UsFv8P8NJdTREpY1vzqKqZKvdp
# asset: EPjFWdd5AufqSSqeM2qN1xzybapC8G4wEGGkZwyTDt1v
# maxAmountRequired: "5420000" ← 5.42 USDC
# payTo: <owner pubkey> ← derive recipient ATA from this
# extra.feePayer: <CDP pubkey> ← use as transaction.payerKey
// 4. Decode PAYMENT-REQUIRED, verify budget, build the partial-signed v0 tx
import {ComputeBudgetProgram, Connection, Keypair, PublicKey,
TransactionMessage, VersionedTransaction} from '@solana/web3.js';
import {createTransferCheckedInstruction, getAssociatedTokenAddress} from '@solana/spl-token';
import bs58 from 'bs58';
// 4a. Parse the 402 response
const paymentRequired = JSON.parse(
Buffer.from(phase1Headers['payment-required'], 'base64url').toString());
const sessionId = phase1Headers['x-session-id'];
const {payTo, asset, maxAmountRequired, extra} = paymentRequired.accepts[0];
// 4b. Spending-safeguard checks BEFORE signing
const SPEND_LIMIT_ATOMIC = BigInt(50_000_000); // $50 = 50e6 atomic USDC
if (BigInt(maxAmountRequired) > SPEND_LIMIT_ATOMIC) throw new Error('over budget');
if (asset !== 'EPjFWdd5AufqSSqeM2qN1xzybapC8G4wEGGkZwyTDt1v') throw new Error('wrong mint');
// 4c. Build the transaction
const signer = Keypair.fromSecretKey(bs58.decode(process.env.SOLANA_SIGNER_KEY));
const conn = new Connection('https://api.mainnet-beta.solana.com', 'confirmed');
const mint = new PublicKey(asset);
const owner = new PublicKey(payTo); // OWNER, not an ATA
const feePayer = new PublicKey(extra.feePayer); // CDP signs this slot
const senderAta = await getAssociatedTokenAddress(mint, signer.publicKey);
const recipientAta = await getAssociatedTokenAddress(mint, owner);
const {blockhash} = await conn.getLatestBlockhash('finalized'); // 'finalized' is older but accepted by all validators — reduces timing sensitivity
const message = new TransactionMessage({
payerKey: feePayer,
recentBlockhash: blockhash,
instructions: [
ComputeBudgetProgram.setComputeUnitLimit({units: 200_000}),
ComputeBudgetProgram.setComputeUnitPrice({microLamports: 1000}),
createTransferCheckedInstruction(senderAta, mint, recipientAta,
signer.publicKey, BigInt(maxAmountRequired), 6),
],
}).compileToV0Message();
const tx = new VersionedTransaction(message);
tx.sign([signer]); // partial — leaves feePayer slot
// Assert on the pre-compilation array — MessageV0 exposes `compiledInstructions`, not `instructions`.
// Reading `tx.message.instructions` throws TypeError. Use the source array passed to TransactionMessage.
if (message.version !== 0) throw new Error('expected v0 message');
if (tx.message.compiledInstructions.length !== 3) throw new Error('expected exactly 3 instructions');
if (tx.serialize().length > 1232) throw new Error('tx too large');
const txB64 = Buffer.from(tx.serialize()).toString('base64'); // inner: plain base64
const inner = {x402Version: 2, scheme: 'exact',
network: 'solana:5eykt4UsFv8P8NJdTREpY1vzqKqZKvdp',
payload: {transaction: txB64}};
const headerValue = Buffer.from(JSON.stringify(inner)).toString('base64url'); // outer: base64url
# 5. Phase 2 — same host as Phase 1, echo X-Session-Id from step 3
curl -X POST https://x402.cryptorefills.com/v1/orders \
-H "Content-Type: application/json" \
-H "PAYMENT-SIGNATURE: <headerValue from step 4c>" \
-H "X-Session-Id: <sessionId from step 4a>" \
-d '<same body as Phase 1>'
# → HTTP/1.1 200
# {"order_id":"cr_xxx","status":"processing","poll_url":"/v1/orders/cr_xxx", ...}
# 6. Poll
curl https://x402.cryptorefills.com/v1/orders/cr_xxx
# → {"status":"completed",
# "deliveries":[{"voucher_code":"XXXX-YYYY-ZZZZ","brand_name":"Amazon.nl", ...}]}
如果步骤 1–6 无法适用于你的场景,失败情况已记录在 references/troubleshooting.md 中。
字段名称映射(x402 与 MCP)
如果在 x402 和 MCP 技能之间切换,请注意以下字段名称差异:
| 概念 | x402(本技能) | MCP(cryptorefills-buy) |
|---|---|---|
| 礼品卡代码 | voucher_code | deliverable.pin_code |
| PIN | pin(单独字段) | 包含在 pin_code 中 |
| 订单状态 | status(单个字段) | order_state + payment_state |
| 订单 ID 格式 | 带 cr_ 前缀 | UUID |
关键注意事项
两种支付通道
- 国家代码:x402 端点使用小写(
us,而非US)。MCP 技能使用大写——端点不同,规则也不同。 - 品牌名称:区分大小写——请使用
/v1/brands响应中的准确值。 X-Preferred-Network值:区分大小写,必须为小写——仅限base或solana。在多支付通道主机上,Base或Solana(首字母大写)会返回400 invalid_network。- 金额精度:使用 402 中的准确
maxAmountRequired,不要四舍五入或修改。 - 外层编码:两种支付通道的
PAYMENT-SIGNATURE外层封装都使用 base64url 编码(与网关的解码器一致)。 - 不要混用支付通道:会话在阶段 1 选定的支付通道上固定。不要尝试在阶段 2 切换支付通道。
- 阶段 2 使用相同主机:将阶段 2 的 POST 请求发送到阶段 1 使用的同一主机。会话与主机绑定。
- 未签名的 402:如果 402 没有
X-Payment-Required-Signature,或其签名未通过任何一项检查,都必须拒绝——绝不能以“TLS 连接看起来没问题”为由继续处理。对收到的PAYMENT-REQUIRED标头字符串进行哈希;不要重新序列化解码后的 JSON。
Base
- USDC 合约:在 Base 上必须准确为
0x833589fCD6eDb6E08f4c7C32D4f71b54bdA02913。 - 链 ID:必须为
8453(Base 主网)。链不正确 = 签名无效。 - 支付超时:402 的
expiresAt字段提供截止时间(约 15 分钟)。请在过期前签名并重新提交。 - Nonce:每笔交易必须唯一。使用加密安全的随机 32 字节值。
- EIP-712 域:必须与 Base 上 USDC 合约的域分隔符一致。
Solana
- 网络字符串:必须使用完整的 CAIP-2
solana:5eykt4UsFv8P8NJdTREpY1vzqKqZKvdp,不能使用"solana"或"solana-mainnet"。 - **
payTo是 OWNER 公钥,不是 ATA。**协调方会根据(owner, mint)推导收款方 ATA。 - **使用
TransferChecked(0x0c),不要使用Transfer(0x03)。**CDP 会以unknown_error拒绝后者。 - 必须恰好有 3 条指令,且顺序如下:ComputeBudget 设置限制、ComputeBudget 设置价格、TransferChecked。CDP 要求指令数量为 3 至 6 条。
payerKey= PAYMENT-REQUIRED 中的extra.feePayer。CDP 会在结算时为该账户签名并支付 SOL Gas 费。- 交易数据包限制:1232 字节。规范的 3 条指令结构完全符合限制。
- 区块哈希有效窗口:约 60 秒。部分签名前立即重新获取;Phase 1 和 Phase 2 之间不要插入用户提示。
- 在 Phase 2 中回传 Phase 1 响应中的
X-Session-Id——这是必需的(SPL 交易是不透明的,因此网关没有其他方式查找会话)。 - 内部编码:PAYMENT-SIGNATURE JSON 中的
payload.transaction是普通 base64(Solana 惯例)——只有外层封装使用 base64url。
参考资料
只有在需要了解本技能文件之外的详细信息时,才加载参考资料。
| 文件 | 在以下情况下加载…… | 内容 |
|---|---|---|
references/protocol.md | 需要确切的签名方法——Base 的 EIP-712 域和类型,或 Solana 的完整 VersionedTransaction 构建方法——或需要验证 402 证明 | 两阶段流程、请求头、各支付通道的 PAYMENT-REQUIRED 结构、X-Payment-Required-Signature 验证(verify402)、Base EIP-712 / EIP-3009 详情、Solana 三指令方法 |
references/endpoints.md | 需要 API 调用的确切请求 / 响应架构 | REST API 参考、主机表、完整请求头列表、错误响应代码 |
references/troubleshooting.md | 请求失败或返回意外状态 | 各支付通道的错误目录和恢复方法 |