尧图网络科技YAOTU DIGITAL 获取报价
获取报价
首页 / 资讯中心 / 文章详情

云建站自动建站系统源码:代理续费与分润回调实战解析

发布时间:2026/9/29 18:57:45

资讯中心
01
ARTICLE

云建站自动建站系统源码:代理续费与分润回调实战解析

云建站自动建站系统源码:代理续费与分润回调实战解析
简介这是一套基于JSP开发的云建站自动建站系统源码面向建站服务商、代理及希望低成本开展网站业务的个人/团队解决传统建站成本高、效率低的问题。系统支持在线开通网站、自动分配/绑定域名、可视化编辑并内置成熟云端模板库一键导入即可快速上线可实现平均每个网站服务器成本仅几毛钱。资源包共1882个文件大小约137.43MB以JSP页面、Java class文件、jar包为核心逻辑配以HTML/JS/CSS前端界面和PNG/JPG/GIF等图片素材整体结构完整便于二次部署与业务扩展。目前已有65人学习下载。压缩包内包含完整Tomcat运行环境相关配置、批处理脚本及数据库/安全证书文件适合直接搭建后测试运营。无论是用于快速建站变现还是学习多租户建站系统的架构设计都能获得一套可落地的成熟业务闭环。1. 云建站自动建站系统源码先搞清它卖的是「工具」还是「生意」拿到一套自称云建站自动建站系统源码的东西里面带代理和各种续费功能还有云端模版一键极速建站很多人的第一反应是「我可以用它给别人做网站了」。这么想没错但只对了一半。这套系统真正的价值不在「自动建站」那一下而在「代理 续费」这条链路——自动建站是获客手段代理帮你把建站能力批量卖出去续费才是持续进账的闸门。适合谁一类是接企业建站、想从一次性报价转成按年订阅的服务商另一类是手里有客户资源、想搭一套分销体系的站长。这篇就按「是什么 → 怎么做 → 坑在哪」的顺序把这套系统从目录结构讲到分润回调。2. 拆开看核心模块自动建站、代理续费、云端模板各自要解决什么这类源码一套下来通常由三块拼成自动建站引擎、代理分销与续费系统、云端模板库。三块耦合很深但职责必须分清楚否则后面加功能时到处打补丁。2.1 自动建站不是「做网站」是「复制并装配」自动建站的本质不是从零生成 HTML而是「模板复制 占位符替换 配置落库」。用户选一个模板、填一个域名系统把模板目录整体复制一份到站点目录再把模板里的{{site_name}}、{{contact_phone}}这类变量替换成用户提交的内容最后往数据库里插一条站点记录。这个模型决定了系统性能瓶颈不在 PHP 执行而在文件 IO。模板包哪怕只有 5 MB用户同时点建站时磁盘复制就是最现实的考验。所以模板包的设计要「小而完整」页面骨架、样式、图片分离大图走云端不进模板包。常见做法是用一个manifest.json描述模板元信息{ name: demo-corp, version: 1.0.0, entry: index.html, variables: [site_name, contact_phone, address], thumb: thumb.png, tags: [企业, 响应式] }variables数组就是可替换的占位符白名单。替换时只处理这个名单里的变量比无脑全局替换安全得多这个点后面避坑章节还会展开。2.2 代理与续费为什么这两个功能比建站本身值钱自动建站是一次性交付无论卖 99 还是 999钱收完就结束了。但「代理 续费」把一次性生意变成了订阅制代理商帮你拉客户客户按年续费平台和代理商按比例分成。这套机制里三个角色各取所需角色核心诉求系统提供的功能平台主扩大客户量、获得稳定续费现金流代理层级管理、分润比例配置、续费订单处理代理商低门槛转售建站能力、赚差价独立后台、专属推广链接、佣金明细终端客户快速有个网站、续费省心一键建站、到期提醒、在线续费实现层面用户表要留出parent_id字段标记谁发展的再留一个agent_level决定分成比例。续费不只是「订单支付成功」它的关键动作是「把站点的expire_at往后推」。这套逻辑必须在服务端集中处理不能散落在各个控制器里否则审计分润时会对不上账。2.3 云端模板模板放本地还是对象存储「云端模版一键极速建站」里的「云端」对用户来说是概念对开发者来说是部署位置。模板可以放本地磁盘也可以放对象存储取决于模板总量和更新频率维度本地目录对象存储读取速度快文件系统直接读略慢要走网络请求扩展性单机上限多机部署要同步天然分布式更新成本rsync 覆盖即可上传新包、刷新 CDN适用规模模板少于 100 套、单机部署模板量大、多节点、有更新推送需求起步阶段我一般建议本地目录把模板放在data/templates/template_id/下路径里带模板 ID 而不是模板名避免改名时路径失效。等站点量上来、需要多机部署时再迁对象存储业务层只保留一个getTemplatePackage($templateId)的接口切换存储层不影响建站主流程。2.4 技术选型为什么这类源码多是 PHP MySQL市面上流通的「源码建站」系统绝大多数是 PHP MySQL 组合。不是因为 PHP 最强而是它是部署门槛最低的方案买了虚拟主机就能跑装个宝塔面板就能上 production。对卖源码的人来说交付成本低对买家来说跟单成本低。如果你的目标是长期运营而不是转手卖源码用 Python/Java 也能做但要做好心理准备你的客户代理商大多只会用宝塔面板你交付的运行环境越接近「面板可运维」售后问题越少。建议在 config 里把数据库连接、站点根目录、模板目录全部集中到一份配置文件并且兼容通过环境变量覆盖这样源码交付到不同人手里改一行就能跑。3. 本地跑通最小系统目录规划、建库脚本与自动建站的主流程理解源码最快的方式是在本地跑一个最小闭环建库 → 填模板 → 调用建站接口 → 访问生成的站点。下面这套是我拆过几套类似源码后的通用落地路径不依赖特定框架。3.1 目录规划把「平台」「站点」「模板」三层分开最常见的翻车是「所有站点文件混在代码目录里」导致升级源码时把客户站点覆盖掉。正确做法是把平台代码、生成的站点、模板库存放在三个互不干扰的根目录cloudsite/ ├── app/ # 平台代码 │ ├── controllers/ │ ├── models/ │ └── services/ ├── config/ # 全局配置 │ └── config.php ├── data/ │ ├── sites/ # 自动生成的客户站点根目录 │ │ └── demo.com/ # 每个站点一个文件夹 │ └── templates/ # 云端模板包 │ └── demo-corp/ │ ├── manifest.json │ └── files/ ├── storage/ # 日志、临时文件、缓存 └── public/ # Web 入口 └── index.phpdata/sites和data/templates都要在配置里显式指出来并且保证 Web 服务只把public/作为站点根目录。客户生成的站点虽然也在磁盘上但绝不允许通过平台域名直接访问而是通过「绑定域名 伪静态」路由到对应目录。这个隔离是安全底线后面避坑章节会讲 Session 串号时再提一次。3.2 建库脚本最少四张表把站点、订单、分润分成独立实体很多源码把订单和分润揉在一张表里短期能跑代理一多就乱。最小闭环需要四张表用户表含代理字段、站点表、订单表、分润表。站点表是核心CREATE TABLE station ( id int(11) unsigned NOT NULL AUTO_INCREMENT, domain varchar(191) NOT NULL COMMENT 客户绑定的域名, template_id int(11) NOT NULL COMMENT 使用的模板ID, status tinyint(1) NOT NULL DEFAULT 0 COMMENT 0试用 1正常 2到期锁定, expire_at int(11) NOT NULL DEFAULT 0 COMMENT 到期时间戳0永久, owner_id int(11) NOT NULL COMMENT 站点所属用户ID, created_at int(11) NOT NULL DEFAULT 0, PRIMARY KEY (id), KEY idx_owner (owner_id), KEY idx_expire (expire_at) ) ENGINEInnoDB DEFAULT CHARSETutf8mb4;status和expire_at是两条独立控制线status1只代表「未被锁定」真正决定能不能访问的是expire_at是否已过。用「状态 时间戳」双字段而不是只靠状态是为了让续费逻辑更干净——续费只是把expire_at往后推不需要额外改状态。用户表在基础注册字段外必须加代理相关字段和订单表外键ALTER TABLE user ADD COLUMN parent_id int(11) NOT NULL DEFAULT 0 COMMENT 上级代理ID, ADD COLUMN agent_level tinyint(1) NOT NULL DEFAULT 0 COMMENT 代理等级0普通用户, CREATE TABLE order ( id int(11) unsigned NOT NULL AUTO_INCREMENT, order_no varchar(32) NOT NULL COMMENT 业务订单号, trade_no varchar(64) NOT NULL DEFAULT COMMENT 支付平台流水号, station_id int(11) NOT NULL, months tinyint(1) NOT NULL DEFAULT 12 COMMENT 续费月数, amount decimal(10,2) NOT NULL, agent_id int(11) NOT NULL DEFAULT 0 COMMENT 归属代理, status tinyint(1) NOT NULL DEFAULT 0 COMMENT 0待支付 1已支付, PRIMARY KEY (id), UNIQUE KEY idx_order_no (order_no), KEY idx_agent (agent_id) ) ENGINEInnoDB DEFAULT CHARSETutf8mb4;订单表里冗余了agent_id这是有意为之。分润结算以订单快照为准不实时去查「这个站点属于谁」因为代理关系可能调整历史订单按下单时的代理算账才对得上。3.3 自动建站主流程一个 createSite() 的骨架整个系统最核心的函数就一个叫做createSite()。它把「选模板 → 复制文件 → 替换变量 → 发布目录 → 落库」串成一条原子链?php function createSite(int $userId, string $domain, int $templateId): int { $template getTemplate($templateId); if (!$template || !is_file($template[package])) { throw new RuntimeException(模板不存在或包文件缺失); } $siteRoot rtrim(SITE_ROOT, /) . / . $domain; if (is_dir($siteRoot)) { throw new RuntimeException(该域名目录已存在禁止覆盖); } // 先解压到临时目录避免半成品站点被访问 $tmpDir $siteRoot . .tmp; if (!copyTemplatePackage($template[package], $tmpDir)) { throw new RuntimeException(模板复制失败请检查磁盘空间); } // 只替换 manifest 白名单里的变量 renderTemplateVars($tmpDir, [ site_name $domain, site_year date(Y), ]); // 目录发布采用原子 rename if (!rename($tmpDir, $siteRoot)) { throw new RuntimeException(站点目录发布失败请检查目录权限); } $stationId insertStation($userId, $domain, $templateId); initSiteConfig($siteRoot, $stationId); return $stationId; }这段代码里三个细节值得说。第一先复制到.tmp再rename是为了避免建站中途失败时留下一个能访问但缺文件的站点rename在同一文件系统下是原子操作要么旧目录要么新目录不会出现「半个新站点」。第二模板复制和变量替换分离复制失败时不会产生脏数据。第三整个函数用异常而不是返回false因为调用方需要区分「模板不存在」「磁盘不足」「目录已存在」三种失败原因统一false会让排查变得靠猜。配置参数集中在config/config.php?php return [ db [ host getenv(DB_HOST) ?: 127.0.0.1, port 3306, name getenv(DB_NAME) ?: cloudsite, user getenv(DB_USER) ?: root, pass getenv(DB_PASS) ?: , ], site_root dirname(__DIR__) . /data/sites, template_root dirname(__DIR__) . /data/templates, ];用getenv()覆盖默认值是为了让源码在本地、测试机、生产机能用同一份代码跑不需要每换一台机器就改一遍文件。3.4 跑通后怎么验证访问一个占位站点建库、填好配置后从后台手动触发一次建站然后验证三件事目录是否生成、数据库是否有记录、站点是否可访问。curl -sI http://127.0.0.1:8080/data/sites/demo.com/index.html正常情况下应返回200 OK并且Content-Type是text/html。如果返回 403多半是目录权限问题如果 404检查public/根目录和伪静态规则。这里我习惯再补一刀find /path/to/sites/demo.com -type f | wc -l确认文件数量与模板files/里一致。数量对不上说明复制或解压环节有丢文件需要回去查manifest.json里files/目录是否被完整打包。4. 代理与续费链路分润计算、到期锁定与回调安全模板建站只是入口这套系统真正要长期运转的部分是「代理发展客户 → 客户续费 → 平台分润 → 到期锁定」这条业务链。下面按数据模型、续费订单、到期锁站、分润结算四段讲。4.1 代理与用户的数据关系绑定只做一次结算按快照用户表加了parent_id之后代理绑定就简单了注册时带上?pid代理ID注册成功后把代理 ID 写入parent_id。这里有个容易踩的坑——绑定动作必须在用户首次注册时固化之后不允许用户自行修改parent_id否则会出现「这个客户到底算谁发展」的纠纷。分润比例建议放等级配置表而不是写死在代码里代理等级分成比例说明130%普通代理只能推广250%高级代理可发展下级代理370%总代可自定义下级分成这条设计带来的问题是「分润按哪一级算」。业内常见做法是写死在订单表里下单时根据parent_id当时所属等级计算并冗余到order.agent_id和order.amount。这样即使代理后面升级、降级历史订单结算不受影响。4.2 续费订单从下单到回调的完整链路续费的核心动作是「创建待支付订单 → 用户支付 → 支付平台回调 → 延长站点到期时间」。回调处理是所有订单逻辑里最需要小心的因为支付平台会重试推送且同一笔订单可能推送多次?php public function handleNotify(string $platform, array $payload): string { if (!$this-verifySign($platform, $payload)) { $this-log(sign_fail, $payload); return fail; } $orderNo $payload[out_trade_no]; $order \OrderModel::findByNo($orderNo); // 幂等判断已处理的订单直接返回成功不重复续期 if (!$order || $order[status] ! 0) { return success; } \OrderModel::markPaid($orderNo, $payload[trade_no]); \StationModel::extendExpire($order[station_id], $order[months]); return success; }这段处理了三个关键点。第一验签失败必须返回fail让支付平台继续重试同时本地记录日志排查。第二status ! 0直接返回success保证回调重试不会把expire_at多加几个月。第三extendExpire内部实现是expire_at max(expire_at, now) months * 30 * 86400用max是因为存在「用户提前续费」的场景不能让提前续费把原有到期时间冲掉。4.3 到期锁定不续费发生的不是删除是降级到期站点绝不能删数据而是锁住入口。锁站逻辑用一个 CLI 脚本跑定时任务*/5 * * * * php /var/www/cloudsite/cli/lockExpiredStations.php /data/logs/lock.log 21脚本内部就一句核心 SQLUPDATE station SET status 2 WHERE status 1 AND expire_at 0 AND expire_at UNIX_TIMESTAMP();锁站之后前台访问时判断status2就只展示「站点已到期请联系服务商续费」页面管理后台也不能进入。这里需要注意的是「锁站」不要写成「删除站点目录」否则客户续费后数据全没了售后直接炸锅。4.4 分润结算按订单汇总不按实时关系代理后台要能看到「我发展的客户、其中多少续费了、我该拿多少钱」。结算 SQL 按订单表汇总即可SELECT agent_id, agent_level, COUNT(*) AS order_count, SUM(amount) AS total_amount, SUM(amount * rate / 100) AS commission FROM order INNER JOIN user ON order.agent_id user.id WHERE order.status 1 AND order.paid_at BETWEEN :start AND :end GROUP BY agent_id, agent_level;注意SUM(amount * rate / 100)里的rate必须来自下单时的代理等级而不是当前等级。正确做法是在订单表里冗余一个agent_rate字段下单时把比例写死。否则代理等级一调整历史结算就会偏离客户下单时的约定这是代理渠道最敏感的信任问题。5. 避坑源码建站最容易翻车的 5 个现场以下五条都是我拆这类系统时见过的真实事故逐条按「现象 → 原因 → 解决」记录建议收藏。5.1 站点一多所有子站路由全部 404现象本地单站跑得好好的把源码部署到生产客户绑定的子域名访问时全部 404平台主站却正常。原因Nginx/Apache 的伪静态规则只覆盖了public/下的主站子站目录在data/sites/下没有对应的 rewrite 规则。更隐蔽的是PHP 运行在public/之外子站目录里的入口文件根本没被 Web 服务识别。解决把子站访问统一收敛到一个入口。Nginx 下最常见的配置是「域名匹配后指向public/site.php由它按域名解析站点目录」server { listen 80; server_name *.client.example.com; root /var/www/cloudsite/public; location / { if (!-e $request_filename) { rewrite ^/(.*)$ /site.php?path$1 last; } } }这里site.php只做一件事从 HTTP Host 头解析域名查station表找到站点根目录再渲染对应站点页面。不要为每个子站在 Nginx 里单独写一个server块那会让运维变成体力活。5.2 云端模版上传解压后建站失败函数被禁用了现象模板包上传成功但点击「极速建站」后一直转圈日志里出现「Class ZipArchive not found」。原因这套系统的模板包是 zip 格式解压依赖ZipArchive扩展很多面板为了「安全」默认禁用或未安装或者把proc_open、exec全禁了模板解压时静默失败。解决先确认扩展再谈解压。php -m | grep zip没有输出就安装扩展apt install php-zip或宝塔面板里直接装fileinfo、zip扩展。另外上传时注意upload_max_filesize和post_max_size模板包动辄几十 MB默认 2 MB 的上传限制会让「一键上传」在第一步就失败。建议在后台显式显示这两个值而不是让用户去猜。5.3 续费回调被伪造有用户「免费」给自己续了一年现象运营发现某站点到期时间异常延长但支付后台没有对应订单。原因回调接口没有验签或者验签逻辑只判断了「参数存在」没判断「签名合法」。攻击者直接拿着out_trade_no和trade_no请求回调地址系统就把订单标记为已支付并续期了。解决回调入口第一步必须验签验签失败直接fail。使用支付平台官方 SDK 的verify()方法不要自己拼签名串同时订单状态幂等判断不能少。我见过最离谱的写法是回调里只查order_no存在就续费连金额都不比对——一定要校验「回调金额 订单金额」金额对不上的一律拒绝。5.4 多站点共用 SessionA 站用户登录后跳到了 B 站现象多个客户的子站都建在同一套平台上客户 A 登录后刷新一下跳到了客户 B 的站点且会话状态混乱。原因所有子站共享同一个 PHP Session 存储目录会话 ID 也没做站点隔离。同一个浏览器访问 A、B 两个子站时PHP 默认用同一个PHPSESSID串号就成了必然。解决Session 需要按站点维度隔离。最简单的做法是在site.php里根据域名设置独立的 session 名称?php $host $_SERVER[HTTP_HOST]; $site getSiteByDomain($host); session_name(SITE_ . $site[id]); session_start();这样不同站点的会话 ID 天然不同互不干扰。如果子站是纯静态页面压根别开 Session只有子站带会员登录时才需要这套隔离。5.5 模板变量替换把用户内容也替换了现象客户在站点后台填写了公司介绍内容里含{{site_name}}字样保存后这个字样被替换成了域名页面内容出现「脏数据」。原因模板渲染时用了全局str_replace对所有可能包含变量的内容一刀切替换。而用户提交的正文也是「内容」同样会被扫一遍。解决采用白名单定界符 渲染顺序控制。模板里的变量写成{{site_name}}但在渲染用户内容时先把用户提交的所有{{转义成{{对应的 HTML 实体再执行模板变量替换或者干脆模板引擎只对模板文件做渲染不碰数据库里用户内容。后者更干净实现上就是「渲染发生在模板文件层面而不是输出层面」。6. 把「一键极速建站」提速模板打包、解压落地与缓存预热前面把系统跑通了最后聊怎么把「极速」两个字做实。自动建站如果耗时超过 10 秒用户感知就很差。提速的关键不在 PHP 代码而在模板包管理和文件落地策略。模板打包时严格控制包体积cd /data/templates/demo-corp zip -r ../demo-corp.zip manifest.json files/ thumb.png打包前先把files/里的图片压缩一遍大图转 WebP、去掉未用的样式和脚本一个 20 MB 的模板压到 5 MB 以内解压时间能差出三四倍。注意zip -r会包含隐藏文件模板里有.DS_Store或.git目录时要先排除掉否则会在每次建站时复制一堆垃圾文件。解压落地时坚持「先临时目录、后原子改名」的原则上一章代码里已经写了。这里补一个细节改名完成后对模板目录做一次缓存预热。预热有两个层面一是文件层面?php function warmupTemplateCache(string $siteDir): void { $files new RecursiveIteratorIterator( new RecursiveDirectoryIterator($siteDir) ); foreach ($files as $file) { if ($file-isFile() $file-getExtension() php) { opcache_compile_file($file-getPathname()); } clearstatcache(true, $file-getPathname()); } }这段代码在站点发布成功后跑一次把站点内的 PHP 文件提前编译进 OPcache用户第一次访问时就不用现场编译首屏速度能快一截。对静态站点预热的意义在于把目录结构、文件统计信息刷进系统缓存避免第一次请求时现遍历目录。最后建议做一个「一键自检」的 CLI 脚本每套模板上线前跑一遍检查项方法期望结果模板包完整性unzip -t package.zip无 error占位符覆盖检查manifest.json的variables是否齐全与模板文件内变量一致建站耗时记录createSite()耗时本地环境不超过 3 秒站点可访问curl 站点域名返回 200续费链路模拟支付回调到期时间正确延长我自己的习惯是每套模板上线前都必须跑完这五项才开放给代理使用宁可多花十分钟自检也别等客户踩到坑再来售后。这套系统说到底技术门槛不高真正考验的是把「自动建站 → 代理分销 → 续费锁定」这条链路做得没有漏洞每一个环节少踩一个坑运营时就多一分从容。希望帮到你。本文还有配套的精品资源点击获取
02
RELATED NEWS

相关资讯

更多网站建设与数字化升级内容

03
WHY YAOTU

想打造同款高转化官网?

懂行业、懂生意,从建站到增长一站式陪跑

◈

场景化定制

不做模板站,围绕你的业务场景量身设计,小众不撞款。

◐

营销型架构

以转化目标组织内容与路径,让官网真正带来询盘。

▲

全周期服务

设计、开发、运营、运维一体,上线只是开始。

免费获取你的建站方案

留下需求,专属顾问 24 小时内为你输出方案建议。