二级域名分发系统源码部署指南:自助申请、自动解析与到期回收全流程

发布时间:2026/10/8 9:32:19
二级域名分发系统源码部署指南:自助申请、自动解析与到期回收全流程 简介这是一套面向企业建站、IDC服务商及个人开发者的2025二级域名分发系统商业版源码解决大量子域名快速创建、解析、续费与租赁管理问题。包体共2000个文件约51.17MB以1219个PHP业务文件、259个JSON配置与接口数据、190个Markdown说明文档、124个PNG界面素材为主并含JS/CSS、SQL、环境配置等方便前后台部署和二次开发。前台提供用户注册、域名申请/续费、解析设置后台支持管理员配置域名模板、用户权限与系统监控源码内含教程及演示站点可快速跑通完整分发流程。已有539人学习下载适合需要搭建域名租赁平台或完善二级域名管理体系的开发者参考。1. 2025二级域名分发系统一套源码把域名出租、解析、到期收回来做域名分发、子域名业务的人都会遇到同一个尴尬手里攥着主域名用户却要一个个手工开。客户要个二级域名你得登录DNS后台加记录、等生效、手记到期时间客户一多这套手工流程就是灾难。这套2025商业版二级域名分发系统源码解决的就是这个闭环——用户在前台自助申请二级域名系统自动调用解析API写入DNS记录到期自动回收释放管理员只需在后台添加主域名、配置解析凭证、设好套餐价格。它适合做域名租赁、建站服务分发、个人子域名自助平台的开发者也适合想快速搭建一个可运营的域名分发网站的站长。下面这套部署和改造过程是我按商业版常见结构拆出来的完整落地路径。2. 核心业务流程与数据模型域名申请、解析绑定、续费到期的完整闭环2.1 角色拆解管理员、用户、主域名三级结构这套系统里用户和域名的关系是「多对多」的一个用户可以在多个主域名下申请子域名一个主域名下也可以挂多个用户的不同子域名。数据模型不能简单地在用户表里加一个domain字段而要把主域名、子域名、用户三者分开建模。管理员侧的动作是添加主域名比如 example.com、配置该域名在DNS服务商处的API凭证、设置允许申请的前缀规则和套餐价格。用户侧的动作是注册登录、选择一个主域名、申请一个未被占用的子域名、系统自动写DNS记录并返回解析目标。我一般建议把「主域名」看成一个独立的资源池而不是一条配置项。这样后续做多域名聚合、按主域名统计收益、按主域名单独设置解析策略时SQL都不用大改。这套源码的商业版正是按这个思路铺的数据表结构后面二开加功能时能省很多事。2.2 核心数据表域名表、解析记录表、订单与到期表真正决定业务能不能跑通的表是下面这几张我把关键字段和用途列出来表名关键字段用途domain_mainid, name, api_type, app_id, app_secret, status主域名资源池存DNS服务商类型与API凭证domain_recordid, user_id, main_id, sub_prefix, record_type, record_value, ttl, status每条已分发的二级域名记录sub_prefix就是用户申请的标识user_accountid, username, password_hash, level用户表level决定可用套餐order_infoid, user_id, record_id, plan_id, pay_status, expire_time购买与续费记录到期时间在这里这里最容易设计反的是domain_record表。很多新手会把sub_prefix直接当成主键但实际业务里同一个子域名可能被删除后再次申请而且需要保留历史记录所以用自增id做主键sub_prefix加唯一索引即可。record_type字段建议直接存字符串类型记录类型是A还是CNAME后续调API时不用再做映射转换也方便前台展示时直接显示。订单与到期表要特别注意expire_time这个字段。建议用int存时间戳而不是用datetime。原因是后续算到期、写cron定时任务、做续费计算时时间戳直接加减比较省事也避免时区问题导致到期时间错乱。这套源码在MySQL里统一用时间戳存储排错时会省不少事。2.3 自动解析逻辑新增记录、删除记录、状态同步三段式系统最核心的代码是解析控制层。它对外暴露的动作只有三个创建解析、删除解析、查询解析状态。无论底层接的是DNSPod还是其他服务商API上层业务都只调用这三个接口。创建解析的顺序很关键——必须先查库判断占用再调API创建API返回成功后再落库。这个顺序不能反否则会出现库里没有占用、DNS侧却已经有了的脏数据。def create_subdomain_instance(user_id, main_domain, sub_prefix, target): # 1. 先查主域名是否存在且可用 main db.query(domain_main, {name: main_domain, status: 1}) if not main: return {code: 1, msg: 主域名未上架或已停用} # 2. 再查子域名是否已被占用库内唯一索引兜底 exists db.query(domain_record, {main_id: main[id], sub_prefix: sub_prefix}) if exists: return {code: 2, msg: 该二级域名已被占用} # 3. 调DNS服务商API创建记录成功后返回记录id dns_record_id dns_api.create_record( main[app_id], main[app_secret], domainmain_domain, sub_domainsub_prefix, record_typeA, record_valuetarget, ttl600 ) # 4. API成功才落库保证两边一致 db.insert(domain_record, { user_id: user_id, main_id: main[id], sub_prefix: sub_prefix, dns_record_id: dns_record_id, status: 1, create_time: now() }) return {code: 0, msg: success}这里dns_api.create_record的参数顺序和返回值格式要跟你实际接的API对齐。许多商业版默认对接的是腾讯云DNSPod参数是domain、subDomain、recordType、recordValue、ttl返回值里带recordId。如果接阿里云参数名会变成RR、Type、Value需要做一层适配层不要在业务代码里散落调用。删除解析的时机有两个用户主动释放、后台到期回收。无论是哪种都必须先调API删除DNS记录再更新库里的status字段为0。如果只删库不删DNS解析还会继续生效到期回收就等于白做。查询状态一般用于后台的「解析体检」功能比对库内记录和DNS侧记录找出不同步的记录并修正。3. 部署上线实操环境要求、安装步骤与多域名接入配置3.1 环境检查PHP、MySQL 与伪静态规则这套源码是PHPMySQL架构商业版常见要求是PHP 7.2以上、MySQL 5.6以上、Nginx或Apache均可。部署前先确认三件事PHP是否启用了pdo_mysql扩展、MySQL是否允许连接、伪静态规则是否已写入站点配置。前两个用phpinfo就能查伪静态则要看服务器软件类型。我在Nginx下部署时的站点配置如下重点是location的rewrite规则。如果用的是Apache把规则转到.htaccess就行但AllowOverride必须设为All否则规则不会生效。server { listen 80; server_name sub.example.com; root /var/www/subapp; index index.php; location / { # 非真实文件或目录时重写到入口文件 if (!-e $request_filename) { rewrite ^/(.*)$ /index.php?/$1 last; } } location ~ \.php$ { fastcgi_pass 127.0.0.1:9000; fastcgi_param SCRIPT_FILENAME $document_root$fastcgi_script_name; include fastcgi_params; } location ~* \.(jpg|jpeg|png|gif|ico|css|js)$ { expires 7d; } }这套配置里有两个容易翻车的点。第一if (!-e $request_filename) 只能放在location /里放到server级别会导致静态资源也被重写。第二fastcgi_pass的地址要跟实际安装的PHP-FPM监听地址一致配置8000还是9000取决于php-fpm.conf里的listen项我遇到过因为这里不一致导致所有PHP页面全部502的情况。站点根目录的runtime目录必须保证可写。多数商业版源码把缓存、日志、上传文件都放在runtime子目录里权限不到位时表现很迷惑前台能打开后台登录却报500或者提交申请时提示路径错误。我一般直接chown给www用户再chmod 755比无脑777靠谱一点。# 项目根目录执行把运行权限交给nginx用户 chown -R www:www /var/www/subapp chmod -R 755 /var/www/subapp/runtime chmod -R 755 /var/www/subapp/upload3.2 安装向导数据库初始化与后台入口验证把源码上传到站点根目录后访问域名会进入安装向导。安装向导做的事基本是固定的检查环境、填写数据库地址和账号、设置管理员密码、写入install.lock文件。数据库导入一般有两种方式一是向导里自动执行SQL文件二是手动导入源码包内的sql文件老版本里更常见的是手动方式。手动方式下先建库再导入# 创建数据库字符集用utf8mb4避免特殊字符乱码 CREATE DATABASE IF NOT EXISTS subapp DEFAULT CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci; # 命令行导入源码包内的数据库文件 mysql -u root -p subapp /var/www/subapp/database/install.sqlinstall.sql里通常包含表结构和一份默认数据默认数据里会有一个主域名示例和管理员账号装完后记得在后台改掉默认密码。安装完成后向导会自动生成install.lock之后想重新安装必须手动删除这个文件但要注意这会清空已配置的数据除非你有数据库备份否则别轻易操作。后台入口路径在安装说明里一般有标注常见的有admin.php或者直接二级目录/admin。登录后第一件事不是急着加域名而是去系统设置里检查站点名称、备案信息、支付参数是否被正确写入配置文件。配置文件通常是config.php里面存着数据库连接和API密钥建议设置600权限防止被其他用户读取。3.3 接入第一台主域名API凭证配置与连通性测试主域名接入是最容易出现挫败感的一步。在后台的「主域名管理」里添加域名填入域名名称、选择DNS服务商类型、粘贴API凭证。这里说的API凭证不是域名管理后台的登录密码而是服务商开放平台上生成的SecretId和SecretKey两者作用域完全不同填错后系统的表现是添加域名成功但申请子域名时API调用一直报鉴权失败。在DNSPod侧创建密钥后建议先在第三方API调试工具里手动调一次记录列表接口确认密钥有权限操作该域名。有的服务商要求子账号单独授权某域名的权限主账号密钥默认全权限子账号密钥如果不授权域名列表接口能通创建记录接口却会报错这就是「读取正常、写入失败」的典型症状。系统提供的连通性测试按钮很实用。点击测试后系统会实际调用一次查询接口拉取该域名下的记录列表并在界面上展示请求耗时和记录数。如果测试返回失败优先检查两项密钥是否复制完整前后不要带空格、域名是否没有在服务商处完成实名认证。多数服务商对未实名域名的API写操作会直接拒绝。连通性测试通过后主域名才算真正接入完成前台用户才能看到并申请这个域名下的子域名。这一步我一般会顺手在服务商控制台刷新一次确认系统查询到的记录和后台显示一致排除系统内部缓存导致的假通过。4. 参数配置地图解析API、套餐限制与到期任务怎么调4.1 套餐与价格规则时长、限额、单人可持有数商业版的核心盈利逻辑是「域名租赁」套餐配置直接决定收益。后台的套餐管理里一般可以设置套餐名称、价格、时长天/月/年、可申请的子域名数量上限、是否允许泛解析前缀。这些参数里最容易忽略的是「单人可持有数」这个限制不设的话一个用户可以无限申请子域名把资源池占满。我把常见套餐参数列一下方便对号入座参数项典型值说明套餐名称基础版 / 专业版前台展示用建议区分明显价格9.9 / 49.9按元计配合支付接口时长30 / 365 天到期后自动回收可申请数量3 / 10限制总量防止滥用记录类型A / CNAME决定用户填写IP还是域名是否允许泛解析否允许后子域名可填*不建议开放泛解析开关要单独提一下。泛解析意味着用户可以申请*前缀所有未匹配的子域名都会指向他的目标这在商业环境里基本等于把主域名整个交出去了一旦用户拿去做不合规的内容主域名会被连带拉黑。我一般强烈建议生产环境关闭泛解析只允许具体前缀宁可少做点生意也别把根域名搭进去。套餐价格和时长配置好之后前台申请页会直接读取这些参数渲染成列表。如果改了套餐参数发现前台没变化优先检查后台是否生成了缓存商业版系统通常会把套餐列表缓存到runtime目录改完配置后点一下「更新缓存」按钮再验证。4.2 解析记录默认参数TTL、记录值校验、前缀黑名单每条自动创建出来的DNS记录都有默认参数这部分在系统设置里集中配置。TTL建议设600也就是10分钟太短会增加DNS查询量太长则用户改完解析半天不生效。记录值校验规则也要设置A记录必须是合法IPv4地址CNAME记录必须是合法域名这个校验放在服务端做不能只依赖前端。前缀黑名单是很多人忽略但非常重要的配置。至少要把以下前缀禁掉www、mail、smtp、pop、imap、ftp、webmail、ns1、ns2、blog。这些前缀要么是邮件服务器在用要么是管理服务在用属于主域名的「保留区」。如果不设置黑名单用户申请了mail前缀你的邮件服务就废了。// 系统设置中的黑名单示例按需增减 $forbidden_prefix [www, mail, smtp, pop, imap, ftp, webmail, ns1, ns2, blog, admin, api]; // 申请时校验 if (in_array($sub_prefix, $forbidden_prefix)) { return [code 3, msg 该前缀为系统保留不可申请]; }这段逻辑很简单但位置很关键。校验必须放在服务端申请接口里而不仅是前端JS里。原因很直接接口是公开的有人绕过前端直接POST请求就能把黑名单绕过去。服务端校验一次、数据库唯一索引兜底一次这才是双层保险。我见过一个站只在前端做了黑名单被人用脚本刷了一整页mail前缀的解析记录处理起来相当被动。除了黑名单还要注意前缀的格式校验。二级域名前缀只能包含字母、数字和连字符不能以连字符开头或结尾长度限制在1到63个字符之间。这个校验用正则或者系统自带的验证器都能做不加的话用户填个带空格的非法前缀在DNS服务商API那边会直接报参数错误用户看到的错误提示还不明不白。4.3 到期任务与自动回收cron定时脚本配置到期回收是这套系统区别于普通域名管理面板的功能。它靠系统定时任务触发脚本逻辑是扫描order_info里expire_time小于当前时间的记录对每一条执行「停用解析」——先把DNS记录删除再把domain_record.status改为0同时释放该用户的可申请名额一个。我一般把回收脚本配置成每10分钟跑一次太频繁会增加API调用量太久了用户到期后还能访问影响续费转化。下面是crontab的典型写法注意脚本路径和执行用户必须正确# 每10分钟执行一次到期回收 */10 * * * * cd /var/www/subapp php think cron:recycle /var/www/subapp/runtime/recycle.log 21 # 每30分钟执行一次解析体检比对库内记录与DNS侧记录 */30 * * * * cd /var/www/subapp php think cron:sync /var/www/subapp/runtime/sync.log 21回收任务必须保证「可重复执行」。即使上一次执行到一半PHP内存超限崩了下一次执行时也不能重复扣用户名额或重复调API删记录。实现上一般靠记录状态机判断status1表示正常解析中status0表示已回收cron只处理status1且已到期的记录。这样就算脚本被重复触发也不会对已回收的记录做二次操作。日志是排查到期回收问题的第一现场。recycle.log里每一行应该记录记录id、子域名、到期时间、API返回结果。如果发现日志里有大量API error但库里状态已经改成0的记录说明代码顺序有问题——应该是API删除成功后才改库而不是先改库再调API。这一点在删除逻辑里已经强调过上线前务必检查一遍回收脚本的代码顺序。5. 避坑与排查部署运营中翻车的高发点与处理办法5.1 添加主域名成功但申请子域名时API报鉴权失败现象后台添加主域名时一切正常连通性测试也能通过但用户前台提交申请后系统提示API鉴权失败记录没有创建。原因这条翻车路径很典型元凶是域名与服务商平台之间的授权不一致。连通性测试通常只调用查询接口而创建记录是写操作。某些服务商尤其是用了子账号密钥的场景对读和写的权限是分开的子账号有读取权限但没有写入权限或者有写入权限但没有对该域名的授权。解决先去服务商开放平台检查密钥对应的账号权限确认该账号对该主域名拥有读写权限。如果用的是子账号需要在服务商平台上把该域名加到子账号的授权列表里。还有种不明显的原因密钥填对了但系统配置的是旧版API地址服务商升级接口后旧地址返回鉴权失败。这类问题去查系统日志里的API请求URL和返回体返回体会明确指出问题所在。5.2 申请时提示域名已占用但实际库里没有这条记录现象用户申请某个子域名系统提示「该二级域名已被占用」去数据库里查domain_record表却发现没有记录。原因根源在「唯一索引的检查时机」。如果代码是先往库里插占位记录再调API创建解析而API调用失败导致插入回滚此时占用状态是正常的临时状态。但如果是先SELECT再判断就会有一个并发窗口两个请求同时查到前缀未被占用然后都走创建流程后写的那条就会提示已占用。解决把判断逻辑改成「先插占位后调API失败回滚」或者给sub_prefix加唯一索引后直接尝试INSERT捕获Duplicate entry错误再返回占用提示。第二种方式更稳不依赖查询与写入之间的时间差并发下不会出现双写问题。同时建议把DNS解析侧的记录也纳入检查库里没有但DNS侧存在的记录同样应该提示已占用否则会出现「申请成功但解析不生效」的假象。5.3 泛解析记录把未开通的子域名全部指向同一台服务器现象主域名下配置了泛解析*记录后所有未单独创建的子域名都能访问指向同一台服务器导致未开通的域名也能打开页面。原因这是DNS层面的经典坑。泛解析记录会兜底所有未匹配的二级域名如果你在服务商处为某个主域名手动加了*或者之前开通过泛解析套餐那么即使分发系统只创建了少数几条具体记录其他未创建前缀的域名也会被泛解析兜到服务器上。解决首选方案是删除服务商侧的泛解析记录让未创建的子域名默认无解析。如果业务上确实需要泛解析那就要在分发系统里做一层「白名单校验」——所有访问请求进入应用后先查domain_record表里是否真的存在这个前缀且状态为1不存在就直接拒绝。这种做法能兜住泛解析带来的滥用风险但会多一层查询开销。我生产环境上一律禁用泛解析宁可多创建几条明确记录。5.4 到期回收后用户说域名还能打开现象后台手动执行回收脚本日志显示回收成功但用户反馈域名仍然能访问。原因这里有个容易被忽略的时延问题。回收脚本确实调了API删除DNS记录但DNS的TTL还在生效。TTL设600秒意味着递归解析器会把结果缓存10分钟10分钟内用户访问仍然能拿到旧IP。如果TTL设成了3600甚至更长回收后一个小时都能访问运营上就会产生「回收没生效」的投诉。解决两件事一起做。第一把创建记录时的TTL尽量调小比如300或600让回收生效时间控制在合理范围。第二回收成功后前台用户中心的域名状态同步标记为「已回收」让用户能明确看到状态变化。不要跟用户解释DNS缓存原理直接告诉他「解析配置已删除全球生效可能需要几分钟」用户体验好得多。如果被测出回收后两小时还能开页面优先检查TTL设置不要先怀疑脚本。5.5 后台页面打开白屏或重定向循环现象部署完成后前台正常后台打开出现白屏或者地址栏一直在index.php和login.php之间跳来跳去进不去登录页。原因这类问题大多数跟伪静态规则和runtime缓存有关。白屏常见的元凶是PHP报错被隐藏了或者入口文件里的调试模式被关闭错误信息只写进日志不显示看起来就像整个页面没有输出。重定向循环通常是伪静态规则写重复了pathinfo模式的rewrite和系统内部的路由跳转打架形成A跳B、B跳A的死循环。解决排查白屏先看runtime/log目录里的错误日志大多数情况下是某个扩展未安装或权限不足日志里写得很清楚。排查重定向循环则把伪静态规则临时注释掉访问index.php?s/admin/login试试能不能直达能的话就是rewrite规则写错。把规则精简成只对非真实文件重写一次很少解决不了。6. 二开进阶三件小事把商业版变成可复验的租赁平台6.1 支付回调与订单状态的骨架商业版源码里支付接口通常是预留的你需要在系统设置里填支付网关的appid和密钥然后核对回调地址是否正确指向系统定义的notify方法。上线前务必用测试金额走一遍完整支付流程确认支付成功后order_info里的pay_status被置为1、expire_time被正确写入这一步直接决定后续续费逻辑能不能跑通。6.2 给用户一个可查的状态页域名租赁业务里用户最关心的是「我的域名什么时候到期」。二开时在用户中心加一个状态页展示每条子域名的申请时间、到期时间、解析目标值、当前状态再放一个「一键续费」按钮。这个页面不复杂但它能把后台的到期数据透明化减少用户来问客服的频次也降低到期纠纷。6.3 用一条自查脚本把全链路验收变成习惯上线交付前我习惯写一个自查脚本把「申请-解析-回收」全链路走一遍确认系统真正可用而不是表面配置完成。脚本直接用命令行PHP跑# 创建一条测试子域名记录返回的id和解析值 php think test:apply --prefixchecktest --target1.2.3.4 # 查询该记录是否真实存在调API php think test:query --prefixchecktest # 手动触发到期回收逻辑回收后确认DNS侧已删除 php think test:recycle --prefixchecktest三条命令依次执行完再回到DNS服务商控制台刷新一下确认记录确实删除这套系统才算验收通过。从那以后我每次部署完这套系统都会强制走一遍这个check流程顺手把返回的记录id和解析值对一遍不做这步就总觉得心里没底。这套流程也帮我挡掉过好几次配置遗漏希望也能帮到你少走我当年连文档都没翻完就盲目上线的弯路。本文还有配套的精品资源点击获取