285 lines
6.3 KiB
Markdown
285 lines
6.3 KiB
Markdown
# 甘草 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` 并根据输出进一步诊断。
|