curl_init() 報「Call to undefined function」新浪/微博/支付寶等開放平台 SDK 依賴 cURL 實現 HTTPS 請求、表單提交、Cookie 管理、憑證驗證。PHP 默認未啟用 cURL 擴展,需手動配置。
file_get_contents() 強?| 能力 | file_get_contents | cURL |
|---|---|---|
| HTTP 方法 | 僅 GET | GET/POST/PUT/DELETE/PATCH/HEAD... |
| 請求頭控制 | 極其有限 | 完全自定義 |
| Cookie 管理 | 手動拼接 | 自動存儲/發送/持久化 |
| SSL/TLS | 基本支持 | 憑證驗證、客戶端證書、TLS 版本控制 |
| 超時控制 | 僅 default_socket_timeout | 連接/執行/名稱解析分別設置 |
| 多請求並發 | 不支持 | curl_multi_* 異步並發 |
| 進度回調 | 無 | 上傳/下載進度實時回調 |
| 代理支持 | 有限 | HTTP/HTTPS/SOCKS4/5 全支持 |
php.ini<?php phpinfo(); ?>
在瀏覽器查看 Loaded Configuration File 路徑(如 C:\Apache24\bin\php.ini),不是 PHP 安裝目錄下的 php.ini!
; php.ini 中搜索並取消註釋 extension=curl
PHP 7.2+ 無需具體 php_curl.dll,統一用 extension=curl。
將 PHP 安裝目錄下以下文件複製到 Apache 的 bin 目錄(如 C:\Apache24\bin\)或系統 PATH 目錄:
libcrypto-*.dll(OpenSSL 加密庫)libssl-*.dll(OpenSSL SSL 庫)libssh2.dll(SFTP/SCP 支持,可選)nghttp2.dll(HTTP/2 支持,可選)注意:不要複製到 C:\Windows\System32!會污染系統環境,導致版本衝突。
httpd.exe -k restart # 或服務管理器重啟 Apache2.4
再次訪問 phpinfo(),搜索「cURL support → enabled」。
<?php
$ch = curl_init();
curl_setopt_array($ch, [
CURLOPT_URL => 'https://httpbin.org/get',
CURLOPT_RETURNTRANSFER => true,
CURLOPT_TIMEOUT => 10,
CURLOPT_SSL_VERIFYPEER => true, // 生產必須開啟
CURLOPT_CAINFO => __DIR__ . '/cacert.pem', // 指定 CA 憑證包
]);
$response = curl_exec($ch);
if ($response === false) {
throw new RuntimeException('cURL 錯誤: ' . curl_error($ch), curl_errno($ch));
}
$httpCode = curl_getinfo($ch, CURLINFO_HTTP_CODE);
curl_close($ch);
var_dump(json_decode($response, true));
?>
# Ubuntu/Debian sudo apt update && sudo apt install php8.2-curl sudo systemctl restart php8.2-fpm nginx # CentOS/RHEL/Rocky/Alma sudo dnf install php-curl # 或 php82-php-curl (Remi 源) sudo systemctl restart php-fpm nginx
<?php
// 完整的 cURL 選項模板,適配新浪/微博 OAuth
$ch = curl_init();
curl_setopt_array($ch, [
CURLOPT_URL => 'https://api.weibo.com/oauth2/access_token',
CURLOPT_POST => true,
CURLOPT_POSTFIELDS => http_build_query([
'client_id' => 'YOUR_APP_KEY',
'client_secret' => 'YOUR_APP_SECRET',
'grant_type' => 'authorization_code',
'redirect_uri' => 'https://your.com/callback',
'code' => $_GET['code'],
]),
CURLOPT_RETURNTRANSFER => true,
CURLOPT_TIMEOUT => 15,
CURLOPT_CONNECTTIMEOUT => 5,
CURLOPT_SSL_VERIFYPEER => true,
CURLOPT_SSL_VERIFYHOST => 2,
CURLOPT_CAINFO => __DIR__ . '/cacert.pem', // 必須!
CURLOPT_USERAGENT => 'YourApp/1.0 (+https://your.com)',
CURLOPT_HTTPHEADER => [
'Accept: application/json',
'Content-Type: application/x-www-form-urlencoded',
],
// 可選:Cookie 持久化(多步驟 OAuth 需要)
CURLOPT_COOKIEJAR => sys_get_temp_dir() . '/weibo_cookie.txt',
CURLOPT_COOKIEFILE => sys_get_temp_dir() . '/weibo_cookie.txt',
]);
$response = curl_exec($ch);
if ($response === false) {
error_log('新浪 OAuth cURL 錯誤: ' . curl_error($ch));
// 降級處理或拋出異常
}
$httpCode = curl_getinfo($ch, CURLINFO_HTTP_CODE);
curl_close($ch);
$result = json_decode($response, true);
if ($httpCode !== 200 || empty($result['access_token'])) {
throw new RuntimeException('獲取 access_token 失敗: ' . ($result['error_description'] ?? '未知錯誤'));
}
// 存儲 $result['access_token']、$result['expires_in']、$result['uid']
?>
cacert.pemcURL 驗證 HTTPS 服務器憑證需要信任根憑證。下載最新版:
wget https://curl.se/ca/cacert.pem -O /etc/ssl/certs/cacert.pem # 或 PHP 目錄 wget https://curl.se/ca/cacert.pem -O /usr/local/php/cacert.pem
在 php.ini 全局配置:
curl.cainfo = /etc/ssl/certs/cacert.pem openssl.cafile = /etc/ssl/certs/cacert.pem
| 錯誤信息 | 原因 | 解決 |
|---|---|---|
| SSL certificate problem: unable to get local issuer certificate | 缺少 CA 憑證包 | 配置 CURLOPT_CAINFO 或 curl.cainfo |
| Could not resolve host | DNS 解析失敗 | 檢查服務器 DNS、/etc/resolv.conf、防火牆 |
| Connection timed out | 網絡不通/防火牆攔截 | 檢查安全組、iptables、目標 IP 端口通達性 |
| Protocol "https" not supported | cURL 編譯無 OpenSSL | 重裝 php-curl、確保 libssl 存在 |
| cURL error 60 | 同 SSL 憑證問題 | 同上 |
<?php
function multiCurl(array $urls, int $maxConcurrent = 10): array {
$mh = curl_multi_init();
$handles = [];
$results = [];
foreach ($urls as $i => $url) {
$ch = curl_init($url);
curl_setopt_array($ch, [
CURLOPT_RETURNTRANSFER => true,
CURLOPT_TIMEOUT => 10,
CURLOPT_SSL_VERIFYPEER => true,
CURLOPT_CAINFO => '/etc/ssl/certs/cacert.pem',
]);
curl_multi_add_handle($mh, $ch);
$handles[$i] = $ch;
// 控制並發數
if (count($handles) >= $maxConcurrent) {
$results = array_merge($results, executeMulti($mh, $handles));
$handles = [];
}
}
if ($handles) $results = array_merge($results, executeMulti($mh, $handles));
curl_multi_close($mh);
return $results;
}
function executeMulti($mh, &$handles): array {
$running = null;
do { curl_multi_exec($mh, $running); } while ($running);
$results = [];
foreach ($handles as $i => $ch) {
$results[$i] = [
'content' => curl_multi_getcontent($ch),
'http_code' => curl_getinfo($ch, CURLINFO_HTTP_CODE),
'error' => curl_error($ch),
];
curl_multi_remove_handle($mh, $ch);
curl_close($ch);
}
return $results;
}
?>
CURLOPT_SSL_VERIFYPEER => falseCURLOPT_POSTFIELDS、Content-Type、Cookie 持久化curl_multi_* 或 Swoole/ReactPHP 異步客戶端配好 cURL,PHP 對接任何 HTTP API 都不再是夢魘!