开源PHP在线客服系统WeLive部署实战:踩坑与二次开发
2026/9/2 23:07:55 网站建设 项目流程

简介:WeLive是一款可独立部署的企业级PHP在线客服系统,基于WebSocket实现全双工通信,面向需要为网站或App快速接入客服能力的开发者、企业及外包团队。资源包共287个文件,涵盖56个PHP核心模块、127个PNG界面素材、20个JS交互脚本和13个CSS样式,另有MP3提示音、GIF动图及SQL数据库文件等,整体仅1.6MB,结构精简便于部署。功能上支持Web/移动端、中英文自动切换、5种配色,并可设置AI机器人自动回复、访客上传图片/文件,客服坐席无限制,适合无人值守和多端接入场景;5.9.0版本还新增了访客提示音选择、单/多窗口切换、离线访客管理等近十项优化。已有330人学习浏览,开发者可借此研究在线客服系统架构、WebSocket消息推送及二次开发,也可直接部署到自有服务器开展业务。 做独立站这些年,我一直缺一个能自己掌控的客服入口。访客来了想联系我,不是被自动回复绕晕,就是只能干等邮件回复。后来我把一套免费开源PHP在线客服系统——WeLive——部署到了自己的服务器上,这个问题才算真正解决。WeLive基于PHP开发,源码开源可控,尤其适合中小站点和外包项目。这篇文章不聊虚的,只说我从下载源码到二次开发跑通的全过程,以及那些文档里没写的坑。

1. 为什么我会选WeLive而不是商业客服系统

1.1 商业系统看起来很美,账单却很诚实

我刚接一个小电商项目时,客户点名要在线客服,我第一反应是去注册几家商业客服SaaS。界面确实漂亮,功能也确实全,但一看价格方案就头大:坐席费按人头算,一个客服一个月几十上百,年度账单下来比我服务器租金还贵;消息量、会话数、离线留言推送,每个都能拆成独立收费项目。到后面想导出聊天记录做分析,居然还要开更高档套餐。小站点一天可能就几十个会话,为了这个去承担一套完整的商业化定价,不划算。

更关键的是数据归属。商业系统的聊天记录都在厂商服务器上,万一平台政策变动或服务中断,历史会话说没就没了。对依赖客服转化的小电商站来说,这是悬在头上的风险。我当时的底线很明确:要么客户接受用QQ/微信,要么就把客服系统掌握在自己手里。WeLive这种开源PHP项目成了最自然的选择。

1.2 WeLive解决的核心问题

WeLive能做的,和一个基础商业客服系统差不太多:多客服同时接入、客服分组与分配、访客识别、常用语回复、离线留言、历史会话记录、简单的数据统计。访客在电脑端访问网站时,右下角弹出一个客服浮窗,点击就能发起对话;客服打开工作台,看到在线访客列表,接过来开始聊,整个链路是完整的。

最让我看重的是,这套系统直接用PHP编写,底层是常见的Web技术,不需要部署Node或者Java那一套体系。我手上大部分服务器都是经典的LNMP/LAMP环境,下载源码、配好数据库、改一下配置文件就能跑起来。后续要改逻辑、加功能,也是在自己熟悉的PHP代码里改,没有黑盒。对于只想解决"网站上有个人能即时跟访客说话"这个需求的人来说,WeLive的性价比是真的高。

1.3 谁适合用WeLive,谁不适合

以我实际体验下来的判断:个人站长、中小型电商、外包项目交付、以及那些对数据敏感、不愿意把客户聊天上云的企业,都适合用WeLive。它的定位就不是上百坐席的呼叫中心,而是"三五个客服接待日常咨询"这样一个区间。

反过来,如果你的业务是每天几千上万的并发会话,团队也没人懂PHP,那我建议你还是老老实实上商业客服平台或直接采购企业级方案。开源系统意味着部署、维护、二次开发都要自己兜底,没有厂商的SLA。想清楚这一条,再决定要不要自建。

2. 部署跑通:环境、下载、伪静态那些事

2.1 技术栈和版本选择

WeLive基于ThinkPHP 3.2.3框架开发,这是一个比较有年头的PHP框架。部署之前,我特意确认了运行环境:PHP官方推荐5.3以上,但为了少踩坑,我直接选了5.6版本;数据库用MySQL 5.6/5.7都行,我是用的5.7。Web服务器选Nginx,Apache也能跑,只是伪静态规则写法不同。

这里要提醒一句:别手痒直接上PHP 7.4或者8.x,除非你做好了自己改代码的准备。ThinkPHP 3.2.3是2014年前后的产物,很多写法在高版本PHP上会直接报错,后面我会展开讲。我用的是宝塔面板来管理环境,直接装一个PHP 5.6的站点,省去不少编译的麻烦。新手如果不会手动编译,用面板是最稳的。

下载源码时,认准官方GitHub仓库或项目主页,解压后把整个目录放到网站的根目录。我当时下载的是最新release包,解压出来能看到Application、Public、ThinkPHP这几个主要目录,数据库文件通常在根目录或docs目录下,后缀是.sql。

2.2 安装步骤与数据库初始化

整个安装过程不复杂,核心就三步:建库、导数据、改配置。先通过phpMyAdmin或命令行创建一个数据库,比如we_live,字符集选择utf8mb4,然后把SQL文件导入。命令行导入更直接:

mysql -uroot -p we_live < welive.sql

导入成功后,打开Application/Common/Conf/config.php,把数据库地址、库名、用户名、密码改成自己的:

<?php return array( 'DB_TYPE' => 'mysql', 'DB_HOST' => '127.0.0.1', 'DB_NAME' => 'we_live', 'DB_USER' => 'your_db_user', 'DB_PWD' => 'your_db_password', 'DB_PORT' => '3306', 'DB_PREFIX' => 'we_', );

改完保存,浏览器访问站点首页,理论上就能看到引导页面或者登录入口。第一次登录后,系统会自动初始化管理员账号,这个入口的URL一般是:

http://你的域名/index.php?s=/Admin/Login/index

如果你只想快点看到效果,可以直接访问这个后台地址。默认的管理员账号密码是什么,以你下载版本里的说明为准,但我强烈建议登录后第一时间改掉,趁现在还来得及,不要拖。

2.3 Nginx伪静态和目录权限

如果你不想每次都用index.php?s=这种难看的URL,就需要配置伪静态。网上好多教程用的规则是从Apache搬过来的,在Nginx下不一定生效。我当时踩完坑后,把能用的规则存到了nginx配置的location部分:

location / { if (!-e $request_filename) { rewrite ^/index.php(.*)$ /index.php?s=$1 last; rewrite ^(.*)$ /index.php?s=$1 last; break; } }

配置完reload一下Nginx,再用友好的URL访问后台,比如:

http://域名/Admin/Login/index

APACHE用户则在根目录放.htaccess文件,规则一般是:

<IfModule mod_rewrite.c> RewriteEngine On RewriteCond %{REQUEST_FILENAME} !-f RewriteCond %{REQUEST_FILENAME} !-d RewriteRule ^(.*)$ index.php?s=/$1 [QSA,PT,L] </IfModule>

目录权限方面,必须保证Application/Runtime目录可写,否则页面打开就是各种报错。对新手来说,最简单粗暴的方式是直接设置777权限,但要清醒意识到生产环境这么做有风险,等跑通了再收紧也不迟。

3. 踩坑实录:从白屏到正常聊天的完整排查链路

3.1 最大坑:ThinkPHP3.2.3的PHP版本兼容性

我第一次部署时,图省事直接用宝塔默认的PHP 7.4装,结果打开首页白屏,啥提示都没有。然后我去翻了Nginx的error.log和PHP的日志,看到的是一堆关于each()函数被移除、mcrypt相关函数消失之类的报错。原因很清楚:ThinkPHP 3.2.3的底层用了一些老函数,在PHP 7.2之后会逐个被标记废弃或直接移除,于是整个框架直接崩溃。

这类问题排查起来很费劲,因为框架入口会做大量的兼容性判断,一个小函数报错就可能让整个请求走到500页面。当时我有两条路:一条是把代码里所有老函数换成新写法,工程量不小且后续维护麻烦;另一条是直接给站点指定PHP 5.6版本。我选了后者。宝塔里切换PHP版本只需要在站点设置里改一下,一分钟搞定,然后页面瞬间正常。这个操作思路其实挺朴素:老项目用老运行时,稳定优先。

如果你用的是Docker环境,那也是同样的道理。直接拉一个php:5.6-apache镜像,再把代码挂进去,至少能少掉一大部分兼容性问题。新手千万不要在国外论坛上搜PHP 7.4的修复补丁,折腾半天性价比极低。

3.2 Runtime目录写权限引发的各种灵异报错

环境切回PHP 5.6后,我本以为万事大吉,结果登录后台时又有零星报错,不是提示模板缓存无法写入,就是提示日志目录不可写。一看就是Application/Runtime没有写权限。系统运行时会在Runtime目录下生成模板编译文件、缓存文件和日志文件,如果这个目录对PHP进程不可写,所有需要写盘的操作都会失败。

解决方法是给Runtime目录设置权限:

chmod -R 777 /www/wwwroot/你的站点/Application/Runtime

生产环境如果想更稳一点,可以递归设置目录属主为PHP-FPM运行用户,比如www用户:

chown -R www:www Application/Runtime chmod -R 755 Application/Runtime

我到现在都记得,当时折腾完这个,后台终于能正常登录了。这种"看起来是业务报错,实际是系统权限问题"的坑,在PHP老项目里特别常见,遇到类似问题先检查目录权限,往往能少走不少弯路。

3.3 伪静态404和数据库字符合集

权限搞定后,我又遇到了一个典型问题:安装了伪静态规则后,访问后台首页404,但用index.php?s=/Admin/Login/index这个原始URL却能正常访问。排查过程是这样的:

  • 先确认伪静态规则是否被正确载入:在Nginx配置里加了一段rewrite,reload后访问依然404。
  • 再看Nginx错误日志,发现请求被送到了PHP-FPM,但PHP返回404,这说明ThinkPHP自身的URL路由没有识别到路径。
  • 最后检查发现,Nginx rewrite规则里把路径重写成了index.php?s=/Admin,而ThinkPHP在伪静态模式下期望的是s=/Admin/Login/index,少了后面的部分。

最终的规则就是上面2.3节那段,用if (!-e $request_filename)判断文件不存在才重写,然后同时匹配index.php路径和普通路径,问题解决。

另外,数据库字符合集也容易出事。导入SQL后,如果发现中文全是乱码,多半是数据库表和字段的collation不是utf8mb4。建议建库时直接选utf8mb4,字段如果已经是utf8也可以执行一条命令批量转:

ALTER TABLE we_chat CONVERT TO CHARACTER SET utf8mb4 COLLATE utf8mb4_unicode_ci;

别小看字符集,访客消息里混入emoji的时候,utf8编码根本存不下,只有utf8mb4能兜住,不然客服端看到的就会是问号方块。

4. 核心功能与实时消息机制的拆解

4.1 客服工作台和访客端都做了什么

跑起来之后,我先把WeLive的客服端和访客端都仔细用了一遍。客服端是一个独立的后台页面,左边是当前会话列表,中间是聊天窗口,右边显示访客信息,包括IP、来源页面、浏览器和操作系统。会话列表里可以看到访客当前是否在线、等待了多久,客服可以主动发起会话。右侧访客信息对于判断用户需求很有用,比如用户是从哪个推广页进来,直接决定了客服第一句话怎么接。

常用语功能对效率提升特别明显,把售后地址、物流查询、发货时间这类高频回答提前存进去,客服点一下就能发出去,省得每次重复打字。会话结束后,历史记录会保留在后台,方便复盘和售后追查。这些功能虽然不花哨,但日常客服工作该有的都有了。

4.2 访客端嵌入和实时性原理

访客端就是一段JavaScript插件,复制代码嵌到网站的任意页面上,刷新后就能看到右下角的浮窗。点击浮窗,输入昵称和联系方式,就能开始对话。访客端的核心逻辑是向服务器轮询消息:每隔几秒发一次HTTP请求,问"有没有新消息",有就把新消息拉到页面上。

这种轮询机制最大的好处是部署简单,不需要额外维护长连接服务,普通Nginx + PHP-FPM就能扛住中小规模流量。但它有个天然问题:如果同时在线访客多,每个访客的轮询请求会不断打到PHP和MySQL上,数据库压力会快速上升。在只有几十个并发访客的情况下,问题不大,但如果期望支撑上千个同时在线,就必须改造消息推送机制。

4.3 如果要做高并发,该往哪个方向改

我早先做轮询方案时,最担心的是数据库连接被打满。每个轮询请求都会查一次消息表,即便没有新消息,也是一次完整的PHP进程生命周期。改进思路有三条:

  • 把轮询间隔拉长,比如从2秒改成5秒,能显著降低请求量,缺点是消息延迟升高。
  • 引入Redis做短轮询,PHP从内存里读消息,不查MySQL,这一步能把数据库压力降下来。
  • 彻底换成WebSocket,前端的连接保持长连接,服务器有消息直接推过来。实现上可以用GatewayWorker或Swoole,把WeLive的消息收发逻辑抽出来单独做一套服务。

我的建议是:在日活访客过千之前,就别折腾WebSocket了,先把Redis短轮询跑起来,成本低收益明显。我自己就是这么干的,直接把原来查数据库的轮询改成优先读Redis,稳定跑到现在。

5. 二次开发与上线加固:我从这套系统里改了什么

5.1 把默认账号体系换成自己的用户系统

WeLive默认的客服账号是存在自己的表里,管理员在后台维护。但我的场景里,客服就是网站前台注册的运营人员,我不想维护两套账号。于是改造思路是:客服登录时,直接用自己用户系统的账号接口去校验,校验通过后,再把登录状态写进WeLive的session。

具体来说,修改Application/Admin/Controller/LoginController.class.php里的登录方法,把原来查we_admin表的逻辑去掉,换成调用自己的用户认证接口。密码校验我建议用password_verify(),因为老项目里很多还是md5加盐,新改的用户系统不应该再走md5了。

为了平滑过渡,我做了个兼容逻辑:先判断是否是老哈希格式,如果是就走老校验,否则走新认证接口。这样老客服账号还能继续用,同时新账号也能从用户系统登录。改完后,客服人员不需要记住两个用户名密码,体验好很多。

5.2 访客身份识别与消息通知

访客进站时,WeLive默认用cookie生成一个guest_id来识别身份。这意味着同一个用户只要清了cookie,客服端就认不出他来了。我把它改成了优先读取自己主站的用户ID:用户已登录,就把用户的昵称、手机号写入访客信息;没登录,才走原来的cookie方案。这个改动对客服效率提升明显,咨询时直接看到"张三(VIP)",第一句话就能带上称呼。

消息通知也是值得扩展的点。WeLive本身有离线留言功能,访客在客服不在线时提交留言。我需要让客户第一时间知道有留言进来,于是接入了微信公众号模板消息:留言入库时,在保存逻辑里加一个钩子,调用微信模板消息接口把"客户姓名+留言内容摘要"推给客服的微信。

public function addMessage($data) { $message_id = M('chat_message')->add($data); if ($data['is_offline'] == 1) { // 调用微信模板消息推送 WechatTemplate::sendOfflineNotice($data['username'], $data['content']); } return $message_id; }

改造逻辑很简单,但用户体验提升非常直观,客服不用一直盯后台,手机也能及时收到提醒。

5.3 上线前的安全加固清单

开源系统部署到公网,有几件事千万不能省:

  • 修改后台入口路径,默认的Admin目录太容易被扫描器命中,我直接改名了控制器目录或在路由层做了映射。
  • 给后台登录接口加访问限制,如果客服IP固定,可以在Nginx层限制IP白名单。
  • 上传目录禁用PHP执行权限,防止有人传个webshell上去。Nginx下可以这样配:
location ~ ^/Upload/.*\.(php|php5)$ { deny all; }
  • 数据库密码不要用弱密码,腾讯云的端口访问记录里能清清楚楚看到有人在扫MySQL的3306端口。
  • 定时清理历史会话,我用crontab每周清掉3个月前的聊天记录:
0 4 * * 1 mysql -uroot -p你的密码 we_live -e "DELETE FROM we_chat_message WHERE create_time < UNIX_TIMESTAMP(DATE_SUB(NOW(), INTERVAL 3 MONTH));"

从我个人的体验来说,WeLive这套开源PHP在线客服系统最大的价值不是它有多少黑科技,而是它可以完全按自己节奏去改造。从部署时的版本坑,到权限问题,再到二次开发的账号对接和消息推送,每一步都能在PHP代码里找到答案。如果你正在找一个能自己掌握数据的客服方案,又想顺手熟悉一下老ThinkPHP项目的维护思路,拿WeLive当练手项目,比网上那些只提供演示版的付费系统实用得多。

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

需要专业的网站建设服务?

联系我们获取免费的网站建设咨询和方案报价,让我们帮助您实现业务目标

立即咨询