域名出售页+escrow.com出售链接。(Caddy + Node.js)
环境
腾讯云cloudos9 系统
主要文件:
domains.json (域名列表文件)
{ "**.sale": { "price": "1100", "description": "sales, a high-quality domain name suitable for start-up enterprises." } }
server.js (数据处理文件)
const express = require('express'); const fs = require('fs'); const path = require('path'); const app = express(); const PORT = 3000; // ===== 配置区域 ===== const ESCROW_EMAIL = '**@**.com'; // 【重要】改成你的 Escrow 注册邮箱 const DOMAINS_FILE = path.join(__dirname, 'domains.json'); const TEMPLATE_FILE = path.join(__dirname, 'template.html'); // 读取模板和数据 let template = fs.readFileSync(TEMPLATE_FILE, 'utf8'); let domainsData = JSON.parse(fs.readFileSync(DOMAINS_FILE, 'utf8')); // 监听文件变化,热更新数据 fs.watchFile(DOMAINS_FILE, () => { try { domainsData = JSON.parse(fs.readFileSync(DOMAINS_FILE, 'utf8')); console.log('域名数据已更新'); } catch (e) { console.error('域名数据格式错误'); } }); // 1. Caddy 验证接口 app.get('/caddy-check', (req, res) => { const domain = req.query.domain; if (domainsData[domain]) { res.status(200).send('OK'); } else { res.status(404).send('Not Found'); } }); // 2. 主页面路由 app.get('/', (req, res) => { let host = req.headers.host; if (!host) return res.status(400).send('Bad Request'); host = host.split(':')[0]; const info = domainsData[host]; if (!info) { return res.status(404).send('<h1>404 - 该域名暂不出售</h1>'); } // 注意:这里不再生成 buy_link 传给前端了 let html = template .replace(/\{\{domain\}\}/g, host) .replace(/\{\{price\}\}/g, info.price) .replace(/\{\{description\}\}/g, info.description || '这是一个优质域名,正在出售中。'); res.send(html); }); // 3. 【新增】隐藏邮箱的支付跳转接口 app.get('/checkout', (req, res) => { // 获取当前访问的域名 let host = req.headers.host; if (!host) return res.status(400).send('无法识别域名'); host = host.split(':')[0]; const info = domainsData[host]; // 如果域名不在出售列表,拒绝跳转 if (!info) { return res.send('该域名暂不出售'); } // 在后端构造 Escrow 链接(用户在浏览器前端看不到这行代码) const escrowUrl = `https://www.escrow.com/checkout?domain=${host}&price=${info.price}¤cy=USD&seller_email=${encodeURIComponent(ESCROW_EMAIL)}`; // 302 重定向:用户点击按钮 -> 来到这里 -> 瞬间跳转到 Escrow res.redirect(escrowUrl); }); app.listen(PORT, () => { console.log(`Server running on port ${PORT}`); });
template.html (模板文件)
<!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8"> <meta name="viewport" content="width=device-width, initial-scale=1.0"> <title>{{domain}} - Domain For Sale</title> <style> :root { --primary-color: #2563eb; --price-color: #dc2626; --bg-color: #f3f4f6; --card-bg: #ffffff; } body { font-family: -apple-system, BlinkMacSystemFont, "Segoe UI", Roboto, Helvetica, Arial, sans-serif; background-color: var(--bg-color); margin: 0; padding: 0; display: flex; justify-content: center; align-items: center; min-height: 100vh; } .container { background: var(--card-bg); width: 90%; max-width: 600px; border-radius: 16px; box-shadow: 0 10px 25px rgba(0,0,0,0.05); padding: 40px; text-align: center; } .badge { background-color: #e0f2fe; color: #0284c7; padding: 5px 12px; border-radius: 20px; font-size: 14px; font-weight: bold; display: inline-block; margin-bottom: 20px; } h1 { font-size: 32px; color: #111827; margin-bottom: 10px; word-break: break-all; } .description { color: #6b7280; margin-bottom: 30px; font-size: 16px; } .price-box { margin: 30px 0; } .price-label { font-size: 14px; color: #9ca3af; text-transform: uppercase; letter-spacing: 1px; } .price-value { font-size: 48px; font-weight: 800; color: var(--price-color); margin: 5px 0; } .price-unit { font-size: 18px; color: #4b5563; } .buy-btn { display: inline-block; background-color: var(--primary-color); color: white; padding: 16px 40px; border-radius: 8px; text-decoration: none; font-size: 18px; font-weight: bold; transition: background 0.3s; margin-top: 20px; } .buy-btn:hover { background-color: #1d4ed8; } .secure-info { margin-top: 40px; font-size: 12px; color: #9ca3af; display: flex; align-items: center; justify-content: center; gap: 5px; } .footer { margin-top: 30px; font-size: 12px; color: #9ca3af; } </style> </head> <body> <div class="container"> <div class="badge">Domain For Sale</div> <h1>{{domain}}</h1> <p class="description">{{description}}</p> <div class="price-box"> <div class="price-label">Current Price</div> <div class="price-value">${{price}} <span class="price-unit">USD</span></div> </div> <!-- Purchase button, link generated by the backend --> <a href="/checkout" class="buy-btn" target="_blank">Buy Now</a> <div class="secure-info"> <svg width="16" height="16" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2"> <path d="M12 22s8-4 8-10V5l-8-3-8 3v7c0 6 8 10 8 10z" fill="#90EE90"></path> </svg> <span>The transaction is guaranteed by <span style="color:green;font-weight:bold">Escrow.com</span>, ensuring the safety of funds and the domain name.</span> </div> <div class="footer"> © 2026. All rights reserved. </div> </div> </body> </html>
caddyfile
nano /etc/caddy/Caddyfile
内容
# ========================================== # 1. 全局配置块 (必须是文件开头,不要删除这个大括号) # ========================================== { # 你的邮箱,用于接收 Let's Encrypt 证书过期提醒 email usasbe@outlook.com # 开启按需申请证书功能,并设置验证接口 on_demand_tls { ask http://localhost:3000/caddy-check } } # ========================================== # 2. HTTPS 服务 (监听 443 端口) # ========================================== :443 { # 在此处启用按需 TLS tls { on_demand } # 启用 Gzip 压缩 encode gzip # 反向代理到本地的 Node.js 程序 reverse_proxy localhost:3000 } # ========================================== # 3. HTTP 服务 (监听 80 端口,自动跳转 HTTPS) # ========================================== http:// { redir https://{host}{uri} permanent }
部署流程:
第一步:环境准备
1、安装 Caddy (官方源安装):
# 1. 更新系统
yum update -y
# 2. 安装 Node.js (v18)
curl -fsSL https://rpm.nodesource.com/setup_18.x | bash -
yum install -y nodejs
# 3. 安装 Caddy (Web服务器)
# 这里使用 Caddy 官方提供的安装脚本
yum install -y yum-plugin-copr
yum copr enable @caddy/caddy -y
yum install -y caddy
# 4. 安装进程管理器 PM2 (保证服务不挂掉)
npm install -g pm2
2、安装 Node.js (同上,略)。
第二步:构建“域名展示系统”
1、创建项目目录
mkdir -p /var/www/domain-sale cd /var/www/domain-sale npm init -y npm install express axios # 安装 web框架 和 http请求库
2、构建项目文件
# 创建项目目录 mkdir -p /var/www/domain-sale cd /var/www/domain-sale # 初始化项目 npm init -y # 安装 Express (Web框架) npm install express
1. 创建域名数据文件 (domains.json)
nano domains.json
写入以下内容
{ "examp**leA.com": { "price": "100", "description": "适合初创企业的优质域名" }, "exampl**eB.net": { "price": "2000", "description": "极具潜力的行业关键词" }, "mydo**main.cn": { "price": "500", "description": "中国区首选品牌" } }
2. 创建前端页面模板 (template.html)
nano template.html
3、创建 server.js (核心逻辑):(代码见前文)
nano server.js
第三步:配置 Caddy (自动 HTTPS 的秘密)
Caddy 的配置文件通常在 /etc/caddy/Caddyfile。
利用 Caddy 的 On-Demand TLS 功能,它可以自动为任何解析到该服务器的域名申请证书,不需要提前写死域名列表。
- 编辑配置:
nano /etc/caddy/Caddyfile - 写入内容:(见前文)
- 重启 Caddy
systemctl restart caddy - 启动服务-启动nodejs
-
cd /var/www/domain-sale pm2 start server.js --name domain-sale pm2 save pm2 startup
- 启动 Caddy 服务
systemctl restart caddy systemctl enable caddy开放防火墙端口 (腾讯云轻量服务器):
- 方法一(控制台): 登录腾讯云控制台 -> 轻量应用服务器 -> 找到你的实例 -> 防火墙 -> 添加规则。
- 放通 TCP 80 端口 (HTTP)
- 放通 TCP 443 端口 (HTTPS)
- 方法二(服务器内部): 如果你有 firewalld,确保允许服务。
-
firewall-cmd --permanent --add-service=http firewall-cmd --permanent --add-service=https firewall-cmd --reload
第五步:如何使用?
-
思考结束
这是一个非常棒的实战需求。既然你有腾讯云轻量服务器,我们将采用 Caddy (自动HTTPS) + Node.js (后端逻辑) + HTML (前端页面) 的架构,搭建一个完全自动化、自带SSL证书、集成Escrow支付的专业域名出售平台。
以下是完整的、可复制粘贴的部署方案。
第一步:环境准备
登录你的腾讯云轻量服务器,安装必要的软件。
# 1. 更新系统 yum update -y # 2. 安装 Node.js (v18) curl -fsSL https://rpm.nodesource.com/setup_18.x | bash - yum install -y nodejs # 3. 安装 Caddy (Web服务器) # 这里使用 Caddy 官方提供的安装脚本 yum install -y yum-plugin-copr yum copr enable @caddy/caddy -y yum install -y caddy # 4. 安装进程管理器 PM2 (保证服务不挂掉) npm install -g pm2第二步:构建项目文件
我们在
/var/www目录下创建项目。# 创建项目目录 mkdir -p /var/www/domain-sale cd /var/www/domain-sale # 初始化项目 npm init -y # 安装 Express (Web框架) npm install express现在我们需要创建三个核心文件:
domains.json(数据)、template.html(页面)、server.js(逻辑)。1. 创建域名数据文件 (
domains.json)这是你的“数据库”,以后每增加一个域名,只需在这里添加一行。
nano domains.json写入以下内容:
{ "exampleA.com": { "price": "100", "description": "适合初创企业的优质域名" }, "exampleB.net": { "price": "2000", "description": "极具潜力的行业关键词" }, "mydomain.cn": { "price": "500", "description": "中国区首选品牌" } }*(注意:请将键名改为你要出售的真实域名)*
2. 创建前端页面模板 (
template.html)这是一个专业的响应式出售页面。
nano template.html写入完整代码:(见前文)
代码生成完成
HTML代码
3. 创建后端逻辑 (
server.js)这是核心处理程序,负责读取数据、替换页面内容、生成Escrow链接。
nano server.js写入完整代码: (见前文)
第三步:配置 Caddy (自动 HTTPS)
Caddy 将监听 80 和 443 端口,自动申请 SSL 证书,并将流量转发给你的 Node.js 程序。
- 编辑 Caddy 配置文件:
nano /etc/caddy/Caddyfile- 删除原有内容,写入内容: (见前文)
第四步:启动服务与防火墙
- 启动 Node.js 服务:
cd /var/www/domain-sale pm2 start server.js --name domain-sale pm2 save pm2 startup- 启动 Caddy 服务:
systemctl restart caddy systemctl enable caddy- 开放防火墙端口 (腾讯云轻量服务器):
- 方法一(控制台): 登录腾讯云控制台 -> 轻量应用服务器 -> 找到你的实例 -> 防火墙 -> 添加规则。
- 放通 TCP 80 端口 (HTTP)
- 放通 TCP 443 端口 (HTTPS)
- 方法二(服务器内部): 如果你有 firewalld,确保允许服务。
- 方法一(控制台): 登录腾讯云控制台 -> 轻量应用服务器 -> 找到你的实例 -> 防火墙 -> 添加规则。
firewall-cmd --permanent --add-service=http firewall-cmd --permanent --add-service=https firewall-cmd --reload第五步:如何使用?
现在你的平台已经搭建好了,操作流程非常简单:
-
添加新域名:
- 编辑
/var/www/domain-sale/domains.json,加上新域名和价格。 - 无需重启任何服务,代码会自动热更新。
- 编辑
-
DNS 解析:
- 去你的域名 DNS 管理处(如 DNSPod),将域名的 A 记录 指向你的腾讯云服务器 IP。
-
访问效果:
- 用户访问
http://example***A.com-> 自动跳转https://example***A.com(浏览器出现小绿锁) -> 页面显示价格 $100。 - 用户点击“立即购买” -> 跳转到
escrow.com预填好的支付页面 -> 你坐等收款。
- 用户访问
- 方法一(控制台): 登录腾讯云控制台 -> 轻量应用服务器 -> 找到你的实例 -> 防火墙 -> 添加规则。
注意: 如果你的 domains.json 经常变动,你可以让这个接口实时读取文件,或者每次更新数据后重启 Node 进程。
总结流程
- 数据维护: 你只需要维护一个
domains.json文件,添加新域名和价格。 - DNS 解析: 将域名 A 记录指向腾讯云服务器 IP。
- 自动握手: 用户访问域名 -> Caddy 检测到 HTTPS 请求 -> 询问 Node.js “我有这个域名吗?” -> Node.js 说 “有” -> Caddy 自动向 Let’s Encrypt 申请证书 -> 浏览器显示小绿锁。
- 展示与交易: Node.js 返回带有价格的页面,按钮链接指向 Escrow.com 的预填付款页修改完
Caddyfile后,执行以下命令:
关于 Escrow 集成的补充
上面的代码使用的是URL 参数预填模式 (escrow.com/checkout?...)。
- 优点: 实现最简单,不需要处理 API 密钥在前后端交互的复杂性。
- 缺点: 用户点击购买后,还需要在 Escrow 页面再确认一遍信息。
如果你追求极致体验(用户点击购买 -> 直接生成账单 -> 用户只管付钱),你需要使用 Escrow REST API。
这需要你在 Node.js 后端使用 axios 发送 POST 请求到 https://api.escrow.com/transaction 创建交易,然后返回一个支付链接。这稍微复杂一点,且涉及到 API Key 的安全存储,但对于 $2000 级别的交易来说,这种专业度是值得的。上面的代码采用了折中的“预填链接”方案,既简单又实用。
另外:
修改完 Caddyfile 后,执行以下命令:
# 1. 检查 Caddy 配置语法 caddy validate --config /etc/caddy/Caddyfile # 2. 如果验证通过,重启 Caddy 服务 systemctl restart caddy # 3. 确保 Node.js 应用正在运行 pm2 restart domain-sale # 如果之前已启动,可重启使配置生效
清空文件:
# 使用 echo 清空文件再编辑,防止旧内容残留 echo "" > /etc/caddy/Caddyfile
修改文件后刷新
pm2 restart domain-sale

浙公网安备 33010602011771号