1. 项目概述为什么TPShop部署不是“点几下就完事”的体力活TPShop环境部署与数据库验证完整指南——这标题里藏着三个关键动作“部署”“验证”“完整”。它不是教你怎么下载一个压缩包、解压、改个config.php就喊“搞定”的速成课。我带过十几支开发团队从某高校电商实训实验室到某初创公司技术部几乎每支队伍在第一次跑通TPShop时都卡在同一个地方后台能打开商品列表空白订单提交报错日志里满屏“SQLSTATE[HY000] [2002] Connection refused”。问题出在哪不是PHP版本不对也不是MySQL没启动而是部署过程被当成了安装向导而数据库验证被当成了“看看phpmyadmin能不能连上”这种表面功夫。TPShop作为一套基于ThinkPHP框架的开源电商系统它的运行依赖于三层耦合Web服务层Nginx/Apache、脚本执行层PHP及其扩展、数据持久层MySQL 表结构 初始化数据。这三者之间不是并列关系而是存在严格的启动顺序、权限约束和状态依赖。比如TPShop的install.php脚本在创建数据库表时会调用think\migration\Migrator类执行迁移命令而该类又强依赖pdo_mysql扩展是否启用、mysqli.default_socket路径是否指向正确的socket文件、以及MySQL用户是否拥有CREATE ROUTINE权限——这些细节官方文档一笔带过但实操中任何一个缺失都会导致“页面白屏但无报错”这种最折磨人的状态。所以这份指南的核心价值不在于告诉你“该点哪个按钮”而在于帮你建立一套可验证、可回溯、可复现的部署心智模型。它适合三类人刚接触PHP电商系统的应届生需要避开教科书里不会写的坑负责交付的实施工程师要确保客户服务器上一次跑通以及想把TPShop当练手项目的自学开发者得明白每个配置项背后的真实作用。接下来的内容全部来自我在6台不同配置服务器CentOS 7/8、Ubuntu 20.04/22.04、阿里云ECS、腾讯云CVM、本地VirtualBox虚拟机、Mac M1芯片上反复重装、抓包、断点调试的真实记录。没有理论堆砌只有哪一步该敲什么命令、为什么这么敲、不这么敲会怎样。2. 环境准备与方案选型为什么拒绝一键脚本坚持手动分步搭建2.1 为什么不用Docker或宝塔面板先说结论Docker镜像封装了太多黑盒逻辑宝塔面板隐藏了关键路径和权限细节两者都会让你在后续排查数据库连接超时、文件上传失败、Redis缓存穿透等问题时彻底迷失。我试过用某知名TPShop Docker镜像在CentOS 7上部署后前台商品图显示为红叉查日志发现是/runtime目录权限为755而非777而镜像内www-data用户UID与宿主机不一致导致PHP进程无法写入。修复它需要进容器改/etc/passwd再重启整个容器——这已经超出了“部署”的范畴变成了“系统运维”。宝塔同理。它自动生成的Nginx配置里root指令指向/www/wwwroot/tpshop/public看似正确但TPShop的public/index.php中有一行define(ROOT_PATH, __DIR__ . /../);这个..向上跳转时如果/www/wwwroot/tpshop目录本身权限是755PHP-FPM以www用户身份运行就会因“跨目录访问被禁”而报错。宝塔不会告诉你这个open_basedir限制在哪里配置你得去翻/www/server/php/80/etc/php.ini里的open_basedir字段再手动追加路径。这种“看似省事实则埋雷”的方案对学习者是灾难。因此本指南坚持纯手工分步搭建每一步都明确说明执行命令的当前工作目录命令预期输出的关键字符串失败时最可能的原因及快速验证方式这不是为了炫技而是为了让你在任何一台新服务器上都能靠自己还原出完整的运行环境。2.2 操作系统与软件版本的硬性选择逻辑TPShop官方文档写着“支持PHP 7.1”但实际测试中PHP 8.0会导致think\cache\driver\File类中的set方法因serialize()函数行为变更而静默失败表现为登录态无法保持。MySQL方面8.0默认启用caching_sha2_password认证插件而TPShop的PDO连接字符串若未显式指定charsetutf8mb4就会因认证协议不匹配直接拒绝连接。所以我们的组合是经过23次交叉验证后锁定的操作系统CentOS 7.9内核3.10.0-1160或 Ubuntu 20.04.6 LTS理由前者是企业级服务器最广泛使用的稳定版后者是LTS中对PHP 7.4兼容性最好的版本。避免使用CentOS 8已停止维护或Ubuntu 22.04PHP 8.1默认启用JIT编译与TPShop部分扩展冲突。Web服务器Nginx 1.20.1理由比1.18更稳定比1.22少了对QUIC协议的冗余支持减少配置复杂度。Apache虽可运行但.htaccess重写规则在TPShop中易与public/.htaccess冲突导致URL路由失效。PHP版本7.4.33非7.4.0因后者存在openssl_encrypt函数内存泄漏Bug理由TPShop 4.1.x系列代码库大量使用符号抑制错误而PHP 8.0将操作符标记为Deprecated导致大量Notice级警告阻塞JSON响应。MySQL版本5.7.39非8.0.x理由TPShop安装脚本中think\db\Connection类的getFields()方法硬编码了SHOW COLUMNS FROMtable_name语法而MySQL 8.0对SHOW语句的权限检查更严格普通用户需额外授予SELECT权限才能执行否则安装过程卡在“正在创建数据表”不动。提示所有软件包均从官方源获取拒绝第三方PPA或RPM Fusion仓库。例如Ubuntu下安装PHP 7.4必须执行sudo apt install php7.4-cli php7.4-fpm php7.4-mysql php7.4-curl php7.4-gd php7.4-mbstring php7.4-xml php7.4-zip php7.4-opcache缺一不可。少装php7.4-opcache首页加载时间会从320ms飙升至1.8s——这是我在某电商促销活动前夜踩过的坑凌晨三点紧急补装才保住流量入口。2.3 目录结构设计为什么/var/www/tpshop不能直接解压到/var/www/html很多教程让你把TPShop源码解压到/var/www/html然后通过http://server-ip/访问。这在单站点环境下看似可行但会引发两个致命问题第一/var/www/html通常是Apache默认DocumentRoot而我们用的是Nginx。若Nginx配置中root /var/www/html;那么访问http://server-ip/install.php时Nginx会尝试执行/var/www/html/install.php但TPShop的入口文件实际在/var/www/html/public/index.php。你得手动修改Nginx配置把location /块里的try_files $uri $uri/ /index.php?$query_string;改成try_files $uri $uri/ /public/index.php?$query_string;——这违反了ThinkPHP的“public为Web根目录”设计哲学后续升级极易出错。第二权限管理失控。/var/www/html目录通常属于root:root而PHP-FPM进程以www-dataUbuntu或nginxCentOS用户运行。若直接解压所有文件属主都是rootPHP进程无法写入/runtime和/public/uploads导致日志无法生成、商品图无法上传。因此我们采用分离式目录结构/var/www/tpshop/ # 源码根目录属主 root:root权限 755 ├── application/ # 应用模块含控制器、模型 ├── public/ # Web根目录Nginx的root指向此处 │ ├── index.php # 入口文件 │ └── static/ # 静态资源 ├── runtime/ # 运行时目录属主 www-data:www-data权限 777 └── uploads/ # 上传目录同上这个结构的好处是Nginx配置只需一行root /var/www/tpshop/public;所有URL路由天然适配runtime和uploads目录可单独授权不影响源码安全未来要部署多个TPShop实例如测试站、预发站只需复制/var/www/tpshop并改名Nginx配置微调即可。注意runtime目录权限必须是777不是755。因为TPShop的think\log\driver\File类在写日志时会先mkdir(dirname($filename), 0777, true)若父目录权限不足mkdir会失败并抛出ErrorException。我曾因误设为755在CentOS上看到mkdir(): Permission denied in /var/www/tpshop/thinkphp/library/think/log/driver/File.php on line 87查了两小时才发现是/var/www/tpshop/runtime的父目录/var/www/tpshop权限问题。3. 核心部署步骤详解从解压到首页渲染的每一步验证点3.1 源码获取与完整性校验为什么SHA256比MD5更值得信赖TPShop官网提供多个版本下载但镜像站常有缓存延迟导致下载的ZIP包损坏。我见过最诡异的一次某公司运维从官网下载tpshop_v4.1.2.zip解压后application/database.php文件末尾多出半行乱码导致hostname 127.0.0.1变成hostname 127.0.0.1 // 这里有不可见字符PHP解析时直接报Parse error: syntax error, unexpected end of file。因此下载后必须做双重校验文件大小比对官网标注tpshop_v4.1.2.zip大小为28.7MB29,999,104字节用ls -lh tpshop_v4.1.2.zip确认。SHA256哈希校验官网提供SHA256值a1b2c3d4e5f6...此处为示意执行sha256sum tpshop_v4.1.2.zip | cut -d -f1输出必须完全一致。MD5已被证明存在碰撞漏洞SHA256是当前通用标准。校验通过后解压到/var/www/sudo mkdir -p /var/www/tpshop sudo unzip tpshop_v4.1.2.zip -d /var/www/tpshop/ # 注意必须用unzip不能用tar -zxvf因为官网提供的是ZIP格式解压完成后立即执行目录权限初始化# 设置源码目录为root只读 sudo chown -R root:root /var/www/tpshop sudo chmod -R 755 /var/www/tpshop # 创建并授权runtime和uploads目录 sudo mkdir -p /var/www/tpshop/runtime /var/www/tpshop/public/uploads sudo chown -R www-data:www-data /var/www/tpshop/runtime /var/www/tpshop/public/uploads sudo chmod -R 777 /var/www/tpshop/runtime /var/www/tpshop/public/uploads实操心得chmod -R 777看起来危险但这是TPShop框架强制要求。其think\cache\driver\File类在生成缓存文件时会调用file_put_contents($filename, $content, LOCK_EX)若$filename所在目录无写权限函数返回false且不抛异常导致缓存永远不生效。我曾用755权限跑了一周发现商品搜索响应时间从200ms涨到2.3s最后用strace -p $(pgrep php-fpm) -e tracewrite跟踪到write(7, , 0) 0写入0字节才定位到是/runtime/cache目录无写权限。3.2 Nginx配置location块里的try_files为什么必须带/index.php?$query_stringNginx配置是TPShop能否正确路由的关键。常见错误是照搬ThinkPHP通用配置写成location / { try_files $uri $uri/ /index.php; }这会导致所有请求包括/static/css/app.css都被重写到/index.php静态资源无法加载。正确配置必须精确匹配TPShop的public目录结构server { listen 80; server_name localhost; root /var/www/tpshop/public; # 关键root指向public目录 index index.php; location / { try_files $uri $uri/ /index.php?$query_string; # 关键带$query_string } location ~ \.php$ { include snippets/fastcgi-php.conf; fastcgi_pass unix:/run/php/php7.4-fpm.sock; fastcgi_param SCRIPT_FILENAME $document_root$fastcgi_script_name; } location ~ /\.ht { deny all; } }这里有两个核心点root /var/www/tpshop/public让Nginx知道/static/css/app.css对应物理路径/var/www/tpshop/public/static/css/app.css。try_files $uri $uri/ /index.php?$query_string$query_string参数至关重要。TPShop的URL路由如/index/goods/index/id/123.html会被Nginx重写为/index.php?/index/goods/index/id/123.html而ThinkPHP的think\App::run()方法正是通过$_SERVER[QUERY_STRING]解析路由。若漏掉?$query_string$_SERVER[QUERY_STRING]为空路由解析失败返回404。验证方式重启Nginx后用curl -I http://localhost/应返回HTTP/1.1 200 OK用curl -I http://localhost/static/css/app.css应返回HTTP/1.1 200 OK且Content-Type: text/css。若后者返回404一定是root路径没指向public。3.3 PHP-FPM配置listen.owner与user不一致时的权限陷阱PHP-FPM的www.conf配置中user和group定义了子进程运行身份listen.owner和listen.group定义了Unix socket文件的所有者。若两者不一致Nginx无法与PHP-FPM通信。在Ubuntu 20.04上PHP 7.4-FPM默认配置为; /etc/php/7.4/fpm/pool.d/www.conf user www-data group www-data listen /run/php/php7.4-fpm.sock listen.owner www-data listen.group www-data这没问题。但在CentOS 7上若你手动编译PHP常会设成user nginx group nginx listen.owner nginx listen.group nginx此时Nginx配置中的fastcgi_pass unix:/run/php/php7.4-fpm.sock;会失败因为Nginx主进程以root运行但worker进程以nginx用户运行而socket文件属主是nginx:nginx权限660Nginx worker可以访问。但问题来了TPShop的runtime目录属主是www-data:www-data我们在2.3节设的而PHP-FPM子进程以nginx用户运行无法写入/var/www/tpshop/runtime结果就是日志不生成、缓存不命中、Session丢失。解决方案只有一个统一用户。在CentOS上创建www-data用户并赋予权限sudo useradd -r -s /bin/false www-data sudo usermod -a -G www-data nginx sudo chown -R www-data:www-data /var/www/tpshop/runtime /var/www/tpshop/public/uploads然后修改/etc/php-fpm.d/www.confuser www-data group www-data listen.owner www-data listen.group www-data重启PHP-FPMsudo systemctl restart php-fpm。常见问题执行sudo systemctl status php-fpm显示active (running)但curl http://localhost/仍502 Bad Gateway。此时用sudo ss -tuln | grep 9000检查PHP-FPM是否监听TCP端口默认不监听或用sudo ls -l /run/php/php7.4-fpm.sock确认socket文件存在且权限为srw-rw----属主www-data:www-data。若不存在是PHP-FPM没启动成功看sudo journalctl -u php-fpm -n 50 --no-pager找错误。3.4 数据库初始化mysql -u root -p tpshop.sql为什么总是失败TPShop安装包里的data/tpshop.sql不是标准SQL文件。它包含三类内容CREATE DATABASE IF NOT EXISTS tpshop DEFAULT CHARACTER SET utf8mb4 COLLATE utf8mb4_unicode_ci;USE tpshop;大量INSERT INTO语句其中部分INSERT的VALUES字段包含NULL或空字符串但目标表字段定义为NOT NULL DEFAULT 。直接mysql -u root -p tpshop.sql会报错ERROR 1138 (22004) at line 123: Invalid use of NULL value原因是MySQL 5.7默认开启STRICT_TRANS_TABLES模式禁止向NOT NULL字段插入NULL。正确做法是分步导入创建数据库并指定字符集mysql -u root -p -e CREATE DATABASE tpshop DEFAULT CHARACTER SET utf8mb4 COLLATE utf8mb4_unicode_ci;临时关闭严格模式再导入mysql -u root -p -e SET GLOBAL sql_mode(SELECT REPLACE(sql_mode,STRICT_TRANS_TABLES,)); mysql -u root -p tpshop /var/www/tpshop/data/tpshop.sql导入后恢复严格模式安全起见mysql -u root -p -e SET GLOBAL sql_modeSTRICT_TRANS_TABLES,NO_ZERO_IN_DATE,NO_ZERO_DATE,ERROR_FOR_DIVISION_BY_ZERO,NO_AUTO_CREATE_USER,NO_ENGINE_SUBSTITUTION;但更稳妥的方式是用TPShop自带的install.php。访问http://localhost/install.php按向导输入数据库信息。install.php内部会自动处理STRICT_TRANS_TABLES兼容性并在创建表时添加ENGINEInnoDB DEFAULT CHARSETutf8mb4避免后续出现Incorrect string value错误。实操心得install.php向导中“数据库地址”填127.0.0.1不要填localhost。因为localhost在MySQL中会触发socket连接而127.0.0.1走TCP连接更稳定。若填localhost在某些CentOS系统上会因/etc/hosts解析慢导致连接超时。4. 数据库验证全流程从连接测试到业务逻辑穿透的四层校验4.1 第一层基础连接验证5秒级这是最快速的“心跳检测”。在服务器终端执行mysql -h 127.0.0.1 -u tpshop_user -ptpshop_pass -D tpshop -e SELECT VERSION();预期输出----------- | VERSION() | ----------- | 5.7.39 | -----------若报错ERROR 1045 (28000): Access denied for user说明数据库用户密码错误或权限不足若报错ERROR 2003 (HY000): Cant connect to MySQL server说明MySQL服务未启动或防火墙拦截。注意-h 127.0.0.1必须显式指定不能省略。因为mysql -u user -p默认host为localhost会走socket而TPShop代码中hostname 127.0.0.1走TCP两者认证方式不同。确保测试环境与运行环境一致。4.2 第二层表结构与数据完整性验证30秒级TPShop核心业务表共47张但关键验证只需5张tpshop_config存储网站名称、LOGO路径等全局配置tpshop_goods商品主表is_on_sale1表示上架tpshop_users用户表is_lock0表示未被锁定tpshop_order订单表order_status IN (0,1,2)表示待付款、待发货、已完成tpshop_region地区表id1必须是“中国”执行以下SQL验证数据是否存在且合理mysql -h 127.0.0.1 -u tpshop_user -ptpshop_pass tpshop -e SELECT COUNT(*) as config_count FROM tpshop_config WHERE namesite_name; SELECT COUNT(*) as goods_count FROM tpshop_goods WHERE is_on_sale1; SELECT COUNT(*) as users_count FROM tpshop_users WHERE is_lock0; SELECT COUNT(*) as order_count FROM tpshop_order WHERE order_status IN (0,1,2); SELECT COUNT(*) as region_count FROM tpshop_region WHERE id1; 预期所有COUNT(*)结果均大于0。若config_count0说明install.php未完成配置写入需重新运行安装向导若goods_count0可能是data/tpshop.sql导入不全需检查SQL文件末尾是否有-- End of dump字样。4.3 第三层应用层连接验证2分钟级这是模拟TPShop代码的实际数据库调用。在/var/www/tpshop目录下创建test_db.php?php require_once thinkphp/start.php; // 测试数据库连接 try { $db think\Db::connect(); $result $db-query(SELECT VERSION() as ver); echo DB Version: . $result[0][ver] . \n; // 测试读取配置 $config $db-name(config)-where(name, site_name)-find(); echo Site Name: . ($config ? $config[value] : NOT FOUND) . \n; // 测试写入临时表 $db-execute(CREATE TEMPORARY TABLE test_temp (id INT)); $db-execute(INSERT INTO test_temp VALUES (1)); $count $db-query(SELECT COUNT(*) as c FROM test_temp)[0][c]; echo Temp Table Count: . $count . \n; } catch (Exception $e) { echo DB Error: . $e-getMessage() . \n; }执行php test_db.php预期输出DB Version: 5.7.39 Site Name: TPShop商城 Temp Table Count: 1若报错SQLSTATE[HY000] [2002] No such file or directory说明application/database.php中hostname填成了localhost应改为127.0.0.1若报错SQLSTATE[42000]: Syntax error or access rule violation说明数据库用户缺少CREATE TEMPORARY TABLES权限需执行GRANT CREATE TEMPORARY TABLES ON tpshop.* TO tpshop_userlocalhost; FLUSH PRIVILEGES;4.4 第四层业务逻辑穿透验证5分钟级这是最终验收。手动模拟一个完整购物流程访问http://localhost/确认首页正常加载商品列表有数据。点击任意商品进入详情页URL形如http://localhost/goods-123.html确认商品图、价格、库存显示正常。点击“加入购物车”F12打开浏览器开发者工具切换到Network标签刷新页面找到/index.php?mHomecCartaaddCart请求确认Response为{status:1,msg:\u52a0\u5165\u8d2d\u7269\u8f66\u6210\u529f,result:1}JSON中文转义。访问http://localhost/Home/Cart/cartList确认购物车页面显示该商品。提交订单填写收货地址支付方式选“货到付款”提交后跳转到/Home/Order/orderConfirm确认订单号生成。这一步验证了从Web路由、控制器调用、模型查询、数据库写入、Session保持到前端渲染的全链路。若卡在第3步addCart返回{status:0,msg:\u7528\u6237\u672a\u767b\u5f55}说明Session未生效检查/var/www/tpshop/runtime/session目录权限是否为777若第5步订单号为空检查tpshop_order表的order_sn字段是否设置了AUTO_INCREMENT执行ALTER TABLE tpshop_order MODIFY order_sn VARCHAR(50) NOT NULL FIRST;修复。排查技巧当业务流程某一步失败不要猜直接查日志。TPShop日志在/var/www/tpshop/runtime/log/按日期分文件。例如20230901.log中搜索addCart会看到类似[2023-09-01 14:22:33] LOG.INFO: CartController-addCart start [] [][2023-09-01 14:22:33] LOG.ERROR: SQL Error: SQLSTATE[23000]: Integrity constraint violation: 1048 Column user_id cannot be null [] []这说明addCart方法中$data[user_id]为空需检查登录态验证逻辑。5. 常见问题与实战排障那些官方文档绝不会告诉你的细节5.1 问题速查表症状、原因、解决命令三列对照症状可能原因解决命令访问首页显示“502 Bad Gateway”PHP-FPM未运行或socket文件权限错误sudo systemctl status php7.4-fpm→sudo systemctl start php7.4-fpmsudo ls -l /run/php/php7.4-fpm.sock→sudo chown www-data:www-data /run/php/php7.4-fpm.sock安装向导卡在“正在创建数据表”进度条不动MySQL用户缺少CREATE ROUTINE权限mysql -u root -p -e GRANT CREATE ROUTINE ON tpshop.* TO tpshop_userlocalhost; FLUSH PRIVILEGES;商品图显示红叉URL为http://localhost/public/uploads/goods/1/2023/09/1.jpgNginxroot未指向public目录或public/uploads权限不足sudo nano /etc/nginx/sites-enabled/default→ 确认root /var/www/tpshop/public;sudo chmod -R 777 /var/www/tpshop/public/uploads后台登录后立即退出无法保持登录态session.save_path指向的目录无写权限或session.cookie_httponly为offsudo mkdir -p /var/www/tpshop/runtime/sessionsudo chown -R www-data:www-data /var/www/tpshop/runtime/sessionsudo chmod -R 777 /var/www/tpshop/runtime/session搜索商品返回空列表但数据库中有数据tpshop_goods表的is_on_sale0或goods_name字段被htmlspecialchars二次转义mysql -u tpshop_user -ptpshop_pass tpshop -e UPDATE tpshop_goods SET is_on_sale1 WHERE id123;5.2 “页面白屏但无错误”的终极排查法这是TPShop部署中最令人抓狂的问题。Nginx错误日志/var/log/nginx/error.log和PHP错误日志/var/log/php7.4-fpm.log均为空浏览器F12也看不到JS错误。根本原因是ThinkPHP的error_reporting被设为0且display_errorsOff所有错误被静默吞掉。解决步骤临时开启PHP错误显示编辑/etc/php/7.4/fpm/php.ini找到display_errors Off改为display_errors On找到error_reporting E_ALL ~E_DEPRECATED ~E_STRICT确保未被注释。重启PHP-FPMsudo systemctl restart php7.4-fpm。在浏览器访问http://localhost/此时白屏会变成红色错误提示如Fatal error: Uncaught Error: Class think\Validate not found说明thinkphp/library/think/Validate.php文件缺失或路径错误。检查/var/www/tpshop/thinkphp目录是否存在权限是否为755library/think下是否有Validate.php。我的经验90%的“白屏无错”问题根源都在thinkphp目录。TPShop安装包有时会把thinkphp放在/var/www/tpshop/thinkphp但public/index.php中require __DIR__ . /../thinkphp/start.php;的..向上跳转后实际路径是/var/www/tpshop/thinkphp/start.php。若你误把thinkphp解压到了/var/www/tpshop/application/thinkphp就会导致require失败。用find /var/www/tpshop -name start.php确认路径。5.3 Redis缓存启用后的“商品价格不更新”问题TPShop支持Redis缓存配置在application/database.php中cache [ type redis, host 127.0.0.1, port 6379, password , select 0, ],启用后修改商品价格前台仍显示旧价。这是因为TPShop的GoodsLogic类中getGoodsInfo()方法会先查Redis缓存goods_info_123若存在则直接返回不查数据库。解决方法不是关Redis而是主动清除缓存方式一在后台“系统设置”→“数据备份”→“清空缓存”点击“确定”。方式二命令行清除redis-cli -h 127.0.0.1 -p 6379 KEYS goods_info_* | xargs redis-cli -h 127.0.0.1 -p 6379 DEL方式三在代码中修改商品后调用cache(goods_info_.$goods_id, null);。注意Redis的KEYS命令在生产环境慎用会阻塞Redis。线上应改用SCAN命令redis-cli -h 127.0.0.1 -p 6379 --scan --pattern goods_info_* | xargs -r redis-cli -h 127.0.0.1 -p 6379 DEL5.4 HTTPS部署后“微信支付回调失败”的证书链问题当Nginx配置HTTPS后微信支付回调URL如https://shop.com/Home/Payment/weixinNotify常返回cURL error 60: SSL certificate problem。这不是TPShop代码问题而是Nginx的SSL证书链不完整。解决方案获取完整证书链从证书颁发机构下载fullchain.pem包含域名证书中间证书而非仅domain.crt。Nginx配置中ssl_certificate指向fullchain.pemssl_certificate_key指向domain.keyssl_certificate /etc/ssl/fullchain.pem; ssl_certificate_key /etc/ssl/domain.key;重启Nginxsudo systemctl restart nginx。验证用openssl s_client -connect shop.com:443 -servername shop.com 2/dev/null | openssl x509 -noout -text | grep CA Issuers应显示中间证书颁发者URL。最后分享一个小技巧TPShop的application/config.php
阅读完成 · 觉得有帮助?