代理与买家
把付费的 Gonka URL 当作普通 HTTP 资源。遇到 402,在本地签署转账并重试。切勿把私钥发给协调器或卖家。
请求周期
- 按卖家文档的方法调用付费 URL(示例是
GET /demo)。 - 若状态不是 402,即可结束 — 资源免费或已支付。
- 读取
PAYMENT-REQUIRED。它是标准 base64 JSON。正文是同一对象,便于 curl。 - 从
accepts选一项(GNK 或 USDC,除非卖家只列了一种)。 - 构建并签署一笔 Gonka
TxRaw,向payTo支付不少于amount的asset。 - 用
PAYMENT-SIGNATURE(支付载荷的 base64)重复原始请求。 - 在 200 时读取
PAYMENT-RESPONSE获取交易哈希。可在 gonka.gg 查询。
对 /demo 的一次完整循环得到 23B76D1281F9EFCC7AFC90659480CF3219A7099959C0513720769F700E9B73B2。命令、RPC 核对和浏览器链接见 快速开始。
选择 accept
每个 accepts[] 项是一条报价。你必须完全按公布条件满足其中一条:
scheme | 必须为 exact。 |
|---|---|
network | 必须为 cosmos:gonka-mainnet。 |
amount | 原子单位。可以多付;少付会被拒绝。 |
asset | ngonka 或 USDC 的 CW-20 地址。 |
payTo | 商户 gonka1…。交易收款人必须匹配。 |
maxTimeoutSeconds | 将 authorization.timeoutAt 设为现在加上小于该值的秒数(CLI 使用 55 秒)。 |
extra.paymentFlow | upfront — 卖家会在提供资源前先结算。 |
签署支付
GNK
一条 /cosmos.bank.v1beta1.MsgSend:从你的地址到 payTo,金额 amount,denom ngonka。手续费 0ngonka。协调器期望 gas 上限 120000。
USDC
一条针对 USDC 合约的 /cosmwasm.wasm.v1.MsgExecuteContract,消息为:
{
"transfer": {
"recipient": "<payTo>",
"amount": "<atomic amount>"
}
}签名规则
- 对
sha256(SignDoc)使用 SIGN_MODE_DIRECT。 - secp256k1,64 字节紧凑签名(r||s)。
- AuthInfo 中的公钥必须推导出
from地址。 chain_id为gonka-mainnet。account_number和sequence必须是 LCD/cosmos/auth/v1beta1/accounts/{from}的当前值。过期 sequence 会以stale_sequence拒绝。
本仓库中的 CLI 已会构造该交易。若你已有 CosmJS 或 inferenced,也可自写签名器。
带请求头重试
PAYMENT-SIGNATURE 是以下对象的 base64:
{
"x402Version": 2,
"accepted": { "...the PaymentRequirements you chose" },
"payload": {
"signature": "<base64 64-byte secp256k1 signature>",
"authorization": {
"from": "gonka1…",
"to": "gonka1…",
"amount": "1000",
"denom": "ngonka",
"timeoutAt": 1710000000
},
"signedTx": "<base64 protobuf TxRaw>"
}
}对于 USDC,accepted.asset 和 authorization.denom 是 CW-20 合约地址。字段含义见 协议。
Fetch 封装
代理运行时的草图。用现有 Gonka 钱包签署 buildAndSign(accepted)。
async function paidFetch(url, key, opts = {}) {
const first = await fetch(url, opts);
if (first.status !== 402) return first;
const required = JSON.parse(atob(first.headers.get("PAYMENT-REQUIRED")));
const accepted = required.accepts[0];
const payload = await buildAndSign(accepted, key);
return fetch(url, {
...opts,
headers: {
...(opts.headers || {}),
"PAYMENT-SIGNATURE": btoa(JSON.stringify(payload)),
},
});
}重试与失败
- 不要自己广播交易。协调器会广播你附上的
signedTx。 - 若 settle 返回
stale_sequence,重新查询账户并再签一次。不要复用旧载荷。 - 若得到
replayed_payment,该TxRaw已经结算过。签署新交易(新 sequence)。 settlement_pending表示已广播但未在时限内确认上块。再次付款前先在浏览器查哈希。- 付款账户必须有足够余额。
/verify会检查;若不足,/settle会在链上失败。
全部代码见 错误。