ARTICLE DETAIL

资讯详情

深耕网站建设、视觉设计与SEO优化的一线实战洞察。

全开源付费短剧小程序源码:从支付闭环到部署上线的完整实践指南

全开源付费短剧小程序源码:从支付闭环到部署上线的完整实践指南

简介:全开源付费小剧场短剧影视小程序源码,面向希望快速搭建短剧点播、付费观看业务的开发者和运营者。资源同时涵盖支付收益模块、影视片素材与搭建教程,可支撑学生练手、个人创业或商业运营场景。包内共2002个文件,以1144个js核心逻辑文件、307个json配置文件为主,辅以192个html页面、118个vue组件及151个md说明文档,压缩包总大小约157.55MB,整体结构清晰。已有1353人学习下载。该源码支持无限滑动、预加载、视频预览等高性能交互,并提供仿抖音壁纸效果;业务上支持付费、免费、任务解锁等自由配置,搭配会员体系、成熟代理机制以及多平台支付灵活配置,多重加密保障交易安全。搭建时上传源码、导入SQL并修改配置即可运行,配套教程可进一步降低上手门槛。

1. 全开源付费小剧场短剧小程序源码:我这个月拿它跑通了支付闭环

上个月拆了一套号称“全开源”的付费小剧场短剧影视小程序源码,前后端加支付回调加影视素材加搭建教程一整套。实话说,网上这套源码的版本很多,但大多阉割了支付模块,要么把收益逻辑藏起来,要么在后台埋了后门。这套不一样的地方在于支付收益链路是完整的——用户在小程序里看剧、充值、下单,钱能真正走到你账上,你还能查订单、做分润。对想低成本验证短剧付费模型、或者给地方号做私域流量的个人和小团队来说,这就是一套能直接用的底盘。适合谁?独立开发者、有域名的运营者、已经在做影视站想往小程序迁的人。不适合谁?完全没摸过服务器的人,下文会给你省掉一半爬坑时间。

2. 先拆工程:这套小程序源码的前后端结构与本地跑通

2.1 拿到源码先看什么目录

我拆过的影视小程序源码不少,这套的目录组织算是清晰的那一档。前端是uniapp写的,能一次编译成微信小程序、H5 和 App;后端是 PHP,接口和后台管理在一个工程里;另外带一份 MySQL 初始化脚本和一份部署文档。建议你拿到压缩包后不要直接拖进编辑器,先按文件结构理一遍,因为后面改支付、改分润都要回这里找对应文件。

前端工程里最重要的几个目录:pages存放所有页面,components是自定义组件,api目录把全部接口请求封装成了统一的请求方法,改接口域名只动一处;后端工程的application目录下按模块分控制器,public是入口目录,Nginx 伪静态要指到这里;数据库脚本一般在sql目录下,是一个.sql文件,导入即可。

2.2 前端本地跑通:HBuilderX 到微信开发者工具

前端用的是 uniapp 打包,所以本地跑通的最快路径是装 HBuilderX,把前端目录导入进去,然后选择“运行到小程序模拟器”。第一次跑的时候微信开发者工具会自动拉起并加载编译产物,前提是你在 HBuilderX 里配置过微信开发者工具的安装路径。

// manifest.json 里需要改的核心配置 { "mp-weixin": { "appid": "你的小程序AppID", "setting": { "urlCheck": false, // 本地调试不开域名校验 "es6": true, "minified": true }, "usingComponents": true } }

我一般建议先用测试号跑通流程,再去注册正式小程序换 AppID。urlCheck 设为 false 是本地调试的关键,不然请求接口会因域名没备案直接拦截。编译完成后微信开发者工具会生成一个临时预览,能看到首页分类、剧集列表和播放页,这一步只验证前端壳子通不通,接口报错是正常的,后端还没起。

2.3 后端接口本机起服务:PHP 环境与数据库导入

后端工程跑起来需要 PHP 7.2 以上和 MySQL 5.7 以上。我用的环境是 PHPStudy,省去自己配环境的时间。先把sql目录下的初始化脚本导入数据库,这个脚本里面有十几张表——用户表、剧集表、订单表、分润表、素材表都在里面。然后改application/database.php里的数据库连接配置,再配置伪静态规则,接口就能通了。

// 伪静态规则(Nginx) location / { if (!-e $request_filename) { rewrite ^(.*)$ /index.php?s=$1 last; } }

伪静态不配好,后端接口一律 404。配好之后,前端请求https://你的域名/api/user/login能返回 JSON,就说明前后端已经联通了。此时你在微信开发者工具里重新编译,小程序应该能拿到首页数据。这一步跑通后,才算把整套源码“接上了电”。逻辑上就这么简单:前端页面 → 统一接口层 → PHP 控制器 → 数据库,数据流是单向的,中间断了哪一环都出问题。

3. 支付收益模块:从下单参数到回调验签的完整链路

3.1 支付方式怎么选:微信支付原生还是易支付

这套源码里支付模块做了两种接入方式:一个是原生微信支付,需要用已认证的小程序账号去微信支付商户平台开通;另一个是易支付这种第三方聚合支付,好处是你不需要企业资质也能跑通收款,坏处是到账有手续费且资金先经过第三方。很多人第一次搭这种付费小程序会纠结选哪个,我的建议是:自己测试选易支付,正式上线且有营业执照直接上微信支付原生。

两种方式在后台的切换是一个开关,对应参数在application/extra/pay.php里。这张表对比一下选型:

对比项微信支付原生易支付第三方
资质要求营业执照 + 小程序认证邮箱注册即可
到账时效T+1 结算实时或 T+1,看服务商
手续费0.6%常见 1%~3%
回调安全性官方签名机制更稳依赖服务商实现
适合场景正式运营测试、个人起步

3.2 下单接口构造:把充值金额传给支付网关

前端拿到用户选择的价格档位后,会调api/order/create这个接口。控制器接收参数、生成订单号、写入订单表,再返回预付单信息给小程序端调起支付窗。这里最需要注意的坑是订单号不能重复、金额单位是分(整数),以及签名用的密钥必须和支付平台后台保持一致。

// application/api/controller/Order.php 中的下单核心逻辑 public function create() { $user_id = input('post.user_id'); $price_id = input('post.price_id'); // 价格档位ID,对应 vip 套餐表 $price_info = db('price')->where('id', $price_id)->find(); // 金额务必按“分”存,避免浮点误差 $order_sn = 'SP' . date('YmdHis') . mt_rand(1000, 9999); $order_data = [ 'order_sn' => $order_sn, 'user_id' => $user_id, 'goods_name' => $price_info['name'], 'total_fee' => intval($price_info['price'] * 100), 'status' => 0, 'create_at' => time() ]; db('order')->insert($order_data); // 调用支付类生成支付参数 $pay_result = \app\common\Pay::unifiedorder($order_data); return json(['code' => 1, 'data' => $pay_result]); }

下单接口有两个参数要特别留意:total_fee必须是整数分,前端传过来的是元,所以控制器里intval($price * 100)这步不能省;order_sn我习惯加一个日期前缀,方便日后对账时一眼看出哪天产生的订单。\app\common\Pay::unifiedorder()是统一支付封装,里面有微信支付和易支付的分支,各自的请求参数差异较大,但封装完成后业务层不用关心底层。

3.3 回调验签:这里写错钱就进不了账

支付完成之后,支付平台会往你的异步回调地址发一个通知。小程序端能不能显示“支付成功”不重要,后台订单状态变不变、余额加不加才是关键。回调地址在后台支付配置里填的是https://你的域名/api/pay/notify,这个控制器必须做验签,不然别人可以伪造回调把余额刷爆。

// 微信支付回调验签逻辑(核心片段) public function notify() { $data = file_get_contents('php://input'); $result = json_decode($data, true); // 1. 先校验签名 $sign = $result['sign']; unset($result['sign']); ksort($result); $stringA = urldecode(http_build_query($result)); $stringB = $stringA . '&key=' . config('pay.wechat_key'); if (md5($stringB) !== $sign) { return json(['code' => 0, 'msg' => '签名错误']); } // 2. 再验证订单号和金额是否一致 $order = db('order')->where('order_sn', $result['out_trade_no'])->find(); if (!$order || $order['total_fee'] != $result['total_fee']) { return json(['code' => 0, 'msg' => '订单异常']); } // 3. 处理重复通知:幂等更新 if ($order['status'] == 1) { return json(['code' => 1, 'msg' => 'success']); } db('order')->where('order_sn', $result['out_trade_no'])->update([ 'status' => 1, 'pay_at' => time() ]); // 这里再给用户加会员时长或余额 return json(['code' => 1, 'msg' => 'success']); }

验签这步三个细节决定成败:一、签名串拼接前必须ksort排序,按 ASCII 码从小到大排,这个顺序错了签名必挂;二、回调可能发很多次,先判断订单状态为已支付就直接返回成功,否则会造成重复加余额;三、返回给支付平台的应答必须是success字符串且状态码 200,不能返回乱七八糟的 JSON。易支付的验签方式和微信有差异,但核心逻辑一模一样:先验签,再查订单,最后幂等更新。这一串代码是这套源码里最值得细读的部分,因为后面做分润、做转介绍都要依赖订单表里的pay_at字段。

3.4 分润与结算:平台抽成和代理分润怎么配

短剧小程序常见的玩法是“平台 + 代理”模式,代理有自己的推广码,用户通过代理的码进入小程序并付费,代理拿分成。这套源码的后台里,分润比例是可以直接配置的,配置项在config/site.php里,分别有agent_rate和platform_rate两个值。

// 分润比例配置示例 'agent_rate' => 0.3, // 代理拿 30% 'platform_rate' => 0.7, // 平台拿 70% // 下单成功后自动给代理写分润记录 db('agent_income')->insert([ 'user_id' => $order['agent_id'], 'order_sn' => $order['order_sn'], 'amount' => intval($order['total_fee'] * config('site.agent_rate')), 'create_at' => time() ]);

分润记录写入的时机放在支付回调成功之后,不是下单时。因为只有回调确认了,钱才真正到账,此时生成的分润记录才不会被作废。代理提现走后台审批,这一点对个人起步来说很实用——你不用接自动打款,手动转账人工确认即可。

4. 影视片源与播放体系:素材怎么组织、播得动、防得住

4.1 剧集与素材的表结构拆解

这套源码的短剧库不是简单的一张表,而是分类、剧、集三个层级。分类表管的是“甜宠”“悬疑”“逆袭”这种栏目;剧表存的是每部剧的名称、封面、简介、价格;集表存的是每一集的视频地址、时长、排序。这样设计的好处是前端可以按栏目做聚合,后端运营可以单独给每一集设置试看/付费状态。

-- 剧集表核心字段 CREATE TABLE `video` ( `id` int(11) NOT NULL AUTO_INCREMENT, `category_id` int(11) NOT NULL COMMENT '所属分类ID', `title` varchar(255) NOT NULL COMMENT '剧名', `cover` varchar(500) DEFAULT NULL COMMENT '封面图地址', `intro` text COMMENT '简介', `price` decimal(10,2) DEFAULT '0.00' COMMENT '整剧价格', `status` tinyint(1) DEFAULT '1' COMMENT '1上架 0下架', PRIMARY KEY (`id`) ); CREATE TABLE `video_episode` ( `id` int(11) NOT NULL AUTO_INCREMENT, `video_id` int(11) NOT NULL COMMENT '所属剧ID', `episode_no` int(11) DEFAULT '1' COMMENT '第几集', `video_url` varchar(500) NOT NULL COMMENT '视频地址', `is_free` tinyint(1) DEFAULT '0' COMMENT '是否试看', PRIMARY KEY (`id`) );

前端的播放页逻辑是:先看当前用户是否已购买整剧,买过就放全集;没买就只放is_free = 1的集数,点付费集时弹出支付窗口。这套机制对应到数据库就是order表里加了一个video_id和order_type字段,下单时区分是买会员还是买单剧。

4.2 播放器接入与防盗链的平衡

源码里的播放器用的是原生video标签外包了一层自定义控制栏,没有引入第三方播放器 SDK,这样对小程序的兼容性最稳。视频地址如果直连存储服务器,会遇到一个现实问题:懂技术的人拿到视频直链可以绕过付费随便看。这个源码的做法是提供了两个可选项——放防盗链白名单(只允许你的域名和微信小程序的请求),或者走 Token 签名播放。

// 前端播放页请求播放地址(已封装 Token 校验) uni.request({ url: '/api/video/play', data: { video_id: 12, episode_no: 3 }, success(res) { // res.data.url 是带 token 的临时播放地址 this.videoUrl = res.data.url; } })

后端控制器里video/play会先校验用户是否已购买当前集,通过后生成一个带过期时间的签名 URL。签名 URL 的好处是即使被转发出去,几分钟后自动失效,比单纯依赖 Referer 白名单更抗爬。不过要注意签名过期时间别设太短,小程序的 video 组件在视频缓冲后有时会重新请求资源地址,太短会导致播一半报错。我一般设 30 分钟的expire。

4.3 批量导入素材:后台不是只能一条条加

如果你手里已经有一批短剧素材,一条条在后台添加会想骂人。这套源码的后台自带了批量导入功能,支持的格式是 CSV,列头分别是:分类名称、剧名、封面URL、简介、价格、集数、视频地址。运营同学用 Excel 整理好后另存为 CSV 上传,系统会按分类名称自动创建或匹配分类,按剧名分组创建剧与集。

# CSV 导入模板示例 分类名称,剧名,封面URL,简介,价格,集数,视频地址 逆袭,我的绝品人生,https://xxx.com/cover1.jpg,底层逆袭故事,9.9,20,https://xxx.com/ep01.mp4 逆袭,我的绝品人生,https://xxx.com/cover1.jpg,底层逆袭故事,9.9,20,https://xxx.com/ep02.mp4

注意看第二行的第 7 列是ep02.mp4,说明这个 CSV 是按一集一行的方式排列的,集数会自动按第 6 列的值判定。批量导入之后建议去前台页面刷新一遍看看封面是否正常、播放是否流畅。很多人卡在这一步是因为拿到的视频地址是来自网盘分享页而非直链,这种地址小程序播放不了,必须先转成 mp4 或 m3u8 可访问的直链。

5. 部署上线与避坑:从服务器到小程序后台的完整流程

5.1 服务器配置与 HTTPS 是第一个门槛

小程序上线有个硬性要求:所有请求的接口域名必须是 HTTPS 且在微信后台配置过合法域名。所以部署这套源码的服务器最低配置建议是 2 核 4G 起步,带宽按实际用户量走,前期 5M 够用。系统选 CentOS 7 或 Ubuntu 20.04 都行,关键是装好 Nginx、PHP 7.2 和 MySQL 5.7,然后把public目录设为网站根目录。

配置项推荐值说明
CPU/内存2核4G低于这个跑 PHP 加 MySQL 会卡
带宽5M 起步视频走 CDN 的话这里可以小
PHP 版本7.2+低于 7.2 部分函数会报错
HTTPS必须微信小程序强制要求

HTTPS 证书我这边用的是免费版,申请和部署大约十分钟搞定。配完证书记得在 Nginx 里加上把 80 端口请求重写到 443 的规则,不然用户访问 http 链接时会报错。配置完可以用浏览器访问一下接口文档地址,看到 JSON 输出就说明 HTTPS 链路正常。

5.2 微信小程序后台那三项配置不能错

源码编译成小程序并上传代码后,真正要打磨的是微信公众平台的后台配置。一般的流程是:在小程序后台“开发管理—开发设置”里拿到 AppID 和 AppSecret,填到前端manifest.json和后端config里;然后在“开发管理—服务器域名”里配置 request 合法域名和 uploadFile 合法域名,这一步漏了请求全部被拦截;最后在“设置—基本设置”里把业务域名也加上。

// 前端请求封装:统一带 token 头 // utils/request.js 里的核心代码 const request = (url, data, method = 'GET') => { const token = uni.getStorageSync('token'); return new Promise((resolve, reject) => { uni.request({ url: BASE_URL + url, method, data, header: { 'Authorization': 'Bearer ' + token }, success: (res) => { // 这里和拦截器不一样,登录失效要跳登录页 if (res.statusCode === 401) { uni.navigateTo({ url: '/pages/login/login' }); } resolve(res.data); }, fail: reject }); }); };

前端utils/request.js里的BASE_URL要改成你的 HTTPS 域名,这里只改一处,全项目生效。注意Authorization这个头里 Bearer 后面的空格不能省,省了后端的 JWT 解析直接返回 401。小程序登录流程调用的接口是后端api/user/login,这个过程会到微信官方换取openid,后端再返回自定义的 token 给前端存起来。

5.3 三个必踩的坑:现象、原因、解决

这套源码我跑完部署到正式上线,前后翻过三次车,每次都跟你们复盘一下。

坑一:支付回调收不到,订单一直待支付。

现象是前端调起支付窗,用户付了钱,小程序上却永远显示未支付,后台订单状态也是 0。原因是我的服务器宝塔面板默认开了防火墙,回调端口被拦了,或者 Nginx 没放行对应的 PHP 文件路径。解决方法是先在服务器上执行curl -x POST https://你的域名/api/pay/notify看返回是否正常,再检查防火墙和安全组有没有放行 443 端口。如果返回 404,优先查伪静态规则。

坑二:视频播放卡顿,进度条一拖就转圈。

现象是视频能播但拖动进度条后缓冲很久,尤其是 mp4 文件。原因是没用 Range 请求支持的播放方式,mp4 文件被整包下载,一个 200MB 的视频要先加载很久才能拖。解决方法是把视频转成 HLS(m3u8)格式切片分发,或者在 Nginx 里加上mp4模块支持 Range,我用的是后者,视频文件不变但拖动流畅了。

坑三:微信登录报“code 换取 session_key 失败”。

现象是用户点微信授权登录后,后端接口一直报这个错。原因一般有两个:一个是 AppSecret 在服务端配错了,另一个是前端拿到的 code 被重复使用,微信的 login code 只能用一次。解决方法是确认后端config里的 AppSecret 和公众平台一致,并在前端每次登录时都重新调uni.login()获取新 code,不要缓存起来重用。

6. 之后怎么办:支付日志闭环与二次开发的两个习惯

6.1 先给支付做日志闭环,再谈功能加量

源码跑通只是第一步,真正判断一套系统能不能长期用,是看它的日志和可观测性。我强烈建议你上线前给支付回调加一个文件日志,把每次回调的原始数据、验签结果、订单号、处理状态按行写入runtime/log目录下的按天日志文件。这样用户说“我付了钱没到账”的时候,你能掏出日志甩在他脸上。加日志的方式不必额外装引入组件,PHP 原生file_put_contents就够。

// 给支付回调加一行日志,每天一个文件 file_put_contents( runtime_path() . 'pay_' . date('Ymd') . '.log', date('H:i:s') . ' | ' . json_encode($result) . PHP_EOL, FILE_APPEND | LOCK_EX );

这一行为什么重要?因为支付回调是异步的,很多问题只在特定网络条件下出现,线上环境你根本无法复现。有一次我排查一个分润 bug,把回调日志打开一看,发现是代理用户在回调到达前就取消了分销关系,导致写入代理 ID 为空。没有日志,这个问题我可能得猜一整晚。

6.2 登录拿手机号的合规姿势

短剧小程序的用户留存逻辑绕不开手机号绑定。这套源码里,前端如果直接调用uni.getPhoneNumber拿到的code是不能直接换取手机号的,必须把这个code通过你自己的后端去微信官方接口换取。注意下来源,相比早年用明文手机号+验证码的方式,现在微信对老用户默认是静默授权,新用户会弹窗询问授权。合规的姿势是:拿到code后,后端调用微信的接口换取手机号,再写入用户表的phone字段,前端不要传明文手机号,也不要在本地存储手机号。

// 前端:将 wx.login 的 code 与手机号 code 一起提交 uni.login({ provider: 'weixin', success: (loginRes) => { uni.getPhoneNumber({ success: (phoneRes) => { // phoneRes.code 是动态令牌,不是手机号本身 uni.request({ url: '/api/user/bindPhone', data: { login_code: loginRes.code, phone_code: phoneRes.code } }); } }); } });

前端两个 code 的区分是个高频踩坑点。login_code用于换取用户的身份标识(openid),phone_code是换取手机号的动态令牌,两个都是有时效的,用错了后端一定报错。这套源码在这块的处理是后端写了两个独立的接口方法,分别对应两种换码逻辑,你只要确保前端别把代码传混就行。

6.3 抓包调接口的习惯,建议现在就养

小程序开发调试不能只看控制台打印,抓包看真实请求才是排查问题的可靠手段。浏览器开发者工具在微信开发者工具里可以直接抓到小程序的网络请求,看请求头、响应体、状态码一个不落。我每次改完接口,都会看一眼真实发出的请求参数和自己脑补的是否一致——经常有前端传了字符串、后端要整数的情况,抓包一眼就能发现。

从那以后我每次部署一套新的源码,都强制走一遍这个流程:数据库导入 → 后端伪静态 → 前端编译 → 支付测试单 → 抓包看回调 → 看日志核对订单状态。这个流程帮我排掉了至少一半的低级问题。这套源码全开源这点帮了大忙,支付链路的每一环你都能改能查,真要遇到别人收费源码里藏着不明 API 地址的情况,你也能自己把代码审一遍再上线。希望帮到你。

本文还有配套的精品资源,点击获取

返回列表