跳转至
  • migrated legacy_doc_id: D3-ARCH-DEPLOY-M6.2-STAGE0 level: l3

M6.2 · VPS 账号申请与采购零基础指南

本文定位

本文是 M6.2 VPS 后端部署里程碑的"阶段 0 前置准备"权威零基础手册,面向非运维背景的开发者。 覆盖:VPS 基础概念科普、腾讯云香港轻量应用服务器选型与下单、Resend 邮件服务账号申请、企微群机器人 Webhook 创建、以及 4 个账号全部就绪后的验收清单。 阅读完本文后,即可衔接 07web-m6.1-deploy-plan.md §5.3阶段 1 VPS 基础环境初始化

与既有文档的关系

文档 定位 读者
本文 零基础账号申请 + 采购科普 非运维背景开发者 · 新人
07web-m6.1-deploy-plan.md §5.3 M6.2 架构决策 + 简化 TODO 已懂运维的架构评审者
xisound-api/TODOLIST.md §3` 后端仓完整 40+ TODO 分阶段清单 实施者
docs-site-deployment.md M6.1.1 文档站部署手册 参考文档站落地经验

本文不回答什么

  • 本文只覆盖账号采购(阶段 0 前置准备),不覆盖 VPS 登录后的加固、Docker 安装、nginx 配置、SSL 签发等运维动作 · 那些在阶段 1-6 的对应手册中
  • 本文不假设你懂 SSH / Linux / Docker / DNS,但本文也不替代这些技术的系统学习 · 遇到生僻术语时会给出一段式解释

1. 什么是 VPS · 零基础科普

1.1 从"放网站的地方"开始

如果你从来没部署过后端服务,可能会有这样的疑问: "前端 Astro 官网通过 Cloudflare Pages 已经上线了(www.joysnd.com),那后端 .NET API 怎么上线?"

答案是:你需要一台 7×24 小时开机、有公网 IP 的计算机,把 xisound-api 的 Docker 容器跑在上面,然后把 api.joysnd.com 这个域名解析到它的公网 IP。 这台"计算机"就是 VPS

1.2 VPS 到底是什么

VPS = Virtual Private Server · 虚拟专用服务器

概念 通俗解释
物理服务器 一台真实的 1U/2U 机架式电脑,放在机房里,功耗 300-800W。一台就是一台。
虚拟化 用 KVM / Xen / Hyper-V 等技术,把一台物理服务器"切割"成多台看起来独立的虚拟机,每台都有独立的 CPU、内存、磁盘、IP。
VPS 其中一台虚拟机 · 你只租一台而不是整台物理机 · 价格从 ¥30/月 起
公有云厂商 腾讯云 / 阿里云 / AWS / Google Cloud / 华为云 · 他们买了大量物理服务器、做了虚拟化、把虚拟机按月/按年出租给你

打个比方: - 物理服务器 = 整栋别墅(贵、自己装修) - VPS = 公寓里的一套房(便宜、物业管基础设施、你管屋内)

1.3 VPS vs 云服务器 vs 容器 vs Serverless

很多人把 "VPS"、"云服务器"、"ECS"、"轻量应用服务器"混在一起,其实它们本质相似但定位不同:

产品形态 典型产品 控制粒度 适合场景 价格(月) 本项目
传统 VPS DigitalOcean / Linode / Vultr 🟢 完全控制(root) 长期运行服务 · 自建架构 $5-20 可选
云服务器 ECS 腾讯云 CVM / 阿里云 ECS 🟢 完全控制(root) 企业级 · 弹性扩容 · 复杂网络 ¥80-300 本项目过重
轻量应用服务器 腾讯云 Lighthouse / 阿里云轻量 🟢 完全控制(root) 个人/小团队 · 固定配置 · 价格友好 ¥30-90 推荐
容器服务 腾讯云 TKE / AWS ECS 🟡 只管容器 K8s 运维团队 · 微服务集群 ¥200-1000+ 本项目过重
Serverless Cloudflare Workers / AWS Lambda 🔴 只写函数 短期事件触发 · 无状态 按调用计费 本项目需要长连接 DB

本项目选型:腾讯云轻量应用服务器(Lighthouse)。 理由:价格友好(¥60-80/月)、root 权限完整、性能够跑 .NET + PostgreSQL + Redis + nginx、公网流量包 1 TB 够用、可灵活绑定域名。

1.4 本项目 VPS 承载什么

graph TB
    subgraph CFNode["Cloudflare 边缘"]
      User[访客浏览器]
      CFWWW[www.joysnd.com<br/>CF Pages 纯静态]
      CFAPI[api.joysnd.com<br/>CF DNS 解析 · 橙色云]
    end

    subgraph VPSNode["腾讯云轻量应用服务器 · 香港 · 2C4G 80G"]
      Nginx[nginx:1.27<br/>80/443 反代]
      APIContainer[xisound-api<br/>.NET 8 · :5000]
      Postgres[postgres:16<br/>:5432]
      Redis[redis:7<br/>:6379]
      Certbot[certbot<br/>Let's Encrypt 证书]
    end

    User -->|HTTPS GET 页面| CFWWW
    User -->|HTTPS fetch /api/lead| CFAPI
    CFAPI -->|回源 HTTPS| Nginx
    Nginx -->|HTTP 127.0.0.1:5000| APIContainer
    APIContainer -->|TCP 5432| Postgres
    APIContainer -->|TCP 6379| Redis
    Nginx -.ACME 续签.-> Certbot

    class CFWWW,CFAPI xyL1
    class Nginx,APIContainer xyL4
    class Postgres,Redis xyL5
    class Certbot xyL3
    class User xyL0
    class CFNode xySgL0; class VPSNode xySgL3;
终端用户 Cloudflare 边缘 证书自动化 应用层容器 数据层容器

通俗解释:你要租一台 2 核 CPU、4 GB 内存、80 GB 磁盘的香港虚拟机,在上面用 Docker 跑 5 个容器(nginx + .NET API + PostgreSQL + Redis + certbot),对外只开 80/443 端口,让访客通过 https://api.joysnd.com 访问到后端 API。


2. 为什么选腾讯云香港轻量应用服务器

2.1 决策维度

本节给出"为什么不选 A/B/C 而选它"的横向对比,帮助你理解本项目的选型逻辑。

2.2 地域选择 · 为什么是香港

地域 代表机房 备案要求 对海外访客延迟 对内地访客延迟 月带宽均价 本项目
中国大陆 腾讯云上海/北京 🔴 强制 ICP 备案(20-30 工作日) 🟡 200-400ms 🟢 20-50ms ¥60-100 ⛔ 备案周期长
中国香港 腾讯云香港 🟢 免备案 🟢 50-150ms 🟡 60-120ms ¥60-80 推荐
新加坡 腾讯云新加坡 🟢 免备案 🟢 50-100ms 🔴 150-300ms ¥70-90 🟡 内地访客慢
美国西部 腾讯云硅谷 🟢 免备案 🔴 200-400ms 🔴 180-250ms ¥70-90 ⛔ 延迟差

香港结论

腾讯云香港轻量应用服务器满足"免备案 + 内地可用 + 海外可达 + 价格友好"四要素 · 是本项目最优解。 未来若 M6.4+ 需支撑大陆高并发,可以保留香港作为海外入口,另起一台阿里云大陆节点(届时启动 ICP 备案流程)。

2.3 厂商选择 · 为什么是腾讯云

厂商 产品名 香港节点 最低价(2C2G) 流量包 控制台体验 本项目
腾讯云 轻量应用服务器 🟢 香港 ¥24/月起 1 TB 🟢 中文 · 流畅 推荐
阿里云 轻量应用服务器 🟢 香港 ¥24/月起 1 TB 🟢 中文 · 流畅 🟢 同级备选
华为云 耀云服务器 L 实例 🟢 香港 ¥30/月起 1 TB 🟡 中文 · 界面复杂 🟡 可用
AWS Lightsail 🟢 新加坡 $5/月 1-2 TB 🔴 英文 · 付款美元 ⛔ 国内开发者门槛高
Vultr Regular Cloud Compute 🟡 东京 $6/月 1-2 TB 🔴 英文 · 支付宝不支持 ⛔ 付款麻烦

为什么不选阿里云

阿里云和腾讯云产品能力几乎对等,本项目选腾讯云仅因公司已有其他腾讯云资源(COS / 微信生态协同),并非阿里云能力不足。 如果你更熟悉阿里云控制台,直接选阿里云轻量应用服务器亦可 · 本文的申请流程在阿里云上 95% 相通。

2.4 产品线选择 · 为什么是轻量应用服务器(Lighthouse)

腾讯云同时存在 3 个看起来很像的产品,新手容易混淆:

产品 官方名 定位 规格灵活度 价格 本项目
云服务器 CVM Cloud Virtual Machine 企业级 IaaS · 完全自定义 VPC/子网/ACL 🟢 任意组合 ¥150-500+/月 ⛔ 过重过贵
轻量应用服务器 Lighthouse 开发者友好 · 固定套餐 · 开箱即用 🟡 套餐化 ¥24-100/月 推荐
裸金属云服务器 Bare Metal 物理机独占 · 不虚拟化 🟢 完全物理 ¥3000+/月 ⛔ 大企业用

不要误点 CVM

腾讯云控制台左侧同时有"云服务器 CVM"和"轻量应用服务器"两个入口 · 新手很容易点错。 CVM 面向企业级,起步价 ¥150/月且按流量计费 · 本项目必须轻量应用服务器(Lighthouse)· 固定套餐、含 1 TB 流量包、无隐藏扣费。


3. 腾讯云账号申请详细流程

3.1 准备材料(3 分钟)

动手前请准备好:

  • 手机号(接收验证码 · 建议用长期可用的号码,绑定账号后变更手续较麻烦)
  • 身份证(个人实名认证 · 需正反面照片) 企业营业执照(企业实名认证 · 需对公账户打款验证)
  • 邮箱(接收账单、告警、续费提醒 · 建议用团队共享邮箱如 ops@joysnd.com
  • 支付方式(支付宝 / 微信 / 银联信用卡 · 个人账号建议绑定支付宝免密支付避免断费)

个人 vs 企业认证

维度 个人认证 企业认证
申请难度 🟢 5 分钟 🟡 1-2 个工作日(对公打款验证)
可购产品 🟡 部分高风险产品受限(如 95 带宽) 🟢 全产品线
发票类型 🟡 只能普票 🟢 增值税专票
本项目 够用(M6.2 只要轻量服务器) 可选

建议:如果你是公司员工,直接让财务配合走企业认证(能开专票、利于报销)· 如果只是自己折腾,个人认证足够。

3.2 注册账号(Step-by-Step)

  1. 打开浏览器访问 https://cloud.tencent.com
  2. 右上角点击 注册 按钮
  3. 当前(2026-05)界面提供 3 种注册方式:
  4. 微信扫码注册(最快 · 自动绑定微信 · 推荐)
  5. 手机号注册(手机号 + 验证码 + 设置密码)
  6. 邮箱注册(邮箱 + 验证链接 + 手机号绑定)
  7. 选择微信扫码注册后:
  8. 微信扫码
  9. 填写昵称(日后可改)
  10. 绑定手机号 · 收验证码填入
  11. 勾选服务协议 · 点击注册
  12. 注册完成后自动跳转到腾讯云控制台首页

常见坑 · 微信注册后如何添加密码

微信扫码注册默认没有密码,只能微信扫码登录。 如果你希望支持"账号密码登录"(比如 CI/CD 里用 API 密钥),进入右上角头像 → 账号信息 → 安全设置 → 设置登录密码

3.3 实名认证(5-30 分钟)

必须完成实名认证才能购买任何产品

未认证账号可以注册但不能下单 · 点击购买时会强制跳转到实名认证页。

个人认证流程(当前 2026-05 UI):

  1. 右上角头像 → 账号中心 → 左侧 认证管理
  2. 选择个人认证
  3. 填写:
  4. 真实姓名(与身份证一致)
  5. 身份证号
  6. 上传身份证正反面照片(或用微信扫码 → 人脸识别一键认证)
  7. 选择人脸识别(推荐 · 30 秒完成) · 或银行卡认证(绑定一张本人银行卡 · 打款 0.01 元验证)
  8. 提交后 · 人脸识别约 1 分钟通过 · 银行卡认证约 1 小时通过

企业认证流程

  1. 同上路径选企业认证
  2. 填写:
  3. 企业名称(与营业执照完全一致)
  4. 统一社会信用代码(18 位)
  5. 法定代表人姓名 + 身份证号
  6. 上传营业执照副本扫描件
  7. 认证方式二选一:
  8. 法人人脸识别(法人本人操作 · 5 分钟通过)
  9. 对公打款(腾讯云向企业账户打入一笔随机小额 · 你查看到账金额后填回 · 1-3 个工作日)
  10. 提交后等待审核

3.4 账户充值(可选但推荐)

为避免下单时还要切到支付宝,建议预先充值 ¥100-200 到腾讯云账户:

  1. 控制台右上角头像 → 费用中心充值
  2. 选择支付方式(支付宝 / 微信 / 网银 / 信用卡)
  3. 充值 ¥100(够 1 个月轻量服务器 + 预留费用)
  4. 到账实时

代金券可以省钱

注册完成后,访问 https://cloud.tencent.com/act/new新用户专享页 · 通常有 "新用户首单 1 折""¥99 年付 2C2G" 等福利 · 值得薅羊毛。 当前(2026-05)轻量应用服务器常见福利:香港 2C2G 40GB · ¥160/年(折合 ¥13.3/月)· 但 2C2G 对本项目略紧,建议加预算到 2C4G。


4. 腾讯云轻量应用服务器下单详细指南

4.1 进入购买页

  1. 腾讯云控制台首页 → 搜索框输入 轻量
  2. 点击 轻量应用服务器 · Lighthouse
  3. 左上角 新建 按钮 → 进入购买页

当前(2026-05)购买页关键配置项(自上而下)

  1. 地域 Region
  2. 镜像 Image
  3. 实例套餐 Instance Plan
  4. 购买时长 Duration
  5. 实例名称 Instance Name
  6. 数量 Quantity

下面逐项详解。

4.2 配置项 1 · 地域选择

可选地域(2026-05) 延迟 本项目推荐
上海 / 北京 / 广州 / 成都 / 南京 内地快 · 海外慢 ⛔ 需 ICP 备案
中国香港 🟢 平衡 · 免备案 选这个
新加坡 海外快 · 内地慢
东京 / 首尔 / 硅谷 / 法兰克福 / 莫斯科 / 曼谷 / 孟买 / 圣保罗 区域站点 · 对本项目无意义

操作:直接点击 中国香港

4.3 配置项 2 · 镜像(最重要 · 用户明确要求详解)

这是本文用户最关心的部分。腾讯云镜像分 4 大类 · 差异巨大:

4.3.1 四种镜像类型全貌

镜像类型 典型选项 特点 本项目推荐度
应用模板镜像 WordPress / LAMP / 宝塔面板 / Node.js / Typecho / 微擎 预装特定应用栈 · 开箱即用 · 锁定技术栈 ⭐ 不推荐
操作系统镜像 Ubuntu 22.04/24.04 / CentOS ⅞ / Debian 11/12 / Windows Server 2019/2022 纯净 OS · 完全自定义 · 灵活度最高 ⭐⭐⭐⭐⭐ 推荐
容器镜像 CentOS 7.6 + Docker CE / Ubuntu 20.04 + Docker CE OS + 预装 Docker · 省一步安装 · Docker 版本可能较旧 ⭐⭐⭐ 备选
自定义镜像 从自有实例快照创建 批量部署 · 灾备恢复 · 首次部署不适用 ⭐⭐ M6.2 后可用于扩容

下面对前 3 类逐项展开说明 · 让你真正"知道每种选项在做什么"。

4.3.2 应用模板镜像(⭐ 不推荐)

是什么:腾讯云预先做好的一键搭建镜像,点进去就能跑起某类应用。 典型选项(当前 2026-05)

应用模板 预装内容 适合谁
WordPress PHP 8 + MySQL 8 + Apache + WordPress 最新版 做博客/企业站 · 不写代码
LAMP / LNMP Linux + Apache/Nginx + MySQL + PHP 传统 PHP 程序员
宝塔面板 CentOS + 宝塔面板(Web UI 运维) 不会命令行的小白站长
Node.js Ubuntu + Node.js + PM2 JS 后端新手
Typecho PHP + MySQL + Typecho(轻博客) 小众博客爱好者
微擎 微信公众号开发框架 微擎生态开发者
Gitlab 自建 Git 代码托管 需要私有 Git 的团队
Matomo 开源 Google Analytics 替代品 注重隐私的分析

为什么不适合本项目: 1. 我们要跑的是 .NET 8 + Docker Compose · 没有任何现成模板匹配 2. 应用模板预装的软件很难卸载干净(残留 MySQL/Apache 占端口、吃内存) 3. 你不会真的用 WordPress 模板去跑 .NET · 反而徒增清理成本

不要选宝塔面板模板

宝塔面板(bt.cn)在国内站长圈流行 · 但它会劫持 80/443 + SSH 默认端口 + 安装自己的 nginx · 与本项目的 Docker Compose 编排严重冲突。 如果不慎选了宝塔,需要 bt stop && bt uninstall 清理后才能用于本项目 · 不如一开始就选纯净 OS 镜像。

4.3.3 操作系统镜像(⭐⭐⭐⭐⭐ 本项目选这个)

是什么:裸操作系统 · 只有内核 + 基础工具(ssh / bash / vim / curl)· 什么应用都不装,完全由你控制。

当前(2026-05)可选选项

OS 发行版 版本 支持周期 本项目推荐
Ubuntu 22.04 LTS 长期支持至 2027-04 + 2032-04 安全维护 ⭐⭐⭐⭐⭐ 首选
Ubuntu 24.04 LTS 长期支持至 2029-04 + 2034-04 安全维护 ⭐⭐⭐⭐ 更新但 Docker 生态适配稍慢 可选
Ubuntu 20.04 LTS 长期支持至 2025-04 已结束 · 2030-04 ESM 付费维护 🔴 临近 EOL
Debian 12 社区长期支持至 2028-06 ⭐⭐⭐⭐ 比 Ubuntu 更精简 · 适合有 Debian 经验的 备选
Debian 11 社区长期支持至 2026-08 🟡 临近 EOL
CentOS 7.6 官方 2024-06 EOL · 无新补丁 🔴 安全风险
CentOS Stream 8/9 滚动发行 · 企业生产不稳定 🔴
Rocky Linux 9 CentOS 替代 · 企业稳定 🟡 Docker Hub 镜像较少 备选
Windows Server 2019/2022 付费 · 按小时计费 🔴 本项目不需要

本项目最终选择

Ubuntu 22.04 LTS 理由: 1. Ubuntu 生态成熟 · Docker/nginx/certbot 文档质量最高 · 出问题 Google 搜索结果最多 2. 22.04 支持到 2027-04 正式更新 + 2032-04 安全更新 · 足够覆盖本项目 2-3 年生命周期 3. apt 包管理器简单 · 新手友好 4. 社区 Docker Compose 模板 90% 以 Ubuntu 22.04 为基础

操作:购买页 → 镜像标签切到 系统镜像 → 选 Ubuntu → 版本选 22.04 LTS 64 位

4.3.4 容器镜像(⭐⭐⭐ 备选)

是什么:操作系统镜像的"预装 Docker CE"变体 · 省一步 apt install docker.io

当前(2026-05)可选选项

容器镜像 预装内容 本项目推荐
CentOS 7.6 + Docker 19.03 系统 EOL + Docker 旧版本
Ubuntu 20.04 + Docker CE 系统临近 EOL
Ubuntu 22.04 + Docker CE 24.x 系统长期支持 · Docker 较新 🟡 可选

为什么降为备选: - 预装的 Docker 版本不是最新(通常比官方稳定版落后 1-2 个大版本) - 后续升级 Docker 需要手动 apt upgrade docker-ce,步骤和从零安装差不多 - 你真正省的只有 1 条命令 · 不值得用"非纯净系统"换这点便利

推荐路径

选 Ubuntu 22.04 纯净系统 · 然后按官方文档 https://docs.docker.com/engine/install/ubuntu/ 安装最新版 Docker CE · 总耗时 2-3 分钟 · 版本永远最新。

4.3.5 自定义镜像(⭐⭐ 首次部署不用)

是什么:你把自己已部署好的实例打成快照 · 下次部署新机器时直接选这个快照 · 所有环境/代码都在。 本项目何时用:M6.2 首台部署完成后,可以打一份快照作为"黄金镜像" · 未来 M6.4 横向扩容时批量使用。 首次下单不涉及 · 跳过。

4.4 配置项 3 · 实例套餐(价格)

当前(2026-05)腾讯云香港轻量应用服务器套餐:

套餐名 CPU 内存 系统盘 月流量 峰值带宽 月价(原价) 月价(首年特惠)
入门型 2 核 2 GB 50 GB SSD 300 GB 30 Mbps ¥28 ¥13
通用型 I 2 核 2 GB 60 GB SSD 1000 GB 30 Mbps ¥40 ¥24
通用型 II 2 核 4 GB 80 GB SSD 1000 GB 30 Mbps ¥80 ¥60
高配型 4 核 8 GB 120 GB SSD 1500 GB 30 Mbps ¥155 ¥120
旗舰型 8 核 16 GB 180 GB SSD 2000 GB 40 Mbps ¥315 ¥250

本项目推荐 · 通用型 II(2C4G 80G)

理由: - .NET 8 + PostgreSQL + Redis + nginx 5 容器并行 · 2G 内存会触发 OOM · 必须 4G - 80 G SSD 足够放 Docker 镜像(2-3 GB)+ PostgreSQL 数据(首年预计 < 5 GB)+ nginx 日志(2 GB/月轮转) - 1000 GB/月 流量对初创官网流量绰绰有余(按 10 万 PV/月 · 每 PV 500 KB 计 · 约 50 GB/月) - 30 Mbps 峰值带宽 = 3.75 MB/s = 够同时服务 ~75 个并发 HTTPS 连接

不要选入门型 2G 内存

很多教程为省钱推荐 2C2G 入门型 · 对于只跑 nginx + 一个进程的个人博客够用。 本项目 5 个 Docker 容器同时跑 · 2G 内存会频繁触发 Linux OOM Killer · 数据库随机重启 · 极难排查多花 ¥36/月(¥60→¥80 首年 / ¥40→¥80 续费)换稳定性 · 强烈推荐

套餐命名与价格会随腾讯云产品线更新变动

腾讯云 2024-2026 年多次调整轻量应用服务器套餐命名 · 可能出现: - "入门型 / 通用型 I / 通用型 II / 高配型 / 旗舰型"(2024-2025 经典命名) - "锐驰型 / 企业型"(2026 新增命名) - 限时特惠价如"54 元/月 2C2G"(极限折扣 · ⚠️ 不要贪便宜选 2C2G

认准 4 个硬指标 · 忽略套餐命名差异: - CPU ≥ 2 核 - RAM = 4 GB(绝不选 2G · 本项目 5 容器并行会 OOM) - 磁盘 ≥ 80 GB SSD - 流量 ≥ 1000 GB/月 · 带宽 ≥ 30 Mbps

符合以上条件的任一套餐都可用 · 价格通常 ¥60-100/月(首年特惠) / ¥80-120/月(续费)。 看到"90 元 2C4G 入门型"或"95 元 2C4G 锐驰型"都是合格的 · 别被命名差异迷惑。

4.5 配置项 4 · 购买时长

时长 计费模式 折扣 本项目推荐
1 个月 包月 无折扣 🟡 首次试水
3 个月 包月 无折扣
6 个月 包月 8.5 折 🟡
1 年 包年 8 折 推荐(¥60/月 × 12 × 0.8 ≈ ¥576)
2 年 包年 6 折 🟢 资金宽裕可选
3 年 包年 5 折 🟢 资金宽裕可选 · 但 3 年产品线可能变化

M6.2 首台买 1 年

建议 1 年 · 一方面享受 8 折 · 另一方面业务增长后可能需要升配(通用型 II → 高配型),1 年周期正好给重新评估留窗口。 不要买 3 年 · 虽然 5 折便宜 · 但 3 年期间硬件规格、价格、产品形态都可能变化 · 锁死资金不划算。

4.6 配置项 5 · 实例名称

  • 默认:Lighthouse-hash(不推荐)
  • 推荐命名xisound-api-prod-hk-01
  • 格式:<项目>-<服务>-<环境>-<地域>-<序号>
  • 好处:未来有多台实例时一眼分辨用途

4.7 配置项 6 · 数量

  • 首次下单:1 台
  • 未来 M6.4+ 扩容再加

4.8 结算与支付

  1. 右侧配置预览面板核对:
  2. ✅ 中国香港
  3. ✅ Ubuntu 22.04 LTS
  4. ✅ 通用型 II(2C4G 80G 1000GB 30Mbps)
  5. ✅ 1 年
  6. ✅ xisound-api-prod-hk-01
  7. 点击 立即购买
  8. 跳转到订单页 · 勾选服务协议 · 点击 去支付
  9. 支付方式选择(账户余额 / 支付宝 / 微信 / 网银)
  10. 支付成功后约 2-3 分钟实例创建完成

4.9 初次登录验证

实例创建后,回到轻量应用服务器控制台:

  1. 找到 xisound-api-prod-hk-01 实例 · 点击实例名进入详情
  2. 顶部记录 公网 IP(形如 43.xxx.xxx.xxx) · 写到本地笔记
  3. 点击右上角 登录 按钮 → 选择 OrcaTerm(腾讯云内置 Web 终端)
  4. 首次登录提示设置 root 密码 · 设置一个强密码 16+ 位(大写 + 小写 + 数字 + 符号)
  5. 执行:cat /etc/os-release · 应输出 Ubuntu 22.04 LTS
  6. 执行:free -h · 应显示 Mem: 3.8G(4G 减去内核占用)

实例就绪

至此腾讯云部分完成 · 你手上有: - [x] 一台 Ubuntu 22.04 LTS 的 2C4G VPS - [x] 公网 IP(记入笔记) - [x] root 密码(记入密码管理器) - [x] 可通过 OrcaTerm Web 终端登录(未来会配 SSH 密钥)

4.10 常见坑

坑 1 · 流量包超额按带宽计费

轻量应用服务器套餐含 1000 GB/月流量 · 超出部分按 ¥0.80/GB 计。 本项目正常情况下月流量 < 100 GB · 远不会超。 但如果被 CC 攻击/爬虫爆刷 · 可能一夜流量超万 GB · 账单炸裂。 缓解:必须在 Cloudflare 端开启橙色云代理api.joysnd.com 走 CF 回源 · CF 拦截恶意流量 · VPS 只收合法请求)。

坑 2 · 香港节点不能 ping 的误解

轻量应用服务器香港节点默认关闭 ICMP(ping)以防扫描 · 但 TCP/HTTP/HTTPS 正常可达。 不要因为 ping 43.xxx.xxx.xxx 无响应就以为实例挂了 · 用 curl -I http://公网IP 或浏览器访问才是正确验证。

坑 3 · 安全组默认只开 SSH

新实例默认防火墙只开 22(SSH)/ 3389(Windows 远程) · 80/443 未开 · 部署 nginx 后 curl http://公网IP 会超时。 解决:轻量应用服务器控制台 → 实例详情 → 防火墙 页 → 添加规则 TCP 80 / TCP 443 / 0.0.0.0/0 · 保存即时生效。

坑 4 · 续费断费导致实例销毁

包年到期后 · 腾讯云给 15 天宽限期 · 宽限期后实例进入回收站再保留 7 天 · 之后物理销毁 · 数据不可恢复。 缓解:务必开启自动续费(控制台 → 续费管理 → 开启自动续费 · 绑定支付宝免密支付)。


5. Resend 账号申请

5.1 什么是 Resend · 为什么选它

Resend 是一家 2023 年起迅速崛起的开发者友好型邮件发送 SaaS · 定位对标早期的 SendGrid / Mailgun · 主打"5 分钟接入 + 清晰 API + 合理价格"。

本项目为什么需要邮件服务: - 用户在官网提交留资表单 → 后端触发邮件通知给运营邮箱(hello@joysnd.com) - 未来 M6.3 账号系统会需要"注册验证码邮件 / 密码重置邮件"

Resend vs 自建 SMTP vs 国内邮件服务

方案 接入难度 送达率(海外) 送达率(国内 QQ/163) 免费额度 本项目
自建 postfix SMTP 🔴 需配 SPF/DKIM/DMARC/反垃圾 · 香港 IP 段信誉差 🔴 20-50% 进垃圾箱 🔴 10-30% 进垃圾箱
Resend 🟢 5 分钟 · 国际标准 API 🟢 95%+ 🟡 70-85% 3000 封/月 · 永久免费 推荐
SendGrid 🟡 注册审核严 🟢 95%+ 🟡 70-85% 100 封/天 · 免费 🟢 同级备选
Mailgun 🟡 信用卡验证 🟢 95%+ 🟡 70-85% 5000 封/月 · 前 3 个月免费 🟢 备选
阿里云 DirectMail 🟢 简单 🟡 70-90% 🟢 85-95% 200 封/天 · 免费 🟡 需 ICP 备案(M6.4 再接入)
腾讯云 SES 🟢 简单 🟡 70-90% 🟢 85-95% 50 封/天 · 免费 🟡 需 ICP 备案

本项目选 Resend

理由: 1. M6.2 阶段没有 ICP 备案 · 国内服务商用不了 2. Resend 3000 封/月免费额度对初创官网足够(留资 + 验证码合计 < 500 封/月) 3. API 设计极简(POST /emails JSON 一行调通) · 本项目 ResendEmailService.cs 已实现 4. 海外送达率优秀 · 国内 QQ/163 可以通过 M6.4 切阿里云 DirectMail 补齐

5.2 注册流程(当前 2026-05 UI)

  1. 打开 https://resend.com
  2. 右上角 Sign In → 点击 Sign up
  3. 提供 邮箱 + 密码(推荐用 GitHub OAuth · 一键登录)
  4. 收到验证邮件 · 点击链接激活账号
  5. 首次登录向导:
  6. 填写 Organization name · 填 XisoundXisound Inc.
  7. 填写 Team size · 选 1-10
  8. 填写 Use case · 选 Transactional email(交易邮件)
  9. 进入 Dashboard

5.3 获取 API Key

  1. Dashboard 左侧 API Keys
  2. 右上角 Create API Key
  3. 填写:
  4. Name: xisound-api-prod(标识用途)
  5. Permission: Sending access(只发不读)
  6. Domain: All Domains(首次可选 All · 后续加严)
  7. 点击 Add · 生成形如 re_xxxxxxxxxxxxxxxxxxxxxxxxxxx 的密钥
  8. 立即复制保存到密码管理器 · 页面关闭后无法再查看
  9. 粘贴到 xisound-api/.envRESEND_API_KEY=re_xxx

密钥只显示一次

Resend 为安全只在创建时显示完整 Key · 关页后 Dashboard 里只能看到前缀 re_xxx...*** · 如果弄丢了就只能删掉旧 Key 重建

5.4 免费版限额与升级路径

套餐 月邮件数 域名数 联系人 月价
Free 3000 1 无限 $0
Pro 50,000 10 无限 $20
Scale 100,000 10 无限 $90

本项目 M6.2-M6.4 全程 Free 套餐足够 · 预计 2-3 年不会升级。

5.5 首次测试

Resend 免费版未验证域名前 · 只能用 onboarding@resend.dev 作为发件人寄给你自己注册邮箱(等效沙盒)。 Dashboard 左侧 EmailsSend test email 即可发送测试邮件 · 5 秒内到达即 OK。

5.6 域名验证详细手册(5-15 分钟 · 建议 M6.2 部署后立即执行)

本节定位升级

早期草稿曾把"域名验证"标记为 M6.4 的任务 · 但实战反馈表明: 1. 验证过程只改 DNS · 完全不影响现有 QQ/阿里/网易企业邮箱(§5.6.1 会解释原理) 2. 不验证域名时 · Resend 只能用 onboarding@resend.dev 作发件人 · 收件人看着像垃圾邮件 3. 整个过程只要 5-15 分钟 · 建议 M6.2 VPS 部署跑通后立即做这一步

本节把整个过程手把手写清楚 · 含与 QQ 企业邮箱共存的详细机制 + 3 大必踩坑 + 失败排查 + curl 自测。

5.6.1 为什么验证域名 · 与 QQ 企业邮箱如何共存

为什么要验证

状态 发件人显示 送达率
未验证 onboarding@resend.dev 🔴 95% 进垃圾箱(陌生域名)
已验证 noreply@send.joysnd.com 🟢 95%+ 进收件箱(熟悉品牌)

关键机制Resend 把发信隔离到 send.joysnd.com 子域 · 不是改 joysnd.com 主域。

这意味着: - 主域 joysnd.com · 继续被 QQ 企业邮箱托管(ops@joysnd.com / hello@joysnd.com 正常收发) - 子域 send.joysnd.com · 由 Resend 托管 · 用于 noreply@send.joysnd.com 系统发信

两者在 DNS 里是完全独立的两条记录 · 互不打架。

一张图理解"招牌相同 · 内部分流"的机制:

joysnd.com                         ← 公司总部地址
├── 总部收发室 (QQ 企业邮箱) · 不动
│   └── 处理: ops@, support@, hello@ 等人工邮件
└── 新开一个分部 send.joysnd.com   ← Resend 托管 · 新加
    └── 处理: noreply@send. 的系统自动邮件

总部和分部的招牌都写着"joysnd" · 客户看不出区别
但内部走不同的办公流程 · 互不打扰 ✅

5.6.2 Resend 给你的 4 条 DNS 记录详解

🚨 关键前提 1 · 在 Resend 添加域名时必须输入 send.joysnd.com 子域

这是本节最容易踩错的第一步 · 也是用户反馈指出的歧义点

  • ❌ 如果在 Resend Dashboard 的 Add Domain 输入框里输入 joysnd.com(主域)· Resend 验证的是主域 · 你之后的发信地址只能是 @joysnd.com(如 noreply@joysnd.com)· 不能用 @send.joysnd.com
  • 本节方案:在 Add Domain 输入框里输入 send.joysnd.com(完整写出子域)· Resend 验证的是子域 send.joysnd.com · 之后发信用 noreply@send.joysnd.com · 完全与 QQ 企业邮箱主域隔离

为什么本文选"子域方案"而非"主域方案": - 子域方案:完全不碰主域的 MX/SPF/DMARC · QQ 企业邮箱零影响 · 回滚也容易(直接删 4 条 DNS) - 主域方案:必须合并主域 SPFv=spf1 include:spf.mail.qq.com include:amazonses.com ~all)· 一处写错就导致 QQ 邮件送达率骤降 · 风险高

如果你之前误输入了 joysnd.com 主域(按 v1.0/v1.1 初版操作): 1. Resend Dashboard → Domains → 找到 joysnd.com 那一行 → 右侧菜单 → Delete 2. 删除 Cloudflare 里已添加的对应 4 条记录(如果已经加过) 3. 重新点 Add Domain · 这次输入 send.joysnd.com 4. 按本节 §5.6.4 重新添加 4 条 DNS 记录(所有 Name 都以 .send 结尾 · 详见下方"关键前提 2")

🚨 关键前提 2 · Resend 显示的 Name 填到 Cloudflare 时必须补 .send 后缀(v1.3 新增)

这是用户四轮反馈指出的第二个深层坑 · 也是 v1.3 的核心修正:

原理: - Resend Dashboard 显示的 Name 字段是相对于"验证域" send.joysnd.com 的路径(因为你在 Add Domain 输入的是 send.joysnd.com) - Cloudflare DNS 面板管理的是 zone joysnd.com 的记录 · Name 字段是相对于 zone 根的路径 - 两者相差一段:验证域 send.joysnd.com 相对于 zone joysnd.com 多出一段 .send - 所以把 Resend 给的 Name 粘贴到 CF 时 · 每一个都要在末尾追加 .send 后缀

完整映射表

记录 Resend UI 显示的 Name Cloudflare 实际填入的 Name 最终完整域(CF 自动补 .joysnd.com
DKIM resend._domainkey resend._domainkey.send resend._domainkey.send.joysnd.com
MX send send.send send.send.joysnd.com
SPF TXT send send.send send.send.joysnd.com
DMARC TXT _dmarc _dmarc.send _dmarc.send.joysnd.com

"send.send" 不是写错 · 而是完全正确 —— 它表示"send.joysnd.com 子域下再挂一个 send 子子域" · 这是 Resend 底层 AWS SES 对每个验证域默认生成的"发信通道"(bounce/feedback MX + SPF)路径。

绝佳的副作用:所有 Resend 相关记录(含 DMARC)全部挂在 send.joysnd.com 子域树下 · 完全不碰主域 · QQ 企业邮箱的主域 MX/SPF/DMARC 保持零改动。

Resend Dashboard → DomainsAdd Domain → 输入 send.joysnd.com(⚠️ 带 send. 前缀 · 不是光 joysnd.com)→ Create 后 · Resend 会生成 4 条 DNS 记录 · 每条的作用如下(Name 列给的是填入 Cloudflare 时的正确值 · 已含 .send 后缀):

# 类型 CF 里的 Name 内容示例 作用
1 TXT resend._domainkey.send p=MIGfMA0GCSqGSIb3DQEBAQUAA4GN...wIDAQAB DKIM 签名公钥(最关键 · 证明邮件没被篡改)
2 MX send.send feedback-smtp.us-east-1.amazonses.com(优先级 10) send.send.joysnd.com 的退信处理(AWS SES 标准路径)
3 TXT send.send v=spf1 include:amazonses.com ~all send.send.joysnd.com 的 SPF(授权 AWS SES 代发)
4 TXT _dmarc.send v=DMARC1; p=none; 挂在 send 子域树的 DMARC · 与主域 QQ 邮箱 DMARC 完全隔离(更安全)

各字段的专业解释

  • DKIM(DomainKeys Identified Mail):Resend 用私钥签名每封邮件 · 收件方用你在 DNS 发布的公钥验签 · 证明邮件没被篡改
  • MX(Mail Exchange):声明 send.joysnd.com 的退信投递到哪 · Resend 自动处理退信统计
  • SPF(Sender Policy Framework):授权 amazonses.com 代你发 @send.joysnd.com 邮件
  • DMARC(Domain-based Message Authentication, Reporting & Conformance):告诉收件方"如果 DKIM 和 SPF 都失败怎么处理" · p=none 表示"只监控不拦截" · 是最安全的起步策略

5.6.3 操作前 · 确认现有 DNS 状态

在 Cloudflare DNS 面板先看清你现有的邮件相关记录(以 QQ 企业邮箱为例):

类型 名称 内容 代理状态
MX joysnd.com(或 @ mxbiz1.qq.com(优先级 5) 🔘 仅 DNS
MX joysnd.com(或 @ mxbiz2.qq.com(优先级 10) 🔘 仅 DNS
TXT joysnd.com(或 @ v=spf1 include:spf.mail.qq.com ~all 🔘 仅 DNS

添加 Resend 后 · DNS 列表变化对照

【原有 3 条 · QQ 企业邮箱 · 一条都不用改】
MX   joysnd.com          mxbiz1.qq.com                          优先级 5
MX   joysnd.com          mxbiz2.qq.com                          优先级 10
TXT  joysnd.com          v=spf1 include:spf.mail.qq.com ~all

【新增 4 条 · Resend 托管 · 全部以 .send 结尾 · 挂在 send.joysnd.com 子域树】
TXT  resend._domainkey.send   p=MIGfMA...wIDAQAB                  (DKIM)
MX   send.send                feedback-smtp.xxx.amazonses.com    优先级 10
TXT  send.send                v=spf1 include:amazonses.com ~all   (SPF)
TXT  _dmarc.send              v=DMARC1; p=none;                   (DMARC · 也挂 send 子域)

核心要点: - QQ 邮箱的 3 条记录一条都不动 - Resend 的 4 条记录全部挂在 send.joysnd.com 子域树下resend._domainkey.send / send.send / _dmarc.send) - 完整 DNS 隔离 · 主域 joysnd.com 的 MX/SPF/DMARC 均零改动 · QQ 邮箱零影响

5.6.4 在 Cloudflare 添加 4 条记录 · Step-by-Step

CF Dashboard → joysnd.comDNSRecords → 右上角 Add record · 逐条添加:

5.6.4.1 记录 1 · DKIM(最关键)
字段
Type TXT
Name resend._domainkey.send(⚠️ 注意末尾是 .send · 对应子域方案)
Content p=MIGfMA0G...wIDAQAB(Resend 给的完整字符串 · 几百字符)
Proxy status 🔘 仅 DNS(灰色云朵 · TXT 无法代理 · CF 会强制灰色)
TTL Auto

点击 Save

Name 字段的精确写法

本节采用子域方案(在 Resend Add Domain 时输入 send.joysnd.com)· 所以 DKIM 的 Name 应该是 resend._domainkey.send(CF 会自动补 .joysnd.com → 最终全称 resend._domainkey.send.joysnd.com)。

  • ❌ 错误 A:resend._domainkey.send.joysnd.com(写完整域名 · CF 再补一次主域 → 重复 · 验证失败)
  • ❌ 错误 B:resend._domainkey(漏了 .send · 这是主域方案的写法 · 与本节子域方案不匹配 · 会导致 Resend 验证不通过)
  • ✅ 正确:resend._domainkey.send(CF 自动补 .joysnd.com

如果 Resend 界面显示的 Name 形如 resend._domainkey.send.joysnd.com 完整域名(某些 UI 版本会这样显示)· 粘贴到 CF 时去掉末尾的 .joysnd.com 主域后缀再填入(因为 CF 会自动补)。

5.6.4.2 记录 2 · send.send 子域 MX
字段
Type MX
Name send.send(⚠️ 注意是两个 send · 不是写错 · 见 §5.6.2"关键前提 2")
Mail server feedback-smtp.us-east-1.amazonses.com(按 Resend 实际给的填 · 区域可能不同)
Priority 10
TTL Auto

点击 Save

为什么是 send.send 而非 send

  • Resend UI 显示的 Name = send(相对于验证域 send.joysnd.com
  • 填到 CF(zone = joysnd.com)时需要加 .send 后缀 → send.send
  • 最终完整域名 = send.send.joysnd.com
  • 这是 AWS SES 给每个验证域默认分配的"发信退信通道"路径 · 不是写错

与主域 MX 零冲突: - 现有 joysnd.com → mxbiz1.qq.com主域的 MX(QQ 企业邮箱) - 新加 send.send.joysnd.com → feedback-smtp.xxx.amazonses.com两层子域下的 MX(Resend/AWS SES) - DNS 系统里它俩是完全独立的不同域名 · 并存无冲突

5.6.4.3 记录 3 · send.send 子域 SPF
字段
Type TXT
Name send.send(与 MX 记录的 Name 完全一致)
Content v=spf1 include:amazonses.com ~all
Proxy status 🔘 仅 DNS
TTL Auto

点击 Save

绝不要合并主域 SPF · 这是最大的坑

网上部分教程说"一个域名只能有一条 SPF" · 让你把两条合并成:

v=spf1 include:spf.mail.qq.com include:amazonses.com ~all
你的情况下不需要这样做 · 原因: - 主域 joysnd.com 只能有 1 条 SPF(现在是 QQ 的 · 不动) - 子域 send.send.joysnd.com 只能有 1 条 SPF(新加 Resend 的) - 两条 SPF 分属不同域名 · 和平共处

如果你手贱合并主域 SPF · QQ 企业邮箱的送达率会骤降(因为 SPF 被改写 · 邮件服务商反欺诈校验失败)。

5.6.4.4 记录 4 · DMARC(可选但建议)
字段
Type TXT
Name _dmarc.send(⚠️ 末尾加 .send · 与其他 3 条一致)
Content v=DMARC1; p=none;
Proxy status 🔘 仅 DNS
TTL Auto

点击 Save

DMARC 挂在 send 子域树 · 与主域 QQ 邮箱完全隔离(v1.3 修正)

v1.2 曾错误要求把 DMARC 填成 _dmarc(主域)· v1.3 修正为 _dmarc.send(子域)· 理由:

  • 在 Resend 注册的是 send.joysnd.com · Resend UI 的 Name 字段 _dmarc相对于验证域的 · 所以填到 CF 时要补 .send 后缀 → _dmarc.send
  • 最终完整域名 = _dmarc.send.joysnd.com · 只对 send.joysnd.com 子域树的发信生效 · 不影响主域 joysnd.com(即 QQ 企业邮箱)
  • 这比"挂在主域"更安全:你可以随便调整 Resend 的 DMARC 策略(p=nonep=quarantinep=reject)· 不会有任何可能影响到 QQ 邮件的风险

p=none = 只监控不拦截 · 是最安全的起步策略 · 等 Resend 跑稳 1-2 周后可以考虑升级到 p=quarantine(让收件方把伪造的 @send.joysnd.com 邮件标为垃圾)。

首次部署担心的话 · 可以先跳过这条 · Resend 本身不强依赖 DMARC · 只是加了更安全。

5.6.4.5 添加完成后 · 总检查

你的 DNS 列表应该看到7 条邮件相关记录

【原有 3 条 · QQ 企业邮箱】
MX   joysnd.com          mxbiz1.qq.com                           优先级 5
MX   joysnd.com          mxbiz2.qq.com                           优先级 10
TXT  joysnd.com          v=spf1 include:spf.mail.qq.com ~all

【新增 4 条 · Resend · 子域方案 · 全部以 .send 结尾】
TXT  resend._domainkey.send   p=MIGfMA...wIDAQAB
MX   send.send                feedback-smtp.xxx.amazonses.com    优先级 10
TXT  send.send                v=spf1 include:amazonses.com ~all
TXT  _dmarc.send              v=DMARC1; p=none;

5.6.5 回 Resend 点 Verify · 等待验证

  1. Resend Dashboard → Domains → 点击 joysnd.com
  2. 点击 Verify DNS Records 按钮
  3. Resend 会查询全球 DNS 系统 · 比对 4 条记录
  4. 通常 1-10 分钟全部变绿 ✅(偶尔需要 30 分钟)
  5. 所有行变 Verified 后 · 域名状态变成 Verified

5.6.6 验证成功后 · .NET 发件代码示例

验证成功后 · 在 xisound-api/src/Services/EmailServices.cs(或相应的邮件发送逻辑处)把发件地址改成:

var email = new EmailRequest {
    From = "羲音官网 <noreply@send.joysnd.com>",     // ← 注意 send 子域
    To = new[] { "ops@joysnd.com" },
    ReplyTo = "support@joysnd.com",                    // ← 用户回信走 QQ 企业邮箱
    Subject = "【新留资】张三 · 某声学公司",
    Html = "<p>...</p>"
};
await _resendClient.Emails.SendAsync(email);

对收件人看到的邮件头:

From:      羲音官网 <noreply@send.joysnd.com>    ← 系统发信地址
Reply-To:  support@joysnd.com                     ← 用户"回复"时自动指向这里

用户回信 → 进 QQ 企业邮箱 → 运营团队看到 → 完美闭环

相应地 · 更新 VPS 上的 .env.production

Resend__FromAddress=羲音官网 <noreply@send.joysnd.com>
Resend__ReplyTo=support@joysnd.com

5.6.7 三个最容易踩的坑(必看)

坑 1 · Name 字段被填成完整域名

  • ❌ 错误:resend._domainkey.joysnd.com
  • ✅ 正确:resend._domainkey

Cloudflare 会自动补主域 · 写完整会变成 resend._domainkey.joysnd.com.joysnd.com(重复)· 验证永远失败。

坑 2 · 手贱合并主域 SPF

Resend 给你的 SPF 是加在 send 子域 · 不是主域。 如果你听信网上教程"一个域名只能有一条 SPF"的说法 · 改掉主域 joysnd.com 的 SPF · QQ 企业邮箱的送达率会骤降

规则: - 主域 SPF 只能有 1 条(保留 QQ 的不动) - 子域 SPF 只能有 1 条(新加 Resend 的) - 两者分属不同域名 · 不冲突

坑 3 · DKIM 粘贴时被截断或带引号

Resend 给的 DKIM 内容很长(几百字符)· 粘贴时: - ❌ 不要在内容两端手动加 " 双引号(CF 会自动处理) - ❌ 不要换行 · 整段一行粘贴 - ❌ 不要漏字符(有些浏览器复制会截断)

粘贴后确认最后几个字符是 wIDAQAB(这是 RSA 公钥的固定结尾)· 如果不是 · 说明复制不完整 · 重新来。

5.6.8 验证失败排查

症状 1 · Resend 点 Verify 后一直转圈 / 红叉

排查顺序

Step 1 · 本地 PowerShell 查 DNS 是否已生效(子域方案对应的查询命令 · v1.3 修正所有目标路径):

nslookup -type=TXT resend._domainkey.send.joysnd.com
nslookup -type=TXT send.send.joysnd.com
nslookup -type=MX send.send.joysnd.com
nslookup -type=TXT _dmarc.send.joysnd.com
  • 如果返回 Non-existent domain · 说明 DNS 还没传播 · 等 10-30 分钟再试
  • 可先 ipconfig /flushdns 清本地 DNS 缓存

Step 2 · 检查 CF 里是否有代理云朵

  • 所有 TXT 记录必须是"仅 DNS"灰色云朵
  • 如果是橙色云朵 · CF 会屏蔽 TXT 查询 · 点击改回灰色

Step 3 · 用在线工具跨区域查询

  • https://dnschecker.org → 查 resend._domainkey.send.joysnd.com(DKIM)或 send.send.joysnd.com(SPF)的 TXT 记录
  • 看全球各地 DNS 是否都能查到
  • 如果部分地区查不到 · 继续等(DNS 传播在海外 CN 有时延)
症状 2 · 验证通过但发信失败

最常见原因:代码里 From 地址写错

  • noreply@joysnd.com(这是主域 · Resend 没验证主域)
  • noreply@send.joysnd.comsend 子域 · 已验证)

其次检查: - API Key 是否过期(Resend Dashboard → API Keys 查看) - .env.production 是否真的加载了新值(docker compose logs api | grep ResendEmailService

5.6.9 curl / PowerShell 最终自测

验证全部通过后 · 在本地 PowerShell 跑一下确认完整闭环(替换 re_YOUR_KEY_HERE 为真实 API Key):

$body = @{
    from = "羲音官网 <noreply@send.joysnd.com>"
    to = @("你自己的邮箱@qq.com")
    reply_to = "support@joysnd.com"
    subject = "Resend 域名验证成功测试"
    html = "<h2>✅ 打通</h2><p>这封邮件从 Resend 发出 · From 地址是 send.joysnd.com 子域 · Reply-To 指向 QQ 企业邮箱。</p>"
} | ConvertTo-Json -Depth 3

Invoke-RestMethod -Uri "https://api.resend.com/emails" `
    -Method POST `
    -Headers @{ Authorization = "Bearer re_YOUR_KEY_HERE" } `
    -ContentType "application/json; charset=utf-8" `
    -Body $body

预期三项全中 = Resend 域名验证完美闭环 ✅: 1. PowerShell 返回 { id: "xxx-xxx-xxx" }(邮件 ID) 2. 目标邮箱 1-30 秒内收到邮件 · 发件人显示 羲音官网 <noreply@send.joysnd.com> 3. 点击回复 · 收件人自动填为 support@joysnd.com(QQ 企业邮箱)

5.6.10 小结 · 3 步搞定

joysnd.com                         ← 公司总部地址
├── 总部收发室 (QQ 企业邮箱) · 不动
│   └── 处理: ops@, support@, hello@ 等人工邮件
└── 新开一个分部 send.joysnd.com   ← Resend 托管 · 新加
    └── 处理: noreply@send. 的系统自动邮件

总部和分部的招牌都写着"joysnd" · 客户看不出区别
但内部走不同的办公流程 · 互不打扰 ✅

最终 3 步清单

  1. ✅ 按 §5.6.4 在 Cloudflare 加 4 条记录(5 分钟)
  2. ✅ 回 Resend 点 Verify DNS Records(等 1-10 分钟)
  3. ✅ 用 §5.6.9 的 PowerShell 发一封测试邮件(确认闭环)

5.7 常见坑

坑 1 · Gmail 邮箱注册 Resend 可能限额更严

部分反馈 Gmail 邮箱注册的账号被默认限额为 100 封/月 · 而团队域名邮箱账号正常 3000 封。 建议:用团队域名邮箱(如 ops@joysnd.com)注册 · 避免意外限额。

信息 · Resend 不支持中文邮件主题的"某些特性"

Resend 的文本内容完全支持 UTF-8 中文 · 但Reply-To / From 显示名如果含中文可能触发部分邮箱客户端的编码问题。 解决:From: "羲音官网 <noreply@joysnd.com>" 写法 · 不要把中文放到 Reply-To 标头字段的纯文本里。


6. 企微群机器人 Webhook

6.1 为什么需要企微机器人

本项目的留资表单提交流程:

  1. 访客提交表单
  2. 后端写入 PostgreSQL
  3. 后端触发 Resend 发邮件给运营邮箱
  4. 后端同时推送一条消息到企微群 · 让商务团队第一时间看到

企微机器人便宜、免费、即时到达手机、比邮件响应快得多 · 是 toB 销售线索场景的事实标准。

6.2 企业微信 vs 个人微信 · 不要搞混

微信产品 用户对象 群机器人 本项目
个人微信(wechat.com) C 端个人 ⛔ 无官方群机器人 API 不行
企业微信(work.weixin.qq.com) B 端组织 · 免费版 200 人 🟢 群机器人 Webhook 官方支持 本项目用这个

不要在个人微信群里找群机器人

个人微信没有官方机器人 API · 市面上所谓"个人微信机器人"都是逆向协议 · 随时被封号。 必须使用企业微信

6.3 企业微信申请流程

如果公司已有企业微信,跳到 §6.4。 如果没有,按以下流程注册:

  1. 打开 https://work.weixin.qq.com
  2. 右上角 企业注册 → 选择企业
  3. 填写:
  4. 企业名称(和营业执照一致 · 或自定义团队名)
  5. 行业
  6. 企业规模
  7. 管理员姓名 + 手机号(建议 CEO / CTO 本人)
  8. 手机号收验证码
  9. 注册完成 · 自动跳转到 Web 管理后台
  10. 个人开发者可以选小型团队方案 · 不需要营业执照 · 直接个人微信扫码即可创建一个"临时组织"

6.4 创建群并拉人

  1. 管理员的个人微信下载安装 企业微信 App(iOS/Android/Win/Mac)
  2. 登录企业微信 App
  3. 底部 工作台 → 右上角 +发起群聊
  4. 选择 2 个以上同事(最少 3 人才能启用群机器人) · 建议包含商务负责人 + 运营 + 本地测试号
  5. 群名:Xisound · 留资线索通知
  6. 创建成功

群机器人的最小人数要求

企业微信群必须至少 3 人才能启用机器人功能 · 2 人群(你 + 同事)不行。 变通:拉自己的其他企微账号 / 测试账号 / 同事的测试号凑够 3 人。

6.5 创建群机器人并获取 Webhook URL

  1. 企业微信 App 打开刚建的群
  2. 右上角 ...群管理
  3. 下拉找到 群机器人 → 点击
  4. 添加机器人
  5. 机器人名称:xisound-lead-bot
  6. 机器人头像(可选 · 用羲音 Logo)
  7. 创建完成 · 显示 Webhook URL,形如:
    https://qyapi.weixin.qq.com/cgi-bin/webhook/send?key=xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx
    
  8. 点击"复制"按钮 · 粘贴到 xisound-api/.envWEWORK_WEBHOOK_URL=https://...

Webhook URL 等同密钥

任何持有这个 URL 的人都能向你的群发消息 · 不要: - 提交到 Git - 贴到截图里 - 发到公开聊天

如果泄漏 · 群管理里重置 Webhook 即可让旧 URL 失效。

6.6 测试 Webhook

本地 PowerShell 执行(替换 YOUR_KEY):

$webhookUrl = "https://qyapi.weixin.qq.com/cgi-bin/webhook/send?key=YOUR_KEY"
$body = @{
    msgtype = "text"
    text = @{
        content = "【测试】羲音留资机器人接通 · $(Get-Date -Format 'yyyy-MM-dd HH:mm:ss')"
    }
} | ConvertTo-Json -Depth 3

Invoke-RestMethod -Uri $webhookUrl `
    -Method POST `
    -Body $body `
    -ContentType "application/json; charset=utf-8"

预期: - 企微群立即收到一条机器人消息 - PowerShell 输出 errcode: 0, errmsg: ok

6.7 限流规则

企微机器人硬限流每个机器人每分钟最多 20 条消息 · 超出会返回 errcode: 45009

本项目影响评估: - 留资峰值按每分钟 5 条 · 远不超限 - 但若未来接入每笔订单通知 / 每次错误报警 · 要注意汇总后再发(如每分钟聚合一次)

错误重试策略

xisound-api/src/Services/WeworkBotNotifier.cs 中已实现: - 失败重试 3 次(指数退避 1s / 2s / 4s) - 最终失败降级为日志(不抛异常阻塞主流程) - 空 WEWORK_WEBHOOK_URL 时输出 [WeworkBot-NoOp] 不发送

6.8 支持的消息类型

msgtype 用途 本项目
text 纯文本 + @人 ⭐ 首选
markdown 富文本(加粗/链接/颜色) ⭐ 美化后切换
image 图片(需 base64 + md5) 🟡 未来
news 图文卡片(带跳转链接) 🟡 未来点击跳转后台
file 文件(需先上传拿 media_id)

首版使用 markdown 即可实现"新留资\n姓名:张三\n邮箱:...\n立即查看 →"效果。


7. 验收清单 · 所有账号就绪

完成本文所有步骤后,对照下列清单自查。全部打勾才可进入阶段 1 VPS 基础环境初始化

7.1 腾讯云

  • 腾讯云账号已注册(微信/手机号/邮箱任一)
  • 已完成实名认证(个人或企业)
  • 账户余额 ≥ ¥100 或已绑定支付宝免密
  • 已购买轻量应用服务器(Lighthouse)
  • 地域:中国香港
  • 镜像:Ubuntu 22.04 LTS 64 位
  • 套餐:通用型 II(2C4G 80G SSD · 1000 GB/月 · 30 Mbps)
  • 时长:1 年
  • 实例名:xisound-api-prod-hk-01
  • 实例创建成功 · 状态 运行中
  • 公网 IP 已记录(43.xxx.xxx.xxx
  • root 密码 已保存到密码管理器
  • OrcaTerm Web 终端可登录
  • cat /etc/os-release 确认 Ubuntu 22.04
  • free -h 确认 ~3.8 G 可用内存
  • 防火墙已开 TCP 80 / 443(阶段 1 部署 nginx 前开)
  • 已开启自动续费

7.2 Resend

必做项(M6.2 阶段 0 前置准备):

  • Resend 账号已注册
  • 邮箱已验证
  • API Key 已创建(名为 xisound-api-prod)
  • API Key 已保存到密码管理器(形如 re_xxx...)
  • 免费版限额确认 3000 封/月
  • 已用 onboarding@resend.dev 发送过一封测试邮件

建议 M6.2 部署跑通后立即做(§5.6 详细手册):

  • Resend Dashboard 添加域名 joysnd.com(§5.6.2)
  • Cloudflare DNS 加 4 条记录(DKIM/MX/SPF/DMARC · §5.6.4)
  • QQ 企业邮箱 3 条原有记录一条都未动(§5.6.3)
  • Resend 点 Verify DNS Records 全部变绿 Verified(§5.6.5)
  • PowerShell Invoke-RestMethod 发一封测试邮件(§5.6.9)
  • 收件方能看到发件人 羲音官网 <noreply@send.joysnd.com> · 点"回复"自动填 support@joysnd.com(§5.6.6)

7.3 企业微信

  • 企业微信已注册(管理员账号)
  • 群聊 Xisound · 留资线索通知 已创建(至少 3 人)
  • 群机器人 xisound-lead-bot 已创建
  • Webhook URL 已复制并保存到密码管理器
  • PowerShell Invoke-RestMethod 测试成功(errcode: 0
  • 群内收到测试消息

7.4 前置阶段 0 · 总开关

  • xisound-api/.env 本地文件已填入真实 RESEND_API_KEY
  • xisound-api/.env 本地文件已填入真实 WEWORK_WEBHOOK_URL
  • xisound-api/.env 已确认在 .gitignore 中(不会提交)
  • 本地 dotnet run 再次跑通 · 提交测试留资 → 群内收到消息 + 邮箱收到邮件(不再是 [NoOp] 日志)

8. 下一步 · 进入阶段 1

当 §7 清单全部打勾后 · 你已完成 M6.2 阶段 0 前置准备

下一步的三条主路径(M6.2 阶段 1+2+3 · 一份权威手册覆盖)

阶段 核心动作 权威手册
阶段 1 · VPS 基础环境 SSH 密钥、用户降权、fail2ban、Docker 安装、交换分区 m6.2-vps-deploy-stage123.md §1
阶段 2 · 服务编排 docker-compose.prod.yml 5 容器 · PostgreSQL migrations · nginx HTTP-only 首启 m6.2-vps-deploy-stage123.md §2
阶段 3 · DNS + HTTPS + 前端 CF DNS 加 api · certbot 签发 · nginx HTTPS 切换 · Full strict · PUBLIC_API_BASE_URL m6.2-vps-deploy-stage123.md §3

启动前必看 · §0 密钥泄漏应急处置

如果 M6.1 阶段已经把真实的 Resend API Key 或企微 Webhook 提交到过 Git 历史,必须先完成新手册 §0 的吊销 + 清理 + force push 流程,然后再进入 §1 的 VPS 基础环境初始化。

准备就绪

完成本文 · 你已跨过 M6.2 最大的"新手门槛"(搞清楚 VPS 是什么 + 买到手 + 3 个账号到位)。 后续阶段都是具体命令操作 · 按手册复制粘贴即可 · 不再有"选型纠结"和"注册疑虑"。


9. 附录

9.1 术语表

术语 中文 一句话解释
VPS 虚拟专用服务器 一台从物理机切出的虚拟机 · 你拥有完整 root
Lighthouse 轻量应用服务器 腾讯云面向开发者的 VPS 产品线
CVM 云服务器 腾讯云面向企业的 VPS 产品线 · 更贵更灵活
ICP 备案 互联网信息服务许可 在中国大陆运营网站需向工信部报备 · 20-30 个工作日
SSH Secure Shell 加密的远程登录协议 · VPS 管理的标准入口
Docker 容器化技术 把应用 + 依赖打包成可移植镜像 · 一键运行
Docker Compose 容器编排工具 用 YAML 声明多个容器如何协同启动
nginx 反向代理服务器 接收 HTTPS 请求 · 转发给内部应用 · 处理 SSL/限流/静态文件
Webhook 回调 URL 第三方服务向你指定 URL 推消息的机制(本项目用于企微机器人)
SMTP 简单邮件传输协议 邮件服务器间投递邮件的标准协议
Resend SaaS 邮件服务 把 SMTP 复杂性封装成 HTTP API 的开发者工具
SPF/DKIM/DMARC 邮件防伪三件套 域名所有者声明哪些服务器有权发件 · 防止伪造
CORS 跨域资源共享 浏览器安全机制 · 限制不同域的 JS 互相请求
Cloudflare Pages CF 的静态站托管 免费 · 自动 HTTPS · 全球 CDN · 本项目官网用它

9.2 价格速查(2026-05)

项目 月价(首年) 月价(续费) 年价(首年) 年价(续费)
腾讯云轻量 通用型 II(2C4G 80G 1TB) ¥60 ¥80 ¥576(8 折) ¥768
Resend Free $0 $0 $0 $0
企业微信基础版 ¥0 ¥0 ¥0 ¥0
Cloudflare Free(DNS + Pages + CDN) $0 $0 $0 $0
M6.2 月度成本合计 ¥60 ¥80 ¥576 ¥768

9.3 所有账号信息保存模板(填完后用密码管理器加密)

# M6.2 账号清单 · 请用 1Password / Bitwarden / KeePass 加密存储
# 禁止提交到 Git · 禁止 Slack / 邮件裸传

tencent_cloud:
  account_login: "<手机号  微信绑定>"
  account_password: "<强密码>"
  real_name_auth: "<个人 / 企业>"
  instance_name: "xisound-api-prod-hk-01"
  public_ip: "<43.xxx.xxx.xxx · 实例创建后填>"
  root_password: "<VPS root 强密码>"
  region: "hk"
  plan: "lighthouse-general-2c4g80g"
  expire_date: "<YYYY-MM-DD · 一年后>"

resend:
  account_email: "<ops@joysnd.com 或类似>"
  api_key: "re_xxxxxxxxxxxxxxxxxxxxxxxxxx"
  api_key_name: "xisound-api-prod"
  plan: "Free · 3000/mo"

wework:
  admin_phone: "<注册手机号>"
  group_name: "Xisound · 留资线索通知"
  bot_name: "xisound-lead-bot"
  webhook_url: "https://qyapi.weixin.qq.com/cgi-bin/webhook/send?key=xxxx-xxxx-xxxx-xxxx"
  rate_limit: "20 msg/min"

9.4 变更记录

版本 日期 作者 变更
v1.0 2026-05-06 AlgoDepartment 首次定稿 · 覆盖 VPS 科普 + 腾讯云 4 种镜像详解 + Resend/企微机器人申请全流程 · 用户反馈驱动 · 面向非运维新手
v1.1 2026-05-06 AlgoDepartment 基于二轮用户反馈增补: §5.6 域名验证从"M6.4 延后"改写为 10 小节手把手手册(与 QQ 企业邮箱共存机制 + 4 条 DNS 记录逐条详解 + 3 大必踩坑 + 失败排查 + PowerShell 自测) · §4.4 新增"套餐命名与价格变动"info(避免"54 元 2C2G"等特惠诱惑) · §7.2 验收清单拆为必做/建议两组
v1.2 2026-05-07 AlgoDepartment 基于三轮用户反馈修正关键歧义: §5.6.2 明确要求在 Resend Add Domain 输入框填写 send.joysnd.com(而非主域 joysnd.com)· 否则发信地址无法使用 @send.joysnd.com · §5.6.2/§5.6.3/§5.6.4.1/§5.6.4.5/§5.6.8 把 DKIM Name 从 resend._domainkey 改为 resend._domainkey.send(子域方案对应 selector)· 在 §5.6.2 顶部加显眼 danger admonition 提供"已误按主域操作"的回滚路径
v1.3 2026-05-07 AlgoDepartment 基于四轮用户反馈彻底修正所有 Name 字段: 用户实测发现在 Resend 注册 send.joysnd.com 后 · Resend UI 的 Name 字段是相对于验证域的 · 填到 Cloudflare 时必须每个都加 .send 后缀(CF zone 是主域 joysnd.com)。v1.2 只修正了 DKIM · 本轮修正剩余 3 条:MX sendsend.send · SPF sendsend.send · DMARC _dmarc_dmarc.send。§5.6.2 新增"关键前提 2"danger admonition 含完整 Resend Name ↔ CF Name 映射表。附带好处:DMARC 也挂到 send 子域树下 · 主域 joysnd.com 的 MX/SPF/DMARC 全部零改动 · 与 QQ 企业邮箱完全隔离

9.5 相关文档

  • 07web-m6.1-deploy-plan.md · M6.1 官网 + M6.2 VPS 部署权威方案 v2.0
  • docs-site-deployment.md · M6.1.1 MkDocs 文档站部署手册
  • xisound-api/TODOLIST.md · 后端仓完整 7 阶段 40+ TODO
  • xisound-website/TODOLIST.md · 前端仓完整 6 阶段 35+ TODO
  • 07_web/doc/M6-deployment-guide.md · 本地开发副本(非权威)

反馈与改进

本文基于用户首次部署实战反馈编写 · 如遇到以下情况请反馈: - 腾讯云 UI 变更导致截图描述过时 - Resend 免费版政策调整 - 企业微信机器人规则变更 - 发现新的坑点未被覆盖

反馈方式:在 06_docs 仓库提交 PR 修订本文 v1.1。