X402:面向开发者的互联网原生加密付费墙协议

发布: (2025年12月24日 GMT+8 15:42)
15 min read
原文: Dev.to

Source: Dev.to

X402:为开发者打造的互联网原生加密付费墙协议

在当今的网络生态系统中,内容创作者和开发者正日益寻求一种 去中心化、无需信任 的方式来对其作品进行货币化。传统的支付网关往往依赖于中心化的服务商,这不仅带来了高额手续费,还引入了审查和数据泄露的风险。X402 正是为了解决这些痛点而诞生的——它是一套基于区块链的原生加密付费墙协议,旨在让开发者能够 直接在浏览器层面 实现内容付费。

目录

  1. 为什么需要 X402?
  2. 核心概念
  3. 工作流程概览
  4. 实现细节
  5. 示例代码
  6. 常见问题
  7. 未来路线图

为什么需要 X402?

  • 去中心化:不再依赖 Stripe、PayPal 等中心化支付网关。
  • 即时结算:交易在链上完成,几乎零延迟。
  • 隐私保护:用户只需提供加密钱包地址,无需泄露个人身份信息。
  • 可编程:开发者可以自定义付费规则、访问时长以及内容解锁方式。

“在 Web3 时代,内容付费应该像加载图片一样自然。” — Ankita Sharma


核心概念

概念说明
Paywall Contract部署在以太坊或兼容链上的智能合约,负责管理付费、验证和内容解锁。
Access Token由合约签发的 JWT(JSON Web Token),包含用户钱包地址、付费时间戳以及访问权限。
Client SDK前端 JavaScript 库,负责与合约交互、生成签名请求以及验证 Access Token。
Resolver服务器端中间件,用于在用户请求受保护资源时检查 Access Token 的有效性。

工作流程概览

sequenceDiagram
    participant User as 用户 (钱包)
    participant Browser as 浏览器 SDK
    participant Contract as Paywall 合约
    participant Server as 内容服务器

    User->>Browser: 发起付费请求
    Browser->>Contract: 调用 `payAndUnlock()` 并发送签名
    Contract-->>Browser: 返回 Access Token
    Browser->>Server: 携带 Token 请求受保护资源
    Server-->>Browser: 返回解锁的内容
  1. 用户 在页面上点击“解锁”按钮。
  2. 浏览器 SDK 调用智能合约的 payAndUnlock() 方法,自动弹出钱包签名窗口。
  3. 合约在确认支付后生成 Access Token 并返回给前端。
  4. 前端在随后的 HTTP 请求头中携带该 Token。
  5. 服务器端 Resolver 验证 Token(签名、过期时间、支付金额),若合法则返回受保护的内容。

实现细节

1. 智能合约(Solidity)

// SPDX-License-Identifier: MIT
pragma solidity ^0.8.0;

contract X402Paywall {
    address public owner;
    uint256 public price; // 以 wei 为单位

    mapping(address => uint256) public lastPaid;

    event Paid(address indexed payer, uint256 timestamp);

    constructor(uint256 _price) {
        owner = msg.sender;
        price = _price;
    }

    function payAndUnlock() external payable {
        require(msg.value >= price, "Insufficient payment");
        lastPaid[msg.sender] = block.timestamp;
        emit Paid(msg.sender, block.timestamp);
    }

    function getLastPaid(address user) external view returns (uint256) {
        return lastPaid[user];
    }
}
  • 合约仅提供 payAndUnlock() 方法,接受固定金额的 ETH(或兼容链的原生代币)。
  • lastPaid 用于记录用户最近一次付费的时间戳,供服务器端验证访问时长。

2. 前端 SDK(TypeScript)

import { ethers } from "ethers";

export class X402Client {
  private provider: ethers.providers.Web3Provider;
  private contract: ethers.Contract;

  constructor(rpcUrl: string, contractAddress: string, abi: any) {
    this.provider = new ethers.providers.Web3Provider((window as any).ethereum);
    this.contract = new ethers.Contract(contractAddress, abi, this.provider.getSigner());
  }

  async payAndGetToken(): Promise<string> {
    const tx = await this.contract.payAndUnlock({ value: ethers.utils.parseEther("0.01") });
    await tx.wait();

    // 这里使用后端 API 生成 JWT,前端只负责转发钱包地址
    const response = await fetch("/api/generate-token", {
      method: "POST",
      headers: { "Content-Type": "application/json" },
      body: JSON.stringify({ address: await this.provider.getSigner().getAddress() })
    });

    const { token } = await response.json();
    return token;
  }
}
  • 支付 通过 payAndUnlock 完成,金额写死在合约中(可通过构造函数或 setPrice 方法动态调整)。
  • Token 生成 交由后端完成,以防止前端泄露私钥或签名逻辑。

3. 服务器端 Resolver(Node.js / Express)

const jwt = require("jsonwebtoken");
const { ethers } = require("ethers");

// 合约 ABI 与地址
const contractAbi = [...];
const contractAddress = "0xYourContractAddress";
const provider = new ethers.providers.JsonRpcProvider(process.env.RPC_URL);
const contract = new ethers.Contract(contractAddress, contractAbi, provider);

function verifyAccessToken(req, res, next) {
  const authHeader = req.headers.authorization;
  if (!authHeader) return res.status(401).json({ error: "Missing token" });

  const token = authHeader.split(" ")[1];
  try {
    const payload = jwt.verify(token, process.env.JWT_SECRET);
    const { address, iat } = payload;

    // 检查链上支付记录
    contract.getLastPaid(address).then((timestamp) => {
      if (timestamp.toNumber() < iat) {
        return res.status(403).json({ error: "Payment not found" });
      }
      // 可选:检查付费有效期(如 24 小时)
      const now = Math.floor(Date.now() / 1000);
      if (now - iat > 24 * 3600) {
        return res.status(403).json({ error: "Token expired" });
      }
      // 通过验证
      req.user = { address };
      next();
    });
  } catch (err) {
    return res.status(401).json({ error: "Invalid token" });
  }
}
  • JWT 中的 iat(Issued At)用于与合约的 lastPaid 时间戳比对,确保用户已完成支付。
  • 通过 verifyAccessToken 中间件后,后端即可安全地返回受保护的资源(如 Markdown、图片或 API 数据)。

示例代码

下面展示一个完整的 React 页面,演示如何使用 X402 SDK 解锁一篇付费文章。

import React, { useState } from "react";
import { X402Client } from "./x402Client";

const contractAddress = "0xYourContractAddress";
const abi = [ /* 合约 ABI */ ];

export default function PaidArticle() {
  const [content, setContent] = useState<string>("🔒 这是一篇付费文章,请先解锁。");
  const [loading, setLoading] = useState(false);
  const client = new X402Client("", contractAddress, abi);

  const unlock = async () => {
    setLoading(true);
    try {
      const token = await client.payAndGetToken();
      const res = await fetch("/api/articles/secret", {
        headers: { Authorization: `Bearer ${token}` },
      });
      const data = await res.text();
      setContent(data);
    } catch (e) {
      console.error(e);
      alert("解锁失败,请检查钱包是否已连接并完成支付。");
    } finally {
      setLoading(false);
    }
  };

  return (
    <div>
      <h1>付费文章标题</h1>
      <p>{content}</p>
      {content.startsWith("🔒") && (
        <button onClick={unlock} disabled={loading}>
          {loading ? "解锁中…" : "支付 0.01 ETH 解锁"}
        </button>
      )}
    </div>
  );
}

提示:在生产环境中,请务必使用 HTTPS,并在后端对 price 进行二次校验,以防止前端篡改支付金额。


常见问题

问题解答
X402 支持哪些链?目前已在 Ethereum 主网、Goerli 测试网 以及 Polygon 部署。后续计划支持 Arbitrum、Optimism 等 L2。
是否可以使用 ERC-20 代币支付?合约示例使用原生代币(ETH/BNB),但可以通过 ERC-20 transferFromPermit 方式进行扩展。
Token 有效期多久?默认 24 小时,可在后端配置 TOKEN_TTL 环境变量进行自定义。
如何防止重放攻击?JWT 中的 iat 与链上 lastPaid 时间戳必须匹配,且每次支付都会更新 lastPaid,从而使旧 Token 失效。
是否需要中心化的后端来生成 JWT?是的,后端负责签名 JWT 并校验链上支付记录。可以使用 Serverless(Vercel、Cloudflare Workers)实现无状态部署。

未来路线图

  • 跨链支付:通过 LayerZeroWormhole 实现一次支付在多链上通用。
  • 可组合的付费模型:支持 订阅、一次性付费、分段付费 等多种业务场景。
  • 浏览器原生插件:推出 X402 Chrome/Edge 扩展,让用户无需离开页面即可完成支付。
  • 标准化元数据:制定 x402.json 描述文件,类似 manifest.json,用于声明付费规则和合约信息。

结语

X402 为开发者提供了一

什么是 X402?

X402 是一个 链无关 协议,允许内容提供者、API 所有者和开发者在授予资源访问权限之前要求使用加密货币进行微支付。

关键特性

  • 利用 USDC 等稳定币以避免波动。
  • 支持使用 EIP‑3009 或类似标准的免 gas 支付。
  • 通过 facilitators 抽象区块链复杂性,使买卖双方的支付过程无缝。

核心概念

当客户端请求付费墙资源时:

  1. 服务器返回 HTTP 402 + 支付指令。
  2. 客户端完成支付。
  3. 在授权成功后交付资源。

理想使用场景

  • 需要自动化按使用付费计费的 AI 驱动应用
  • 需要低摩擦变现的 API 提供商
  • 保护付费文章或视频的内容创作者
  • Web3 生态系统中的物联网 / 机器对机器支付

为什么 X402 存在

传统支付解决方案的问题

  • 高最低费用 → 对微交易不切实际
  • 摩擦感——用户必须创建账户,输入支付信息
  • 退款争议
  • 自动化受限——AI 代理或后端服务无法使用

X402 如何解决这些问题

  • 在 HTTP 上实现即时、无摩擦的微支付
  • 支持 AI 或软件代理的编程式支付
  • 减少对中心化支付处理器的依赖
  • 将网络本身变成可付费、可编程的环境

关键组件

组件角色
客户端(买方)请求资源,收到 402 响应,构建并发送已签名的支付授权。可以是用户、AI 代理或后端服务。
资源服务器(卖方)托管内容或 API,定义支付要求,验证支付,并在结算后交付资源。
中介者验证客户端的已签名支付并执行区块链结算。可以是托管的(例如 Coinbase X402 中介者)或自行托管。

X402 工作流

1. 客户端请求资源

GET /premium-data HTTP/1.1
Host: example.com

2. 服务器响应 HTTP 402

HTTP/1.1 402 Payment Required
X-PAYMENT-REQUIRED: {
  "amount": "0.05",
  "currency": "USDC",
  "chain": "base-sepolia"
}

3. 客户端签署支付授权

(使用 EIP‑3009 或者中介 SDK)

const auth = await wallet.signAuthorization({
  amount: "0.05",
  to: merchantAddress
});

4. 客户端重新发送带支付的请求

fetch("/premium-data", {
  headers: { "X-PAYMENT": JSON.stringify(auth) }
});

5. 服务器通过中介验证支付

  • 签名和负载验证
  • 资金可用性和结算
  • 若有效,则链上执行

6. 服务器交付资源

HTTP/1.1 200 OK
Content-Type: application/json

{ "secret": "Premium content unlocked!" }

序列图:(展示客户端、服务器和中介之间的交互)

开发者使用案例

使用案例付款类型为什么选择 X402?
AI 模型推理$0.01/request按使用付费,无需订阅
API 变现每次 API 调用大规模微交易
内容付费墙每篇文章/视频无需用户账户
物联网 / 自动化服务按使用量完全程序化支付
AI 对 AI 交易自动完全自治

入门套件集成

X402 入门套件 (dabit3/x402-starter-kit) 简化了服务器端的集成工作。

设置

git clone https://github.com/dabit3/x402-starter-kit
cd x402-starter-kit
pnpm install
pnpm dev

配置支付需求

export const paymentConfig = {
  "/premium-data": "$0.05",
  "/ai-inference": "$0.10"
};

添加中间件

app.use(
  expressX402({
    paymentConfig,
    facilitatorUrl: process.env.FACILITATOR_URL
  })
);

定义付费接口

app.get("/premium-data", (req, res) => {
  res.json({ secret: "Premium content unlocked!" });
});

客户端流程

const auth = await wallet.signAuthorization({
  amount: "0.05",
  to: merchantAddress
});

fetch("/premium-data", {
  headers: { "X-PAYMENT": JSON.stringify(auth) }
});

最佳实践

  • 在主网部署前,请在 Base Sepolia 或其他测试网进行测试。
  • 使用稳定币以降低波动性。
  • 缓存支付授权,以避免重复的区块链验证。
  • 实施监控/日志记录,以捕获结算失败和支付错误。
  • 确保您的中介端点具备弹性,能够应对请求激增。

为什么 X402 很重要

  • 实现 按使用付费的网络经济
  • 支持自主 AI 代理的支付。
  • 减少对中心化处理器的依赖。
  • 在网络协议中标准化加密付费墙。
  • 降低全球微交易的摩擦。

X402 不仅是一个支付协议——它是一个可编程、可货币化的网络框架。

安全性与可靠性考虑

  • 严格验证签名的真实性。
  • 使用随机数或过期时间戳防止重放攻击。
  • 确保协调者能够正确处理并发的结算请求。
  • 对高频率的程序化支付考虑限流和节流。
  • 始终监控结算失败并提供备选机制。

Conclusion

X402 代表了一场范式转变:它允许在网络上进行原生、无摩擦、可编程的支付,为开发者、AI 服务和内容创作者解锁新的变现模式。通过集成 X402,平台可以:

  • 按需实现微规模服务的变现
  • 启用自主机器支付
  • 减少对传统支付处理器的依赖
  • 标准化全球微支付基础设施

简而言之,它将整个网络转变为可编程的经济体。

Back to Blog

相关文章

阅读更多 »