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

285 lines
6.3 KiB
Markdown
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
# 甘草 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` 并根据输出进一步诊断。