创建x402HTTP客户端 create-typescript-x402-client

创建支持Algorand自动支付的x402 HTTP客户端,适用于构建消费x402保护API的应用程序,实现自动支付处理、签名交易、配置支付策略等功能。

DApp开发 0 次安装 0 次浏览 更新于 3/4/2026

创建x402 HTTP客户端(Fetch和Axios)

构建能够自动检测402 Payment Required响应、签名Algorand交易并使用支付凭证重试请求的HTTP客户端——所有操作均透明进行。

先决条件

在使用此技能之前,请确保:

  1. Node.js或浏览器环境支持TypeScript
  2. Algorand钱包或私钥用于签名支付交易
  3. USDC余额在目标网络(测试网或主网)上的付款人账户中

核心工作流程:402支付流程

关键洞见是wrapFetchWithPaymentwrapAxiosWithPayment截获402响应,签名交易组,并使用支付头重试原始请求——全部自动完成:

客户端请求(GET /api/premium)
         |
         v
   服务器响应
         |
         +-- 状态 != 402 --> 原样返回响应
         |
         +-- 状态 == 402 -->
               |
               +-- 解析PaymentRequired(头部V2/体V1)
               +-- 通过注册的x402Client选择方案
               +-- 构建原子交易组
               +-- 使用ClientAvmSigner(钱包或私钥)签名
               +-- 编码PAYMENT-SIGNATURE头
               +-- 用支付头重试原始请求
               |
               v
           返回重试响应

如何进行

第1步:安装依赖项

对于基于Fetch的客户端:

npm install @x402-avm/fetch @x402-avm/avm algosdk

对于基于Axios的客户端:

npm install @x402-avm/axios @x402-avm/avm algosdk axios

第2步:实现ClientAvmSigner

ClientAvmSigner接口是将您的钱包或私钥连接到x402支付系统的桥梁。

接口:

interface ClientAvmSigner {
  address: string;
  signTransactions(
    txns: Uint8Array[],
    indexesToSign?: number[],
  ): Promise<(Uint8Array | null)[]>;
}

对于Node.js(私钥):

import algosdk from "algosdk";

const secretKey = Buffer.from(process.env.AVM_PRIVATE_KEY!, "base64");
const address = algosdk.encodeAddress(secretKey.slice(32));

const signer = {
  address,
  signTransactions: async (txns: Uint8Array[], indexesToSign?: number[]) => {
    return txns.map((txn, i) => {
      if (indexesToSign && !indexesToSign.includes(i)) return null;
      const decoded = algosdk.decodeUnsignedTransaction(txn);
      const signed = algosdk.signTransaction(decoded, secretKey);
      return signed.blob;
    });
  },
};

对于浏览器(@txnlab/use-wallet):

import { useWallet } from "@txnlab/use-wallet-react";
import type { ClientAvmSigner } from "@x402-avm/avm";

function useAvmSigner(): ClientAvmSigner | null {
  const { activeAccount, signTransactions } = useWallet();
  if (!activeAccount) return null;
  return {
    address: activeAccount.address,
    signTransactions: async (txns: Uint8Array[], indexesToSign?: number[]) => {
      return signTransactions(txns, indexesToSign);
    },
  };
}

第3步:创建和配置x402Client

import { x402Client } from "@x402-avm/fetch"; // 或 "@x402-avm/axios"
import { registerExactAvmScheme } from "@x402-avm/avm/exact/client";

const client = new x402Client();
registerExactAvmScheme(client, { signer });

第4步:包装Fetch或Axios

Fetch:

import { wrapFetchWithPayment } from "@x402-avm/fetch";

const fetchWithPay = wrapFetchWithPayment(fetch, client);
const response = await fetchWithPay("https://api.example.com/premium-data");

Axios:

import axios from "axios";
import { wrapAxiosWithPayment } from "@x402-avm/axios";

const api = wrapAxiosWithPayment(axios.create(), client);
const response = await api.get("https://api.example.com/premium-data");

第5步:添加支付策略(可选)

策略在选择之前过滤支付要求。它们按顺序应用:

import type { PaymentPolicy } from "@x402-avm/fetch";

const maxAmount: PaymentPolicy = (version, reqs) => {
  return reqs.filter((r) => BigInt(r.amount ?? "0") <= BigInt("5000000"));
};

const preferAlgorand: PaymentPolicy = (version, reqs) => {
  const algoReqs = reqs.filter((r) => r.network.startsWith("algorand:"));
  return algoReqs.length > 0 ? algoReqs : reqs;
};

client.registerPolicy(preferAlgorand).registerPolicy(maxAmount);

第6步:添加生命周期钩子(可选)

监控和控制支付生命周期:

client.onBeforePaymentCreation(async ({ selectedRequirements }) => {
  const amountUSDC = Number(selectedRequirements.amount) / 1_000_000;
  console.log(`Paying $${amountUSDC.toFixed(6)} USDC`);
  if (amountUSDC > 10) {
    return { abort: true, reason: "Amount exceeds $10 limit" };
  }
});

client.onAfterPaymentCreation(async () => {
  console.log("Payment signed successfully");
});

client.onPaymentCreationFailure(async ({ error }) => {
  console.error("Payment failed:", error.message);
});

重要规则/指南

  1. 在包装之前始终注册一个方案registerExactAvmScheme(client, { signer })必须在wrapFetchWithPaymentwrapAxiosWithPayment之前调用
  2. AVM_PRIVATE_KEY格式 – Base64编码的64字节密钥(32字节种子+32字节公钥)
  3. 地址派生 – 始终使用algosdk.encodeAddress(secretKey.slice(32)),永远不要使用前32个字节
  4. 单次重试 – 包装器在402之后重试一次。如果重试也返回402,错误会被传播
  5. Axios的拦截器顺序 – 先添加您自己的拦截器,然后最后调用wrapAxiosWithPayment
  6. 基于配置的替代方案 – 使用wrapFetchWithPaymentFromConfig/wrapAxiosWithPaymentFromConfig进行声明式设置,无需手动构建x402Client
  7. 通配符网络 – 在基于配置的设置中使用"algorand:*"以匹配任何Algorand网络

基于配置的设置(替代方案)

而不是手动创建一个x402Client,使用基于配置的方法:

import { wrapFetchWithPaymentFromConfig, type x402ClientConfig } from "@x402-avm/fetch";
import { ExactAvmScheme } from "@x402-avm/avm";

const config: x402ClientConfig = {
  schemes: [
    {
      network: "algorand:SGO1GKSzyE7IEPItTxCByw9x8FmnrCDexi9/cOUJOiI=",
      client: new ExactAvmScheme(signer),
    },
  ],
  policies: [maxAmount],
};

const fetchWithPay = wrapFetchWithPaymentFromConfig(fetch, config);

常见错误/故障排除

错误 原因 解决方案
Failed to parse payment requirements 服务器返回的402无效体 检查服务器是否运行x402兼容中间件
Failed to create payment payload 余额不足或错误的网络 确保在正确的网络上有USDC余额
Payment already attempted 支付发送后服务器返回402 支付被拒绝;检查facilitator日志
No network/scheme registered 服务器需要一个未注册的网络 使用registerExactAvmScheme注册所需的方案
Payment creation aborted 一个beforePaymentCreation钩子返回中止 审查钩子逻辑;检查金额限制
All payment requirements were filtered out 策略去除了所有选项 放宽策略或注册额外的方案
No client registered for x402 version: 2 根本没有注册方案 调用registerExactAvmScheme(client, { signer })

阅读支付收据

在成功的付费请求之后,检查响应头:

import { decodePaymentResponseHeader } from "@x402-avm/fetch";

const paymentResponseHeader = response.headers.get("PAYMENT-RESPONSE");
if (paymentResponseHeader) {
  const receipt = decodePaymentResponseHeader(paymentResponseHeader);
  console.log("Transaction settled:", receipt);
}

参考资料/进一步阅读