319 lines
7.9 KiB
Markdown
319 lines
7.9 KiB
Markdown
# 甘草 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 了!
|