创建x402保护端点的支付墙UI
为Algorand和多链上x402保护的端点创建支付墙UI。当构建带有服务器端中间件和客户端钱包集成的支付门控内容时使用,设置PaywallBuilder与网络处理器,与Express/Hono/Next.js集成,配置钱包发现(Pera,Defly,Lute),或构建多网络支付墙(AVM+EVM+SVM)。强烈触发包括"创建x402支付墙"、“PaywallBuilder”、“avmPaywall”、“支付墙”、“支付墙中间件”、“402支付页面”、“支付墙HTML”、“支付门控内容”。
创建x402保护端点的支付墙UI
构建服务器端中间件,为浏览器提供支付HTML页面,为API客户端提供JSON 402响应,自动集成Algorand钱包(Pera,Defly,Lute)。
先决条件
在使用此技能之前,请确保:
- 后端框架(Express.js,Hono,或Next.js)
- 一个运行中的中介服务,可通过URL访问
- 一个Algorand地址接收付款(payTo地址)
核心工作流程:服务器端支付墙架构
支付墙系统有两个方面。服务器中间件检测到缺少付款并提供JSON 402或HTML支付墙页面。HTML页面处理钱包连接、签名和重试:
浏览器请求
|
v
[服务器中间件]
|
+-- 有PAYMENT-SIGNATURE头吗?
| |
| +-- 是:验证付款,结算交易,返回内容
| +-- 否:这是一个浏览器请求(Accept: text/html)?
| |
| +-- 是:返回支付墙HTML页面(402)
| +-- 否:返回JSON 402响应
|
v
[支付墙HTML页面]
|
+-- 读取window.x402配置
+-- 显示钱包连接UI(Pera/Defly/Lute)
+-- 用户连接钱包并批准付款
+-- 用PAYMENT-SIGNATURE头重试请求
+-- 成功后重定向到付费内容
如何进行
第1步:安装依赖
服务器端包:
npm install @x402-avm/paywall @x402-avm/avm @x402-avm/core
加上你的框架中间件:
# Express.js
npm install @x402-avm/express
# Hono
npm install @x402-avm/hono
# Next.js
npm install @x402-avm/next
第2步:使用PaywallBuilder创建支付墙
PaywallBuilder创建一个PaywallProvider,生成HTML支付墙页面。按优先顺序注册网络处理器——第一个匹配的获胜:
import { createPaywall, avmPaywall } from "@x402-avm/paywall";
const paywall = createPaywall()
.withNetwork(avmPaywall) // 支持algorand:*网络
.withConfig({
appName: "我的高级API",
appLogo: "https://example.com/logo.png",
testnet: true,
})
.build();
对于多网络支持,注册多个处理器:
import { createPaywall, avmPaywall, evmPaywall, svmPaywall } from "@x402-avm/paywall";
const paywall = createPaywall()
.withNetwork(avmPaywall) // algorand:*
.withNetwork(evmPaywall) // eip155:*
.withNetwork(svmPaywall) // solana:*
.withConfig({ appName: "通用支付墙", testnet: true })
.build();
第3步:定义受保护的路由
路由指定每个端点所需的付款:
const routes = {
"/api/premium-content": {
accepts: {
scheme: "exact",
network: "algorand:SGO1GKSzyE7IEPItTxCByw9x8FmnrCDexi9/cOUJOiI=",
asset: "10458941", // 测试网上的USDC ASA ID
payTo: "YOUR_ALGORAND_ADDRESS_HERE",
price: "$0.01", // 0.01 USDC
maxTimeoutSeconds: 300,
},
description: "访问高级内容",
mimeType: "application/json",
},
};
第4步:应用中间件(Express.js)
import express from "express";
import { paymentMiddleware, x402ResourceServer } from "@x402-avm/express";
const app = express();
const server = new x402ResourceServer({ url: process.env.FACILITATOR_URL! });
app.use(paymentMiddleware(routes, server, { testnet: true }, paywall));
app.get("/api/premium-content", (req, res) => {
res.json({ content: "这是付费内容。" });
});
app.listen(3000);
第4步(替代):应用中间件(Hono)
import { Hono } from "hono";
import { paymentMiddleware, x402ResourceServer } from "@x402-avm/hono";
const app = new Hono();
const server = new x402ResourceServer({ url: process.env.FACILITATOR_URL! });
app.use("*", paymentMiddleware(routes, server, { testnet: true }, paywall));
app.get("/api/premium-content", (c) => {
return c.json({ content: "高级内容已解锁!" });
});
export default app;
第4步(替代):应用中间件(Next.js)
中间件方法:
// middleware.ts
import { paymentProxy, x402ResourceServer } from "@x402-avm/next";
const server = new x402ResourceServer({ url: process.env.FACILITATOR_URL! });
const proxy = paymentProxy(routes, server, { testnet: true }, paywall);
export async function middleware(request: NextRequest) {
if (request.nextUrl.pathname.startsWith("/api/premium")) {
return proxy(request);
}
return NextResponse.next();
}
路由处理器方法(withX402):
// app/api/premium/route.ts
import { withX402, x402ResourceServer } from "@x402-avm/next";
const server = new x402ResourceServer({ url: process.env.FACILITATOR_URL! });
async function handler(request: NextRequest) {
return NextResponse.json({ content: "高级内容!" });
}
export const GET = withX402(handler, routeConfig, server, { testnet: true }, paywall);
重要规则/指南
- 处理器顺序很重要——
withNetwork()调用确定优先级。第一个处理器的supports()对于付款要求返回true被使用 - avmPaywall支持
algorand:*——任何以algorand:开头的网络都被匹配 - 测试网与主网——在
PaywallConfig和中间件配置中设置testnet: true/false - USDC ASA ID——测试网:
10458941,主网:31566704 - 需要中介URL——中间件需要一个运行中的中介来验证和结算付款
- Tree-shaking——只导入你需要的网络处理器。
avmPaywall可以从@x402-avm/paywall或@x402-avm/paywall/avm导入 - 多路由——在路由对象中定义多个条目,每个都有自己的价格、描述和资产
钱包集成
AVM支付墙HTML页面使用@wallet-standard/app发现Algorand钱包:
| 钱包 | 类型 | 特性 |
|---|---|---|
| Pera Wallet | 移动+WalletConnect | algorand:signTransaction |
| Defly Wallet | 移动+WalletConnect | algorand:signTransaction |
| Lute Wallet | 浏览器扩展 | algorand:signTransaction |
支付墙页面自动:
- 通过钱包标准发现可用钱包
- 显示钱包选择UI
- 检查连接账户的USDC余额
- 处理交易签名
- 用支付头重试原始请求
- 成功后重定向到付费内容
多网络支付墙
通过在accepts中指定数组,在多个链上接受付款:
const routes = {
"/api/premium": {
accepts: [
{
scheme: "exact",
network: "algorand:SGO1GKSzyE7IEPItTxCByw9x8FmnrCDexi9/cOUJOiI=",
asset: "10458941",
payTo: "ALGO_ADDRESS_HERE",
price: "$0.01",
maxTimeoutSeconds: 300,
},
{
scheme: "exact",
network: "eip155:84532",
asset: "0x036CbD53842c5426634e7929541eC2318f3dCF7e",
payTo: "0xEVM_ADDRESS_HERE",
price: "$0.01",
maxTimeoutSeconds: 30,
},
],
description: "高级内容 - 用Algorand或Base上的USDC支付",
mimeType: "application/json",
},
};
自定义支付墙处理器
如果内置支付墙不满足您的需求,实现自定义PaywallNetworkHandler:
import type { PaywallNetworkHandler } from "@x402-avm/paywall";
const customHandler: PaywallNetworkHandler = {
supports(requirement) {
return requirement.network.startsWith("algorand:");
},
generateHtml(requirement, paymentRequired, config) {
return `<!DOCTYPE html>
<html><body>
<h1>支付${requirement.amount}以访问</h1>
<script>window.x402 = ${JSON.stringify({ paymentRequired, ...config })};</script>
</body></html>`;
},
};
const paywall = createPaywall()
.withNetwork(customHandler)
.build();
常见错误/故障排除
| 错误 | 原因 | 解决方案 |
|---|---|---|
| 浏览器中未显示支付墙 | 中间件未应用或路由未匹配 | 检查路由模式是否匹配请求路径 |
| 浏览器返回JSON 402 | 浏览器未发送Accept: text/html |
确保直接浏览器导航,而不是程序化获取 |
| 未检测到钱包 | 未安装钱包扩展 | 安装Pera,Defly或Lute钱包 |
| “余额不足” | 账户没有USDC | 在正确网络上为钱包充值USDC |
| 无法访问中介 | 错误的URL或服务关闭 | 验证FACILITATOR_URL环境变量 |
| 付款未结算 | 中介签名者未注资 | 确保中介地址有ALGO支付费用 |
参考资料/进一步阅读
- REFERENCE.md - 详细的API参考
- EXAMPLES.md - 完整的代码示例
- x402-avm 示例仓库
- x402-avm 文档