简介:WIFI共享小程序独立版源码是一套面向个人开发者与本地运营团队的共享WiFi平台搭建方案,核心解决从零开发小程序门槛高的问题。资源包共收录2004个文件,约68.07MB,其中php、js、json等文件覆盖后端接口与配置逻辑,jpg、png等素材提供界面与视觉资源,css、sql、md等文件则对应样式、数据库及技术说明,目录结构清晰便于定位。方案同时包含硬件选购与部署指导,如打印机型号选择、相关设备下载落地,并给出市场分析、拓展员/团长招募、活动策划、会员管理等运营策略,帮助使用者从技术到商业完成全链路搭建。已有198人学习下载,适合希望快速搭建自主共享WiFi平台、且需要运营方法支撑的中小团队与个人。
1. WIFI共享小程序独立版源码:一次买断、自己部署的流量生意
店里的WiFi密码贴在吧台,顾客坐下来第一句是「WiFi密码多少」,老板每天要被问几十遍。把密码换成一个小程序码,顾客扫码后看一段广告,密码自动弹出来,店家省了反复口头报密码,开发者靠广告流量主分成赚钱——这就是WIFI共享小程序独立版源码在做的事。所谓「独立版」,和按年付费的SaaS版相对,源码一次性买断,部署在自己的服务器、用自己的小程序账号,数据、广告位、分店管理全在自己手里,适合有基础开发能力的人做本地化运营或二开。这篇文章不聊「破解别人的WiFi」那种灰色玩法,只说合规场景:店家授权分享自家WiFi密码,小程序负责把「报密码」这个动作变成一次有广告价值的交互。下面从选型、建库、写接口、调小程序到排坑,按一套能直接落地的方案讲。
2. 独立版源码的选型判断:先想清楚变现闭环,再挑技术栈
2.1 共享WiFi的商业模式:广告解锁密码、扫码连接与流量主分成
顾客扫码之后发生什么,决定了这个项目到底靠什么赚钱。最常见的链路是:顾客用微信扫桌上的二维码,进入小程序对应页面,小程序识别出这是哪家店、哪个WiFi,然后弹出一个激励视频广告,顾客看完广告,界面上显示出WiFi密码,附带「一键复制」按钮。顾客的每一次扫码,在小程序后台记一次曝光、一次广告完成数,微信广告平台按月结算流量主收益。这个模式的关键数据有两个:单次广告单价和扫码转化率。单次激励视频的广告收入通常在几分钱到几毛钱不等,由广告主出价和用户质量决定,扫码转化率则取决于店面的客流和顾客是否愿意看完广告。所以选源码之前,先别急着挑技术栈,应该先算一笔账:一个日均扫码50次的小店,按30%到40%的广告完播率,月收入大致能覆盖一个云服务器费用,做成连锁店或区域代理后,收益才值得认真运营。技术选型要服务的核心指标,就是「尽可能不打断扫码流程」和「广告播放完成后再给密码」这两件事。
2.2 技术栈选型:为什么常见做法是 uni-app 前端 + PHP 后端 + MySQL
市面上的「独立版源码」跑的最多的组合是 uni-app 写小程序前端、PHP 写后端接口、MySQL 存数据。这不是因为这套技术最新,而是因为它最符合这类项目的真实处境。uni-app 的一大优势是同一套 Vue 代码可以编译到微信小程序,也能出支付宝、抖音或 H5,后续想覆盖更多端不用重写;而且它封装了微信登录、广告组件、存储等接口,开发量比原生小程序小不少,尤其适合「小程序抓包调试、真机预览、快速改版」这种高频迭代节奏。后端选 PHP 而非 Java 或 Go,理由很实际:独立版源码的买家大多是中小开发者,PHP 部署门槛低,虚拟主机能跑,Nginx + PHP-FPM 的运维资料遍地都是,出了问题好找人修。如果你更熟悉 Node.js,思路完全一致,接口逻辑不受语言限制,但要注意独立版源码的文档和后续维护往往跟着主流方案走,用 PHP 能减少自己踩坑的成本。
2.3 三个关键设计决策:token与密码下发、二维码静态/动态、广告位放哪里
动手写代码前,有三个决策直接影响后面所有表结构和接口设计。第一个是密码怎么下发。不能让小程序的每个请求都能直接查密码,否则别人抓包就能绕过广告拿到明文;常见做法是密码在后端加密存储,小程序端先登录拿 token,看完广告拿到一个一次性凭证,再用凭证换密码。第二个是二维码用静态还是动态。静态二维码把参数直接编进小程序码里,顾客扫码后小程序把参数带给后端,适合单店、密码不常改的场景;动态二维码是后台按 WiFi 记录生成 code,店主改密码后同一个码还能用,不用重新打印,适合连锁和多店场景。实际做的时候,两种模式最好都支持:页面上的正式物料用动态码,测试时用静态码临时验证。第三个是广告位放哪里。激励视频体验最重但单价高,适合放「查看密码」这一步;插屏广告干扰小但单价低,适合放「进店首页展示」或「复制密码后返回」的间隙。我的建议是主流程只放一个激励视频,广告位越少,顾客完成率越高,收益反而更稳。
3. 后端部署:从建库到接口下发WiFi密码(可抄作业)
3.1 数据库表结构:wifi 表、访问记录表、二维码参数表
先建库。共享WiFi的核心数据只有三类:WiFi信息、访问记录、店长或管理员账号。WiFi 表是核心,存店名、WiFi 名、密码密文、二维码 key、状态和点击量。密码不能存明文,用 varbinary 类型存 AES 加密后的字节,避免数据库泄露后密码直接暴露。访问记录表用来做统计和风控:谁、什么时间、扫了哪个码、有没有看完广告。下面这份 SQL 是实际项目里可以拿来改的基线:
CREATE TABLE `wifi_info` ( `id` int(11) unsigned NOT NULL AUTO_INCREMENT, `shop_name` varchar(64) NOT NULL DEFAULT '' COMMENT '门店名称,扫码后展示', `wifi_name` varchar(64) NOT NULL COMMENT 'WiFi SSID', `wifi_password` varbinary(255) NOT NULL COMMENT 'AES加密后的密码密文', `qr_key` varchar(32) NOT NULL COMMENT '二维码唯一标识,扫码后解析', `status` tinyint(4) NOT NULL DEFAULT '1' COMMENT '1启用 0停用', `hit_count` int(11) unsigned NOT NULL DEFAULT '0' COMMENT '累计曝光次数', `created_at` datetime NOT NULL DEFAULT CURRENT_TIMESTAMP, `updated_at` datetime NOT NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP, PRIMARY KEY (`id`), UNIQUE KEY `uk_qr_key` (`qr_key`) ) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COMMENT='共享WiFi信息表'; CREATE TABLE `scan_log` ( `id` int(11) unsigned NOT NULL AUTO_INCREMENT, `wifi_id` int(11) unsigned NOT NULL COMMENT '关联wifi_info.id', `openid` varchar(64) NOT NULL COMMENT '用户openid', `ad_finished` tinyint(4) NOT NULL DEFAULT '0' COMMENT '广告是否完整播放 0未完成 1完成', `created_at` datetime NOT NULL DEFAULT CURRENT_TIMESTAMP, PRIMARY KEY (`id`), KEY `idx_wifi_id` (`wifi_id`), KEY `idx_openid` (`openid`) ) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COMMENT='扫码与广告完成记录';qr_key是扫码流量的入口,必须加唯一索引,后端接口靠它定位是哪家店的哪个 WiFi。hit_count是运营看板的核心指标,能直接反映物料贴出去之后每天被扫了多少次。scan_log里的ad_finished字段很关键,广告是否完整播放要由前端上报,但后端要做二次校验:同一 openid 短时间内重复扫码,只算一次有效广告,防止刷量。如果后续要做多店管理,建议再加一张shop_user表,把 openid 或手机号和wifi_info.id关联成多对多,这样店长登录后只能看到自己门店的数据。
3.2 两个核心接口:扫码解析与密码解密下发
接口最少需要三个:登录换 token、扫码获取 WiFi 信息、看完广告后获取密码。这里贴一个「扫码解析」接口,它的职责是只返回店名和 WiFi 名,不返回密码;密码由另一个接口在广告完成后单独下发。这样即使扫码页被直接请求,也拿不到密文。
<?php // api/wifi.php - 扫码解析接口 header('Content-Type: application/json; charset=utf-8'); require_once 'db.php'; $qr_key = isset($_GET['qr_key']) ? trim($_GET['qr_key']) : ''; // 二维码key必须符合白名单,防止SQL注入和路径拼接 if (!preg_match('/^[a-zA-Z0-9_-]{4,32}$/', $qr_key)) { exit(json_encode(['code' => 400, 'msg' => '二维码参数不正确'])); } $stmt = $pdo->prepare( 'SELECT id, shop_name, wifi_name, hit_count FROM wifi_info WHERE qr_key = ? AND status = 1 LIMIT 1' ); $stmt->execute([$qr_key]); $row = $stmt->fetch(); if (!$row) { exit(json_encode(['code' => 404, 'msg' => 'WiFi不存在或已停用'])); } // 统计曝光次数,只+1不扣减,便于后续看运营趋势 $pdo->prepare('UPDATE wifi_info SET hit_count = hit_count + 1 WHERE id = ?') ->execute([$row['id']]); exit(json_encode([ 'code' => 0, 'data' => [ 'shop_name' => $row['shop_name'], 'wifi_name' => $row['wifi_name'], 'wifi_id' => $row['id'], ] ]));这个接口的两个关键点:正则白名单校验qr_key,把非法字符直接挡在数据库查询之前,这是防注入最省事的习惯;密码不下发,只回wifi_name,前端拿到后显示「正在连接 XXWiFi」,给用户一种「扫码后马上能连」的预期,真正的密码在广告完成后再请求。实际做广告后下发密码时,要额外带上 token 和 wifi_id,后端先查scan_log确认该 openid 在最近 5 分钟内有一条ad_finished=1的记录,再返回解密后的密码。这个「5 分钟内有效」的窗口期既能防止无限次刷密码,又不会因为顾客看个密码再输半天导致体验断裂。明文密码不要直接写进接口日志或数据库日志,JSON 返回后立即结束请求,避免日志泄露。
3.3 部署参数清单:HTTPS、域名校验、IP白名单和常见服务器配置
接口写完,部署时最容易出问题的不是代码,而是微信侧的域名校验。小程序正式版请求的服务器域名,必须是已备案的 HTTPS 域名,而且要在微信公众平台「开发管理-服务器域名」里配置 request 合法域名。开发阶段可以在开发者工具里勾选「不校验合法域名」,但真机预览和上线都必须走正规域名。给一份我常用的部署参数清单:
| 项目 | 参数建议 | 说明 |
|---|---|---|
| Nginx 站点 | listen 443 ssl; | 必须启用 HTTPS,证书用 Let's Encrypt 或云厂商免费证书均可 |
| PHP 版本 | PHP 7.4 或 8.1 | 版本不要太旧,避免加密库和 JSON 扩展缺失 |
| PHP-FPM | pm.max_children = 20起 | 小店日扫码量几百次,20 个子进程足够,没必要调大 |
| MySQL 连接 | 使用 PDO 预处理语句 | 统一走 prepared statement,避免手写拼接 SQL |
| 请求超时 | PHP 侧max_execution_time = 30 | 广告回调是异步的,接口本身响应要快,别在接口里同步等广告平台 |
| CORS | 只允许小程序域名来源 | 防止别人在网页里直接调用你的接口拿密码 |
部署完成后,先用 curl 验证一遍接口:curl 'https://your.domain.com/api/wifi.php?qr_key=test1234',确认能返回 JSON,再进小程序开发者工具联调。很多「真机连不上、开发者工具能跑」的翻车现场,八成都是合法域名没配置或者证书链不完整,优先排查这两个位置。
4. 小程序前端落地:扫码进店到密码展示的完整链路
4.1 从扫码到 wx.login:拿 code 换 token 的时序
小程序端的启动时序决定了用户从扫码到看到密码要等几秒。正确顺序是:小程序 onLoad 拿到二维码里的参数 → 调用uni.login()拿微信临时 code → 把 code 发给后端换 token → 用 token 查 WiFi 信息。下面是 uni-app 里这一段的写法,兼顾了缓存时间和参数兼容:
// pages/connect/index.vue export default { data() { return { qrKey: '', token: '', wifiInfo: null } }, onLoad(query) { // 小程序码 scene 方式传参时参数会拼在 path 里,query.scene 需要 decodeURIComponent const scene = query.scene ? decodeURIComponent(query.scene) : '' this.qrKey = scene || query.qr_key || '' if (!this.qrKey) { uni.showToast({ title: '二维码参数缺失', icon: 'none' }) return } this.loadToken() }, async loadToken() { const cachedToken = uni.getStorageSync('token') const cachedTime = uni.getStorageSync('token_time') // 设置缓存时间:2 小时内复用 token,避免每次扫码都走一次微信登录 if (cachedToken && Date.now() - cachedTime < 2 * 60 * 60 * 1000) { this.token = cachedToken this.loadWifi() return } const loginRes = await uni.login() const res = await uni.request({ url: 'https://your.domain.com/api/login.php', method: 'POST', data: { code: loginRes.code } }) if (res.data.code === 0) { this.token = res.data.data.token uni.setStorageSync('token', this.token) uni.setStorageSync('token_time', Date.now()) this.loadWifi() } }, async loadWifi() { const res = await uni.request({ url: 'https://your.domain.com/api/wifi.php', method: 'GET', data: { qr_key: this.qrKey }, header: { Authorization: `Bearer ${this.token}` } }) if (res.data.code === 0) { this.wifiInfo = res.data.data // 动态设置小程序头部标题,直接显示门店名,提升本地感 uni.setNavigationBarTitle({ title: this.wifiInfo.shop_name || '共享WiFi' }) } } }这里有几个参数值得较真。token 缓存时间设 2 小时,太短会导致顾客重复扫码时频繁白屏等登录,太长会让后端无法及时踢掉异常会话;实际运营中,顾客一天内多次进店是常态,2 小时是一个「安全感和性能平衡」的经验值。setNavigationBarTitle这个 API 经常被忽略,但它能直接改变小程序顶部的标题文字,把「共享WiFi」换成「XX咖啡馆」,顾客会明显觉得这套系统是这家店自己的,而不是一个到处贴的通用码。query.scene的decodeURIComponent是必写的,小程序码把参数塞进 scene 之后会自动编码,不转码会出现参数错乱。
4.2 激励视频广告位:看过广告再给密码的交互写法
密码展示是整个转化漏斗的最后一步,广告放这里能拿到最高的完播率。用小程序的激励视频组件uni.createRewardedVideoAd,核心逻辑是:先加载广告,播放,用户完整看完后触发 onClose 且isEnded为 true,才允许请求密码接口。代码骨架如下:
// pages/connect/index.vue 中广告与密码获取部分 let rewardedAd = null function getRewardedAd() { if (rewardedAd) return rewardedAd rewardedAd = uni.createRewardedVideoAd({ adUnitId: 'adunit-你的广告位ID' }) rewardedAd.onLoad(() => { console.log('激励视频广告加载成功') }) rewardedAd.onError((err) => { console.error('激励视频广告加载失败', err) }) rewardedAd.onClose((res) => { if (res && res.isEnded) { // 用户完整看完,允许获取密码 fetchPassword() } else { uni.showToast({ title: '看完整段视频才能获取密码', icon: 'none' }) } }) return rewardedAd } function playAd() { const ad = getRewardedAd() ad.show().catch(() => { // 首次加载失败时重新加载再展示,这是官方推荐的补偿写法 ad.load() .then(() => ad.show()) .catch(() => { uni.showToast({ title: '广告暂时不可用,请稍后再试', icon: 'none' }) }) }) } async function fetchPassword() { const res = await uni.request({ url: 'https://your.domain.com/api/password.php', method: 'POST', data: { wifi_id: this.wifiInfo.wifi_id }, header: { Authorization: `Bearer ${this.token}` } }) if (res.data.code === 0) { this.wifiPassword = res.data.data.wifi_password this.showPassword = true } else { uni.showToast({ title: res.data.msg || '密码获取失败', icon: 'none' }) } }这段逻辑里最容易翻车的点有两个。一个是isEnded判断不能省:用户看两秒就退出,不能给密码,这是收益的底线,不能为了体验放松。另一个是show().catch()的补偿:激励视频第一次拉取经常失败,不做 load 再 show 的补偿,用户会卡在「广告加载中」然后流失。密码拿到后,界面要给出「复制密码」按钮,复制用uni.setClipboardData,同时建议在旁边标注「iOS 用户请手动输入,安卓用户可尝试自动连接」。很多顾客拿了密码记不住,复制按钮能显著降低「又问老板一遍」的概率。
4.3 调试下载:真机预览、抓包与合法域名校验
小程序开发最磨人的阶段就是「开发者工具里正常,真机上一片白」。先讲抓包。调试接口时用 whistle 或 Charles 这类抓包工具是常规操作,思路是:在微信开发者工具里开启「不校验合法域名」,把请求代理到抓包工具,然后在小程序端触发一次扫码,观察接口的完整请求和响应。如果发现请求被拦,返回信息里出现not in the domain list,多半是合法域名没配;如果出现证书报错,多半是 HTTPS 证书链不完整。真机预览前,记得在开发者工具里把「不校验合法域名」关掉再测一次,否则会漏掉线上必现的域名问题。常见报错「开发版小程序已过期,请在开发者工具重新扫码」,是开发版二维码的时效机制,重新编译上传一个版本,再在工具里生成新的预览二维码就能解决,不影响线上正式版,不用慌。
5. 避坑排查:共享WiFi小程序独立版上线的6个避坑记录
5.1 扫出来的码是乱码或链接被微信拦截:scene 参数长度与编码
现象:打印出来的小程序码,扫了几次后偶尔进入页面提示「二维码参数缺失」,或者打开后qr_key变成一串被截断的字符。原因:小程序码的 scene 参数有 32 个字符的长度限制,直接把店名或过长的 key 塞进 scene,会被微信截断;另外 scene 内不允许出现某些特殊字符,中文必须编码。解决:qr_key用纯字母数字组合,尽量控制在 16 位以内,例如WX加日期加随机串;前端取到 scene 后先decodeURIComponent再使用。这个坑在后台生成二维码时就要做校验,生成端先检查长度,超过限制直接报错,而不是生成一张大概率失效的二维码。
5.2 「一键连接 WiFi」在 iPhone 上没反应:iOS 限制与手动输入的兜底
现象:安卓手机点了「一键连接」能跳转系统设置,iPhone 点了没反应,或者跳转后弹出一个网页说明文档,用户反而懵了。原因:iOS 的微信内置浏览器对「直接连 WiFi」的 scheme 支持非常有限,没有统一的系统级接口,靠网页 JS 触发连接基本不可靠。解决:把「一键连接」在 iOS 端隐藏或降级为「复制密码」,UI 上直接区分平台,安卓显示「去连接」,iOS 显示「复制密码」。这是很多独立版源码容易忽略的细节,产品上线前要找一台 iPhone 实测这个按钮,不能只看安卓的表现。
5.3 用户反馈「搜不到 WiFi 或连不上」:DHCP、隐藏SSID和频段问题
现象:顾客扫码拿了密码,但在手机 WiFi 列表里找不到这个网络,或者找到之后输入密码一直转圈连不上。原因:这不一定是小程序的问题,但顾客会把它算在小程序头上。展开排查,最常见的是路由器的 DHCP 服务被关闭,手机能搜到信号但无法获取 IP 地址,表现为一直显示「正在连接」;其次是 WiFi 设置了隐藏 SSID,手机不会主动在列表里展示;还有路由器开了 5G 或 6GHz 频段,老手机不支持,导致搜不到。解决:在后台的「门店设置」里加一个备注字段,让店家填写 WiFi 频段和是否隐藏;物料贴纸上也印一行「如果搜不到 WiFi,请看路由器背面确认名称」,把排查成本转移给店家而不是你的客服。这个坑验证了一个道理:共享WiFi小程序管得了密码展示,管不了店家路由器,边界要提前想清楚。
5.4 接口能通但密码一直获取失败:token过期与缓存乱象
现象:顾客上午扫过码,下午再扫,广告看完了,密码接口却返回「登录已过期」。原因:前端把 token 缓存了 2 小时,但微信的 code 换 token 机制有时会因为用户主动清理微信缓存或重新登录而失效;另外独立版源码如果改了 token 生成规则,旧的缓存 token 直接作废。解决:密码接口遇到 token 过期,不要只报错,要返回一个固定的错误码(例如code: 401),前端捕获到这个错误码后自动清掉本地缓存的 token,重新走一遍uni.login()。这个「自动续期」逻辑加在 fetchPassword 的 catch 分支里,比让用户退出重进强得多。前端设置缓存时间时,用uni.getStorageInfo顺手清理掉一个月前的旧记录,能减少很多玄学问题。
5.5 后台统计的扫码数和广告数对不上:计数时机错误
现象:后台报表显示曝光 1000 次,但广告结算后台只有 300 次有效播放。原因:常见原因是把「进入页面」和「扫码成功」都算进了曝光,而广告有效播放的口径是「完整看完」;另一个更隐蔽的原因是加密二维码被同一用户反复扫,每次进入都 +1。解决:曝光数按扫码进入计一次,广告完成数按scan_log中ad_finished=1的条数计,不要把两个字段混在一个数里;同一 openid 5 分钟内的重复扫码只记一次。上线前用两个微信号交替扫码,对比后台数据和广告平台数据,验证口径一致再放开。
5.6 想用家里电脑当服务器部署:公网与域名限制
现象:开发阶段为了省钱,想用家里电脑当服务器,或者用内网穿透工具把本地接口暴露出去,结果真机预览一访问就报「request:fail」。原因:微信小程序正式环境的 request 域名必须是公网可访问且已备案的 HTTPS 域名,家庭宽带的公网 IP 不可控,内网穿透取证链也容易让微信访问失败;这是平台的硬性校验,绕不过去。解决:开发调试阶段用开发者工具加「不校验合法域名」,可以连本地接口;但要给客户演示或上线,至少要租一台最便宜的云服务器,把域名解析过去,申请免费证书。这不是推荐你多花钱,是微信侧的规则就是如此,源码部署这套流程里省不掉。
6. 进阶与验证:把单店共享WiFi做成长期可运营的服务
单店方案跑通后,值得做的第一件事是把二维码从静态改成动态。静态码把 WiFi 信息直接编进码里,店家改密码就要重新打印物料,成本全在运营端;动态码的qr_key指向后台记录,店家在管理后台改密码后,桌上那张码不用换,顾客扫出来仍然是新密码。这一步直接把「维护成本」降了一个量级,也是你从卖源码延伸到做代运营的切入点。
验证这套系统是否合格,我习惯按一个检查清单过一遍:拿两个手机,一个完整看完广告拿密码,一个看两秒退出,确认后者拿不到密码;把 WiFi 密码改成带空格和#的复杂密码,确认展示和复制都正常;断网后重进小程序,确认缓存和 token 逻辑能兜底而不是白屏;连续扫码五次,看后台scan_log是否把重复扫码正确去重。广告位方面,主流程的激励视频按钮要放在视觉中心,文案写「看广告获取密码」,不要诱导点击,否则广告平台审核会找麻烦;流量主后台的收益数据要每周对一次,发现单价比正常低很多,检查是不是广告位类型选错了。小程序每年还要在微信侧做年审,账号到期前记得处理,否则线上版本会受影响。
这套东西值不值得做,我的判断是:作为独立开发者接单或做区域代理,它是少数「需求明确、变现路径短、技术门槛中等」的产品;但指望躺赚不现实,真正的护城河在门店拓展能力和后续的服务响应。我自己的习惯是上线第一个店之后,至少让老板用一周、反复要三次反馈再复制到第二家店,运营数据比代码本身更能说明问题。这个方向上,先把一个店的服务闭环跑顺,再考虑连锁和代理,希望帮到你。
本文还有配套的精品资源,点击获取