我试图用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。

我还尝试了这个修复:如何修复PHP CURL错误60 SSL

这表明我将这些行添加到我的cURL选项:

curl_setopt($process, CURLOPT_CAINFO, dirname(__FILE__) . '/cacert.pem');
curl_setopt($process, CURLOPT_SSL_VERIFYPEER, true);

我在哪里添加选项到我的cURL?显然不是通过命令行,因为我的CLI没有找到命令“curl_setopt”


当前回答

有一天,当Guzzle(5)脚本试图通过SSL连接到主机时,我突然出现了这个问题。当然,我可以在Guzzle/Curl中禁用验证选项,但这显然不是正确的方法。

我在类似的线程中尝试了这里列出的所有内容,然后最终使用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等)时,一切都很好

这促使我联系了我一直试图连接的域名,事实上,他们在他们的一端有一个问题,已经悄然出现。问题解决了,我的剧本又开始运作了。

所以…如果您非常着急,请尝试openssl,并查看您试图连接的位置的响应是否有任何变化。也许有时候这个问题并不那么“地方性”。

其他回答

请确保您直接通过windows资源管理器打开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" 

and

openssl.cafile="C:/DevPrograms/wamp64/bin/php/cacert.pem"

保存php.ini后,您不需要在Wamp图标中“重新启动所有服务”或关闭/重新打开CMD。

我花了太多时间来解决这个问题。

我的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。

这可能是一个边缘情况,但在我的情况下,问题不是客户端配置(我已经有卷曲。在php.ini中配置了cfo),而不是远程服务器没有正确配置:

它没有在链中发送任何中间证书。没有错误浏览网站使用Chrome,但与PHP我得到以下错误。

卷曲度错误60

在远程web服务器配置中包含中级证书后,它工作了。

您可以使用此站点检查服务器的SSL配置:

https://whatsmychaincert.com/

cartalyst/stripe使用的Guzzle,将执行以下操作来查找合适的证书存档来检查服务器证书:

Check if openssl.cafile is set in your php.ini file. Check if curl.cainfo is set in your php.ini file. Check if /etc/pki/tls/certs/ca-bundle.crt exists (Red Hat, CentOS, Fedora; provided by the ca-certificates package) Check if /etc/ssl/certs/ca-certificates.crt exists (Ubuntu, Debian; provided by the ca-certificates package) Check if /usr/local/share/certs/ca-root-nss.crt exists (FreeBSD; provided by the ca_root_nss package) Check if /usr/local/etc/openssl/cert.pem (OS X; provided by homebrew) Check if C:\windows\system32\curl-ca-bundle.crt exists (Windows) Check if C:\windows\curl-ca-bundle.crt exists (Windows)

你需要通过一个简单的测试来确保前两个设置的值是正确定义的:

echo "openssl.cafile: ", ini_get('openssl.cafile'), "\n";
echo "curl.cainfo: ", ini_get('curl.cainfo'), "\n";

或者,尝试将文件写入#7或#8所指示的位置。

你试过…

curl_setopt($process, CURLOPT_SSL_VERIFYPEER, false);

如果你想冒着被中间人攻击的风险,你可以跳过验证。