
简介一套面向本地共享wifi运营场景的小程序独立版源码适合打算快速搭建自主共享wifi平台的团长、拓展员、商家或个人开发者使用。包内共2004个文件以749个php后端脚本、140个js逻辑文件、124个json配置及24个css样式为主并辅以图片、markdown文档与少量视频整体压缩包约68MB目录结构较完整便于按功能模块查阅。已有198人学习下载。源码不仅覆盖小程序搭建与参数配置所需的技术细节且无需从零开发按教程即可完成部署方案还涉及硬件选购如打印机型号选择和设备下载部署等线下环节的指导。运营层面则围绕市场定位、用户引导、活动策划与会员管理提供策略参考帮助整合团长、拓展员、商家资源从零构建并持续运营本地化共享wifi生态是一份技术搭建与商业落地兼备的实用参考。1. WIFI共享小程序独立版源码到底解决什么问题从扫码连网到数据自持店铺老板不想把WiFi密码反复报给客人前台也不愿意每人问一次就答一次。把WiFi密码放到小程序后台客人扫桌上的码小程序自动调起系统连接WiFi这是市面上大多数“WiFi共享小程序”的用法。但它有个绕不开的问题平台版数据都放在服务商那里热点位置、连接记录、密码明文全是别人说了算。独立版源码就是为了把这一层拿回来——前端、后端、数据库全部自己部署密码自己存连接记录自己看出了异常可以翻日志排查。适合谁做这件事呢一类是手上有一台云服务器、会一点后端接口阅读能力的小团队想给客户或门店做一套可定制品牌的小程序另一类是公司内部访客网络管理需要记录谁在什么时间连过WiFi。如果你只是个人想连自家路由器用官方App就够了。独立版源码的投入在于服务器、域名、微信小程序认证还有后续的接口维护但它换来的是数据可控、页面可改、运营规则自己定。2. 独立版源码的技术构成uniapp前端、接口服务与数据库表怎么选2.1 前端为什么选uniapp一次开发覆盖微信小程序、H5和管理后台做WiFi共享小程序最容易踩的第一个坑就是只盯着微信小程序写。等到要做管理员页、做用户协议页、做客服消息跳转时你会发现同样的逻辑要再写一套H5。uniapp在这类项目里的优势是用Vue语法写一套代码同时编译到微信小程序、H5以及其他平台连“微信小程序 vs Android/iOS/鸿蒙”的端差异都只在条件编译里处理不需要维护三套工程。从源码角度看uniapp项目的页面结构是pages目录下每个模块一个文件夹stores里放状态管理common里放请求封装。这套结构对WiFi共享场景足够清楚用户端页面放在pages/connect管理员页面放在pages/admin公共API封装在utils/request.js。真机上跑通微信小程序后需要做管理后台网页时直接再编译一次H5版不用另起炉灶。2.2 后端接口服务的选型Flask还是Node.js独立版为什么建议分开部署WiFi共享小程序的后端业务不重核心就是提供热点列表、校验密码、记录连接行为。常见做法是用Python Flask或Node.js Express写一组REST接口数据库用MySQL。选Flask的原因是这个场景的接口不超过十个用Flask写起来直接一套路由对应一个热点查询不需要引入重型框架但如果你团队更熟JavaScript用Node.js也完全成立关键是接口要保持同样语义前端不用感知后端语言。我建议把后端和小程序前端分开部署而不是塞进同一个服务里。原因是小程序前端只走HTTPS域名后端接口要配SSL证书分开部署时证书出问题只会影响API不会连累页面资源另外后端未来要加管理员登录、设备下线、导出记录这些功能时独立服务也更好扩展。独立版源码的“独立”二字就体现在这里它不是套在某个小程序平台里的配置项而是一个自己控制的接口服务。2.3 数据库三张核心表热点表、连接记录表、管理员表WiFi共享小程序的数据模型可以压缩到三张表。第一张是热点表hotspot记录每个WiFi点的SSID、加密方式、密码密文、门店名称、备注、启停状态第二张是连接记录表connect_log记录哪个用户通过哪个热点连接、连接时间、客户端类型第三张是管理员表admin存账号、密码哈希、角色。热点表和服务商的平台版最大的区别是你可以随时改某一家门店的WiFi名而不影响其他店这就是独立部署的灵活性。这里有个容易忽略的字段hotspot表里要留一个share_code用来生成扫码参数。用户扫码进入小程序时前端只拿到这个短码再向后端换真正的SSID和密码这样二维码贴在桌上不怕被人扫走密码。连接记录表里也要加一个expire_at字段用于做访客WiFi的定时下线这是平台版基本不会给你开放的能力。2.4 源码目录的大致结构与改动边界拿一套独立版源码后先别急着改代码按目录把边界分清。前端uniapp项目的src下pages是页面utils是请求封装static是静态图后端服务按flask route分文件app.py是入口models.py是表结构config.py是环境配置。数据库初始化脚本通常在sql目录里面是建表和种子数据。改动边界我个人一般这样划能不改的尽量不动尤其是请求封装和登录态逻辑。小程序端的登录态、请求头携带token、错误码统一处理这几块是整个项目最容易改坏的地方一旦改错所有页面都会跟着报错。你要改的核心其实只有两处一处是后端config.py的数据库连接和密钥一处是前端utils/request.js里的baseURL。其他页面级定制等跑通后再动。3. 把WIFI共享小程序跑起来初始化数据库、启动接口并发版小程序3.1 初始化数据库建库建表SQL与字段说明拿到源码第一件事不是打开小程序而是先把数据库建起来。下面这个SQL按照常见独立版结构整理了最小表集合字段名做了精简但语义和大多数实现一致CREATE DATABASE IF NOT EXISTS wifi_share DEFAULT CHARACTER SET utf8mb4; USE wifi_share; CREATE TABLE hotspot ( id INT AUTO_INCREMENT PRIMARY KEY, ssid VARCHAR(64) NOT NULL COMMENT WiFi名称, password_cipher VARCHAR(256) NOT NULL COMMENT AES加密后的密码, encrypt_key_id VARCHAR(32) NOT NULL COMMENT 密钥版本, shop_name VARCHAR(128) DEFAULT COMMENT 门店名称, share_code VARCHAR(32) NOT NULL UNIQUE COMMENT 扫码短码, enabled TINYINT(1) DEFAULT 1 COMMENT 是否启用, expire_seconds INT DEFAULT 0 COMMENT 单次连接有效期0为不限, created_at DATETIME DEFAULT CURRENT_TIMESTAMP ) ENGINEInnoDB; CREATE TABLE connect_log ( id INT AUTO_INCREMENT PRIMARY KEY, hotspot_id INT NOT NULL, openid VARCHAR(64) NOT NULL COMMENT 微信用户标识, ssid VARCHAR(64) NOT NULL, client_type VARCHAR(16) DEFAULT COMMENT Android/iOS/devtools, connected_at DATETIME DEFAULT CURRENT_TIMESTAMP, expire_at DATETIME DEFAULT NULL COMMENT 到期时间 ) ENGINEInnoDB; CREATE TABLE admin ( id INT AUTO_INCREMENT PRIMARY KEY, username VARCHAR(32) NOT NULL UNIQUE, password_hash VARCHAR(128) NOT NULL, role VARCHAR(16) DEFAULT admin ) ENGINEInnoDB;这段SQL里有三个设计意图要注意。密码字段叫password_cipher存的是加密后的密文而不是明文后面接口返回时才解密避免数据库泄露直接带走密码share_code加了唯一索引因为扫码场景里前端只传这个码不允许重复connect_log里单独记client_type排查问题时有非常关键的作用——你会发现开发工具、Android、iOS在连接WiFi上的行为完全不一样没有这个字段很难定位日志。3.2 启动后端接口Python Flask示例与关键配置数据库就绪后后端服务用Flask跑一组最小接口。这里演示热点换密码和记录连接行为两个核心接口其他登录、管理类接口按同样模式扩展# app.py from flask import Flask, jsonify, request from flask_cors import CORS import pymysql, os, time, base64 from cryptography.fernet import Fernet app Flask(__name__) CORS(app) # 开发期放开跨域上线前收紧 DB_CONFIG { host: os.getenv(DB_HOST, 127.0.0.1), user: os.getenv(DB_USER, root), password: os.getenv(DB_PASSWORD, your_password), database: wifi_share, charset: utf8mb4, } def get_db(): return pymysql.connect(**DB_CONFIG, cursorclasspymysql.cursors.DictCursor) app.route(/api/hotspot/info, methods[GET]) def hotspot_info(): share_code request.args.get(code, ) db get_db() try: with db.cursor() as cur: cur.execute( SELECT id, ssid, password_cipher, shop_name, expire_seconds FROM hotspot WHERE share_code%s AND enabled1, (share_code,) ) row cur.fetchone() if not row: return jsonify({code: 404, msg: 热点不存在或已停用}) cipher Fernet(os.getenv(ENCRYPT_KEY, ).encode()) password cipher.decrypt(row[password_cipher].encode()).decode() return jsonify({ code: 0, data: { ssid: row[ssid], password: password, shopName: row[shop_name], expireSeconds: row[expire_seconds], } }) finally: db.close() app.route(/api/connect/log, methods[POST]) def connect_log(): body request.get_json() db get_db() try: with db.cursor() as cur: cur.execute( INSERT INTO connect_log (hotspot_id, openid, ssid, client_type) VALUES (%s, %s, %s, %s), (body[hotspotId], body[openid], body[ssid], body.get(clientType, )) ) db.commit() return jsonify({code: 0}) finally: db.close() if __name__ __main__: app.run(host0.0.0.0, port8000)接口逻辑不复杂但有三处参数直接决定线上能不能用。hotspot_info接口用share_code换WiFi信息而不是把全部热点返回前端这样二维码泄露了也只是泄露一个短码攻击者拿到短码后还要过这层接口才能换到密码。密码解密用的ENCRYPT_KEY从环境变量读取不要写死在代码里。connect_log写入前没有校验hotspot_id生产环境建议加一层鉴权至少校验openid是否为当前登录用户否则任何人可以伪造连接记录刷爆数据库。3.3 用微信开发者工具打开小程序前端并配置request域名后端启动后把uniapp工程导入微信开发者工具。第一步修改utils/request.js里的baseURL域名就是你后端服务的HTTPS地址注意必须是HTTPS且已经在微信小程序后台配置过request合法域名。开发者工具里默认不校验合法域名可以先把请求跑通但真机预览必须开启“不校验合法域名”才能调试正式发布前一定关闭。配置域名在小程序后台的“开发管理-服务器域名”里操作request合法域名填接口域名uploadFile合法域名如果有上传图片需求也要加。这里有个容易忽略的细节域名不能带端口号必须是标准443端口如果后端跑在8000端口需要在前面加一层Nginx把80和443转发到8000否则小程序后台拒绝保存域名。3.4 用真机预览验证扫码流程开发者工具里能跑通不代表真机能用WiFi类功能尤其如此。用uniapp编译到微信小程序后点“预览”会生成一个二维码用测试手机扫码打开。手机上先确认能进入热点详情页能看到从后端换回来的SSID和密码再点击连接按钮验证系统弹窗。这一步最容易出现的问题不是代码报错而是权限链路没走通。Android端微信需要定位权限才能扫描附近的WiFiiOS端首次连接要在系统设置里确认加入网络。所以真机预览时准备两台手机一台Android一台iOS把两端行为都记录下来再继续往下调。3.5 本地抓包排查接口返回如果真机上页面拿不到WiFi信息用抓包工具看请求链路。小程序请求走的是HTTPS常规做法是电脑上开抓包工具手机代理到电脑再把抓包工具的根证书装到手机上这样能看到小程序发出去的每个请求和返回体。注意抓包只用于联调阶段证书装到手机上本身有风险联调完要卸掉描述文件。抓包重点看三件事请求头有没有带token、接口返回的JSON是否符合前端预期、后端日志里有没有抛异常。大多数“前端白屏”问题的根因不是小程序代码而是后端返回的data字段名和前端不一致比如后端返回ssid前端读的是wifiName字段对不上就会一直连接失败。4. 小程序连WiFi的核心APIconnectWifi参数、系统权限与扫码分享的边界4.1 连接WiFi的标准调用顺序startWifi与connectWifi参数详解微信小程序连WiFi的能力来自wx.startWifi和wx.connectWifi两个接口顺序不能颠倒。先调用wx.startWifi初始化WiFi模块等success后再调wx.connectWifi传入SSID和密码。直接调connectWifi在部分Android机型上会报“未初始化”错误这是文档里不太会强调的坑。一次完整调用示意如下// pages/connect/index.js connectWifi() { const { ssid, password } this.data.hotspot; wx.startWifi({ success() { wx.connectWifi({ SSID: ssid, password: password, success(res) { wx.showToast({ title: 已连接, icon: success }); wx.getConnectedWifi({ success(res) { this.recordConnectLog(res.wifi.ssid); }.bind(this), }); }, fail(err) { wx.showToast({ title: 连接失败请手动连接, icon: none }); }, }); }, fail() { wx.showToast({ title: WiFi模块初始化失败, icon: none }); }, }); }这段代码对参数有严格要求。startWifi不带任何参数只需要保证在connectWifi之前调用connectWifi的SSID是必选password在目标WiFi是开放网络时为空字符串加密网络必须传明文密码success回调里拿到的是“已发连接指令”而不是“系统已连上”所以紧接着调wx.getConnectedWifi去确认状态。实际开发中iOS端即使connectWifi返回success系统也可能弹窗询问是否加入这个弹窗无法在小程序里控制。4.2 iOS与Android在自动连WiFi上的行为差异不同端对WiFi API的支持程度差异非常大这是共享小程序最需要提前知晓的边界。Android端在微信授权定位后可以做到用户点击按钮直接发起连接系统弹一次确认窗同意后即连上iOS端则限制更多当目标WiFi不是当前路由时小程序无法直接连接只能引导用户跳到系统设置页手动选择网络。处理iOS的常见做法是调用wx.openSystemSetting或wx.openSetting打开系统设置页并在页面里展示步骤引导。更现实的方案是检测到iOS时把密码复制到剪贴板同时提示用户去系统设置的WiFi列表里找到对应SSID粘贴密码。不要试图在iOS上做全自动连接微信不会放开这个能力硬做只会换来用户在审核和真机上的双重抱怨。4.3 动态设置顶部标题与缓存过期时间共享小程序的服务对象是门店门店希望在扫码进入时能看到“欢迎光临XX店”而不是默认的小程序名。这需要在页面onLoad里根据后端返回的门店名调用wx.setNavigationBarTitle把顶部标题改成实际店名。这个接口简单但要注意时机必须在请求到数据后再设置否则会闪一下默认标题。密码在端上的保存也要控制生命周期。不要去localStorage里长期存WiFi密码因为小程序缓存一旦被读取抓到包就能看到明文密码。常见做法是设置一个5到10分钟的缓存时间用wx.setStorageSync存入ssid和password同时记录一个expireTimestamp每次使用前校验当前时间是否超过缓存时间超过就重新向后端请求。微信小程序设置缓存时间有三个可选级别内存变量、storage、storageSync推荐用storageSync因为页面onLoad重新执行时能直接同步读出来。4.4 扫码进入后的参数解析与防伪造共享小程序的主要入口是扫桌上的二维码这个二维码是小程序码而不是普通二维码扫进去后通过场景值拿到热点标识。小程序码的scene参数有长度限制只能传32位以内的可见字符所以后端生成share_code时不要用UUID长串用类似门店ID加随机数的短码比如S1001A8F2。防伪造的关键是share_code本身不能携带密码信息它只是一个索引。攻击者即使抓包拿到这个码也只能请求到对应热点的密码而密码密文由后端统一管理。后端在返回密码前还应该做频率限制同一share_code在短时间内被不同openid频繁请求就触发告警避免有人用脚本批量扫热点密码。4.5 连接记录上报与设备识别连接成功后前端要把这次行为上报给后端这是独立版相对于平台版的核心数据资产。上报时不能只传hotspotId还要传clientType因为开发者工具模拟器的WiFi环境和真机完全不同字段区分能帮你从日志里快速筛出问题设备。clientType的取值可以按平台判断uni.getSystemInfoSync().platform返回android或ios开发者工具环境返回devtools。上报时机放在wx.getConnectedWifi确认已连接之后不要放在connectWifi的success回调里。原因是connectWifi成功只代表指令发出去了未必真连上而getConnectedWifi成功后基本可以确认当前已处于目标网络。上报请求失败不要阻塞用户操作用静默发送后端写日志就好下次连接时再用新的记录覆盖。5. WIFI共享小程序常见坑与排查从开发者工具到真机的五条踩坑记录5.1 现象iOS点击“连接WiFi”后没有弹出系统连接确认客户端在iOS上点了连接按钮页面提示“已连接”但WiFi列表里根本没有这个网络系统也没弹任何确认框。反复点击几次后偶尔能弹一次但大部分时间无反应。原因iOS对私有WiFi网络的连接有系统级限制wx.connectWifi在iOS上只能连接当前已经连上的路由或者切换到系统设置页手动操作。Android上那一套“传参-回调-success”的流程在iOS里并不完整生效success回调只能说明参数被接受了。解决代码里做平台判断iOS端不调用connectWifi改为把密码复制到剪贴板调用wx.setClipboardData然后引导用户打开系统设置页。页面提示文案写成“请选择与小程序提示相同的WiFi名称粘贴密码连接”这一步虽然绕但能覆盖90%以上的iOS用户。5.2 现象Android连上了WiFi但小程序里getConnectedWifi拿不到ssidAndroid真机上系统WiFi列表已经显示已连接但wx.getConnectedWifi返回fail或者ssid是空字符串。开发者工具上一切正常一到真机就翻车。原因Android 10及以上版本限制了应用读取已连接WiFi信息微信小程序也没有过多豁免必须在用户授权定位权限后才能拿到ssid。很多Android rom还会二次弹窗询问“是否允许微信获取位置信息”用户拒绝后小程序就拿不到任何WiFi信息。解决调用getConnectedWifi之前先检查定位权限。小程序端没有直接的“申请定位权限”接口需要触发wx.getLocation并用它的授权流程或者引导用户到小程序设置页打开位置权限。同时做好fail分支拿不到ssid不代表没连上直接把连接记录上报里的ssid字段留空后端再通过热点ID关联不影响业务。5.3 现象开发者工具里所有请求都fail真机却能通在微信开发者工具里打开项目接口请求全部报“request:fail”Network面板里看不到任何响应但同一台电脑上用真机预览接口正常返回数据。原因开发者工具的“不校验合法域名”开关默认关闭而本地联调时接口域名往往是http://192.168.x.x:8000或者后端只监听本地端口没有开启HTTPS。微信小程序要求正式环境必须HTTPS开发者工具在没关闭域名校验时直接拦截了请求。解决联调阶段在开发者工具详情设置里勾选“不校验合法域名、web-view业务域名、TLS版本以及HTTPS证书”再把baseURL指向局域网地址。如果要真机联调在手机微信的调试菜单里同样开启“不校验合法域名”。上线前恢复baseURL成正式HTTPS域名并把不校验合法域名的开关关掉。后端如果用Flask直跑本地环境不要死磕证书直接用这台开发机做内网穿透是最省事的做法。5.4 现象管理员改密后用户还连着旧密码的WiFi后端管理员把某个热点的WiFi密码改掉但已有用户仍然连着旧网络日志里显示该用户用的是旧密码建立连接的。新用户扫同一个码也连不上提示密码错误。原因WiFi密码修改后已经建立会话的设备在断开前仍然保持连接这是网络层的行为小程序无法主动踢掉已连接设备。新用户连不上则大概率是前端缓存了旧密码小程序端把password存在了storage里缓存时间又设得特别长。解决后端连接记录表里加expire_at管理员改密后把该热点未过期的记录批量置为过期。前端把缓存的过期时间缩短到5分钟同时在后端返回的hotspot信息里带一个config_version字段Redis或MySQL里记录当前版本号前端每次扫码时先比较版本号不一致就清掉本地缓存重新请求。更重要的是改密后让管理员在后台把这台设备的“连接有效期”置零引导用户在系统WiFi设置里忘记该网络重连。5.5 现象小程序提审被拒提示类目与功能不符提交审核后微信反馈“小程序涉及收集用户隐私信息未声明”或“功能涉及诱导打开系统设置”。很多共享类小程序第一次提审都会卡在这里。原因小程序读取WiFi信息、申请定位权限、复制剪贴板都涉及用户隐私接口必须在mp后台的“用户隐私保护指引”中声明收集位置信息、剪切板信息。审核员看到你在代码里调用了相关API但指引里没有对应声明就会驳回。解决在微信小程序管理后台的用户隐私保护指引里勾选“位置信息”“剪切板信息”“设备信息”等实际用到的类别并说明用途是“用于连接门店共享WiFi”。代码里尽量把定位权限的调用时机后置用户点击扫描WiFi时才申请而不是启动小程序就要。审核页面不要出现“强制关注公众号才能连WiFi”之类的逻辑一旦被判定为诱导关注基本没有申诉空间。6. 上线后的自检顺序从管理员改密到设备强制下线小程序跑通只是第一步真正值得投入的是把“共享”这件事做成可持续运营。上线前我习惯按三个顺序自检第一步是管理员操作闭环。管理后台至少要有三个入口修改热点密码、查看连接记录、强制下线指定设备。强制下线不要只改数据库要同步更新热点表里的config_version让前端缓存自动失效。这个动作做完后用一台旧手机连上WiFi再去后台点下线验证这台手机是不是在短时间内被系统踢掉。第二步是弱网和异常场景验证。把手机的微信小程序杀掉重新扫同一个码确认能正常回到热点页而不是卡在启动加载页。后端接口在弱网时返回超时前端要能显示“网络不给力”而不是白屏。真实场景里客人站在店里角落扫码时信号很差这一关过不了其他功能再好也会被差评。第三步才是正式发布。把开发者工具里的不校验合法域名开关关掉重新编译上传走一遍完整的审核提交流程。审核通过后再真机扫码跑一次全流程确认线上版本和联调版本行为一致。这套独立版源码做到这个程度已经不只是给客人连WiFi的工具。连接记录里能看到每天的访客高峰时段每个门店热点了多少人密码改了多少次。这些数据从平台版里拿不到却是独立部署最核心的回报。我自己做过的共享类项目里最常被问的一句话是“为什么不能自动连”答案是微信就没开放这个能力与其在系统权限上绕来绕去不如把引导流程和错误提示写清楚客人三步内能连上才是真的体验。希望帮到你少走点系统适配的弯路。本文还有配套的精品资源点击获取