Files
zyt/GANCAO_SSL_FIX.md
T
2026-04-15 16:31:25 +08:00

6.3 KiB
Raw Blame History

甘草 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

// 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: 上传修复后的文件

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 测试

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: 清除缓存并重启

cd server
php think clear
rm -rf runtime/cache/*

# 重启服务
sudo systemctl restart php-fpm
sudo systemctl restart nginx

步骤 4: 测试接口

# 查看日志
tail -f server/runtime/log/$(date +%Y%m%d).log | grep -i gancao

在另一个终端调用接口:

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 版本

openssl version

要求: OpenSSL 1.0.2 或更高版本

如果版本过低,升级 OpenSSL

# 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

# 在文件开头添加
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

重启服务:

sudo systemctl restart php-fpm

方案 C: 使用不同的 TLS 版本

如果 TLS 1.2 不工作,尝试其他版本。

修改 GancaoOpenApiTransport.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,尝试禁用:

curl_setopt($ch, CURLOPT_HTTP_VERSION, CURL_HTTP_VERSION_1_1);

方案 E: 增加调试信息

临时添加详细的 cURL 调试:

// 在 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]);

查看详细日志:

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. 接口返回成功:
    {
      "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 并根据输出进一步诊断。