php 8.5 调用百度翻译 api 报 curl error 60 是因 ssl 证书验证失败,应更新 ca 证书路径并在 php.ini 中配置 curl.cainfo;签名错误源于中文未 urlencode 导致 md5 不一致;file_get_contents 需手动设置 content-type 和 content-length;json_decode 失败需清除 bom 并启用 json_throw_on_error。

PHP 8.5 调用百度翻译 API 报 cURL error 60 怎么办
PHP 8.5 默认启用了更严格的 SSL 验证,而百度翻译 API 的 HTTPS 证书链在某些系统(尤其是旧版 CA 包或 Docker 容器)里可能不被信任,直接导致 cURL error 60: SSL certificate problem。
别关验证,也别硬加 CURLOPT_SSL_VERIFYPEER => false —— 这等于把门敞开。正确做法是更新 CA 证书路径:
- 确认你的 PHP 使用的 cURL 是否绑定了系统 OpenSSL:运行
php -r "print_r(curl_version());",看ssl_version和features里是否有CURL_VERSION_SSL - 下载最新 CA 包:
wget https://curl.se/ca/cacert.pem -O /usr/local/share/ca-bundle.crt(路径可自定) - 在代码里显式指定:
curl_setopt($ch, CURLOPT_CAINFO, '/usr/local/share/ca-bundle.crt'); - 或者全局配置(推荐):在
php.ini加一行curl.cainfo = "/usr/local/share/ca-bundle.crt"
百度翻译 API 签名生成总对不上,sign 参数失效
签名错不是因为算法写错了,而是 PHP 8.5 对字符串拼接和编码更敏感——特别是中文参数没做 urlencode 就直接塞进签名原文,会导致 md5 结果和百度服务器算的不一致。
关键三步必须严格按顺序来:
立即学习“PHP免费学习笔记(深入)”;
- 拼接原始字符串时,所有参与签名的字段(
q、app_id、salt、secret_key)必须先urlencode,再按字典序拼(百度文档说“按参数名排序”,但实际是 ASCII 字符序,app_id在q前) -
q是待翻译文本,哪怕只是"你好",也要urlencode("你好")→%E4%BD%A0%E5%A5%BD,否则签名原文就错了 - 最终签名用
md5(),不是hash('md5', ...);PHP 8.5 已废弃md5()的第三个参数,别传true
示例片段:
$q = "你好";<br>$sign_str = $appid . urlencode($q) . $salt . $secret_key;<br>$sign = md5($sign_str);
用 file_get_contents 发 POST 请求,返回空或 520
百度翻译 API 明确要求 Content-Type: application/x-www-form-urlencoded,而 file_get_contents 默认发的是纯文本,服务端直接拒收,返回模糊的 520 Origin Error 或空响应。
改用 curl 是最稳的,但如果坚持用 file_get_contents,必须手动构造完整上下文:
-
http_build_query()封装参数,别手拼q=xxx&from=auto&to=en -
stream_context_create()中必须设'content'键为 raw POST body,且'header'里明确写Content-Type: application/x-www-form-urlencoded - 不能漏
Content-Length,PHP 不会自动补,得自己算:strlen(http_build_query($data))
PHP 8.5 的 json_decode 解析百度返回结果失败
百度翻译 API 返回的是标准 JSON,但 PHP 8.5 的 json_decode 默认不接受 null、NaN 或带 BOM 的 UTF-8 —— 而部分代理或调试工具可能悄悄加了 BOM,导致 json_last_error() 返回 JSON_ERROR_UTF8。
安全解法是预处理响应体:
- 用
mb_convert_encoding($raw, 'UTF-8', 'UTF-8')清掉非法字节 - 或简单粗暴地删 BOM:
ltrim($raw, "\xEF\xBB\xBF") - 调用
json_decode($cleaned, true, 512, JSON_THROW_ON_ERROR),加JSON_THROW_ON_ERROR让错误立刻暴露,别靠=== null判断
另外注意:百度返回的 trans_result 是数组,但若翻译失败(比如 error_code 非 0),它可能不存在,直接取 $json['trans_result'][0]['dst'] 会触发 Notice —— 动手前先 isset()。











