以下脚本适用于PHP 5.6.23:
$options = [
CURLOPT_POST => 1,
CURLOPT_URL => 'https://uat.dwolla.com/oauth/rest/offsitegateway/checkouts',
CURLOPT_RETURNTRANSFER => 1,
CURLOPT_POSTFIELDS => json_encode(['name'=>'value']),
CURLOPT_HTTPHEADER => ['Content-Type: application/json'],
CURLOPT_SSL_VERIFYPEER => true,
CURLOPT_CAINFO => '/path/to/certs/GoDaddyRootCertificateAuthority-G2.crt',
];
$ch = curl_init();
curl_setopt_array($ch, $options);
if( ! $result = curl_exec($ch)) $err = curl_error($ch);
else $err = null;
curl_close($ch);
if($err) echo $err;
else print_r(json_decode($result,true));
Run Code Online (Sandbox Code Playgroud)
我从Dwolla的付款API得到了预期的响应。为了使脚本更具动态性,我尝试将其更改为引用托管我希望cURL信任的证书的目录。因此,我将最后一个选项(CURLOPT_CAINFO)更改为:
CURLOPT_CAPATH => '/path/to/certs'
Run Code Online (Sandbox Code Playgroud)
但是,这会破坏脚本,并且不会建立连接。错误是:
SSL证书问题:无法获取本地颁发者证书
我知道目录是正确的,并且证书文件有效,因为原始脚本引用了该目录中的证书。我希望cURL扫描目录中的文件并找到所需的证书,但是这没有发生。为什么是这样?
如果您只是将 CApath 指向某个目录并将证书放入该目录,则它不起作用。为了高效地找到正确的 CA 证书,此目录中的文件需要具有从证书主题派生的名称。例如,您可能会在以下位置找到以下内容/etc/ssl/certs:
ff783690.0 -> UTN_USERFirst_Hardware_Root_CA.pem
ff588423.0 -> ComSign_CA.pem
...
Run Code Online (Sandbox Code Playgroud)
这里的文件名基于证书主题的哈希值并指向真实证书。有关如何创建必要文件名的信息,请参阅如何计算 CA 文件名使用的哈希值 。
另请参阅openssl verify的手册页:
-CApath directory
受信任证书的目录。证书应具有以下形式的名称:hash.0 或具有这种形式的符号链接(“hash”是散列的证书主题名称:请参阅 x509 实用程序的 -hash 选项)。在 Unix 下,c_rehash 脚本将自动创建指向证书目录的符号链接。