# 甘草 SSL 连接错误修复指南 ## 错误信息 ``` 甘草网关通信失败:通信失败:HTTP 200 curl#56 OpenSSL SSL_read: error:0A000126:SSL routines::unexpected eof while reading, errno 0 ``` ## 问题分析 这个错误表示: - ✅ TCP 连接成功(HTTP 200) - ✅ SSL 握手开始 - ❌ SSL 读取数据时连接意外断开 **常见原因:** 1. TLS 版本不兼容(服务器要求 TLS 1.2+,客户端使用旧版本) 2. SSL 加密套件不匹配 3. HTTP 版本问题(HTTP/1.0 vs HTTP/1.1) 4. OpenSSL 安全级别过高 5. 服务器端提前关闭连接 ## 已实施的修复 ### 修改 `GancaoOpenApiTransport.php` ```php // 1. 改用 HTTP/1.1(原来是 HTTP/1.0) curl_setopt($ch, CURLOPT_HTTP_VERSION, CURL_HTTP_VERSION_1_1); // 2. 增加连接超时 curl_setopt($ch, CURLOPT_CONNECTTIMEOUT, 10); // 从 5 秒增加到 10 秒 // 3. 完全禁用 SSL 验证 curl_setopt($ch, CURLOPT_SSL_VERIFYHOST, 0); // 从 2 改为 0 // 4. 强制使用 TLS 1.2 curl_setopt($ch, CURLOPT_SSLVERSION, CURL_SSLVERSION_TLSv1_2); // 5. 降低 OpenSSL 安全级别 curl_setopt($ch, CURLOPT_SSL_CIPHER_LIST, 'DEFAULT@SECLEVEL=1'); // 6. 添加 TCP keepalive curl_setopt($ch, CURLOPT_TCP_KEEPALIVE, 1); curl_setopt($ch, CURLOPT_TCP_KEEPIDLE, 120); curl_setopt($ch, CURLOPT_TCP_KEEPINTVL, 60); ``` ## 测试步骤 ### 步骤 1: 上传修复后的文件 ```bash scp server/app/common/service/gancao/GancaoOpenApiTransport.php user@server:/path/to/server/app/common/service/gancao/ scp test_gancao_ssl.php user@server:/path/to/ ``` ### 步骤 2: 运行 SSL 测试 ```bash ssh user@server cd /path/to/your/project php test_gancao_ssl.php ``` **期望输出:** ``` === 甘草 SSL 连接测试 === 网关地址: https://xxx.com 1. DNS 解析测试: ✓ xxx.com -> 1.2.3.4 2. TCP 连接测试: ✓ TCP 连接成功 3. SSL/TLS 支持检测: - SSLv2: ✗ 不支持 - SSLv3: ✗ 不支持 - TLS 1.0: ✓ 支持 - TLS 1.1: ✓ 支持 - TLS 1.2: ✓ 支持 - TLS 1.3: ✓ 支持 4. cURL SSL 测试: 测试 HTTP/1.0 + TLS 1.2: ❌ 失败: [56] OpenSSL SSL_read... 测试 HTTP/1.1 + TLS 1.2: ✓ 成功 (HTTP 200) 测试 HTTP/1.1 + TLS 1.2 + SECLEVEL=1: ✓ 成功 (HTTP 200) 5. OpenSSL 版本信息: 版本: OpenSSL 1.1.1... 6. cURL 版本信息: 版本: 7.x.x SSL 版本: OpenSSL/1.1.1... 7. 测试实际 API 调用 (MAKE_TOKEN): ✓ 成功获取 token (长度: 64) ``` ### 步骤 3: 清除缓存并重启 ```bash cd server php think clear rm -rf runtime/cache/* # 重启服务 sudo systemctl restart php-fpm sudo systemctl restart nginx ``` ### 步骤 4: 测试接口 ```bash # 查看日志 tail -f server/runtime/log/$(date +%Y%m%d).log | grep -i gancao ``` 在另一个终端调用接口: ```bash curl -X POST https://your-domain.com/api/tcm.prescriptionOrder/submitGancaoRecipel \ -H "Content-Type: application/json" \ -H "token: your_token" \ -d '{"id": 订单ID}' ``` ## 如果仍然失败 ### 方案 A: 检查 OpenSSL 版本 ```bash openssl version ``` **要求:** OpenSSL 1.0.2 或更高版本 **如果版本过低,升级 OpenSSL:** ```bash # CentOS/RHEL sudo yum update openssl # Ubuntu/Debian sudo apt-get update sudo apt-get install --only-upgrade openssl # 重新编译 PHP(如果需要) ``` ### 方案 B: 修改 OpenSSL 配置 编辑 `/etc/ssl/openssl.cnf`: ```ini # 在文件开头添加 openssl_conf = openssl_init [openssl_init] ssl_conf = ssl_sect [ssl_sect] system_default = system_default_sect [system_default_sect] MinProtocol = TLSv1.2 CipherString = DEFAULT@SECLEVEL=1 ``` 重启服务: ```bash sudo systemctl restart php-fpm ``` ### 方案 C: 使用不同的 TLS 版本 如果 TLS 1.2 不工作,尝试其他版本。 修改 `GancaoOpenApiTransport.php`: ```php // 尝试 TLS 1.3 curl_setopt($ch, CURLOPT_SSLVERSION, CURL_SSLVERSION_TLSv1_3); // 或者让 cURL 自动选择 curl_setopt($ch, CURLOPT_SSLVERSION, CURL_SSLVERSION_DEFAULT); ``` ### 方案 D: 禁用 HTTP/2 如果使用了 HTTP/2,尝试禁用: ```php curl_setopt($ch, CURLOPT_HTTP_VERSION, CURL_HTTP_VERSION_1_1); ``` ### 方案 E: 增加调试信息 临时添加详细的 cURL 调试: ```php // 在 GancaoOpenApiTransport.php 的 post 方法中添加 curl_setopt($ch, CURLOPT_VERBOSE, true); $verbose = fopen('php://temp', 'w+'); curl_setopt($ch, CURLOPT_STDERR, $verbose); // 在 curl_exec 之后添加 rewind($verbose); $verboseLog = stream_get_contents($verbose); \think\facade\Log::info('cURL verbose output', ['log' => $verboseLog]); ``` 查看详细日志: ```bash tail -f server/runtime/log/$(date +%Y%m%d).log ``` ### 方案 F: 联系甘草技术支持 提供以下信息: 1. `php test_gancao_ssl.php` 的完整输出 2. `openssl version` 输出 3. `php -v` 输出 4. `curl --version` 输出 5. 服务器操作系统版本 询问: - 甘草网关支持的 TLS 版本 - 推荐的 SSL 加密套件 - 是否有特殊的 HTTP 头要求 - 是否有 IP 白名单限制 ## 常见问题 ### Q1: 为什么 HTTP/1.0 会导致问题? A: 某些现代服务器不再支持 HTTP/1.0,或者在 HTTP/1.0 下有不同的 SSL 处理逻辑。HTTP/1.1 是更标准的选择。 ### Q2: SECLEVEL=1 是什么? A: OpenSSL 1.1.0+ 引入了安全级别概念: - SECLEVEL=2(默认):要求 112 位安全性 - SECLEVEL=1:要求 80 位安全性(更宽松) - SECLEVEL=0:允许所有加密套件(不推荐) 降低安全级别可以兼容更多服务器,但会降低安全性。 ### Q3: 为什么要禁用 SSL 验证? A: 在开发/测试环境中,禁用 SSL 验证可以避免证书问题。**生产环境建议启用验证**。 ### Q4: TCP keepalive 有什么用? A: 保持 TCP 连接活跃,防止长时间传输时连接被中断。 ## 验证修复成功 修复成功的标志: 1. ✅ `php test_gancao_ssl.php` 显示 "✓ 成功获取 token" 2. ✅ 接口返回成功: ```json { "code": 1, "msg": "甘草药方上传成功", "data": {...} } ``` 3. ✅ 日志中没有 SSL 错误 4. ✅ 数据库中订单已更新 ## 总结 SSL 连接问题通常是由于: 1. **TLS 版本不匹配** → 使用 TLS 1.2 2. **HTTP 版本问题** → 使用 HTTP/1.1 3. **OpenSSL 安全级别过高** → 降低到 SECLEVEL=1 4. **连接超时** → 增加超时时间 修复后应该能正常连接甘草 API。如果仍有问题,运行 `test_gancao_ssl.php` 并根据输出进一步诊断。