This commit is contained in:
Your Name
2026-04-15 16:31:25 +08:00
parent 906684c1ed
commit 3d9c5dd8f5
47 changed files with 7963 additions and 10 deletions
+318
View File
@@ -0,0 +1,318 @@
# 甘草 API "Array to string conversion" 最终修复
## 问题根源
错误发生在 `GancaoScmRecipelService::getToken()` 方法中:
```php
// 第 126 行
if ($code === '10103' || str_contains($apiMsg, '10103')) {
```
**原因:** 当甘草 API 返回错误时,`$body['status']['msg']` 可能是**数组**而不是字符串,导致:
1. `apiStatusMessage()` 方法尝试将数组转换为字符串
2. `str_contains()` 函数接收到数组参数,触发 "Array to string conversion" 错误
## 已修复的问题
### 1. `apiStatusMessage()` 方法
**修复前:**
```php
$msg = (string) ($body['status']['msg'] ?? '');
```
**修复后:**
```php
$msg = $body['status']['msg'] ?? '';
// 确保 msg 是字符串
if (is_array($msg)) {
$msg = json_encode($msg, JSON_UNESCAPED_UNICODE);
} else {
$msg = (string) $msg;
}
```
### 2. `getToken()` 方法中的 `str_contains()` 调用
**修复前:**
```php
if ($code === '10103' || str_contains($apiMsg, '10103')) {
```
**修复后:**
```php
// 确保 $apiMsg 是字符串,避免 Array to string conversion 错误
$apiMsgStr = is_string($apiMsg) ? $apiMsg : json_encode($apiMsg, JSON_UNESCAPED_UNICODE);
if ($code === '10103' || str_contains($apiMsgStr, '10103')) {
```
### 3. 其他已修复的问题
#### SSL 连接问题(`GancaoOpenApiTransport.php`
- ✅ 改用 HTTP/1.1
- ✅ 强制使用 TLS 1.2
- ✅ 降低 OpenSSL 安全级别
- ✅ 增加连接超时
- ✅ 添加 TCP keepalive
#### 配置类型问题(`GancaoScmRecipelService.php`
- ✅ 确保 `express_type` 是字符串
- ✅ 确保 `callback_url` 是字符串
- ✅ 修复患者年龄格式
- ✅ 优化 `doct_advice` 字段处理
#### 错误处理(`PrescriptionOrderLogic.php` 和 `PrescriptionOrderController.php`
- ✅ 添加详细错误日志
- ✅ 添加异常捕获
- ✅ 添加返回值类型检查
## 完整的修复文件列表
1.`server/app/common/service/gancao/GancaoScmRecipelService.php`
2.`server/app/common/service/gancao/GancaoOpenApiTransport.php`
3.`server/app/adminapi/logic/tcm/PrescriptionOrderLogic.php`
4.`server/app/adminapi/controller/tcm/PrescriptionOrderController.php`
## 部署步骤
### 步骤 1: 上传所有修复文件
```bash
# 上传修复后的文件
scp server/app/common/service/gancao/GancaoScmRecipelService.php user@server:/path/to/server/app/common/service/gancao/
scp server/app/common/service/gancao/GancaoOpenApiTransport.php user@server:/path/to/server/app/common/service/gancao/
scp server/app/adminapi/logic/tcm/PrescriptionOrderLogic.php user@server:/path/to/server/app/adminapi/logic/tcm/
scp server/app/adminapi/controller/tcm/PrescriptionOrderController.php user@server:/path/to/server/app/adminapi/controller/tcm/
# 上传测试脚本
scp test_gancao_config.php user@server:/path/to/
scp test_gancao_ssl.php user@server:/path/to/
scp diagnose_gancao_payload.php user@server:/path/to/
```
### 步骤 2: 验证文件已上传
```bash
ssh user@server
cd /path/to/your/project
# 检查文件修改时间
ls -la server/app/common/service/gancao/GancaoScmRecipelService.php
ls -la server/app/common/service/gancao/GancaoOpenApiTransport.php
ls -la server/app/adminapi/logic/tcm/PrescriptionOrderLogic.php
ls -la server/app/adminapi/controller/tcm/PrescriptionOrderController.php
```
### 步骤 3: 运行配置检查
```bash
php test_gancao_config.php
```
**期望输出:** 所有配置项显示 ✓
### 步骤 4: 运行 SSL 测试
```bash
php test_gancao_ssl.php
```
**期望输出:** 至少一种 SSL 配置测试成功,并且能成功获取 token
### 步骤 5: 清除缓存
```bash
cd server
php think clear
rm -rf runtime/cache/*
rm -rf runtime/temp/*
```
### 步骤 6: 重启服务
```bash
# PHP-FPM
sudo systemctl restart php-fpm
# Nginx
sudo systemctl restart nginx
# 或者 Apache
sudo systemctl restart apache2
```
### 步骤 7: 测试接口
**开启日志监控:**
```bash
tail -f server/runtime/log/$(date +%Y%m%d).log | grep -E "(Gancao|gancao|submitGancao)"
```
**在另一个终端调用接口:**
```bash
curl -X POST https://your-domain.com/api/tcm.prescriptionOrder/submitGancaoRecipel \
-H "Content-Type: application/json" \
-H "token: your_admin_token" \
-d '{"id": 订单ID}'
```
## 预期结果
### 成功的情况
**接口响应:**
```json
{
"code": 1,
"show": 0,
"msg": "甘草药方上传成功",
"data": {
"recipel_order_no": "GC202604...",
"app_order_no": "PO123",
"fee": {
"total": 150.00,
"medicine": 120.00,
"process": 20.00,
"express": 10.00
}
}
}
```
**日志内容:**
```
[info] Gancao MAKE_TOKEN request: {...}
[info] Gancao MAKE_TOKEN response: {...}
[info] Gancao CTM_SUBMIT_RECIPEL payload: {...}
[info] submitGancaoRecipel success: {...}
```
**数据库变化:**
- `prescription_order` 表中对应订单的 `gancao_reciperl_order_no` 字段已更新
- `gancao_submit_time` 字段已更新为当前时间戳
### 失败的情况
如果仍然失败,日志会显示详细错误信息:
**配置错误:**
```
[error] Gancao MAKE_TOKEN api error: {"body": {...}, "apiMsg": "..."}
```
→ 检查 `.env` 配置,特别是 AK/SK
**SSL 连接错误:**
```
[error] Gancao CTM_SUBMIT failed: {"subRet": {...}, "payload": {...}}
```
→ 运行 `php test_gancao_ssl.php` 诊断 SSL 问题
**业务逻辑错误:**
```
[error] submitGancaoRecipel exception: {"message": "...", "trace": "..."}
```
→ 检查处方数据是否完整,药材 ID 是否正确映射
## 常见错误和解决方案
### 错误 1: "Array to string conversion"
**已修复!** 如果仍然出现,请检查:
1. 文件是否正确上传
2. 缓存是否已清除
3. 服务是否已重启
### 错误 2: SSL 连接错误
**解决方案:**
1. 运行 `php test_gancao_ssl.php`
2. 查看哪种 SSL 配置成功
3. 如果都失败,检查 OpenSSL 版本:`openssl version`
4. 联系甘草技术支持确认 SSL 要求
### 错误 3: "MAKE_TOKEN 失败:[10103]"
**原因:** AK/SK 不匹配或密码计算错误
**解决方案:**
1. 检查 `.env` 中的配置:
```env
GANCAO_SCM_BIZ_AK=xxx
GANCAO_SCM_BIZ_SK=xxx
```
2. 确认 BIZ AK/SK 与网关 AK/SK 是否相同
3. 检查服务器时间是否正确:`date`
4. 联系甘草获取正确的 AK/SK
### 错误 4: "药材无法匹配甘草药ID"
**原因:** 药材 ID 映射缺失
**解决方案:**
1. 检查 `zyt_doctor_medicine` 表中药材的 `gid` 字段
2. 或在 `.env` 配置 `herb_id_map`
```php
'herb_id_map' => [
'当归' => 1001,
'黄芪' => 1002,
]
```
## 验证修复成功
✅ **所有以下条件都满足,说明修复成功:**
1. `php test_gancao_config.php` 全部通过
2. `php test_gancao_ssl.php` 显示 "✓ 成功获取 token"
3. 接口返回 `{"code": 1, "msg": "甘草药方上传成功"}`
4. 日志中显示 `submitGancaoRecipel success`
5. 数据库中订单已更新 `gancao_reciperl_order_no`
6. 没有 "Array to string conversion" 错误
7. 没有 SSL 连接错误
## 技术支持
如果以上步骤都无法解决问题,请收集以下信息:
1. **配置检查输出:**
```bash
php test_gancao_config.php > config_check.txt 2>&1
```
2. **SSL 测试输出:**
```bash
php test_gancao_ssl.php > ssl_check.txt 2>&1
```
3. **错误日志:**
```bash
tail -200 server/runtime/log/$(date +%Y%m%d).log > error.log
```
4. **接口响应:**
```bash
curl -X POST ... > response.json 2>&1
```
5. **系统信息:**
```bash
php -v > system_info.txt
openssl version >> system_info.txt
curl --version >> system_info.txt
cat /etc/os-release >> system_info.txt
```
将这些文件发送给技术支持进行分析。
## 总结
这次修复解决了三个主要问题:
1. **Array to string conversion** - 甘草 API 返回的错误消息可能是数组
2. **SSL 连接失败** - TLS 版本和 HTTP 版本不兼容
3. **配置类型错误** - 某些配置值被错误地解析为数组
所有问题都已修复,现在应该可以正常调用甘草 API 了!