
简介这是一套基于PHP开发的微信公众号上门美容服务系统面向中小型美业机构及PHP开发者提供智慧美业O2O业务落地的完整技术方案。系统依托微信公众号实现用户预约、技师管理、订单调度、服务评价等核心功能适用于家政类、轻医美、SPA上门等场景适合具备PHPMySQL基础的中初级开发者学习与二次开发。资源包共2000个文件主体为596个htm/379个html页面模板、546个js交互脚本、327个css样式文件辅以129个txt配置说明和1个sql数据库初始化脚本整体114.97MB结构清晰、模块划分明确含operamasks-ui等前端UI组件及多浏览器兼容样式如editor_ie.css、editor_gecko.css等体现较强的工程化适配能力。目前已有96人学习下载可直接部署运行获取完整前后端代码、响应式界面实现逻辑及微信JS-SDK集成范例。1. 这不是又一个微信模板消息Demo它是一套能真实调度美容师、核销服务单、对接微信支付与公众号菜单的PHP O2O业务系统你在网上搜“PHP 微信公众号 美容”时大概率会看到一堆静态页面、单页预约表单或仅能发模板消息的demo。但这个名为“基于PHP的微信公众号上门美容系统智慧美业O2O”的项目本质是一套面向中小型美业门店落地的轻量级SaaS化业务闭环系统——它用原生PHP非Laravel/ThinkPHP等框架实现从用户在公众号点击“预约美甲师”开始到后台派单、美容师接单、上门服务、微信支付回调、服务完成核销、评价沉淀的全链路。它不依赖复杂中间件适配Apache/NginxPHP 7.2~8.1环境数据库用MySQL 5.7核心逻辑集中在/app/下的控制器与模型层。适合已有微信公众号认证资质、想快速上线“线上预约线下履约”能力的美容院、美甲店、上门化妆工作室。如果你正被“怎么让客户在公众号里真正下单而不是只看文章”困扰这套代码提供的是可调试、可删减、可嵌入现有网站的生产级起点而非教学玩具。2. 搭建前必须厘清的三个技术锚点微信公众号配置、PHP运行时约束、O2O业务状态机设计2.1 微信公众号必须开通的服务类目与接口权限不是“绑定公众号”就完事该系统依赖微信公众号的服务号高级接口能力绝非订阅号或未认证号可运行。部署前需确认公众号已通过微信认证并在“公众号设置 功能设置 服务器配置”中启用以下三项JSAPI支付权限用于生成jsapi_ticket和调起微信内H5支付需在微信商户平台关联同一主体的商户号模板消息接口已升级为“订阅消息”系统用其推送“订单已创建”“美容师已接单”“服务即将开始”三类关键通知需在公众平台后台手动申请对应模板ID如OPENTM207XXXXX并在代码中硬编码填入config/wechat.php的template_id字段网页授权获取用户信息用于静默获取用户OpenID及昵称头像需在“开发 接口权限 网页服务”中开启“网页授权”并配置合法域名如https://yourdomain.com到“业务域名”与“JS接口安全域名”。提示若跳转授权页提示“redirect_uri域名与后台配置不一致”请检查/app/common/wechat.class.php中$this-redirect_uri是否与公众平台填写的完整协议域名端口完全一致例如https://api.yourbeauty.com/oauth.php且该URL能被公网直接访问。2.2 PHP环境必须满足的最小硬性要求否则连登录页都打不开系统使用PHP原生PDO扩展操作数据库依赖curl发起微信API请求且大量使用json_encode()处理Unicode中文。因此PHP配置需满足php.ini中必须启用extensionphp_pdo_mysql.dllWindows或extensionpdo_mysql.soLinuxcurl.cainfo路径需指向有效的CA证书包推荐使用 curl-ca-bundle 否则微信HTTPS接口调用会因SSL证书验证失败而超时date.timezone必须显式设置为中国时区如Asia/Shanghai否则订单时间戳、支付超时计算将错乱upload_max_filesize和post_max_size建议设为32M以支持美容师上传服务过程图片。验证方式在Web根目录下新建phpinfo.php写入?php phpinfo(); ?访问后搜索关键词pdo_mysql、curl、date.timezone确认状态为enabled且值正确。2.3 O2O核心状态流转不是线性流程而是带分支与超时的有限状态机FSM系统订单状态并非简单的“待支付→已支付→已完成”而是严格遵循美业上门服务特性设计的状态机状态码状态名触发条件后续可转入状态0草稿用户填写预约表单但未提交—1待支付用户提交订单生成微信预支付订单0, 2, 9超时关闭2已支付微信支付成功回调/pay/notify.php写入支付时间3, 4, 9用户取消3已派单后台管理员在/admin/order_list.php点击“派单”分配美容师5, 6, 9美容师拒单4待接单订单进入抢单池美容师APP/公众号菜单可查看并点击“接单”3, 5, 6, 9超时自动取消5服务中美容师点击“开始服务”系统记录service_start_time6, 7, 9异常终止6待评价美容师点击“服务完成”触发模板消息通知用户评价7, 9用户超时未评7已完成用户提交评价或系统自动超时关闭默认72小时—9已关闭用户取消、支付超时、美容师拒单、系统异常等所有终止场景—该状态机逻辑实现在/app/model/order.class.php的changeStatus()方法中每个状态变更均校验前置条件如“已支付”才能派单、写入操作日志、触发对应事件如发模板消息。修改状态码映射或跳过校验将直接导致业务逻辑断裂。3. 本地快速跑通最小可行版本从解压到能预约下单的五步实操3.1 解压与目录结构认知关键文件夹与入口文件定位将php版.zip解压至Web服务器文档根目录如/var/www/html/beauty/典型结构如下beauty/ ├── admin/ # 后台管理界面需账号密码登录 ├── app/ # 核心业务逻辑控制器、模型、工具类 │ ├── common/ # 公共类微信SDK、数据库连接、日志 │ ├── controller/ # 控制器order.ctrl.php处理订单user.ctrl.php处理用户 │ └── model/ # 数据模型order.class.php定义订单状态机 ├── assets/ # 静态资源CSS/JS/图片 ├── config/ # 配置文件wechat.php存AppID/AppSecretdb.php存数据库连接 ├── index.php # 前端首页入口公众号菜单指向此 ├── pay/ # 支付相关notify.php接收回调jsapi.php生成支付参数 └── upload/ # 用户/美容师上传文件存放目录需755权限注意/upload/目录必须赋予Web服务器进程写权限如chmod 755 upload否则用户头像、服务图片无法保存/config/db.php中的数据库配置需按实际环境修改否则app/common/db.class.php连接将失败。3.2 数据库初始化执行SQL脚本并验证表结构系统附带database.sql文件包含beauty_users用户、beauty_beauticians美容师、beauty_orders订单、beauty_services服务项目四张核心表。执行步骤# 登录MySQL mysql -u root -p # 创建数据库字符集必须为utf8mb4 CREATE DATABASE beauty_o2o DEFAULT CHARACTER SET utf8mb4 COLLATE utf8mb4_unicode_ci; # 选择数据库并导入 USE beauty_o2o; SOURCE /path/to/your/beauty/database.sql;关键表结构验证执行DESCRIBE beauty_orders;status字段类型为TINYINT(1)取值范围0-9对应前述状态机openid字段为VARCHAR(64)存储微信用户唯一标识pay_time、service_start_time等时间字段为DATETIME非TIMESTAMP避免时区转换歧义。3.3 微信配置文件填充三处硬编码必须同步更新打开/config/wechat.php修改以下三项return [ appid wx1234567890abcdef, // 替换为你的公众号AppID appsecret your_app_secret_here, // 替换为公众号AppSecret mch_id 1234567890, // 替换为微信商户号 key your_merchant_api_key, // 替换为微信商户平台API密钥32位 template_id OPENTM207XXXXX, // 替换为申请到的订阅消息模板ID redirect_uri https://yourdomain.com/oauth.php // 必须与公众号后台配置一致 ];提示key值在微信商户平台“账户中心 API安全”中设置不是商户号密码template_id需在“模板库”中搜索“服务预约”类模板并选用复制其ID粘贴至此。3.4 启动服务并测试首单绕过支付直设状态验证流程为快速验证业务流可临时跳过微信支付环节访问前台首页https://yourdomain.com/index.php点击“立即预约”填写手机号、服务项目、预约时间提交后进入/order/submit.php此时订单状态为1待支付打开数据库执行UPDATE beauty_orders SET status2, pay_timeNOW() WHERE id(SELECT MAX(id) FROM beauty_orders);访问后台https://yourdomain.com/admin/用默认账号admin/password登录在“订单列表”中找到该订单点击“派单”将其状态改为3已派单刷新前台页面应看到订单状态变为“已派单”且显示分配的美容师姓名。此流程验证了从用户提交→订单创建→状态变更→后台操作的全链路证明核心逻辑已就绪。3.5 关键接口调试用curl模拟微信支付回调验证通知处理支付成功后微信服务器会向/pay/notify.php发送XML格式回调。手动模拟可验证该接口是否正常解析并更新订单curl -X POST \ https://yourdomain.com/pay/notify.php \ -H Content-Type: application/xml \ -d xml return_code![CDATA[SUCCESS]]/return_code return_msg![CDATA[OK]]/return_msg result_code![CDATA[SUCCESS]]/result_code openid![CDATA[oAbc1234567890Defghijklmnop]]/openid out_trade_no![CDATA[ORD202310010001]]/out_trade_no transaction_id![CDATA[12345678901234567890123456789]]/transaction_id time_end![CDATA[20231001120000]]/time_end total_fee![CDATA[19900]]/total_fee /xml成功响应应为return_codeSUCCESS/return_code且数据库中对应订单status变为2pay_time被写入。若返回FAIL检查/pay/notify.php第15行$input file_get_contents(php://input)是否能正确读取原始XML——某些Nginx配置会因client_max_body_size过小而截断。4. 美容师端与用户端的关键交互逻辑如何让“上门服务”在线上闭环4.1 美容师接单与服务状态同步基于轮询的轻量级实时方案系统未采用WebSocket或长连接而是通过前端JavaScript定时轮询/api/beautician_status.php获取自身订单状态// 美容师端JS/assets/js/beautician.js function checkOrderStatus() { fetch(/api/beautician_status.php?beautician_id123) .then(res res.json()) .then(data { if (data.status 4 data.order_id) { // 待接单 showNotification(您有新订单订单号 data.order_id); document.getElementById(order-card).style.display block; } else if (data.status 5) { // 服务中 startCountdown(data.service_start_time); // 启动倒计时 } }); } setInterval(checkOrderStatus, 10000); // 每10秒轮询一次后端/api/beautician_status.php逻辑?php require_once ../app/common/db.class.php; $beautician_id $_GET[beautician_id] ?? 0; $sql SELECT id, status, service_start_time FROM beauty_orders WHERE beautician_id ? AND status IN (4,5,6) ORDER BY create_time DESC LIMIT 1; $stmt DB::getInstance()-prepare($sql); $stmt-execute([$beautician_id]); $result $stmt-fetch(PDO::FETCH_ASSOC); echo json_encode($result ?: [status 0]); ?提示轮询间隔设为10秒是平衡实时性与服务器压力的经验值若美容师数量超50人建议在beauty_orders表的beautician_id和status字段上建立联合索引KEY idx_bea_stat (beautician_id,status)避免全表扫描。4.2 用户端服务核销扫码核销与地理位置校验双保险上门服务完成后用户需在公众号内点击“核销码”进入核销页。系统生成的核销码为6位数字非二维码图片由/order/verify_code.php生成// /order/verify_code.php $code str_pad(rand(0, 999999), 6, 0, STR_PAD_LEFT); // 存入数据库并设置15分钟有效期 DB::getInstance()-exec(INSERT INTO beauty_verify_codes (order_id, code, expire_time) VALUES (?, ?, DATE_ADD(NOW(), INTERVAL 15 MINUTE)), [$order_id, $code]); echo $code;核销时美容师输入6位码系统执行查询beauty_verify_codes表验证码存在且未过期校验地理位置调用微信JS-SDK的getLocation接口获取当前经纬度与订单地址的百度地图坐标比对误差≤500米才允许核销更新订单状态为6待评价并记录verify_time。此设计防止美容师在未到达现场时提前核销保障服务真实性。4.3 评价与口碑沉淀结构化评价项与防刷机制用户评价页面/order/evaluate.php提供结构化选项!-- 评分项 -- div classrating-item label服务态度/label select nameattitude option value5非常满意/option option value4满意/option option value3一般/option /select /div !-- 文字评价 -- textarea namecomment placeholder请描述本次服务体验...20-200字/textarea !-- 图片上传最多3张 -- input typefile namephotos[] multiple acceptimage/* maxlength3后端/order/evaluate.php校验逻辑文字评价长度必须在20-200字之间mb_strlen($_POST[comment])图片文件大小总和≤5MB且每张≤2MB同一订单ID不允许重复提交检查beauty_evaluations表是否存在order_id记录评价提交后自动触发模板消息通知商家“用户XXX对订单#123456完成评价综合评分4.8分”。5. 生产环境必须加固的五个安全与性能节点从PHP配置到微信风控5.1 PHP层面禁用危险函数与强制输入过滤php.ini中必须禁用以下高危函数防止任意代码执行disable_functions exec,passthru,shell_exec,system,proc_open,popen,curl_exec,curl_multi_exec,parse_ini_file,show_source所有用户输入必须经filter_var()过滤手机号filter_var($phone, FILTER_SANITIZE_NUMBER_INT)后验证11位数字订单备注htmlspecialchars($_POST[remark], ENT_QUOTES, UTF-8)防止XSS文件上传$_FILES[photo][type]必须严格限制为image/jpeg、image/png且用getimagesize()二次校验。5.2 MySQL层面最小权限原则与SQL注入防护数据库连接账号/config/db.php中配置不应使用root而应创建专用账号CREATE USER beauty_applocalhost IDENTIFIED BY StrongPass123!; GRANT SELECT, INSERT, UPDATE ON beauty_o2o.beauty_users TO beauty_applocalhost; GRANT SELECT, INSERT, UPDATE ON beauty_o2o.beauty_orders TO beauty_applocalhost; -- 仅授予必要表的必要权限禁止DROP、DELETE、FILE等高危权限 FLUSH PRIVILEGES;所有数据库操作必须使用PDO预处理语句杜绝字符串拼接// ✅ 正确预处理 $stmt DB::getInstance()-prepare(UPDATE beauty_orders SET status? WHERE id?); $stmt-execute([$new_status, $order_id]); // ❌ 错误拼接SQL存在注入风险 $sql UPDATE beauty_orders SET status$new_status WHERE id$order_id; DB::getInstance()-exec($sql);5.3 微信接口调用添加请求频率限制与失败重试微信API有调用频次限制如获取access_token每2小时2000次。系统在/app/common/wechat.class.php中实现本地缓存access_token首次调用后存入/runtime/access_token.txt有效期2小时每次调用前读取并校验剩余时间失败重试机制对curl请求封装retryCurl()方法当HTTP状态码非200或返回{errcode:45009}调用超限时延迟1秒后重试最多3次日志记录所有微信API请求与响应写入/runtime/wechat.log便于排查invalid credential等错误。5.4 静态资源优化合并CSS/JS与启用Gzip压缩Nginx配置中加入# 启用Gzip压缩 gzip on; gzip_types text/plain application/javascript text/css application/xml; # 静态资源缓存 location ~* \.(js|css|png|jpg|jpeg|gif|ico|svg)$ { expires 1y; add_header Cache-Control public, immutable; }前端构建时将/assets/js/下多个JS文件合并为all.min.jsCSS同理减少HTTP请求数。index.php中引用改为script src/assets/js/all.min.js?v20231001/script link relstylesheet href/assets/css/all.min.css?v20231001版本号v20231001确保更新后浏览器强制拉取新资源。5.5 订单超时自动关闭基于MySQL事件调度器的无人值守清理利用MySQL事件调度器每日凌晨2点自动关闭超时订单-- 开启事件调度器 SET GLOBAL event_scheduler ON; -- 创建事件 CREATE EVENT close_timeout_orders ON SCHEDULE EVERY 1 DAY DO BEGIN -- 关闭支付超时订单30分钟未支付 UPDATE beauty_orders SET status 9, close_reason pay_timeout WHERE status 1 AND create_time DATE_SUB(NOW(), INTERVAL 30 MINUTE); -- 关闭派单超时订单2小时未接单 UPDATE beauty_orders SET status 9, close_reason assign_timeout WHERE status 4 AND create_time DATE_SUB(NOW(), INTERVAL 2 HOUR); END;此方案无需PHP常驻进程降低服务器资源占用且状态变更会触发模板消息通知用户“订单已关闭”。本文还有配套的精品资源点击获取