X402,一个静态博客盈利化练习
摘要
一位开发者使用 Cloudflare Workers 上的 x402 支付中间件为静态博客实现付费墙,探索基于微交易的盈利模式以替代广告收入的潜力。
暂无内容
查看缓存全文
缓存时间: 2026/07/06 14:04
# x402,一个静态博客货币化实验
来源:https://shtein.me/posts/x402-poc/
## x402
Cloudflare 几天前发布了一篇关于 Monetization Gateway 上线的公告 (https://blog.cloudflare.com/monetization-gateway/)。这具有革命性意义,原因很多。它降低了货币化的高门槛,让你能精确控制收费对象和最低支付额度。这实际上可能改变我们使用互联网的方式,让互联网赖以生存的广告经济过时。
这听起来像是博客或 API 货币化的理想工具。尽管我没有什么可货币化的东西,但这项技术似乎太重要了,我不能不尝试一下。那就开始吧。
## 计划
不幸的是,Cloudflare 的服务似乎仍处于封闭测试阶段(?),这意味着你目前无法自由获取访问权限,需要加入等待列表。所以我们只能自己实现这个功能。这其实更有趣,不是吗?幸运的是,它的设置相当简单。虽然需要给静态博客添加几个活动组件,但没有什么是一天内不能加装的。
那么,我们需要什么才能让这件事工作起来?
1. 一个接收资金的钱包
2. 一个执行支付处理逻辑的 Worker
3. 我们想要设置付费墙的资源
我有第 1 和第 3 项,但没有第 2 项。目前这里我将使用 Cloudflare Workers,因为我的站点就托管在那里。这也决定了我们实现它的语言选择:TypeScript。也许以后我会重新实现它,让它托管在我的本地服务器上,但为了控制实验范围——暂时还是用 Cloudflare。
## 中间件
那么我们直接开始。我们需要的第一件事是一个中间件,它接收请求,确保只有在支付后才授予访问权限,并处理价格披露。官方文档有一个如何在 Hono 中实现它的示例 (https://docs.x402.org/getting-started/quickstart-for-sellers#2-add-payment-middleware),我们将使用这个示例。做一些修改以适应代码在 Cloudflare Worker 上运行而不是独立服务器的情况,放入我们的钱包,并将示例端点替换为更有用的端点——我们就得到了这个:
```
import { Hono } from "hono";
import type { MiddlewareHandler } from "hono";
import { paymentMiddleware, x402ResourceServer } from "@x402/hono";
import { ExactEvmScheme } from "@x402/evm/exact/server";
import { ExactSvmScheme } from "@x402/svm/exact/server";
import { HTTPFacilitatorClient } from "@x402/core/server";
const app = new Hono();
const evmAddress = "0xD040AEACCdFf083C5D4cB221F1533e8719a84F0e";
const svmAddress = "HjexCvNzgxJT3Ni7rb98WF4pQGEX2fN7G6Zh26B19mBc";
const facilitatorClient = new HTTPFacilitatorClient({
url: "https://x402.org/facilitator",
});
let payment: MiddlewareHandler | undefined;
app.use(async (c, next) => {
payment ??= paymentMiddleware(
{
"GET /api/joke": {
accepts: [
{
scheme: "exact",
price: "$0.01",
network: "eip155:84532",
payTo: evmAddress,
},
{
scheme: "exact",
price: "$0.01",
network: "solana:EtWTRABZaYq6iMfeYKouRu166VU2xqa1",
payTo: svmAddress,
},
],
description: "A premium, hand-picked joke",
mimeType: "application/json",
},
},
new x402ResourceServer(facilitatorClient)
.register("eip155:84532", new ExactEvmScheme())
.register("solana:EtWTRABZaYq6iMfeYKouRu166VU2xqa1", new ExactSvmScheme()),
);
return payment(c, next);
});
const jokes = [];
app.get("/api/joke", (c) => {
return c.json({
joke: jokes[Math.floor(Math.random() * jokes.length)],
});
});
export default app;
```
Worker 还需要一个 `wrangler.jsonc`(Cloudflare 专用配置):
```
{
"name": "x402-poc",
"main": "src/index.ts",
"compatibility_date": "2026-07-01",
"compatibility_flags": ["nodejs_compat"],
"env": {
"production": {
"name": "x402-poc",
"routes": [
{ "pattern": "shtein.me/api/*", "zone_name": "shtein.me" }
]
}
}
}
```
其中有两个不太明显的点:`nodejs_compat` 是必需的,因为 x402 包导入了 Node 内置模块(`events`、`crypto`、`url`),没有它构建会失败。而路由是有意只定义在 `production` 环境中:定义了路由后,`wrangler dev` 会模拟该路由的主机,因此中间件生成的 URL 会指向真实域名而不是 localhost。
本地运行:
```
npx wrangler dev
```
发送一个测试请求——我们看到了付费墙:
```
curl -i http://localhost:8787/api/joke
HTTP/1.1 402 Payment Required
Content-Length: 2
Content-Type: application/json
PAYMENT-REQUIRED: eyJ4NDAyVmVyc2lvbiI6MiwiZXJyb3IiOiJQYXltZW50IHJlcXVpcmVkIiwicmVzb3VyY2UiOnsidXJsIjoiaHR0cDovL2xvY2FsaG9zdDo4Nzg3L2FwaS9qb2tlIiwiZGVzY3JpcHRpb24iOiJBIHByZW1pdW0sIGhhbmQtcGlja2VkIGpva2UiLCJtaW1lVHlwZSI6ImFwcGxpY2F0aW9uL2pzb24ifSwiYWNjZXB0cyI6W3sic2NoZW1lIjoiZXhhY3QiLCJuZXR3b3JrIjoiZWlwMTU1Ojg0NTMyIiwiYW1vdW50IjoiMTAwMDAiLCJhc3NldCI6IjB4MDM2Q2JENTM4NDJjNTQyNjYzNGU3OTI5NTQxZUMyMzE4ZjNkQ0Y3ZSIsInBheVRvIjoiMHhEMDQwQUVBQ0NkRmYwODNDNUQ0Y0IyMjFGMTUzM2U4NzE5YTg0RjBlIiwibWF4VGltZW91dFNlY29uZHMiOjMwMCwiZXh0cmEiOnsibmFtZSI6IlVTREMiLCJ2ZXJzaW9uIjoiMiJ9fSx7InNjaGVtZSI6ImV4YWN0IiwibmV0d29yayI6InNvbGFuYTpFdFdUUkFCWmFZcTZpTWZlWUtvdVJ1MTY2VlUyeHFhMSIsImFtb3VudCI6IjEwMDAwIiwiYXNzZXQiOiI0ek1NQzlzcnQ1Umk1WDE0R0FnWGhhSGlpM0duUEFFRVJZUEpnWkpEbmNEVSIsInBheVRvIjoiSGpleEN2TnpneEpUM05pN3JiOThXRjRwUUdFWDJmTjdHNlpoMjZCMTltQmMiLCJtYXhUaW1lb3V0U2Vjb25kcyI6MzAwLCJleHRyYSI6eyJmZWVQYXllciI6IkNLUEtKV05kSkVxYTgxeDdDa1oxNEJWUGlZNnkxNlN4czdvd3pucXRXWXA1In19XX0=
```
`PAYMENT-REQUIRED` 标头是 base64 编码的接受的支付方式和价格列表:
```
{
"x402Version": 2,
"error": "Payment required",
"resource": {
"url": "http://localhost:8787/api/joke",
"description": "A premium, hand-picked joke",
"mimeType": "application/json"
},
"accepts": [
{
"scheme": "exact",
"network": "eip155:84532",
"amount": "10000",
"asset": "0x036CbD53842c5426634e7929541eC2318f3dCF7e",
"payTo": "0xD040AEACCdFf083C5D4cB221F1533e8719a84F0e",
"maxTimeoutSeconds": 300,
"extra": {
"name": "USDC",
"version": "2"
}
},
{
"scheme": "exact",
"network": "solana:EtWTRABZaYq6iMfeYKouRu166VU2xqa1",
"amount": "10000",
"asset": "4zMMC9srt5Ri5X14GAgXhaHii3GnPAEERYPJgZJDncDU",
"payTo": "HjexCvNzgxJT3Ni7rb98WF4pQGEX2fN7G6Zh26B19mBc",
"maxTimeoutSeconds": 300,
"extra": {
"feePayer": "CKPKJWNdJEqa81x7CkZ14BVPiY6y16Sxs7owznqtWYp5"
}
}
]
}
```
这正是我们想要看到的:两个测试网络,精确金额为 1 美分。现在让我们尝试支付,好吗?为了测试这种形式——我们需要一个编程客户端,它能够进行支付并重新发送带有确认的请求。不过在这个特定用例中,我想看看浏览器中的最终用户是否能做到这一点。幸运的是,他们可以!如果你现在从浏览器访问相同的 URL,你会看到这个:
browser-failed-paywall.png
它用简单的英语告诉我们该怎么做才能让它工作,所以让我们来做:
```
npm install @x402/paywall
```
```
import { HTTPFacilitatorClient } from "@x402/core/server";
+import { createPaywall, evmPaywall, svmPaywall } from "@x402/paywall";
@@
new x402ResourceServer(facilitatorClient)
.register("eip155:84532", new ExactEvmScheme())
.register("solana:EtWTRABZaYq6iMfeYKouRu166VU2xqa1", new ExactSvmScheme()),
+ { appName: "Igor's corner", testnet: true },
+ createPaywall().withNetwork(evmPaywall).withNetwork(svmPaywall).build(),
);
return payment(c, next);
});
```
现在尝试访问它,我们看到了一个漂亮的 UI 帮助我们支付访问权限:
browser-success-paywall.png
顶部有充值链接,因为我们当前在测试网上。在生产环境中不会有这个。让我们尝试用 MetaMask 支付。
首先连接 MetaMask:
mm-connected.png
现在如果我们继续实际支付:
signature-request.png
最后我们终于得到了我们付费的内容:
success.png
关于这个最终请求的几点观察:
客户端发送一个签名来确认支付,放在 `PAYMENT-SIGNATURE` 标头中,解码后是:
```
{
"x402Version": 2,
"payload": {
"authorization": {
"from": "0xAF40224e2B8fF2B4840c99d8458A0Fd803b15a0e",
"to": "0xD040AEACCdFf083C5D4cB221F1533e8719a84F0e",
"value": "10000",
"validAfter": "1783263532",
"validBefore": "1783264432",
"nonce": "0x82806d883f9d46e376b9dc9c065560521f1c9064cf58d1d4ea53e9e3be5f01df"
},
"signature": "0x7284c4c0da5cd029fff1f07fd4e5ff5b5c51bf13064b9a50e787f83f6e67555a419b85db77f27cb47a2101e03c38b93d1af9e6e4a3b2712675f35c975ea284d51c"
},
"resource": {
"url": "http://localhost:8787/api/joke",
"description": "A premium, hand-picked joke",
"mimeType": "application/json"
},
"accepted": {
"scheme": "exact",
"network": "eip155:84532",
"amount": "10000",
"asset": "0x036CbD53842c5426634e7929541eC2318f3dCF7e",
"payTo": "0xD040AEACCdFf083C5D4cB221F1533e8719a84F0e",
"maxTimeoutSeconds": 300,
"extra": {
"name": "USDC",
"version": "2"
}
}
}
```
如你所见,它包含了我们的中间件确保支付已进行所需的所有信息。因此它用成功的 `PAYMENT-RESPONSE` 标头响应:
```
{
"success": true,
"payer": "0xAF40224e2B8fF2B4840c99d8458A0Fd803b15a0e",
"transaction": "0x88aefe88050c4faaa650383460451ba1faebe3bdc398793970592e6a4ae787dc",
"network": "eip155:84532"
}
```
以及包含实际内容的响应体。
另一个有趣的部分是,浏览器在另一个 URL 中打开了付费内容,该 URL 是从响应创建的内存对象 URL。我最初以为这是一个很好的 UI,可以防止刷新时重复支付,但看起来不是:付费墙在后台获取内容,由于我们的响应是 JSON 而不是 HTML,它没有东西可以就地渲染,因此它会导航到从响应创建的内存对象 URL。该协议本身是按使用付费的,所以每次你访问 API 时,都会被收费。
### 闭环
好了,现在我们已经看到一切正常,让我们切换到生产网络并全部部署:
```
const facilitatorClient = new HTTPFacilitatorClient({
- url: "https://x402.org/facilitator"
+ url: "https://facilitator.payai.network"
});
@@
- network: "eip155:84532",
+ network: "eip155:8453",
@@
- network: "solana:EtWTRABZaYq6iMfeYKouRu166VU2xqa1",
+ network: "solana:5eykt4UsFv8P8NJdTREpY1vzqKqZKvdp",
@@
new x402ResourceServer(facilitatorClient)
- .register("eip155:84532", new ExactEvmScheme())
- .register("solana:EtWTRABZaYq6iMfeYKouRu166VU2xqa1", new ExactSvmScheme()),
- { appName: "Igor's corner", testnet: true },
+ .register("eip155:8453", new ExactEvmScheme())
+ .register("solana:5eykt4UsFv8P8NJdTREpY1vzqKqZKvdp", new ExactSvmScheme()),
+ { appName: "Igor's corner", testnet: false },
```
`x402.org` 的 facilitator 只处理测试网,所以对于真实网络,我们指向 Dexter (https://dexter.cash/facilitator) 的 PayAI (https://facilitator.payai.network/)——一个免费的 facilitator,处理 Base 和 Solana 主网,无需短信、注册账户或 API 密钥。Dexter 应该做同样的事情,但它宣布的交易从未到达实际网络,导致支付超时;而 PayAI 一切都完美运行。
就这样。你可以点击下面的按钮自己尝试。在那之前,别忘了在 Base 或 Solana 网络上用 USDC 充值你的钱包。
🎩 获取高级笑话($0.01) (https://shtein.me/api/joke)
## 总结
x402 (https://x402.org/) 不仅适用于对 AI 代理设置付费墙,它几乎已经准备好帮助你为博客货币化。无需摆弄像“Buy Me a Coffee”这样的服务,也不用烦扰用户看广告。
即使对于静态站点,它也很容易集成,尽管你需要一些计算资源。但并不多。
目前还没有现成的解决方案,可以为动态内容实现多网络支付并嵌入页面的 DOM 中。至少在这次简短探索中我没有找到。但浏览器似乎已经准备好对页面设置付费墙,使得实现起来非常简单。
相似文章
Monetization Gateway
Cloudflare 宣布推出 Monetization Gateway,使客户能够通过 x402 协议对任何受保护资源(网页、API、数据集、MCP 工具)收费,并在边缘进行稳定币结算,旨在应对AI代理向按使用量付费的转变。
@dulipeng: https://x.com/dulipeng/status/2067450611529093311
这篇文章是一篇实操教程,详细介绍了如何利用 Cloudflare Workers/Pages 免费额度部署一个低成本 VPN,基于开源项目 edgetunnel,并配合 Clash、Shadowrocket 等客户端使用。
AWS WAF 新增 AI 流量变现功能,帮助内容所有者向 AI 机器人收取内容访问费用(10 分钟阅读)
AWS WAF 推出 AI 流量变现功能,允许内容所有者通过网络边缘的可配置定价规则,按请求向 AI 机器人收费,支付通过 Coinbase 处理,并即将支持 Stripe/MPP。
用机器重建我的博客,为机器服务·
作者重建了博客,加入了完整的结构化数据标记(JSON-LD、微格式),并配备了一个由提示词引导的AI协作写作助手,该提示词避免了常见的LLM模式,同时通过CI验证防止数据损坏。
硬核IndieWeb: 每天仅需0.01美元,100%独立运行你自己的网站
本文介绍了一种“硬核IndieWeb”方法,以每天仅需0.01美元的成本运行完全独立的个人网站,强调通过将内容保存在自己的硬盘上并使用最少的托管服务来实现完全控制和便携性。