本文介绍了如何使用 x402 协议在 Rails 应用程序中实现按请求付费的 API 访问控制。通过 Quicknode 提供的 x402-rails 和 x402-payments gem,可以轻松配置 API 端点以要求支付,并生成客户端签名以访问受保护的 API,同时支持 EVM 和 Solana 网络。
传统的 API 货币化依赖于订阅模式和 API 密钥,这为想要简单的,按次付费访问的用户带来了摩擦。x402 支付协议通过使用支付层扩展 HTTP 来解决这个问题,从而实现真正的 按请求付费 访问。
本指南向你展示如何使用 Quicknode 的开源 x402-rails 和 x402-payments gems 将 x402 协议集成到 Rails 应用程序中。 你将学习如何配置 API 以要求付款、保护特定端点,并生成必要的客户端签名以使用 API。
x402-rails gem 创建服务端付费墙x402-payments gem 生成客户端支付签名x402 是一个开放标准,它使用支付层扩展了 HTTP 402 Payment Required 状态代码。 无需管理复杂的计费系统,你可以自动向用户收取他们发出的每个 API 请求的费用。
该协议在一个简单的循环中工作。 让我们逐步分解它,然后在可视图中查看它:
事例 API 调用
curl -i http://localhost:3000/api/weather/paywalled_info
支付请求响应示例
{
"x402Version": 2,
"error": "Payment required to access this resource",
"resource": {
"url": "http://localhost:3000/api/weather/paywalled_info",
"description": "Payment required for /api/weather/paywalled_info",
"mimeType": "application/json"
},
"accepts": [\
{\
"scheme": "exact",\
"network": "eip155:84532", // Base Sepolia CAIP-2 网络标识符\
"amount": "1000", // 最小单位的金额(USDC 为 6 位小数)\
"asset": "0x036CbD53842c5426634e7929541eC2318f3dCF7e", // Base Sepolia 上的 USDC 合约\
"payTo": "YourWalletAddressHere", // 接收钱包\
"maxTimeoutSeconds": 600,\
"extra": {\
"name": "USDC",\
"version": "2"\
}\
}\
],
"extensions": {}
}
PAYMENT-SIGNATURE 标头。支付头示例
Payment Header (PAYMENT-SIGNATURE):
eyJ4NDAyVmVy... # Payment Authorization
带有支付头的 API 调用示例
curl -i -H "PAYMENT-SIGNATURE: eyJ4NDAyVmVy..." http://localhost:3000/api/weather/paywalled_info
成功响应示例
{
"temperature": 72,
"condition": "sunny",
"humidity": 65
}

为了简化 Ruby 中的操作,Quicknode 提供了两个 gems:
x402-rails (服务端):一个 Rails 引擎,提供中间件和控制器助手,可以轻松地为你的 API 端点添加“付费墙”。 它处理签名验证和支付结算。
x402-payments (客户端):一个用于生成复杂的 EIP-712 加密签名和 PAYMENT-SIGNATURE 标头的辅助库,这些签名和标头是使用 x402 驱动的 API 所必需的。
在本节中,我们将使用一个示例应用程序,并解释如何在自己的 Rails 应用程序中设置和配置 x402。
Quicknode 的 qn-guide-examples 存储库中的这个 Rails 项目公开了一个天气 API 和一个高级 API,它们需要 USDC 支付才能访问天气数据。 它演示了:
在深入研究代码之前,让我们从高层次理解应用程序的流程。 如果你对技术细节不感兴趣,请随时直接转到 快速入门 部分。
x402-rails gem 在 config/initializers/x402.rb 中初始化。 它读取接收钱包、协助者 URL、链、货币和乐观模式的环境变量,并设置你的全局配置。 一个典型的配置如下所示:
config/initializers/x402.rb
## config/initializers/x402.rb
X402.configure do |config|
# 你的钱包地址(将收到付款)
config.wallet_address = ENV.fetch("X402_WALLET_ADDRESS", "0xYourWalletAddressHere")
# 处理链上结算的服务。
# 使用公共协助者或你自己的。
config.facilitator = ENV.fetch("X402_FACILITATOR_URL", "https://www.x402.org/facilitator")
# 要使用的区块链网络
config.chain = ENV.fetch("X402_CHAIN", "base-sepolia")
# 支付货币 (USDC 是标准)
config.currency = ENV.fetch("X402_CURRENCY", "USDC")
# 自定义链和Token注册
config.register_chain(
name: "polygon-amoy",
chain_id: 80002,
standard: "eip155"
)
config.register_token(
chain: "polygon-amoy",
symbol: "USDC",
address: "0x41E94Eb019C0762f9Bfcf9Fb1E58725BfB0e7582",
decimals: 6,
name: "USDC",
version: "2"
)
# ==========================================
# 接受多种付款方式
# ==========================================
# 使用 config.accept() 指定要接受哪些链/货币。
# 402 响应将包括所有接受的选项,允许客户端
# 在任何受支持的链上支付。
#
# 如果没有进行 config.accept() 调用,则使用默认的链/货币。
config.accept(chain: "base-sepolia", currency: "USDC")
config.accept(chain: "polygon-amoy", currency: "USDC")
config.accept(chain: "solana-devnet", currency: "USDC")
# 结算模式:
# false(非乐观):等待链上确认
# true(乐观):立即响应,在后台结算
config.optimistic = ENV.fetch("X402_OPTIMISTIC", "true") == "true"
end
这些设置告诉 x402-rails 在哪里接收 USDC 付款、使用哪个链以及是乐观响应还是等待结算。 你还可以在控制器中覆盖每个端点的这些设置,我们很快就会看到。
什么是协助者?
协助者是 x402 支付流程的关键部分。 在客户端发送带有签名支付授权的请求后,服务器会将该授权传递给协助者。 然后,协助者:
这种设计允许客户端支付 API 访问费用,而无需自己提交区块链交易。 他们只签署一条消息(没有 RPC 调用、没有 gas 估算、没有钱包连接过程)。
你可以依赖 x402.org 上的公共协助者,或者如果你想要自定义结算行为、日志记录或支持其他链,可以部署自己的实例。
向 API 端点添加付费墙就像调用 x402_paywall 辅助方法一样简单。 x402-rails gem 将此助手注入到你的控制器中,允许你使用一行代码来要求付款。 在示例 WeatherController 中,paywalled_info action 在返回数据之前收取 $0.001 USDC。
app/controllers/api/weather_controller.rb
class WeatherController < ApplicationController
# Paywalled endpoint (requires payment)
# 付费端点(需要支付)
def paywalled_info
# 1. REQUIRE PAYMENT: This line protects the endpoint.
# 1. 需要付款:此行保护端点。
# It will return a 402 response if payment is missing or invalid.
# 如果缺少或无效的支付,它将返回 402 响应。
x402_paywall(amount: 0.001)
# 2. STOP EXECUTION: If the paywall rendered a 402, stop.
# 2. 停止执行:如果付费墙呈现 402,则停止。
return if performed?
# 3. ACCESS DATA: If payment was successful, continue.
# 3. 访问数据:如果支付成功,请继续。
# Payment info is available in the request environment.
# 支付信息可在请求环境中获得。
payment_info = request.env["x402.payment"]
render json: {
temperature: 72,
condition: "sunny",
humidity: 65,
paid_by: payment_info&.[](:payer),
payment_amount: payment_info&.[](:amount),
network: payment_info&.[](:network),
payment_info: payment_info
}
end
# Free endpoint (no paywall)
# 免费端点(无付费墙)
def public_info
# This endpoint has no paywall and is free.
# 此端点没有付费墙,是免费的。
render json: {
message: "This endpoint is free!",
location: "San Francisco",
timezone: "PST"
}
end
end
示例应用程序的路由在 config/routes.rb 中定义。 这是每个 API 端点(包括免费端点和付费端点)映射到其相应控制器 action 的位置。 天气 API 显示了 x402_paywall 的直接使用,而高级 API 使用 before_action 在多个端点上应用付费墙。
config/routes.rb
Rails.application.routes.draw do
# Define your application routes per the DSL in https://guides.rubyonrails.org/routing.html
# 在 https://guides.rubyonrails.org/routing.html 中定义你的应用程序路由的 DSL
# Reveal health status on /up that returns 200 if the app boots with no exceptions, otherwise 500.
# 在 /up 上显示运行状况,如果应用程序在没有异常的情况下启动,则返回 200,否则返回 500。
# Can be used by load balancers and uptime monitors to verify that the app is live.
# 可供负载均衡器和正常运行时间监控器用来验证应用程序是否已启动。
get "up" => "rails/health#show", as: :rails_health_check
# x402 Payment Protocol Test Endpoints
# x402 支付协议测试端点
namespace :api do
# Weather API endpoints (direct x402_paywall usage)
# 天气 API 端点(直接使用 x402_paywall)
get "weather/paywalled_info", to: "weather#paywalled_info"
get "weather/paywalled_info_sol", to: "weather#paywalled_info_sol"
get "weather/forecast", to: "weather#forecast"
get "weather/public", to: "weather#public_info"
# Premium API endpoints (before_action usage)
# 高级 API 端点(before_action 用法)
resources :premium, only: [ :index, :show ] do
collection do
get :free
end
end
end
end
如果多个端点需要相同的支付逻辑,则无需在每个 action 中重复 x402_paywall。 相反,你可以使用 before_action 过滤器一次性应用它。 这就是高级 API (app/controllers/api/premium_controller.rb) 的结构方式; 它将相同的付费墙应用于多个 action,从而保持控制器干净和一致。
app/controllers/api/premium_controller.rb
module Api
class PremiumController < ApplicationController
# Example of a paywall applied to multiple actions (show and index)
# 已应用于多个 action(show 和 index)的付费墙示例
before_action :require_payment, only: [:show, :index]
def index
payment_info = request.env["x402.payment"]
render json: {
message: "Premium content list",
items: ["Item 1", "Item 2", "Item 3"],
paid_by: payment_info&.[](:payer)
}
end
def show
payment_info = request.env["x402.payment"]
render json: {
message: "Premium content details",
id: params[:id],
content: "This is premium content that requires payment",
paid_by: payment_info&.[](:payer)
}
end
def free
render json: {
message: "This premium controller endpoint is free",
sample: "Here's a sample"
}
end
private
def require_payment
x402_paywall(amount: 0.005, chain: "eip155:84532")
end
end
end
x402 协议旨在跨多个区块链网络工作,并且每个端点都可以指定自己的链设置。 这使你可以灵活地根据你的用例接受不同网络上的支付。
在示例应用程序中,WeatherController 的 paywalled_info_sol 端点要求在 Solana devnet 上进行支付,方法是将默认链覆盖为 solana-devnet。
app/controllers/api/weather_controller.rb
module Api
class WeatherController < ApplicationController
def paywalled_info_sol
x402_paywall(
amount: 0.001,
chain: "solana:EtWTRABZaYq6iMfeYKouRu166VU2xqa1", # Solana devnet CAIP-2 identifier
currency: "USDC",
solana_fee_payer: "FuzoZt4zXaYLvXRguKw2T6xvKvzZqv6PkmaFjNrEG7jm",
wallet_address: "EYNQARNg9gZTtj1xMMrHK7dRFAkVjAAMubxaH7Do8d9Y"
)
# ...
end
end
end
为了提供清晰的错误消息,你可以捕获 x402-rails 引发的特定异常。 这已在 app/controllers/application_controller.rb 中设置。
app/controllers/application_controller.rb
class ApplicationController < ActionController::API
# Application-wide x402 error handling
# 应用程序范围内的 x402 错误处理
rescue_from X402::InvalidPaymentError, with: :render_payment_error
rescue_from X402::FacilitatorError, with: :render_facilitator_error
rescue_from X402::ConfigurationError, with: :render_config_error
private
def render_payment_error(exception)
render json: {
error: "Payment Error",
message: exception.message,
type: "invalid_payment",
status: 402
}, status: :payment_required
end
def render_facilitator_error(exception)
Rails.logger.error("[x402] Facilitator error: #{exception.message}")
render json: {
error: "Payment Service Unavailable",
message: "Unable to process payment. Please try again.",
type: "facilitator_error",
status: 503
}, status: :service_unavailable
end
def render_config_error(exception)
Rails.logger.fatal("[x402] Configuration error: #{exception.message}")
render json: {
error: "Service Configuration Error",
message: "Payment system not properly configured",
status: 500
}, status: :internal_server_error
end
end
我们已经介绍了将 x402 支付集成到 Ruby on Rails 应用程序中的关键技术方面。 现在,让我们开始使用示例项目。
首先,克隆 Quicknode 示例项目:
## Clone the repository
## 克隆存储库
git clone https://github.com/quiknode-labs/qn-guide-examples.git
cd qn-guide-examples/rails/x402-micropayments
## Install dependencies
## 安装依赖项
bundle install
将 .env.example 文件复制到 .env 并更新以下变量。 有关详细信息,请参见文件中的注释。
cp .env.example .env
启动服务器:
bin/rails server -p 3000
你的 API 现在在 http://localhost:3000 上可用。 现在,我们需要学习如何生成有效的支付签名来访问带付费墙的端点。
如前所述,客户端需要生成有效的支付签名(PAYMENT-SIGNATURE 标头)才能访问带付费墙的端点。 示例项目包括一个简单的脚本,用不同的语言生成不同用例的支付签名:
generate-payment.rbgenerate-payment.tsgenerate-payment.py我们将在此指南中使用 Ruby 脚本,但其他语言的过程类似,更多详细信息可在项目的 README 文件中找到。
该脚本使用 bundler/inline 自动安装必要的依赖项,因此你无需设置单独的 Gemfile。
generate_payment.rb
## ... (see full script in the project)
## ...(请参阅项目中的完整脚本)
## Load .env file if it exists
## 如果存在,请加载 .env 文件
require 'dotenv'
Dotenv.load
## Configuration
## 配置
PRIVATE_KEY = ENV.fetch('X402_TEST_PRIVATE_KEY', '0xYourPrivateKeyHere')
PORT = ENV.fetch('PORT', '3000')
PAY_TO = ENV.fetch('X402_WALLET_ADDRESS', 'YourWalletAddressHere')
CHAIN = ENV.fetch('X402_CHAIN', 'base-sepolia')
## Configure x402-payments gem
## 配置 x402-payments gem
X402::Payments.configure do |config|
config.private_key = PRIVATE_KEY
config.chain = CHAIN
config.default_pay_to = PAY_TO
config.max_timeout_seconds = 600
end
## Generate payment header
## 生成支付头
## The gem handles all the EIP-712 signing internally
## 该 gem 在内部处理所有 EIP-712 签名
begin
payment_header = X402::Payments.generate_header(
amount: 0.001, # $0.001 in USD
resource: "http://localhost:#{PORT}/api/weather/paywalled_info",
description: "Payment required for /api/weather/paywalled_info"
)
end
## ... (see full script in the project)
## ...(请参阅项目中的完整脚本)
现在,运行脚本:
ruby generate_payment.rb
该脚本将输出支付头,你可以在客户端中使用该支付头。
注意: 脚本中支付的最大超时时间设置为 600 秒。 你可以根据你的用例调整此值。 否则,支付将在 600 秒后过期。
由于我们已经设置了服务器和支付生成器,因此我们现在可以测试完整的支付流程,并了解 x402 在实践中如何工作。
为你的钱包充值
要测试支付,你需要在 Base Sepolia 测试网上有一些测试 USDC。 你可以从 Circle USDC faucet 获取一些免费的测试 USDC。
首先,尝试在没有支付头的情况下访问带付费墙的端点:
curl -i http://localhost:3000/api/weather/paywalled_info
你应该收到 402 响应,其中包含以下 JSON 载荷:
{
"x402Version": 2,
"error": "Payment required to access this resource",
"resource": {
"url": "http://localhost:3000/api/weather/paywalled_info",
"description": "Payment required for /api/weather/paywalled_info",
"mimeType": "application/json"
},
"accepts": [\
{\
"scheme": "exact",\
"network": "eip155:84532",\
"amount": "1000",\
"asset": "Asset Contract Address", // e.g., USDC on Base Sepolia\
"payTo": "Recipient Address", // The receiving wallet\
"maxTimeoutSeconds": 600,\
"extra": {\
"name": "USDC",\
"version": "2"\
}\
}\
],
"extensions": {}
}
现在,使用 Ruby 脚本(或你首选的支付生成器)生成的支付头来访问带付费墙的端点:
curl -i -H "PAYMENT-SIGNATURE: eyJ4NDAyVmVy..." http://localhost:3000/api/weather/paywalled_info
你应该收到 200 响应,其中包含以下 JSON 载荷:
{
"temperature": 72,
"condition": "sunny",
"humidity": 65,
"paid_by": "0x...",
"payment_amount": "1000",
"network": "base-sepolia"
// ...
}
恭喜! 你已成功将 x402 支付集成到 Ruby on Rails 应用程序中。 现在,你可以使用支付头来访问带付费墙的端点,并享受小额支付的好处。
使用区块链浏览器(例如,Base Sepolia Explorer)来验证支付交易是否已在区块链上成功结算。

你还可以尝试访问免费端点:
curl -i http://localhost:3000/api/weather/public
此端点不需要支付头,因此你应该收到 200 响应,其中包含以下 JSON 载荷:
{
"message": "This endpoint is free!",
"location": "San Francisco",
"timezone": "PST"
}
你现在已经对 x402、x402-rails 和 x402-payments 如何在实际 Rails 应用程序中协同工作有了实际的理解。
从这里,你可以:
如果你遇到困难或有疑问,请在我们的 Discord 中提出。 通过在 X (@Quicknode) 或我们的 Telegram 公告频道 上关注我们,了解最新信息。
如果你对新主题有任何反馈或要求,请 告诉我们。 我们很乐意收到你的来信。
- 原文链接: quicknode.com/guides/x40...
- 登链社区 AI 助手,为大家转译优秀英文文章,如有翻译不通的地方,还请包涵~
如果觉得我的文章对您有用,请随意打赏。你的支持将鼓励我继续创作!