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

7.9 KiB
Raw Blame History

甘草 API "Array to string conversion" 最终修复

问题根源

错误发生在 GancaoScmRecipelService::getToken() 方法中:

// 第 126 行
if ($code === '10103' || str_contains($apiMsg, '10103')) {

原因: 当甘草 API 返回错误时,$body['status']['msg'] 可能是数组而不是字符串,导致:

  1. apiStatusMessage() 方法尝试将数组转换为字符串
  2. str_contains() 函数接收到数组参数,触发 "Array to string conversion" 错误

已修复的问题

1. apiStatusMessage() 方法

修复前:

$msg = (string) ($body['status']['msg'] ?? '');

修复后:

$msg = $body['status']['msg'] ?? '';

// 确保 msg 是字符串
if (is_array($msg)) {
    $msg = json_encode($msg, JSON_UNESCAPED_UNICODE);
} else {
    $msg = (string) $msg;
}

2. getToken() 方法中的 str_contains() 调用

修复前:

if ($code === '10103' || str_contains($apiMsg, '10103')) {

修复后:

// 确保 $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.phpPrescriptionOrderController.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: 上传所有修复文件

# 上传修复后的文件
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: 验证文件已上传

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: 运行配置检查

php test_gancao_config.php

期望输出: 所有配置项显示 ✓

步骤 4: 运行 SSL 测试

php test_gancao_ssl.php

期望输出: 至少一种 SSL 配置测试成功,并且能成功获取 token

步骤 5: 清除缓存

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

步骤 6: 重启服务

# PHP-FPM
sudo systemctl restart php-fpm

# Nginx
sudo systemctl restart nginx

# 或者 Apache
sudo systemctl restart apache2

步骤 7: 测试接口

开启日志监控:

tail -f server/runtime/log/$(date +%Y%m%d).log | grep -E "(Gancao|gancao|submitGancao)"

在另一个终端调用接口:

curl -X POST https://your-domain.com/api/tcm.prescriptionOrder/submitGancaoRecipel \
  -H "Content-Type: application/json" \
  -H "token: your_admin_token" \
  -d '{"id": 订单ID}'

预期结果

成功的情况

接口响应:

{
  "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 中的配置:
    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
    '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. 配置检查输出:

    php test_gancao_config.php > config_check.txt 2>&1
    
  2. SSL 测试输出:

    php test_gancao_ssl.php > ssl_check.txt 2>&1
    
  3. 错误日志:

    tail -200 server/runtime/log/$(date +%Y%m%d).log > error.log
    
  4. 接口响应:

    curl -X POST ... > response.json 2>&1
    
  5. 系统信息:

    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 了!