我正在尝试使用 Stripe 发送 API 请求,但收到错误消息:
cURL 错误 60:SSL 证书问题:无法获取本地颁发者证书
这是我正在运行的代码:
public function chargeStripe()
{
$stripe = new Stripe;
$stripe = Stripe::make(env('STRIPE_PUBLIC_KEY'));
$charge = $stripe->charges()->create([
'amount' => 2900,
'customer' => Input::get('stripeEmail'),
'currency' => 'EUR',
]);
return Redirect::route('step1');
}
我在谷歌上搜索了很多,很多人建议我下载这个文件:cacert.pem,把它放在某个地方并在我的 php.ini 中引用它。这是我的 php.ini 中的部分:
curl.cainfo = "C:\Windows\cacert.pem"
然而,即使在多次重新启动服务器并更改路径后,我也会收到相同的错误消息。
我在 Apache 中启用了 ssl_module,并且在我的 php.ini
中启用了 php_curl。
我也试过这个修复:How to fix PHP CURL Error 60 SSL
这表明我将这些行添加到我的 cURL 选项中:
curl_setopt($process, CURLOPT_CAINFO, dirname(__FILE__) . '/cacert.pem');
curl_setopt($process, CURLOPT_SSL_VERIFYPEER, true);
在哪里向我的 cURL 添加选项?显然不是通过命令行,因为我的 CLI 找不到命令“curl_setopt”
如何解决这个问题呢:
按照 https://curl.se/docs/caextract.html 中的说明下载并提取 cacert.pem
将其保存在文件系统的某个位置(例如,XAMPP 用户可能使用 C:\xampp\php\extras\ssl\cacert.pem)
在您的 php.ini 中,将此文件位置放在 [curl] 部分(将它放在 [openssl] 部分也是一个好主意):
[curl]
curl.cainfo = "C:\xampp\php\extras\ssl\cacert.pem"
[openssl]
openssl.cafile = "C:\xampp\php\extras\ssl\cacert.pem"
重新启动您的网络服务器(例如 Apache)和 PHP FPM 服务器(如果适用)
注意 Wamp/Wordpress/Windows 用户。我有这个问题几个小时,甚至没有正确的答案是为我做的,因为我正在编辑错误的 php.ini 文件,因为这个问题是针对 XAMPP 而不是针对 WAMP 用户的,即使这个问题是针对 WAMP 的。
这就是我所做的
将其放在 C:\wamp64\bin\php\your php version\extras\ssl
内
确保文件 mod_ssl.so
在 C:\wamp64\bin\apache\apache(version)\modules
内
在 Apache 目录 C:\wamp64\bin\apache\apache2.4.27\conf
内的 httpd.conf
中启用 mod_ssl
在 php.ini
中启用 php_openssl.dll
。请注意我的问题是我有两个 php.ini 文件,我需要在这两个文件中都这样做。第一个可以位于您的 WAMP 任务栏图标内。
https://i.stack.imgur.com/GjJfG.png
另一个位于 C:\wamp64\bin\php\php(Version)
找到两个 php.ini
文件的位置并找到行 curl.cainfo =
并给它一个这样的路径
curl.cainfo = "C:\wamp64\bin\php\php(Version)\extras\ssl\cacert.pem"
现在保存文件并重新启动您的服务器,您应该一切顺利
php artisan serv
如果您将 PHP 5.6 与 Guzzle 一起使用,Guzzle 已切换到使用 PHP 库自动检测证书而不是它的进程 (ref)。 PHP 概述了更改here。
找出 PHP/Guzzle 在哪里寻找证书
您可以使用以下 PHP 命令转储 PHP 正在查找的位置:
var_dump(openssl_get_cert_locations());
获取证书包
对于 OS X 测试,您可以使用 homebrew 安装 openssl brew install openssl
,然后在您的 php.ini 或 Zend Server 设置中使用 openssl.cafile=/usr/local/etc/openssl/cert.pem
(在 OpenSSL 下)。
curl 网站上的 curl/Mozilla 还提供了证书包:https://curl.haxx.se/docs/caextract.html
告诉 PHP 证书在哪里
一旦你有了一个包,要么把它放在 PHP 已经在寻找的地方(你在上面找到了),要么在 php.ini 中更新 openssl.cafile
。 (通常,在 Unix 上是 /etc/php.ini
或 /etc/php/7.0/cli/php.ini
或 /etc/php/php.ini
。)
openssl_get_cert_locations
,它使调试变得更加容易。看起来 WAMP 对 apache php 使用与控制台 php 不同的 ini 文件。就我而言,我必须为基于控制台的 php 添加 openssl.cafile="c:/_/cacert.pem"
。上次,通过 apache 使用它时,我需要 curl.cainfo="c:/_/cacert.pem"
才能使其工作。
var_dump(openssl_get_cert_locations());
的语法
var_dump(openssl_get_cert_locations());
是一个 PHP 命令,您需要在 PHP 文件或解释器中运行它。 (为了清楚起见,更新了帖子,说明它是一个 PHP 命令。)
echo "<?php var_dump(openssl_get_cert_locations());" | php
,然后就可以开始了
cartalyst/stripe 使用的 Guzzle 将执行以下操作来查找适当的证书存档以检查服务器证书:
检查您的 php.ini 文件中是否设置了 openssl.cafile。检查 curl.cainfo 是否在您的 php.ini 文件中设置。检查 /etc/pki/tls/certs/ca-bundle.crt 是否存在(Red Hat、CentOS、Fedora;由 ca-certificates 包提供) 检查 /etc/ssl/certs/ca-certificates.crt 是否存在(Ubuntu , Debian; 由 ca-certificates 包提供) 检查 /usr/local/share/certs/ca-root-nss.crt 是否存在 (FreeBSD; 由 ca_root_nss 包提供) 检查 /usr/local/etc/openssl/ cert.pem (OS X; 由 homebrew 提供) 检查 C:\windows\system32\curl-ca-bundle.crt 是否存在 (Windows) 检查 C:\windows\curl-ca-bundle.crt 是否存在 (Windows)
您将需要通过执行一个简单的测试来确保正确定义前两个设置的值:
echo "openssl.cafile: ", ini_get('openssl.cafile'), "\n";
echo "curl.cainfo: ", ini_get('curl.cainfo'), "\n";
或者,尝试将文件写入 #7 或 #8 指示的位置。
如果您无法更改 php.ini,您也可以从如下代码中指向 cacert.pem 文件:
$http = new GuzzleHttp\Client(['verify' => '/path/to/cacert.pem']);
$client = new Google_Client();
$client->setHttpClient($http);
我所做的是在任何 php 脚本中使用 var_dump(openssl_get_cert_locations()); die;
,它为我提供了有关本地 php 正在使用的默认值的信息:
array (size=8)
'default_cert_file' => string 'c:/openssl-1.0.1c/ssl/cert.pem' (length=30)
'default_cert_file_env' => string 'SSL_CERT_FILE' (length=13)
'default_cert_dir' => string 'c:/openssl-1.0.1c/ssl/certs' (length=27)
'default_cert_dir_env' => string 'SSL_CERT_DIR' (length=12)
'default_private_dir' => string 'c:/openssl-1.0.1c/ssl/private' (length=29)
'default_default_cert_area' => string 'c:/openssl-1.0.1c/ssl' (length=21)
'ini_cafile' => string 'E:\xampp\php\extras\ssl\cacert.pem' (length=34)
'ini_capath' => string '' (length=0)
如您所见,我设置了 ini_cafile 或 ini 选项 curl.cainfo。但就我而言,curl 会尝试使用不存在的“default_cert_file”。
我将文件从 https://curl.haxx.se/ca/cacert.pem 复制到“default_cert_file”的位置 (c:/openssl-1.0.1c/ssl/cert.pem),我能够让它工作。
这是我唯一的解决方案。
有一天,当一个 Guzzle(5) 脚本试图通过 SSL 连接到主机时,我遇到了这个问题。当然,我可以禁用 Guzzle/Curl 中的 VERIFY 选项,但这显然不是正确的方法。
我尝试了此处和类似线程中列出的所有内容,然后最终使用 openssl 进入终端以针对我尝试连接的域进行测试:
openssl s_client -connect example.com:443
...并收到前几行表明:
CONNECTED(00000003)
depth=0 CN = example.com
verify error:num=20:unable to get local issuer certificate
verify return:1
depth=0 CN = example.com
verify error:num=21:unable to verify the first certificate
verify return:1
...虽然在尝试其他目的地(即:google.com 等)时一切正常
这促使我联系了我一直试图连接的域,事实上,他们在他们的 END 上遇到了一个问题,这个问题已经悄悄出现了。它已解决,我的脚本又恢复了工作。
所以...如果您要拔掉头发,请给 openssl 一个镜头,看看您尝试连接的位置的响应是否有任何问题。也许这个问题有时并不那么“本地化”。
请确保您直接通过 Window Explorer 打开 php.ini
文件。 (在我的情况下:C:\DevPrograms\wamp64\bin\php\php5.6.25
)。
不要使用系统托盘中 Wamp/Xamp 图标菜单中的 php.ini
快捷方式。在这种情况下,此快捷方式不起作用。
然后编辑该 php.ini
:
curl.cainfo ="C:/DevPrograms/wamp64/bin/php/cacert.pem"
和
openssl.cafile="C:/DevPrograms/wamp64/bin/php/cacert.pem"
保存 php.ini
后,您无需在 Wamp 图标中“重新启动所有服务”或关闭/重新打开 CMD。
php.ini
快捷方式是 .symlink
(0 字节)。它打开(或创建?)文件:<path_to_WAMP_install_location>\wamp64\bin\apache\apache2.4.41\bin\php.ini
(在我的情况下为 74 字节)。此答案建议直接转到您正在使用的 PHP 版本的 WAMP 文件夹,然后编辑该 php.ini
(在我的情况下为 73 字节)文件。
wamp\64\bin\php\php.x.y.z
目录顶部的注释说:`[PHP] ; ****************************************************** ************ ; ****** 不要编辑这个文件 **** 不要编辑这个文件 ****** ; * 此文件仅供 PHP CLI(命令行界面)使用 * ; * 即 Wampserver 内部 PHP 脚本 * ; * 要编辑的正确文件是 Wampmanager Icon->PHP->php.ini * ; * 即 wamp/bin/apache/apache2.xy/bin/php.ini * ; ****************************************************** ************ `` 这是 PHP 7.3.12
<path_to_WAMP_install_directory>\wamp64\bin\php\php7.3.12\phpForApache.ini
,它与 php.ini 文件位于同一目录中,其中包含不应编辑的注释。在同一位置还有 php.ini 的开发版本和生产版本。
你有没有尝试过..
curl_setopt($process, CURLOPT_SSL_VERIFYPEER, false);
如果您想冒遭受中间人攻击的风险,您可以跳过验证。
我找到了一个适合我的解决方案。我从最新的 guzzle 降级到 ~4.0 版,它工作正常。
在 composer.json 添加 "guzzlehttp/guzzle": "~4.0"
希望它可以帮助某人
对于 WAMP,这最终对我有用。
虽然它与其他类似,但此页面上提到的解决方案以及网络上的其他位置都不起作用。一些“次要”细节有所不同。
保存 PEM 文件的位置很重要,但指定的不够清楚。
或者要编辑的 php.ini
文件不正确。或两者兼而有之。
我正在 Windows 10 机器上运行 WAMP 3.2.0 的 2020 安装。
获取pem文件的链接:
http://curl.haxx.se/ca/cacert.pem
复制整个页面并将其另存为:cacert.pem
,在下面提到的位置。
将 PEM 文件保存在此位置
<wamp install directory>\bin\php\php<version>\extras\ssl
例如保存的文件和路径:“T:\wamp64\bin\php\php7.3.12\extras\ssl\cacert.pem”
*(我最初将它保存在其他位置(并在 php.ini 文件中指出了保存的位置,但这不起作用)。可能有也可能没有,其他位置也可以工作。这是推荐的位置 - 我没有知道为什么。)
WHERE
<wamp install directory>
= 您的 WAMP 安装路径。
例如:T:\wamp64\
WAMP 正在运行的 php 的 <php version>
个:(要查找,请转到:WAMP icon tray -> PHP <version number>
如果显示的版本号是 7.3.12,那么目录将是:php7.3.12)
例如:{3 }
要编辑的 php.ini 文件
要打开正确的 php.ini
文件进行编辑,请转到:WAMP icon tray -> PHP -> php.ini
。
例如:T:\wamp64\bin\apache\apache2.4.41\bin\php.ini
注意:它不是 php 目录中的文件!
更新:
虽然它看起来就像我正在编辑文件:T:\wamp64\bin\apache\apache2.4.41\bin\php.ini
,
实际上是在编辑该文件的符号链接目标:T:/wamp64/bin/php/php7.3.12/phpForApache.ini
。
请注意,如果您按照上述说明进行操作,则不会直接编辑 php.ini
文件。您实际上正在编辑一个 phpForApache.ini
文件。 (包含 symlinks 信息的帖子)
如果您阅读了各种 WAMP 目录中 php.ini
文件的 一些 顶部的注释,则它明确指出不要编辑该特定文件。
确保您打开的文件是编辑不包括此警告。
安装扩展 Link Shell Extension 允许我通过添加的选项卡在文件属性窗口中查看符号链接的目标。这是我的SO answer,其中包含有关此扩展程序的更多信息。
如果您在不同时间运行不同版本的 php,您可能需要将 PEM 文件保存在每个相关的 php 目录中。
在 php.ini 文件中进行的编辑:
将 PEM 文件的路径粘贴到以下位置。
取消注释 ;curl.cainfo = 并粘贴到您的 PEM 文件的路径中。例如: curl.cainfo = "T:\wamp64\bin\php\php7.3.12\extras\ssl\cacert.pem"
取消注释 ;openssl.cafile= 并粘贴到您的 PEM 文件的路径中。例如:openssl.cafile="T:\wamp64\bin\php\php7.3.12\extras\ssl\cacert.pem"
学分:
虽然不是官方资源,但这里有一个指向 YouTube 视频的链接,它为我整理了最后的细节:https://www.youtube.com/watch?v=Fn1V4yQNgLs。
所有答案都是正确的;但最重要的是你必须找到正确的 php.ini 文件。在 cmd “php --ini”中检查这个命令不是找到正确的 php.ini 文件的正确答案。
如果你编辑
curl.cainfo ="PATH/cacert.pem"
并检查
var_dump(openssl_get_cert_locations());
那么 curl.cainfo 应该有一个值。如果不是,那不是正确的 php.ini 文件;
*我建议您在 wamp/bin 或 xxamp/bin 或您使用的任何服务器中搜索 *.ini 并一一更改并检查。 *
iis_express/php
上为我工作。谢谢。
我花了太多时间来为我解决这个问题。
我有 PHP 5.5 版,我需要升级到 5.6。
在低于 5.6 的版本中,Guzzle 将使用它自己的 cacert.pem 文件,但在更高版本的 PHP 中,它将使用系统的 cacert.pem 文件。
我还从这里 https://curl.haxx.se/docs/caextract.html 下载了文件并将其设置在 php.ini 中。
在 Guzzles StreamHandler.php 文件 https://github.com/guzzle/guzzle/blob/0773d442aa96baf19d7195f14ba6e9c2da11f8ed/src/Handler/StreamHandler.php#L437 中找到答案
// PHP 5.6 或更高版本将默认查找系统证书。 // < 5.6 时,使用 Guzzle 捆绑的 cacert。
对于那些试图在本地计算机上使用 Wordpress 的应用程序密码功能的人。您需要更新 wp-includes\certificates\ca-bundle.crt
在文本编辑器中打开此文件并附加您的服务器证书。
打开您的自签名证书(.crt)文件并复制所有内容,包括
----开始证书-----
-----结束证书-----
粘贴在 wp-includes\certificates\ca-bundle.crt 的末尾
我刚刚在使用 guzzlehttp/guzzle
composer 包的 Laravel 4 php 框架中遇到了同样的问题。由于某种原因,mailgun 的 SSL 证书突然停止验证,我收到了同样的“错误 60”消息。
如果像我一样,您在无法访问 php.ini
的共享主机上,则无法使用其他解决方案。在任何情况下,Guzzle 都会让这个客户端初始化代码,这很可能会使 php.ini
效果无效:
// vendor/guzzlehttp/guzzle/src/Client.php
$settings = [
'allow_redirects' => true,
'exceptions' => true,
'decode_content' => true,
'verify' => __DIR__ . '/cacert.pem'
];
这里 Guzzle 强制使用其自己的内部 cacert.pem 文件,该文件现在可能已过时,而不是使用 cURL's environment 提供的文件。更改此行(至少在 Linux 上)将 Guzzle 配置为使用 cURL 的默认 SSL 验证逻辑并解决了我的问题:
由于 vendor
中的文件不会被篡改,更好的解决方案是使用 configure the Guzzle client,但这在 Laravel 4 中太难做到了。
希望这可以节省其他人几个小时的调试时间......
这可能是一个边缘情况,但在我的情况下,问题不在于 client conf(我已经在 php.ini
中配置了 curl.cainfo
>),而是远程服务器配置不正确:
它没有在链中发送任何中间证书。使用 Chrome 浏览网站没有错误,但使用 PHP 时出现以下错误。
卷曲错误 60
在远程网络服务器配置中包含中间证书后,它就可以工作了。
您可以使用此站点检查服务器的 SSL 配置:
当我运行 'var_dump(php_ini_loaded_file());'
时,我在我的页面 'C:\Development\bin\apache\apache2.4.33\bin\php.ini' (length=50)'
上得到了这个输出
为了让 php 加载我的证书文件,我必须在此路径 'C:\Development\bin\apache\apache2.4.33\bin\php.ini'
中编辑 php.ini 并在我下载的位置添加 openssl.cafile="C:/Development/bin/php/php7.2.4/extras/ssl/cacert.pem"
并从 https://curl.haxx.se/docs/caextract.html 放置我的证书文件
我在 Windows 10 上,使用 drupal 8、wamp 和 php7.2.4
我正在使用带有免费版 virtualmin 的 Centos 7。使用 Virtualmin,您可以创建一个 wordpress 网站。有一些功能会自动为您更新您的 ssl 证书。我注意到 /etc/httpd/conf/httpd.conf 不包含 SSLCertificateChainFile 条目。应该设置为 /home/websitename/ssl.combined 之类的。相应地更新该文件并重新启动 apache 为我解决了这个问题。我在尝试为 wordpress 安装 jetpack 插件时发现了我的问题。在互联网上搜索使我意识到I didn't have SSL Configured。我按照 Redhat's instructions 了解如何安装证书。我希望这对某人有用。
我对这个问题有一个适当的解决方案,让我们尝试了解这个问题的根本原因。当无法使用系统证书存储中的根证书验证远程服务器 ssl 或远程 ssl 未与链证书一起安装时,就会出现此问题。如果您有一个具有 root ssh 访问权限的 linux 系统,那么在这种情况下,您可以尝试使用以下命令更新您的证书存储:
update-ca-certificates
如果仍然,它不起作用,那么您需要在您的证书存储中添加远程服务器的根证书和临时证书。您可以下载根证书和中间证书并将它们添加到 /usr/local/share/ca-certificates 目录中,然后运行命令 update-ca-certificates
.这应该可以解决问题。同样,对于 Windows,您可以搜索如何添加根证书和中间证书。
解决此问题的另一种方法是要求远程服务器团队将 ssl 证书添加为域根证书、中间证书和根证书的捆绑包。
狂饮版本 5
这个默认配置对我来说很好用。它将禁用所需的 https。
$options = [
'defaults' => ['verify' => false],
];
new GuzzleClient($options);
在其他情况下,您要设置ca的路径,更改为:
['verify' => '/path/to/cacert.pem']
当您使用 Windows 时,我认为您的路径分隔符是 '\'(和 Linux 上的 '/')。尝试使用常量 DIRECTORY_SEPARATOR
。您的代码将更具可移植性。
尝试:
curl_setopt($process, CURLOPT_CAINFO, dirname(__FILE__) . DIRECTORY_SEPARATOR . 'cacert.pem');
编辑:并写下完整路径。我对相对路径有一些问题(也许 curl 是从另一个基本目录执行的?)
如果您使用 WAMP,您还应该在 php.ini 中为 Apache 添加证书行(除了默认的 php.ini 文件):
[curl]
curl.cainfo = C:\your_location\cacert.pem
适用于 php5.3+
不定期副业成功案例分享
curl.cainfo = "C:/cacert.pem"
并且还必须重新启动我的计算机才能使其工作。仅仅重启网络服务器是不够的。希望这会有所帮助:]curl.cainfo
(facepalm)"C:\php\extras\ssl\cacert.pem"
。