简介:一套基于ThinkPHP全新开发的视频打赏平台源码,定位为带盒子试看、图片视频列表与个人免签支付的完整运营方案,面向需要搭建付费视频、打赏变现及代理商体系的站长或个人开发者。系统全开源、无加密、无授权限制,修复了市面流传版本中的后门与漏洞,并新增四种支付接口(公众号支付、U支付个人、云支付、摩登支付),兼顾支付灵活性与域名防封能力。
资源包共1775个文件,压缩包大小约32.82MB。文件类型以450个php源码文件为主,涵盖后端业务逻辑与接口;321个png、141个jpg、130个gif构成前端界面与演示素材;315个js、129个css、159个html负责页面交互与布局;另有13个ttf字体、8个xml配置、3个sql数据库脚本等,结构完整,便于直接部署或二次开发。
目前已有175人学习下载,适合有PHP基础、希望快速上线打赏平台并做定制扩展的开发者。相比加密受限版本,该源码在功能上加入代理商后端批量发布、私有片库一键删除、视频盒子自动获取短链接、域名更换后短链接自动复活等实用特性,是搭建稳定可持续运营平台的可靠选择。
1. 试看+打赏+个人免签支付:这套二开源码到底解决了什么
做内容付费和短视频变现,最卡脖子的往往不是视频上传和展示,而是支付。平台抽成高、审核慢,想自己搭一套带试看、解锁、打赏的闭环,又要处理支付回调、APP打包一堆杂事。这套「最新修复版二开带试看视频打赏平台源码」就是给这个需求准备的基础盘:前端做视频试看、付费解锁、礼物打赏,后台管会员、订单和提现,源码里附带打包盒子,可以把H5前端直接套成安卓APP,同时整合了个人免签支付的接入教程,让没有企业商户号的个人开发者也能先把整条链路跑通。适合有PHP基础、想快速搭一套可演示付费视频产品的人,也适合接私单时不想从零写支付和播放器的开发者。这类项目门槛不高,坑全在细节,下面按我实际二开这类系统的流程讲。
2. 先看清系统骨架:视频打赏平台的五段业务闭环与二开价值
2.1 从试看到打赏:平台的业务闭环怎么走
这类源码本质上是一套内容变现系统。用户进来先看免费的试看片段,产生“这个视频值不值得付费”的判断;要解锁完整版,要么单次付费,要么先充值成余额再消费;看完觉得值,可以再送礼物打赏,金额进入作者账号;作者攒到一定金额申请提现,管理员在后台审核打款。闭环里一共有四方角色:游客或会员、内容作者、平台运营、支付通道。
我为什么先说闭环?因为二开源码最容易烂的地方,就是“页面有,路不通”——前端有试看按钮,后台却找不到设置试看时长的入口;打赏能弹窗,订单表里却没有记录。拿到源码第一件事,不是急着换logo,而是把这条资金链路沿着数据表捋一遍:从试看记录、充值订单、打赏流水到提现记录,每个节点有没有对应的表和后台页面。这套流程捋顺了,后面接支付、打包盒子才不会返工。
2.2 源码目录与数据库结构:二开前先认路
这类二开源码大多基于ThinkPHP 5或FastAdmin这类PHP后台框架搭建,前端部分是H5加播放器组织起来的。典型目录结构是这样:
├── application/ # TP5的应用目录 │ ├── admin/ # 管理后台控制器 │ ├── api/ # H5/APP端接口 │ └── index/ # 前台页面控制器 ├── public/ │ ├── uploads/ # 视频与图片上传目录 │ └── index.php # 入口文件 ├── config/ │ └── database.php # 数据库连接配置 └── install/ # 安装向导(有些版本是手动导入SQL)拿到源码先做三件事。第一,打开config/database.php,看数据库配置项是否齐全、是否预留了后台入口地址配置;第二,看public/uploads下有没有默认的测试视频文件,这决定你本地能不能直接看到试看效果;第三,确认install目录是否存在——没有安装向导的版本需要自己建库导SQL,修复版一般会把SQL文件和默认数据一起准备好,省掉最麻烦的初始化环节。
视频和订单是这条链路的两条主线,核心表一般绕不开下面这两张:
CREATE TABLE `video` ( `id` int(11) NOT NULL AUTO_INCREMENT, `title` varchar(100) NOT NULL COMMENT '视频标题', `cover` varchar(255) DEFAULT NULL COMMENT '封面图', `url` varchar(500) NOT NULL COMMENT '完整视频地址', `try_url` varchar(500) DEFAULT NULL COMMENT '试看视频地址', `try_time` int(11) DEFAULT 0 COMMENT '试看时长,单位秒', `price` decimal(10,2) DEFAULT 0.00 COMMENT '解锁价格', `status` tinyint(1) DEFAULT 1 COMMENT '1上架 0下架', PRIMARY KEY (`id`) ) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COMMENT='视频表'; CREATE TABLE `order` ( `id` int(11) NOT NULL AUTO_INCREMENT, `order_no` varchar(32) NOT NULL COMMENT '订单号', `user_id` int(11) NOT NULL COMMENT '用户ID', `video_id` int(11) NOT NULL COMMENT '视频ID', `amount` decimal(10,2) NOT NULL COMMENT '实付金额', `pay_type` varchar(10) DEFAULT 'wx' COMMENT 'wx/alipay', `status` tinyint(1) DEFAULT 0 COMMENT '0未支付 1已支付 2已退款', PRIMARY KEY (`id`), UNIQUE KEY `order_no` (`order_no`) ) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COMMENT='订单表';这两张表是打通“试看到付费解锁”的最小集合,顺序是:用户发起支付时先生成order记录,状态为0;支付回调确认后把状态改成1;用户再请求播放完整视频时,接口查order表里有没有对应video_id且status=1的记录。很多烂尾源码的问题就出在“发起了订单却没写表”,或者“写了表但播放接口根本没查表”,修复版一般会把这条链路补齐。
2.3 修复版二开改了什么:原版与常见烂尾源码的差距
“二开”不是玄学,它解决的问题都写在代码里。以我做这类项目的经验,一套被反复转卖的源码,最常烂在五个地方:支付回调接口是写死的假回调、管理后台和前端功能对不上、数据库没带默认配置导致安装即报错、调试模式没关到处是报错页面、以及顺手留了后门。所谓修复版,就是有人把这五类问题处理过之后的产物。
其中支付回调是最关键的一处。原版源码为了演示,经常把“支付成功”直接写死在代码里,点击支付就跳成功页,订单表update语句是假的;修复版会补上真实的回调接收逻辑,对接免签或官方支付时,改的是回调地址而不是代码逻辑。另外,修复版一般会把PHP版本兼容性调好:TP5在PHP 7.0到7.4下跑得很顺,很多老源码在PHP 8下直接报class not found,二开修复的核心工作之一就是把这个兼容问题处理掉。
3. 个人免签支付接入:把监听端通知变成订单入账的回调
3.1 免签支付为什么能免签:短信监听、通知读取与码枪监听三条路
个人免签支付解决的是“没有企业商户号怎么收款”的问题。正常支付渠道要企业资质、要审核、要签约;个人场景下,微信和支付宝的收款码是现成的,但平台不会给你回调接口告诉你“谁付了多少钱”。免签支付做的事,就是在安卓设备上跑一个监听程序,盯住收款通知,把到账信息转成标准格式推给你的服务器。
常见有三条路。一是短信监听,设备上装了收款用的手机卡,监听应用解析短信里的到账内容,这种方式延迟高、解析容易出错;二是通知栏监听,利用安卓系统通知机制读取支付APP的推送通知,是目前个人免签的主流方案,准确率相对高;三是扫码枪或收款音箱方案,硬件识别收款码对应的金额和备注,适合固定摊位场景,不适合线上用户自助付款。无论哪条路,落到服务器上都是一个标准HTTP POST回调,你的系统只需要把这个回调接住。
3.2 回调接口怎么接:以“通知监听型”免签为例
不管监听端是哪一种,逻辑都一样:监听端抓到“用户向您付款1元”的通知后,组装成订单号、金额、支付平台、备注、签名这几个字段,POST到你配置的回调URL上。你的系统只需要写好这个URL对应的控制器方法,再把监听端配置里的回调地址指过来。
// application/api/controller/Notify.php public function pay() { // 免签监听端POST过来的参数 $orderNo = input('post.order_no'); // 你系统里的订单号 $amount = input('post.amount'); // 实际到账金额 $platform = input('post.platform'); // wx 或 alipay $sign = input('post.sign'); // 签名 // 1. 验签:监听端和服务器共用同一个密钥 $localSign = md5($orderNo . $amount . $platform . $this->secret); if ($sign !== $localSign) { return json(['code' => 0, 'msg' => 'sign error']); } // 2. 查订单:必须存在且状态为未支付 $order = db('order')->where('order_no', $orderNo)->find(); if (!$order || $order['status'] != 0) { return json(['code' => 0, 'msg' => 'order not found or paid']); } // 3. 金额核对:以数据库订单金额为准,不信回调传参 if (abs($order['amount'] - $amount) > 0.01) { return json(['code' => 0, 'msg' => 'amount mismatch']); } // 4. 入账:事务保证订单状态、余额、流水三表一致 Db::startTrans(); try { db('order')->where('order_no', $orderNo) ->update(['status' => 1, 'pay_type' => $platform, 'pay_time' => time()]); db('user')->where('id', $order['user_id'])->setInc('balance', $order['amount']); db('balance_log')->insert([ 'user_id' => $order['user_id'], 'amount' => $order['amount'], 'type' => 'recharge', 'remark' => $orderNo, 'create_time' => time(), ]); Db::commit(); return json(['code' => 1, 'msg' => 'success']); } catch (\Exception $e) { Db::rollback(); return json(['code' => 0, 'msg' => $e->getMessage()]); } }逻辑说明与参数要点:验签放在最前面,共用密钥用MD5拼接生成,保证监听端POST过来的数据没被伪造;查订单时把“未支付”作为条件,防止同一笔订单被重复入账;金额核对用abs差值不大于0.01元,因为浮点比较不能直接判等;事务保证“订单状态、余额、流水”三张表要么全成功要么全失败。返回值格式要按监听端文档来——有的监听端要字符串success,有的要JSON里的code=1,这里返回JSON,如果你用的监听端不认,就改成它认的形式,否则会出现回调已推送、订单没更新的诡异现象。
3.3 验签与订单入账:防止伪造支付通知的两个硬要求
上面代码里有三个硬要求,缺一个就等着丢单或被人刷。第一是验签,密钥不能写在前端JS里,至少32位随机字符串,监听端和服务端各存一份;第二是金额比对必须用数据库里的订单金额,而不是信任回调传过来的amount——有刷子专门改回调参数,把自己订单的金额改成0.01元来骗入账;第三是幂等,即使用户重复支付,同一订单号只能入账一次,order表status字段的条件就能挡住。
很多人接完回调只看“能支付成功”就收工,其实还应该测两个反例:一是把同一个回调POST两次,第二次必须返回订单已支付的错误,而不是再入一笔账;二是修改任意一个参数字段重新签名,服务端必须拒绝。这两个反例测过了,回调才算真正接完。
3.4 合规底线:个人免签支付的适用范围与风险
我把话说透。个人免签支付的本质是绕过支付机构的官方回调,用监听通知的方式模拟“支付成功”。技术上有延迟、有丢单,账号也随时可能被风控冻结。它适合做演示、私下技术测试、极小规模的个人收款,不适合正式商用;一旦涉及大额资金、资金池、二清嫌疑,风险和账号损失都是实打实的。正式上线的业务,老老实实接官方支付的企业商户号,个人免签只当作把闭环跑通的手段。源码里带免签,是为了让你在没有企业资质的时候也能把开发环境转起来,不是让你拿着它去生产环境刷流水。
4. 用盒子把H5源码套成安卓APP:四个必调参数与页面通信
4.1 盒子不是框架,是WebView壳
标题里说的“带盒子”,指的是源码附带的APP打包壳工程。它的原理很简单:把整套H5前端当成一个网页,用安卓的WebView控件加载进来,外面套上原生壳,做成能装到手机上的APK。不是把PHP代码编译成原生应用,前端逻辑、视频播放、支付页面全都跑在网页里,壳只负责加载URL和提供少数原生能力。
明白这一点,二开思路就清晰了:改功能全在前端和PHP,壳的改动只在包名、入口地址、图标、签名这几处。别在壳里找视频播放逻辑,找不到的。壳和你站点之间的通信越少越好,所有业务逻辑都放网页端,壳保持“只会打开网页”的状态,出问题最好排查。
4.2 打包要改的四个参数:包名、接口域名、图标与签名
拿到打包工程,先改配置文件。不同盒子配置形式不一样,有的用Android Studio工程,有的用通用json配置,但核心字段是同一套。我习惯先改这四个:
{ "app_name": "你的应用名", "application_id": "com.yourdomain.videoplatform", "launch_url": "https://yourdomain.com/index/index", "icon": "./res/icon.png", "http_permission": true, "version_code": 100 }参数说明:application_id是包名,安卓应用的唯一标识,上线前必须改成自己的域名反写,不能用源码默认的包名,否则装新包会覆盖旧包或提示签名冲突;launch_url是APP启动后加载的H5首页,必须写全站绝对地址,带https前缀;http_permission对应安卓明文HTTP开关,只要你的站点还没上HTTPS证书,这里就必须开着,否则安卓9以上版本默认禁止加载明文HTTP页面,打包出来的APP一打开就是白屏;icon换成自己的图标,否则应用商店审核会卡在图标和包名不一致。
4.3 网页与壳的通信:登录态与版本更新走JS桥
壳和网页之间有一个JS桥对象,网页里通过window上挂载的原生方法调用壳的能力。最常见的两个用途是:读取壳端保存的登录态,以及检查版本更新。类似这样:
<script> // 网页端调用壳暴露的原生方法,获取设备端保存的token function getLoginToken() { if (window.AppBridge && window.AppBridge.getToken) { return AppBridge.getToken(); } return ''; } // 登录成功后,把token写回壳端保存,下次冷启动免登录 function saveLoginToken(token) { if (window.AppBridge && window.AppBridge.saveToken) { AppBridge.saveToken(token); } } </script>逻辑说明:网页在WebView里运行,单独用localStorage存登录态没问题;但需要跨冷启动保存、或APP要记住用户时,走壳的token存储更可靠。壳端通过原生接口把getToken、saveToken这些方法暴露给window.AppBridge,网页直接调用即可。二开时要注意:如果源码前端原本走的是微信授权登录,而壳里没有集成对应微信SDK,网页里的微信登录会没有反应,需要改成账号密码登录或短信登录。
5. 上线前必看的避坑清单:支付、播放、打包三类高频翻车点
5.1 支付成功后订单不落库
现象:用户扫码付款,监听端显示已推送,后台订单还是未支付。
原因:最常见是Nginx伪静态规则把回调URL重写掉了,POST请求打到了不存在的路由上,返回404;其次是回调接口返回格式和监听端预期不一致,监听端重试几次后放弃推送;还有一种情况是服务器防火墙拦截了监听端的IP段。
解决:先看监听端日志里回调URL的请求状态码,再手动用curl模拟POST一条测试数据。我一般这样测:
curl -X POST https://yourdomain.com/api/notify/pay \ -d "order_no=TEST202501010001&amount=1.00&platform=wx&sign=you_md5_sign"看返回结果是不是你代码里定义的成功格式。如果curl通、监听端不通,问题就在监听端的推送地址配置或IP白名单上,把回调地址换成公网可访问的域名,别用内网IP。
5.2 试看能播,支付完成后播放页还是白屏
现象:游客访问试看片段正常,支付成功解锁后,播放页面依然提示无权限或直接不开播。
原因:播放接口的鉴权逻辑没把“已支付订单”算进去。常见烂尾是播放接口只判断了is_vip字段,但免签支付入账的是余额和订单状态,两套逻辑没打通。也就是说,支付回调把订单标记成已支付了,但播放器鉴权根本不查订单表。
解决:在播放接口增加判断:视频不是会员专属但需要付费解锁时,查询order表是否存在该用户、该视频且status=1的记录;如果是余额支付,还要确认余额是否已扣减。改完以后,用两个账号分别走“单次付款解锁”和“充值余额后解锁”两条路径,各测一遍。
5.3 盒子打包后首页加载慢或白屏
现象:浏览器访问站点正常,打包成APK后首页白屏或一直转圈。
原因:安卓9开始默认禁止明文HTTP流量,站点没上HTTPS时网页被系统拦掉;或者网页里用了localStorage,但WebView默认没开DOM Storage;还有一种情况是壳的launch_url配成了相对路径或localhost。
解决:把launch_url改成完整https地址;如果暂时没有证书,把盒子的http_permission开关打开;同时在WebView初始化配置里开启DOM Storage、允许JavaScript。改完重新打包,先别做任何功能测试,只验证首页能否打开、视频能否播放。
5.4 修复版源码安装后后台直接报错
现象:导完SQL打开后台,报“Class not found”或数据库连接错误,页面一片红。
原因:PHP版本太高,TP5在PHP 8下会触发大量兼容问题;PHP扩展缺了curl、fileinfo或openssl;SQL文件没导全,默认配置表缺失,后台找不到站点配置。
解决:先把PHP切到7.4版本,这是TP5类源码最省心的环境;再确认php -m里curl、fileinfo、openssl都在;最后重新导一遍SQL,注意.sql文件本身是utf8mb4编码,用源码配套的数据库账号而不是root远程连。报错看一眼log目录下的日志,别直接问卖源码的人,大多数问题日志里写得明明白白。
5.5 源码里藏着的后门与多余管理员账号
现象:上线后被陌生设备登录后台,或站点文件无故被改动。
原因:转手多轮的源码里常留后门,形式包括eval拼接代码、定时任务脚本、以及多出来的管理员账号。这不是危言耸听,是这类源码真实存在的风险。
解决:全局搜索eval(、base64_decode(、system(三个函数,逐一确认上下文;检查admin或user表里有没有你没创建过的管理员账号;删除install目录,防止安装向导被重新执行;改后台入口路径;把数据库密码、免签密钥、后台密码全部重置一轮。做完这些再谈功能上线,不然所有二开工作都是在给别人做嫁衣。
6. 从源码到线上:部署手顺、冒烟验证与最后一道安全自检
6.1 部署四步走
环境我一般用Nginx加PHP 7.4加MySQL 5.7,这套组合跑TP5类源码最省心。第一步建库导SQL,把源码里自带的.sql导入;第二步改config/database.php的地址、库名、账号、密码;第三步把Web运行目录指向public,配好伪静态;第四步登录后台,把站点地址、支付回调URL、监听端推送地址三处配置改成本机实际值。四步做完先别动任何功能,直接跑冒烟验证。
6.2 冒烟验证清单
按顺序测,不要跳步:
| 验证节点 | 操作 | 预期结果 |
|---|---|---|
| 后台登录 | 用管理员账号登录 | 能进后台,无报错 |
| 上传视频 | 上传测试视频并设置试看时长 | 前台能看到试看片段 |
| 发起支付 | 前端点击解锁 | 订单表出现status=0的记录 |
| 模拟回调 | curl POST测试回调数据 | 订单变成已支付、余额到账 |
| 解锁播放 | 用已支付账号播放完整视频 | 能正常播放 |
| 打赏提现 | 走一遍打赏和提现申请 | 状态流转正常 |
6.3 最后一道自检
上面清单跑完,我再补一次安全自检:搜索高危函数、清理多余管理员、删install目录、重置密钥。这套流程是我吃过亏才定下来的——头一回接这类源码,只顾着调支付回调,漏了源码自带的测试管理员账号,演示到一半后台多了一台陌生设备的登录记录。打那以后,接任何转手的PHP源码,第一件事永远是查后门,再谈功能。你这套“修复版二开”源码大概率已经有人替你排过一层雷,但自己按这个顺序过一遍,排掉的雷才是你的。希望帮到你。
本文还有配套的精品资源,点击获取