尧图精选

三端互通与资源采集:知识付费系统开源部署实战指南

🕒 发布时间:2026/10/2 2:19:18 📁 来源:尧图网络
简介这是一套面向知识付费创业者和开发者的三端互通小程序系统源码覆盖微信小程序、PC端与H5公众号支持DIY首页、卡密/图文/视频/音频/网盘等多类型资源发布、二级分销、代理分站、流量主广告和社群挂载等运营功能适合快速搭建知识变现平台或用于二次开发学习。资源包共含2000个文件压缩包约165.41MB以js逻辑脚本、html页面、ts与css样式代码为主辅以jpg/png/gif等界面素材、sql数据库文件、md说明文档和php服务端文件目录结构完整便于按前端、后端、配置与文档分类查阅。已有882人学习下载。通过这套V3.5.6版本源码读者可获取完整的开源代码、DIY设计配置样例、多种资源发布与分销功能实现以及代理分站和移动端自定义方案能直接部署测试也能作为开发知识付费系统时的功能参考。1. 2024 年做内容变现为什么绕不开三端互通 资源采集2024 年做内容变现的人几乎都撞上同一个需求课程得同时在小程序商城、公众号 H5、电脑网页里卖用户在手机上付了钱回到电脑还得能看订单和会员不能各算各的账。资源牛知识付费系统这类开源版就是冲着「小程序 PC H5 三端数据互通 资源采集」这套组合来的。它的价值在于把原本要三套前端、一套后台、外加采集脚本的工程量压缩成一份能部署、能改改就上线的开源项目适合手里已有视频、文档等数字资源想快速开知识付费小程序的个人站长和小团队。一个反直觉的结论是三端互通真正的难点不在界面适配而在会员、订单、支付回调这些数据逻辑。界面只是最上层那层皮数据层立不住三端必然各说各话。2. 三端数据互通的设计先决条件会员、订单、课程表到底怎么建拿到这类开源版我第一件事不是改界面而是把数据库表结构翻开看。三端数据互通不是让三个端长得像而是同一个用户在任意一端登录后看到同一份会员信息、同一份订单、同一份已购课程。要做到这点后端必须是一套库、一套 API前端分三条线去接。每张表的设计都决定了后面联调会不会返工这一章讲的是最核心的三个设计点。2.1 先定架构uniapp 出一套小程序 H5PC 管理端单独走 API常见做法是后端用 ThinkPHP 或 Laravel 这类 PHP 框架小程序和 H5 共用一套 uniapp 代码。uniapp 一套代码能编译出微信小程序、H5、App这是资源牛这类系统省事的关键。PC 管理端则是独立的 Vue 管理后台给站长维护课程、会员、订单、采集任务。三条前端线都不直接连数据库只通过 HTTP API 读写所有业务判断收口在后端。第一个原则就此定死前端永不写业务 SQL任何读写都经过后端统一鉴权。实现层就是一套全局中间件三端同一个接口。// 伪代码API 鉴权中间件小程序、H5、PC 共用 public function handle($request, \Closure $next) { $token $request-header(Authorization, ); $token str_replace(Bearer , , $token); $user db(member)-where(token, $token)-find(); if (!$user || $user[token_expire] time()) { return json([code 401, msg 登录已过期]); } $request-user $user; // 当前用户挂到请求上后续业务直接用 return $next($request); }这套中间件的逻辑三端一致小程序 wx.request、H5 axios、PC axios 都在请求头里带同一个 Authorization Bearer token后端只认这个 token 对应的 member 记录。token_expire 我一般设 7 天小程序端配合静默续期用户无感知。值得注意的 trade-offtoken 存在 member 表意味着同一账号后登录的端会顶掉先登录的端如果想支持多端同时在线要给 token 单独建表并加 device 字段这是开源版默认不做的事需要自己补。2.2 三端共用的三张核心表member、order、course_access三端互通的本质是同一 user_id 在任何端登录看到的订单和已购课程完全一致。下面三张表是我认为最核心的骨架建表时我会按这个思路核对开源版的字段。-- 会员表三端共用user_id 全局唯一 CREATE TABLE member ( id int(11) UNSIGNED NOT NULL AUTO_INCREMENT, openid varchar(64) DEFAULT NULL COMMENT 小程序 openidH5/PC 为空, unionid varchar(64) DEFAULT NULL COMMENT 微信开放平台下同一账号统一标识, nickname varchar(64) NOT NULL DEFAULT , phone varchar(20) DEFAULT NULL COMMENT 手机号H5/PC 端登录凭据, token varchar(64) DEFAULT NULL, token_expire int(11) DEFAULT 0, reg_channel tinyint(4) NOT NULL DEFAULT 1 COMMENT 1小程序 2H5 3PC, created_at int(11) DEFAULT 0, PRIMARY KEY (id), KEY idx_openid (openid), KEY idx_phone (phone) ) ENGINEInnoDB DEFAULT CHARSETutf8mb4; -- 订单表渠道只用 channel 字段区分不拆表 CREATE TABLE order ( id int(11) UNSIGNED NOT NULL AUTO_INCREMENT, order_sn varchar(32) NOT NULL COMMENT 全局唯一订单号, user_id int(11) NOT NULL, course_id int(11) NOT NULL, pay_amount decimal(10,2) NOT NULL DEFAULT 0.00, channel tinyint(4) NOT NULL DEFAULT 1 COMMENT 1小程序 2H5 3PC, status tinyint(4) NOT NULL DEFAULT 10 COMMENT 10待支付 20已支付 30已关闭 40已退款, transaction_id varchar(64) DEFAULT NULL COMMENT 微信支付单号回调幂等用, paid_at int(11) DEFAULT 0, created_at int(11) DEFAULT 0, PRIMARY KEY (id), UNIQUE KEY uk_sn (order_sn), UNIQUE KEY uk_trans (transaction_id) ) ENGINEInnoDB DEFAULT CHARSETutf8mb4; -- 课程权限表三端「买了就能看」的依据 CREATE TABLE course_access ( id int(11) UNSIGNED NOT NULL AUTO_INCREMENT, user_id int(11) NOT NULL, course_id int(11) NOT NULL, created_at int(11) DEFAULT 0, PRIMARY KEY (id), UNIQUE KEY uk_user_course (user_id, course_id) ) ENGINEInnoDB DEFAULT CHARSETutf8mb4;三端互通不是三套库做同步而是所有端读写同一张 order。channel 字段只用于统计这单从哪个端来的不影响订单归属。用户识别分两条路小程序端用 openidH5 和 PC 端用手机号登录如果接了微信开放平台unionid 能把同一微信用户在三个端串起来这是最干净的方案。course_access 表是三端统一的「已购凭证」不管用户从哪个端付的钱只要这张表有记录任意端都能看课。2.3 支付回调和订单状态机数据互通最容易翻车的一层订单状态机我按四态设计10 待支付、20 已支付、30 已关闭、40 已退款。其中 10 到 20 的迁移只能由支付回调触发前端不能自己改状态这是原则。三端会走三种不同支付方式小程序用 wx.requestPaymentH5 用公众号支付PC 用扫码。三个渠道回调同一个接口入账逻辑不幂等就是灾难。// 微信支付回调三端同一套入账逻辑 public function wxNotify() { $data $this-parseWxNotify(); // 验签、解密失败直接返回 fail $order db(order)-where(order_sn, $data[out_trade_no])-find(); if (!$order || $order[status] ! 10) { return success; // 非待支付状态直接返回避免重复入账 } $updated db(order)-where(order_sn, $order[order_sn]) -where(status, 10) // 乐观锁只更新待支付单 -update([ status 20, transaction_id $data[transaction_id], paid_at time() ]); if ($updated) { // 开通课程权限这步和订单更新要放同一事务 db(course_access)-insert([ user_id $order[user_id], course_id $order[course_id], created_at time() ]); } return success; }两个关键参数transaction_id 唯一索引防重复入账微信重试回调时第二次插入直接撞唯一键权限不会开两遍乐观锁 where status10 保证并发回调下只有第一次能更新成功。我以为最坑的是订单更新成功但 course_access 插入失败用户付了钱看不到课所以这两步必须放同一个事务任一步失败就返回 fail 让微信继续重试。前端只问「course_access 有没有记录」不判断支付渠道这样三端的看课逻辑天然一致。3. 本地跑通资源牛开源版部署、双端编译和三端联调的完整路径拿到开源版别急着传服务器先在本地跑通整个链路。我给的最小路径是三步后端起服务管理端能登录uniapp 分别编译出 H5 和小程序并在三端完成一次真实下单。本地能跑通上线就只是换域名和配 https 的问题。3.1 环境准备PHP 版本、MySQL、小程序 AppID 三件事先核对环境开源版跑不起来八成是版本问题不是代码问题。软件推荐版本用途注意PHP8.1 / 8.2后端运行7.4 能跑但别用很多依赖已不兼容MySQL5.7 / 8.0数据存储建库必须 utf8mb4否则中文变乱码Composer2.x安装 PHP 依赖国内先配镜像源否则装到超时HBuilderX最新稳定版编译 uniapp也可用 VSCode 加 uni-app 插件微信开发者工具最新稳定版跑小程序需要真实 AppID小程序端编译必须要一个真实 AppID。用测试号能打开界面但 wx.requestPayment 这类支付接口不可用联调支付还得换真号。本地开发阶段在微信开发者工具里勾选「不校验合法域名」这样 http://127.0.0.1 的接口也能请求上线前再把 https 正式域名配进小程序后台白名单并取消这个勾选。3.2 后端启动导入数据库、改 .env、起本地服务后端以 ThinkPHP 为例换 Laravel 只是命令不同思路一致。# 1. 还原依赖 composer install --no-dev # 2. 复制环境配置并修改数据库连接 cp .env.example .env # 编辑 .envDB_HOST127.0.0.1 DB_PORT3306 # DB_DATABASEresource_niu DB_USERNAMEroot DB_PASSWORD你的密码 # 3. 导入数据库 mysql -uroot -p resource_niu install/resource_niu.sql # 4. 起本地开发服务默认 127.0.0.1:8000 php think run -p 8000.env 里除了数据库连接还有 APP_URL、token 密钥、微信支付三组参数。token 密钥在开源版里通常是占位符上线前必须换成自己的随机串否则别人拿默认密钥可以伪造登录态这是这类开源版最常见的真实漏洞。导入 SQL 报错先查 MySQL 版本和库字符集utf8mb4 没配好会直接在 utf8 字段上炸。3.3 uniapp 双端编译一套代码怎么指向两个不同域名小程序和 H5 的域名不一样H5 是你自己的站点域名小程序必须是配置进后台白名单的 https 域名。代码只有一套用 uni-app 的条件编译区分我习惯的做法是单独抽一个 config 文件。// utils/config.js const ENV { development: { h5Base: http://127.0.0.1:8000/api, mpBase: http://127.0.0.1:8000/api // 开发者工具可关域名校验 }, production: { h5Base: https://www.yourdomain.com/api, // H5 和 PC 共用正式 API 域名 mpBase: https://api.yourdomain.com/api // 小程序必须白名单内的 https 域名 } }; // #ifdef H5 export const BASE_URL ENV[process.env.NODE_ENV development ? development : production].h5Base; // #endif // #ifdef MP-WEIXIN export const BASE_URL ENV[process.env.NODE_ENV development ? development : production].mpBase; // #endif小程序端不能像 H5 那样自由跨域请求域名必须在微信后台「开发管理-服务器域名」里配置且只认 https。H5 端如果后端没配跨域头在 nginx 加 Access-Control-Allow-Origin 即可。PC 管理端是独立 Vue 工程我建议各配各的 .env不要硬塞进 uniapp 仓库混在一起发版容易互相污染。如果 H5 端要接入企业微信客服页面还得额外加载微信 JS-SDK 并调 openCustomerServiceChat这不是开源版默认功能需要自己补。小程序请求封装我固定做成 Promise 形式// utils/request.js import { BASE_URL } from /utils/config.js; export function request(path, { method GET, data {} } {}) { return new Promise((resolve, reject) { uni.request({ url: BASE_URL path, method, data, header: { Authorization: Bearer (uni.getStorageSync(token) || ) }, success: (res) { if (res.data.code 401) { uni.removeStorageSync(token); uni.navigateTo({ url: /pages/login/index }); reject(res.data); return; } resolve(res.data); }, fail: reject }); }); }uni.request 在 H5 端走 ajax在小程序端走 wx.request封装层让业务代码不用感知端差异。401 统一跳登录是必写的否则三端里有一端 token 过期用户会卡在「界面像登录了但所有接口都报错」的假死状态。3.4 三端联调自检登录、下单、回调各跑一遍本地跑通的定义不是能打开首页而是完整走一遍业务主链。我按四步自检PC 管理端注册一个账号去数据库 member 表确认 user_id 和 reg_channel3。同一手机号在 H5 端登录再去小程序端用手机号登录确认两个端拿到同一个 user_id。这一步是三端数据互通的第一道验证对不上就是登录逻辑有分支没走统一表。任一端下载单。本地没有真实微信商户号时常见做法是后端留一个测试回调接口手动把订单推到已支付并写入 course_access等联调阶段再换真实回调地址。去另外两个端刷新已购列表确认课程出现。三端都看到同一门课数据互通才算真通了。local 环境跑通这套链路大概一个小时。你会发现大部分时间花在环境配置而不是业务代码上这是开源版的常态。4. 资源采集模块落地抓取、定时入库、防重复的参数怎么设才不翻车资源牛这类开源版自带的采集开箱即用往往只够演示。我自己跑生产采集一定拆成四步抓列表、抓详情、清洗、入库全部走命令行任务绝不让前端请求实时触发爬虫。实时爬意味着用户在等你的接口目标站一慢你的页面就超时这是架构错误。另外提醒一句采集前先确认目标站内容是否有授权技术能做不代表事情该做。4.1 采集链路设计列表解析、正文抽取、图片转存命令行的采集任务长这样。以 ThinkPHP 命令为例核心是选器和频率两个控制点。// application/command/collect.php public function handle() { $sourceUrl $this-argument(url); // 目标站列表页 $html $this-fetch($sourceUrl); // curl 带 UA 抓取 $links $this-parseLinks($html); // 解析出详情页 URL 和标题 foreach ($links as $item) { $detail $this-fetch($item[url]); $course [ title trim(strip_tags($detail-find(.article-title)-html())), content $detail-find(.article-content)-html(), cover $this-saveCover($detail-find(img)-src), // 图片转存本地/OSS source_url $item[url] ]; $this-saveCourse($course); usleep(random_int(500000, 1500000)); // 每次抓取睡 0.5~1.5 秒 } }选器是采集最大的坑。目标站改一次前端你的正则和选择器全作废。我会把所有选器表达式提到配置文件里目标站改版只改配置不动代码。saveCover 必须把远程图片下载到本地或 OSS否则目标站一加防盗链你的课程封面和正文图片全裂。抓取参数我固定成超时 10 秒、UA 用真实浏览器 UA、失败重试 2 次、单批最多 50 条。这个量级下一个批次的执行时间可控在十分钟内。4.2 定时任务与频率控制别把目标站打挂也别封了自己频率控制是采集活下来的前提。每分钟跑一次的任务一小时内就会被目标站的 web 防火墙盯上轻则 IP 临时封禁重则目标站直接屏蔽你的抓取 UA。我的 crontab 配置crontab -e # 每 30 分钟采集一次错开整点和半点 */30 * * * * cd /www/wwwroot/resource_niu php think collect storage/logs/collect.log 21 # 每天凌晨 4 点重跑失败任务 0 4 * * * cd /www/wwwroot/resource_niu php think collect --retry storage/logs/collect-retry.log 21代码里的 usleep 随机延迟是刻意加的让请求间隔不是固定节奏固定节奏最容易被风控识别。单批 50 条跑完就停不要把整个目标站一次性拉完。你没那么缺内容目标站也没那么抗打。--retry 的重试任务只捞 collect_log 里 status2 的失败记录避免每天凌晨全库扫一遍浪费时间。4.3 清洗去重与入库md5 指纹加唯一索引双保险去重只查标题是新手最爱犯的错。目标站经常在标题后追加栏目名或日期同一条内容换了标题就被当成新课再采一遍。我在采集日志表和课程表里同时做了两道防线CREATE TABLE collect_log ( id int(11) UNSIGNED NOT NULL AUTO_INCREMENT, source_url varchar(255) NOT NULL, title varchar(255) NOT NULL, content_md5 char(32) NOT NULL DEFAULT COMMENT 标题正文指纹, status tinyint(4) NOT NULL DEFAULT 0 COMMENT 0待处理 1成功 2失败 3重复, error_msg varchar(255) DEFAULT NULL, created_at int(11) DEFAULT 0, PRIMARY KEY (id), UNIQUE KEY uk_source_url (source_url) ) ENGINEInnoDB DEFAULT CHARSETutf8mb4;入库前先算指纹// 标题 正文前 500 字做 md5比全文 md5 稳 $fingerprint md5($course[title] . mb_substr($course[content], 0, 500)); $exists db(course)-where(content_md5, $fingerprint)-find(); if ($exists) { $this-logDuplicate($course[source_url]); return; // 标记为重复跳过 }只取正文前 500 字算指纹是因为目标站详情页正文末尾常带随机推荐位或统计代码全文 md5 会导致同一篇文章因为尾部小尾巴不同被反复入库。source_url 唯一索引是第二道保险就算查重逻辑漏了同一条来源链接也插不进第二遍。视频资源我建议只存地址不下载文档资源可以下载转存但下载任务单独起 worker别和抓取任务串在一起一个超时拖死一批。4.4 采集日志与断点续采没有日志的采集等于黑匣子生产采集不是一次跑完的。目标站改版、服务器重启、目标站超时都会中断。我会把每条抓取状态写进 collect_log失败记录 error_msg重跑时 --retry 只处理 status2 的记录。连续失败 5 次以上的 source_url 自动停采避免每次定时任务都拿同一个坏链接反复试。采集是脏活日志就是后悔药没有日志的采集任务等于黑匣子出了问题只能从头再跑而且永远说不清哪条采过哪条没采过。5. 避坑三端互通和资源采集最容易翻车的 5 个高频问题这些坑我基本都踩过一遍每条按「现象 → 原因 → 解决」写大多是部署后一两周内会撞上的问题。提前看过能省掉好几个凌晨。5.1 H5 在微信里登录态反复失效现象H5 端在微信里打开昨天还好好的今天接口全报 401重新登录后过一会儿又掉。 原因开源版默认把 token 存 localStorage微信浏览器在内存回收或深色模式切换时可能清掉更常见的是后端 token_expire 配得太短有人把 7 天写成了 7200 秒。 解决token_expire 按业务设到 7 到 15 天H5 端加静默续期每次请求成功发现剩余有效期不足 1 天就调 /refresh-token 换新 token。小程序端 token 存 storage逻辑一样但小程序没有微信浏览器清 localStorage 的问题重点查后端有效期。5.2 小程序支付回调后订单停在待支付现象用户在小程序里付了钱订单状态没变course_access 没写入用户投诉售后。 原因商户平台配的回调地址是 http 或内网地址微信根本打不到另一个常见原因是回调里更新订单成功但插入 course_access 报错没捕获订单已支付但权限没开。 解决商户平台回调地址必须是公网可访问的 https 地址把更新订单和写入 course_access 放同一个数据库事务任一步失败整体回滚并返回 fail让微信按策略重试。排查时先在小程序开发者工具的 Network 面板看回调接口响应再看商户后台回调记录两步就能定位是网络没通还是事务没提交。5.3 采集资源重复入库现象课程列表里同一个标题出现好几次内容一模一样用户以为你在刷数据量。 原因去重只查 title而目标站会在标题后追加日期或栏目后缀同一条内容换标题就被当新课或者查重和插入之间没有唯一索引兜底并发任务同时跑时出现空窗。 解决按 4.3 的做法标题加正文前 500 字做 md5 指纹课程表建 content_md5 唯一索引当第二道锁并发场景下给采集任务加互斥锁用 Redis 锁或数据库锁保证同一时间只有一个采集进程在写课程表。5.4 三端看到的时间差 8 小时现象小程序里订单和课程显示的时间比实际晚 8 小时H5 和 PC 显示却正常。这种问题最玄学因为数据明明是同一份。 原因后端存的是 int 时间戳本身没有时区概念。问题出在小程序端展示时用 new Date(timestamp).toLocaleString() 做了本地格式化而测试机的时区是 UTCH5 端浏览器时区恰好是东八区所以看起来正常。 解决后端接口只返回 int 时间戳不返回 date 字符串前端统一用一个 dateUtil 工具转成东八区字符串三端调同一个函数。不要在业务代码里散落 toLocaleString 的调用散落一次就埋一颗雷。5.5 域名白名单、类目资质和小程序年审的三重夹击现象本地全通提审被拒提示类目不含「教育 - 在线教育」或者线上正式版白屏而开发者工具里一切正常。 原因知识付费涉及虚拟支付微信要求小程序服务类目必须包含在线教育并上传对应资质正式版不走开发者工具的「不校验合法域名」白名单里少一个域名就整个挂。 解决提审前先核对后台服务类目配好教育类资质服务器域名白名单把 request、uploadFile、downloadFile 三类合法域名全部加齐课程附件若放在 OSSOSS 域名也要加进 downloadFile。再有就是年审我吃过这个亏项目放了两个月没动提审时才发现小程序已过期重新年审又耗了一周。开发者工具提示「开发版已过期」就重新扫码但小程序主体年审过期没人提醒你自己记好到期时间。6. 进阶给开源版补一个分销开关并写三端一致性校验脚本很多开源版不带分销或者带了但逻辑写死。我给自己部署的版本加了一个可控的分销开关做法很朴素一张配置表加一个订单字段。config 表里存 distribute_enableorder 表加 referrer_id。下单时请求带 share_uid 且开关为 1就在支付成功回调里把分享人 id 写进订单结算走后台手动不搞自动提现。加开关的价值是先小范围灰度数据对得上再放开避免返佣算错自己垫钱。分销逻辑和支付回调放一起就是防止有人下单后分享关系对不上账。三端数据互通上线后会悄悄坏掉最典型的就是订单已支付但权限没给。我每次发版前在服务器上跑这两条 SQL输出为空才敢发布-- A. 已支付但没有开课权限的异常单 SELECT o.order_sn, o.user_id, o.course_id, o.status FROM order o LEFT JOIN course_access ca ON ca.user_id o.user_id AND ca.course_id o.course_id WHERE o.status 20 AND ca.id IS NULL; -- B. 有开课权限但没有对应已支付订单的脏数据 SELECT ca.user_id, ca.course_id FROM course_access ca LEFT JOIN order o ON o.user_id ca.user_id AND o.course_id ca.course_id AND o.status 20 WHERE o.id IS NULL;第一条查支付成功但权限没写基本是回调事务没提交第二条查权限比订单多多半是测试时手动插数据忘了清。我自己的习惯是每周五下午把采集日志和这两条对账 SQL 一起过一遍十分钟的事已经避免过好几次「用户说买了课看不到」的售后。做知识付费系统功能可以少数据不能乱三端互通不是上线那天的事是每次改完支付、改完采集都要回来验一遍的事。希望帮到你。本文还有配套的精品资源点击获取
上一篇/下一篇内容由系统自动关联 返回资讯列表 →