二级域名分发系统源码:自动化申请解析与易支付对接实战
简介这份资源是PHP开发的二级域名分发系统源码已对接易支付接口面向需要搭建域名分发平台的站长、个人开发者及中小型服务商可解决多用户二级域名申请、自动分发与在线收款的一体化需求。源码基于PHP7.2环境运行需安装SG11扩展部署时放入根目录解压、先设置伪静态再访问域名即可进入安装流程适合具备一定PHP环境配置与建站经验的技术人员使用。压缩包为rar格式整体约13.83MB文件类型明细上游暂未提供但按此类系统惯例应包含PHP程序文件、前端静态资源、数据库脚本及配置文件等便于直接部署与二次开发。目前已有448人学习下载说明该方案在域名分发场景中具有一定参考价值。读者可借此获得一套可运行的域名分发系统理解易支付对接逻辑、伪静态配置要点与安装排错思路并在此基础上按自身业务需求调整界面与功能模块。1. 二级域名分发系统源码从申请到解析一套能跑通的自动化链路做 SaaS、建站平台或者多租户工具的人迟早会撞上同一个需求让用户自己申请一个xxx.你的主域.com的二级域名申请完自动生效不用你手动去 DNS 后台加记录。用户量一上来手工加解析就是灾难一天几十个申请能把人逼疯。这套「二级域名分发系统源码」解决的就是这件事——它把域名申请、可用性校验、DNS 记录写入、订单支付串成一条自动链路并且已经对接了易支付用户付完款系统自动开通。适合谁适合手里有主域名、想快速搭一个二级域名分发站点的站长和独立开发者尤其是做虚拟主机、短链、博客托管、游戏私服这类需要批量发子域名的场景。源码本身是 PHP 技术栈部署门槛不高但 DNS 接口和支付回调这两块是翻车重灾区下面拆开讲。2. 系统架构与 DNS 解析原理为什么不能只靠一条 A 记录2.1 二级域名分发的核心链路先把整条链路说清楚不然后面配置全是玄学。用户在前台输入想要的二级域名前缀系统做三件事查这个前缀有没有被占用、查主域名当前的解析记录、把新记录写进 DNS。写记录这一步取决于你的主域名托管在哪家 DNS 服务商。常见做法是主域名托管在 Cloudflare、阿里云 DNS、DNSPod 这类提供 API 的服务商系统通过 API 调用添加解析记录。这里有个关键选型问题泛解析还是逐条解析。泛解析就是加一条*.你的主域.com指向服务器 IP所有二级域名自动生效系统只需要记录「谁申请了哪个前缀」不用真的去写 DNS。这种方式最省事但缺点是无法给不同用户指向不同 IP也没法做单独的解析管理。逐条解析则是每个申请都调一次 DNS API 写一条记录灵活但依赖 API 稳定性。这套源码走的是逐条解析路线因为它要对接支付每个用户开通的域名需要独立可控。理解这一点很重要后面排查「域名申请成功但打不开」时第一个要看的就是 DNS 记录到底写进去没有。2.2 主域名与 DNS 服务商的对接配置以 Cloudflare 为例你需要在 Cloudflare 后台生成一个 API Token权限给到Zone.DNS的编辑权限Zone 资源限定到你的主域名。拿到 Token 后填进系统的配置文件。常见做法是把 DNS 配置单独放一个 config 文件方便换服务商。// config/dns.php 常见配置结构 return [ driver cloudflare, // DNS 服务商驱动 api_token 你的Cloudflare_Token, zone_id 你的主域名ZoneID, // 在域名概览页右下角 main_domain example.com, // 主域名不带 www record_type A, // 默认解析类型 default_ip 1.2.3.4, // 默认指向的服务器IP ttl 120, // TTLCloudflare 自动模式填1 ];逻辑说明driver决定调用哪个服务商的 API 封装类源码里一般有CloudflareDriver、AliyunDriver等。zone_id是最容易填错的地方它不是域名本身而是服务商给这个域名分配的唯一 ID填错会直接报 403 或 record not found。default_ip是二级域名默认解析到的服务器地址如果你的分发系统本身和业务服务器不是同一台这里要填业务服务器的 IP。参数怎么改TTL 建议设短一点比如 120 秒方便调试时快速生效生产环境可以调到 600。record_type如果你的业务走 CDN可能要改成 CNAME这时default_ip要换成 CNAME 目标地址。2.3 数据库表结构与域名状态流转源码的数据库一般围绕三张表转用户表、域名申请表、订单表。域名申请表里最关键的是status字段它决定了这个二级域名当前处于什么状态。字段类型说明idint主键user_idint申请用户subdomainvarchar二级域名前缀如testfull_domainvarchar完整域名如test.example.comstatustinyint0待支付 1已开通 2已过期 3已释放dns_record_idvarcharDNS 服务商返回的记录ID删除时要用expire_atdatetime到期时间状态流转是用户提交申请 → status0 生成订单 → 支付回调 → status1 并调用 DNS API 写记录 → 到期未续费 → status2 → 宽限期后 status3 并删除 DNS 记录。dns_record_id这个字段很多人建表时漏掉结果删除域名时找不到记录 ID只能去 DNS 后台手动删血泪经验。3. 易支付对接与支付回调订单状态怎么才能不错乱3.1 易支付接口的请求与签名易支付是一套常见的聚合支付接口对接方式是基于 MD5 签名的表单提交或 API 请求。核心参数包括商户号pid、商户密钥key、订单号out_trade_no、金额money、回调地址notify_url、跳转地址return_url。签名规则通常是把参数按 ASCII 排序后拼接密钥做 MD5。// 发起支付请求的常见封装 function buildPayUrl($order) { $params [ pid $config[pid], type alipay, // 支付方式 out_trade_no $order[order_no], // 商户订单号必须唯一 notify_url $config[notify_url], // 异步回调服务器间通信 return_url $config[return_url], // 同步跳转用户浏览器 name 二级域名开通, money $order[amount], ]; ksort($params); // 按键名升序 $signStr ; foreach ($params as $k $v) { $signStr . $k . . $v . ; } $signStr rtrim($signStr, ) . $config[key]; $params[sign] md5($signStr); $params[sign_type] MD5; return $config[api_url] . ? . http_build_query($params); }逻辑说明ksort排序是签名能否通过的关键顺序错了签名必错。out_trade_no必须全局唯一一般用「日期自增ID随机数」生成重复订单号会导致支付平台拒绝。notify_url是异步回调支付成功后支付平台服务器会 POST 数据到这个地址这是开通域名的真正触发点不是return_url。参数怎么改type按你开通的支付方式填常见有alipay、wxpay。money保留两位小数格式错误有些支付平台会直接拒单。3.2 异步回调的验签与幂等处理回调处理是整个系统最容易出 bug 的地方。支付平台会 POST 一堆参数过来你要做四件事验签、核对金额、检查订单是否已处理、开通域名。// notify.php 回调处理核心逻辑 $data $_POST; $sign $data[sign]; unset($data[sign], $data[sign_type]); ksort($data); $signStr ; foreach ($data as $k $v) { $signStr . $k . . $v . ; } $signStr rtrim($signStr, ) . $config[key]; if (md5($signStr) ! $sign) { exit(fail); // 验签失败必须返回 fail } if ($data[trade_status] ! TRADE_SUCCESS) { exit(fail); } // 幂等先查订单状态已开通直接返回 success $order getOrderByNo($data[out_trade_no]); if ($order[status] 1) { exit(success); } // 核对金额防止篡改 if (bccomp($order[amount], $data[money], 2) ! 0) { exit(fail); } // 开通域名写 DNS 记录 更新订单状态 openDomain($order[id]); exit(success);逻辑说明验签前必须把sign和sign_type从数组里剔除否则签名串会多出这两个字段导致校验失败。返回success是告诉支付平台「我处理好了别再重发」返回fail或什么都不返回支付平台会按策略重试重试次数多了可能触发风控。幂等判断是后悔药——支付平台可能因为网络问题重复回调没有幂等判断就会重复开通、重复扣 DNS 配额。参数怎么改trade_status的值不同支付平台不一样有的用TRADE_SUCCESS有的用1以你对接的易支付文档为准。金额核对用bccomp而不是浮点数直接比较会翻车。3.3 开通域名的原子性处理开通动作包含「写 DNS 记录」和「更新订单状态」两步这两步必须尽量保证原子性。常见做法是先把订单状态改成「开通中」再写 DNS写成功后再改成「已开通」。如果写 DNS 失败订单停在「开通中」方便人工介入或定时任务重试。function openDomain($orderId) { updateOrderStatus($orderId, opening); // 先标记开通中 $order getOrder($orderId); try { $recordId dnsAddRecord($order[subdomain], $order[ip]); saveDnsRecordId($orderId, $recordId); updateOrderStatus($orderId, opened); } catch (Exception $e) { logError(开通失败: . $e-getMessage()); // 保持 opening 状态等定时任务重试 } }逻辑说明先标记「开通中」是为了防止回调重试时重复写 DNS。dnsAddRecord返回的记录 ID 必须存下来删除域名时要用。异常不抛出而是记日志是为了让回调能正常返回避免支付平台一直重试。4. 部署与 Nginx 配置主域名和二级域名怎么共存4.1 环境准备与源码部署源码是 PHP 的常见运行环境是 Nginx PHP-FPM MySQL。部署步骤不复杂但有几个点容易漏。# 1. 拉取源码到站点目录 cd /www/wwwroot unzip domain-dist.zip -d domain-dist # 2. 设置运行目录权限 chown -R www:www domain-dist chmod -R 755 domain-dist chmod -R 777 domain-dist/runtime # 框架运行时目录 # 3. 导入数据库 mysql -u root -p your_db domain-dist/install.sql # 4. 修改数据库配置 vim domain-dist/config/database.php逻辑说明runtime目录给 777 是因为 PHP 框架要写缓存和日志权限不够会报「无法写入」的白屏。数据库配置文件里填 host、user、password、dbname 四项prefix表前缀如果和 install.sql 里不一致要改。参数怎么改PHP 版本建议 7.4 或 8.0太老的 5.6 可能跑不起来某些语法。MySQL 建议 5.7 以上。4.2 Nginx 主域名与二级域名的 server 配置这是热词里问得最多的问题主域名和二级域名怎么在 Nginx 里共存。核心是用泛域名解析配合 server_name 通配符。# 主域名站点 server { listen 80; server_name example.com www.example.com; root /www/wwwroot/domain-dist/public; index index.php index.html; location / { try_files $uri $uri/ /index.php?$query_string; } location ~ \.php$ { fastcgi_pass unix:/tmp/php-cgi.sock; fastcgi_index index.php; fastcgi_param SCRIPT_FILENAME $document_root$fastcgi_script_name; include fastcgi_params; } } # 二级域名泛解析站点 server { listen 80; server_name *.example.com; root /www/wwwroot/user-sites/$host; # 按域名分目录 index index.php index.html; location / { try_files $uri $uri/ /index.php?$query_string; } location ~ \.php$ { fastcgi_pass unix:/tmp/php-cgi.sock; fastcgi_index index.php; fastcgi_param SCRIPT_FILENAME $document_root$fastcgi_script_name; include fastcgi_params; } }逻辑说明server_name *.example.com匹配所有二级域名Nginx 会优先匹配精确域名所以主域名走第一个 server二级域名走第二个。$host变量是当前请求的域名用它做目录可以实现「每个二级域名一个独立目录」。如果你的分发系统只是做跳转第二个 server 可以改成return 301到统一页面。参数怎么改fastcgi_pass的 socket 路径要和 PHP-FPM 配置一致宝塔面板一般是/tmp/php-cgi.sock自己编译的可能是127.0.0.1:9000。root路径按实际部署目录改。4.3 泛解析与逐条解析的配合如果你的系统是逐条解析那 Nginx 的泛解析 server 只是兜底真正生效的是 DNS 里逐条写的记录。这里有个坑泛解析记录*.example.com和逐条记录test.example.com同时存在时DNS 查询会优先返回精确记录所以逐条解析能覆盖泛解析。但如果你先加了泛解析用户申请时系统检测「域名是否可用」会误判——因为泛解析让所有前缀都能解析。常见做法是可用性检测只查数据库不查 DNS。5. 避坑与常见问题排查那些让你怀疑人生的报错5.1 支付成功但域名没开通现象用户付了钱订单显示已支付但二级域名访问不了DNS 里也没有记录。原因回调没收到或者回调收到了但验签失败、金额核对失败导致openDomain没执行。也可能是notify_url填的是内网地址支付平台服务器访问不到。解决先看支付平台的回调日志确认有没有发起回调、返回什么。再看系统日志里有没有验签失败的记录。notify_url必须是公网可访问的完整 URL不能带参数不能是 localhost。验签失败重点检查密钥有没有多余空格、参数排序对不对。5.2 DNS 记录写入报 403 或 record already exists现象调用 DNS API 时报权限错误或者提示记录已存在。原因403 一般是 API Token 权限不够或 zone_id 填错。record already exists 是同一个前缀已经有一条记录可能是上次开通失败残留的。解决Cloudflare 的 Token 要明确给Zone.DNS.Edit权限Zone 资源要选中主域名。zone_id 在域名概览页右下角不是域名本身。遇到记录已存在先调 API 查一下该前缀的记录存在就先删再建或者直接复用。5.3 二级域名解析生效慢现象DNS 记录明明写进去了本地就是打不开换网络又能打开。原因本地 DNS 缓存没刷新或者 TTL 设得太长。解决调试阶段 TTL 设 120 秒用dig test.example.com或在线 DNS 查询工具确认记录是否已生效。本地可以ipconfig /flushdnsWindows或sudo systemd-resolve --flush-cachesLinux刷新缓存。如果用了 CDN还要等 CDN 回源配置生效。5.4 订单号重复导致支付失败现象用户下单时报「订单号已存在」或支付平台拒单。原因订单号生成规则有并发问题同一秒内多个请求生成了相同订单号。解决订单号里加用户 ID 和随机数比如date(YmdHis) . $userId . mt_rand(1000,9999)。数据库对order_no字段加唯一索引插入失败就重新生成。5.5 删除域名后 DNS 记录残留现象用户域名到期释放了数据库里状态也改了但 DNS 里记录还在域名还能访问。原因删除时没拿到dns_record_id或者删除 API 调用失败没重试。解决建表时务必存dns_record_id。删除逻辑做成「先标记待删除定时任务扫描并调 API 删除成功后再改状态」避免一次失败就永久残留。6. 进阶把分发系统做成可运营的产品源码跑通只是起点真要运营还得补几块。第一块是域名前缀的敏感词过滤用户申请admin、api、mail这类前缀要拦截否则容易和你的业务冲突也容易被滥用。常见做法是维护一个保留词库申请时做前缀匹配。第二块是到期提醒和自动续费。expire_at字段有了加一个定时任务到期前 7 天、3 天、1 天分别发提醒到期当天没续费就改状态并删记录。定时任务用 crontab 跑别用用户访问触发不可靠。# crontab 示例每天凌晨检查到期域名 0 2 * * * /usr/bin/php /www/wwwroot/domain-dist/think expire:check /var/log/domain_expire.log 21第三块是解析记录的健康检查。写进去的记录不一定真的能访问可以加一个定时任务对已开通的域名做 HTTP 探测连续失败就告警。这个功能很多分发系统没有但用户投诉「域名打不开」时你能第一时间知道是 DNS 问题还是业务服务器问题。验证方法上我一般会走一遍完整链路注册用户 → 申请域名 → 下单 → 用测试支付环境付款 → 看回调日志 → 查 DNS 记录 →dig验证 → 浏览器访问。每一步都留日志出问题能定位到具体环节。从那以后我每次部署这类系统都强制先跑一遍全链路测试再开放注册不然用户一多问题全堆在一起根本查不过来。希望帮到你。本文还有配套的精品资源点击获取