# 甘草 API "Array to string conversion" 错误修复 ## 问题描述 调用甘草处方下单接口时出现错误: ```json {"code":2,"message":"Array to string conversion"} ``` ## 根本原因 经过分析代码和 API 文档,发现以下几个问题: ### 1. 变量作用域问题 在 `PrescriptionOrderLogic::submitGancaoRecipel()` 方法中,`$appNo` 变量在返回语句中被引用,但实际定义在更早的位置(line 1638),然后又在 line 1658 被重新赋值。这可能导致变量引用错误。 ### 2. 空字符串处理问题 `buildSubmitPayload()` 方法中的 `cradle_store` 字段可能为空字符串,而甘草 API 可能不接受空字符串。 ### 3. 患者年龄格式问题 原代码使用 `sprintf('%d.00', $ageInt)` 格式化年龄,但 API 可能期望简单的整数字符串。 ### 4. doct_advice 字段处理 `doct_advice` 数组中的某些字段可能包含空字符串或未正确处理的值,导致 JSON 编码时出现问题。 ## 修复内容 ### 1. 修复 `GancaoScmRecipelService.php` #### 修改患者年龄格式 ```php // 修改前 $patientAge = sprintf('%d.00', $ageInt); // 修改后 $patientAge = (string) $ageInt; ``` #### 确保 cradle_store 不为空 ```php $preview['cradle_store'] = mb_substr(trim((string) ($c['cradle_store'] ?? '')), 0, 32); if ($preview['cradle_store'] === '') { $preview['cradle_store'] = 'default'; } ``` #### 优化 doct_advice 字段处理 ```php // 确保所有字段都是字符串,避免数组到字符串的转换错误 $tabooStr = $taboo !== '' ? $taboo : '无'; $usageTimeStr = $usageTime; $usageBriefStr = $usageBrief !== '' ? $usageBrief : '遵医嘱'; $othersStr = trim((string) ($rx['usage_notes'] ?? '')); $notesDoctorStr = trim((string) ($order['remark_extra'] ?? '')); $preview['doct_advice'] = [ 'taboo' => $tabooStr, 'usage_time' => $usageTimeStr, 'usage_brief' => $usageBriefStr, 'others' => $othersStr !== '' ? $othersStr : '', 'notes_doctor' => $notesDoctorStr !== '' ? $notesDoctorStr : '', ]; ``` #### 添加调试日志 ```php public static function ctmSubmit(array $submitPayload): array { $transport = self::transport(); // 记录请求负载以便调试 Log::info('Gancao CTM_SUBMIT_RECIPEL payload', ['payload' => $submitPayload]); return $transport->post($submitPayload); } ``` ### 2. 修复 `PrescriptionOrderLogic.php` #### 修复变量引用问题 ```php // 在返回语句中使用正确的变量引用 $fee = $subBody['result']['fee'] ?? []; $appNo = $submitPayload['app_order_no'] ?? ('PO' . (string) $order->id); return [ 'recipel_order_no' => $gcNo, 'app_order_no' => $appNo, 'fee' => is_array($fee) ? $fee : [], ]; ``` #### 添加详细错误日志 ```php use think\facade\Log; // 在 submitGancaoRecipel 方法中添加错误日志 $subRet = GancaoScmRecipelService::ctmSubmit($submitPayload); if ((int) ($subRet['state'] ?? 0) !== 1) { $errMsg = (string) ($subRet['msg'] ?? ''); $response = isset($subRet['response']) ? mb_substr((string) $subRet['response'], 0, 500) : ''; self::$error = '甘草下单通信失败:' . $errMsg . ($response !== '' ? ';响应:' . $response : ''); Log::error('Gancao CTM_SUBMIT failed', ['subRet' => $subRet, 'payload' => $submitPayload]); return false; } $subBody = $subRet['body'] ?? []; if (!GancaoScmRecipelService::isApiSuccess($subBody)) { self::$error = '甘草下单失败:' . GancaoScmRecipelService::apiStatusMessage($subBody); Log::error('Gancao CTM_SUBMIT api error', ['body' => $subBody, 'payload' => $submitPayload]); return false; } ``` ## 测试建议 1. **检查日志文件**:修复后再次调用接口,查看 `runtime/log/` 目录下的日志文件,查找 `Gancao CTM_SUBMIT_RECIPEL payload` 日志,确认发送的数据格式是否正确。 2. **验证必填字段**:根据甘草 API 文档,确保以下字段都有有效值: - `token`:有效的 API token - `df_id`:剂型 ID(如 101 表示饮片) - `amount`:剂量数量 - `m_list`:药材列表(每个药材必须有 `id`、`quantity`、`brief` 字段) - `express_to`:收货地址信息 - `patient`:患者信息 - `doctor`:医生信息 - `callback_url`:回调地址(必须是 HTTPS) 3. **检查配置**:确认 `.env` 文件中的甘草配置完整: ```env GANCAO_SCM_ENABLED=true GANCAO_SCM_GATEWAY_URL=https://xxx GANCAO_SCM_GATEWAY_AK=xxx GANCAO_SCM_GATEWAY_SK=xxx GANCAO_SCM_BIZ_AK=xxx GANCAO_SCM_BIZ_SK=xxx GANCAO_SCM_CALLBACK_URL=https://xxx GANCAO_SCM_CRADLE_STORE=xxx GANCAO_SCM_EXPRESS_TYPE=sf ``` 4. **测试流程**: - 创建一个测试处方订单 - 确保处方审核通过 - 调用 `submitGancaoRecipel` 接口 - 查看返回结果和日志 ## 可能的其他原因 如果修复后仍然出现错误,可能是以下原因: 1. **药材 ID 映射问题**:某些药材的甘草 ID(`gid`)未正确配置 2. **剂型参数问题**:`df101ext` 等剂型扩展参数不符合 API 要求 3. **地址解析问题**:收货地址无法正确解析为省市区 4. **电话号码格式**:电话号码不是 11 位数字 ## 参考文档 - 甘草 API 文档:https://apidoc.igancao.com/service-doc/scm-outer-recipel.html - 特别关注「中药处方下单」和「中药处方下单参数预检查」章节