适用场景:
✔ PHP 调第三方 API 返回乱码
✔ 接口偶尔失败、不稳定
✔ 想搞清楚是接口问题,还是自己代码问题
一、先上「万能调试函数」(直接复制就能用)
function curlDebug($url, $method = 'GET', $data = [], $headers = [])
{
$ch = curl_init();
// 请求方式
if (strtoupper($method) === 'POST') {
curl_setopt($ch, CURLOPT_POST, true);
curl_setopt($ch, CURLOPT_POSTFIELDS, $data);
} else {
if (!empty($data)) {
$url .= (strpos($url, '?') === false ? '?' : '&')
. http_build_query($data);
}
}
curl_setopt_array($ch, [
CURLOPT_URL => $url,
CURLOPT_RETURNTRANSFER => true,
CURLOPT_HEADER => true, // 关键:返回 header + body
CURLOPT_SSL_VERIFYPEER => false,
CURLOPT_SSL_VERIFYHOST => false,
CURLOPT_TIMEOUT => 15,
CURLOPT_ENCODING => '', // 自动解 gzip / deflate
CURLOPT_HTTPHEADER => $headers,
]);
$response = curl_exec($ch);
if ($response === false) {
return [
'error' => curl_error($ch),
];
}
// 分离 header 和 body
$headerSize = curl_getinfo($ch, CURLINFO_HEADER_SIZE);
$rawHeader = substr($response, 0, $headerSize);
$body = substr($response, $headerSize);
curl_close($ch);
// ===== 编码判断 =====
$encoding = mb_detect_encoding(
$body,
['UTF-8', 'GBK', 'GB2312', 'BIG5', 'ISO-8859-1'],
true
);
// 如果不是 UTF-8,转成 UTF-8
if ($encoding && $encoding !== 'UTF-8') {
$body = mb_convert_encoding($body, 'UTF-8', $encoding);
}
return [
'http_header' => $rawHeader,
'detected_encoding' => $encoding ?: '未知',
'body' => $body,
];
}
二、怎么用?(新手 3 秒上手)
$result = curlDebug('https://api.example.com/test');
echo "<pre>";
print_r($result);
你能一次性看到:
- ✅ 接口完整 Header
- ✅ 实际返回内容
- ✅ 系统判断的编码类型
- ✅ 是否被自动转成 UTF-8
📌 调试阶段千万别直接 echo 接口内容,一定要先 print_r。
三、这个模板到底“万能”在哪?
我给你拆一下它解决的 真实痛点。
① 自动判断编码(不再瞎猜)
mb_detect_encoding(...)
能直接告诉你:
- UTF-8
- GBK
- GB2312
- 还是其他奇葩编码
你不用再靠肉眼猜乱码。
② 自动解 gzip(很多人卡死在这)
CURLOPT_ENCODING => ''
这一行,解决了:
- 看着像乱码
- 实际是 gzip 压缩二进制
👉 不加这一句,很多接口你永远看不懂返回值。
③ Header 和 Body 强制分离(查问题神器)
CURLOPT_HEADER => true
你可以清楚看到:
- Content-Type
- charset
- 是否 gzip
- 服务端到底声明了什么
📌 很多接口:Header 写 UTF-8,Body 实际是 GBK,一眼就能发现。
四、最常见的 3 种调试结果解读
情况 1:编码显示 UTF-8,但内容还是乱码
👉 接口声明不可信,实际编码是假的
解决:
手动指定正确编码再转。
情况 2:编码是 GBK,转完就正常
👉 最理想情况,问题结束
情况 3:编码检测失败,全是怪字符
👉 多半是:
- gzip 没解
- 或接口本身返回的不是文本
五、强烈建议的调试顺序(少走 80% 弯路)
1️⃣ 用这个模板看 原始返回
2️⃣ 确认 Header 的 charset
3️⃣ 看 detect_encoding 的结果
4️⃣ 再决定要不要转码
千万别一上来就 iconv / mb_convert_encoding 乱试。
接口乱码不是玄学,
你只是缺一个:
能把“原始真相”扒出来的 cURL 模板。