【PHP】遇到了无数个Apache的curl配置问题【Windows】
希望这篇文章能够对Windows用户提供一些帮助。
环境
-
- Windows 11
-
- PHP 8.1.6
- Apache 2.4
事件的起源
我试图使用Slack API的chat.postMessage从本地主机的Apache发送。
function send_slack(string $text): void
{
// SlackbotのtokenとchannelIDを取得
$token = 'xoxb-XXXXXXXXXXXXXXXXXXXXX';
$channel_id = 'XXXXXXXXXXX';
// クエリ
$query = 'channel='.$channel_id.'&text='.$text;
// APIリクエストのヘッダーを作成
$headers = [
'Authorization: Bearer ' . $token
];
// cURLを使用してAPIリクエストを送信
$ch = curl_init();
curl_setopt($ch, CURLOPT_URL, 'https://slack.com/api/chat.postMessage');
curl_setopt($ch, CURLOPT_RETURNTRANSFER, true);
curl_setopt($ch, CURLOPT_SSL_VERIFYPEER, false);
curl_setopt($ch, CURLOPT_POST, true);
curl_setopt($ch, CURLOPT_POSTFIELDS, $query);
// curl_setopt($ch, CURLOPT_POSTFIELDS, "channel=$channel_id&text=$text");
curl_setopt($ch, CURLOPT_HTTPHEADER, $headers);
$response = curl_exec($ch);
curl_close($ch);
// APIレスポンスを返す
// echo $response;
return;
}
运行时发生了以下错误。
Fatal error: Call to undefined function curl_init() in ...
确实,我没有设置过curl。然后我决定开始配置,并且开始工作了,但是我在搜索到的文章中很少有关于Windows的内容,大部分都是关于Linux的,所以我纠结了大约一个小时。
尝试过的事情
请在命令提示符中显示模块列表。
在命令提示符窗口中执行 php -m。
C:\Users\username>php -m
[PHP Modules]
bcmath
calendar
Core
ctype
curl
date
dom
filter
hash
iconv
json
libxml
mbstring
mysqlnd
openssl
...
[Zend Modules]
curl这个项目出现在这里,但是它没有正常工作,这可能是因为某个模块无法正确加载。
因此,需要尝试一些不同的方法。
确认PHP的设置。
检查php.ini文件
确认项目如下所示。
extension_dirがPHPのextディレクトリを指定している。
extension=curlのコメントアウトを解除している。openSSLのモジュールもついでに確認。
安装curl和openSSL
curl已经下载完成。openSSL我下载了64位版(轻量级),并安装在C:\Program Files目录下。详情略。
查找curl模块的依赖关系
使用PHP附带的deplister.exe程序。在命令提示符中导航到安装PHP的目录,然后执行以下命令。
C:\PHP>deplister.exe ext\php_curl.dll
这就是结果。
C:\PHP>deplister.exe ext\php_curl.dll
php8ts.dll,OK
libcrypto-1_1-x64.dll,OK
libssl-1_1-x64.dll,OK
CRYPT32.dll,OK
WLDAP32.dll,OK
Normaliz.dll,OK
libssh2.dll,OK
nghttp2.dll,OK
KERNEL32.dll,OK
WS2_32.dll,OK
VCRUNTIME140.dll,OK
api-ms-win-crt-heap-l1-1-0.dll,OK
api-ms-win-crt-stdio-l1-1-0.dll,OK
api-ms-win-crt-string-l1-1-0.dll,OK
api-ms-win-crt-runtime-l1-1-0.dll,OK
api-ms-win-crt-convert-l1-1-0.dll,OK
api-ms-win-crt-filesystem-l1-1-0.dll,OK
api-ms-win-crt-time-l1-1-0.dll,OK
api-ms-win-crt-utility-l1-1-0.dll,OK
如果返回的不是OK,而是NOT_FOUND之类的错误,则可能是模块不存在或损坏。安装openSSL和Visual C++可再分发包等能够解决这些文件不齐全的问题。
大部分文章似乎在这里已经解决了(?),但是我并没有解决。经过进一步的调查和研究,我最终通过以下方法使其正常运行。
在httpd.conf文件中添加附加内容。
在文件末尾添加了以下描述。
# cURL
LoadFile "C:\PHP\libssh2.dll"
LoadFile "C:\PHP\libcrypto-1_1-x64.dll"
LoadFile "C:\PHP\libssl-1_1-x64.dll"
我会在重新启动Apache之后,添加一条curl的指令到phpinfo()函数中,可以确认这是否是正确的方法,经过这样的操作,我成功地将信息发送到了Slack,问题得到解决!
刚刚当我以为结束了,却又来了一波。
Fatal error: Uncaught GuzzleHttp\Exception\RequestException: cURL error 60: SSL certificate problem: unable to get local issuer certificate (see https://curl.haxx.se/libcurl/c/libcurl-errors.html) for https://oauth2.googleapis.com/token in ...
这似乎不是发生在Slack API上,而是在调用Google Sheet API时发生的。据说有两种解决方法可供选择。
-
- 禁用SSL证书验证
- 设置正确的根证书
由于1在安全方面不可靠,我尝试了2。
设置根证书
这次使用了提供的证书。关于如何生成自己的证书,请参考其他文章。请从下面链接下载 cacert.pem 文件。
将cacert.pem文件放置在合适的位置,并在php.ini中添加证书路径。我将其放置在openSSL文件夹内,所以配置如下:
curl.cainfo = "C:\Program Files\OpenSSL-Win64\cacert.pem"