僕の場合は、現在限定公開中(ビジネスプランのみのようです)のChatWorkAPIを叩くときに出ました。
ちなみにChatWork APIへの接続方法は、ストックさせていただきましたが、以下の記事を参考にさせていただきました。
ChatWork API を叩く PHP と Python のサンプル
http://qiita.com/wings1685/items/9090f59ab09e73f7c8fb
ただ、ググると、ChatWork関係なく、他のサービス、FacebookやTwitterのAPIでも起きているようですね。
PHPのcurlを使ってSSL(https)のサイトへ接続すると、以下のエラーを吐きます。
"SSL certificate problem, verify that the CA cert is OK.
Details: error:14090086:SSL routines:SSL3_GET_SERVER_CERTIFICATE:certificate verify failed"
まあ、そりゃそうですよね。ローカルサーバなので、サイト証明書なぞ、ないですもの。
どうにかならないものかと、さらに調べてみると、curl本家サイトに、mozilla.org から自動的にぶっこぬいてきた、サイト証明書をアップしているページを見つけました。
ここからpemファイルをダウンロードして、ローカルのどこかに置いて接続時に使ってやれば、どうにか動作するようにはなりますよ、ということらしい。
<?php
$ch = curl_init();
curl_setopt($ch, CURLOPT_URL, 'https://api.chatwork.com/v1/me');
curl_setopt($ch, CURLOPT_HTTPHEADER, array('X-ChatWorkToken: 発行されたAPI用ハッシュ値'));
curl_setopt($ch, CURLOPT_RETURNTRANSFER, true); //データを直接出力せずに文字列で返す
//CA証明書
curl_setopt($ch, CURLOPT_SSL_VERIFYPEER, true);
curl_setopt($ch, CURLOPT_CAINFO, '/var/www/inc/cacert.pem'); //ローカルでの絶対パス指定
//Windowsの場合は、こんな感じ(あくまで絶対パス)↓
//curl_setopt($ch, CURLOPT_CAINFO, 'C:\Users\mhibara\Documents\xampp\htdocs\chatwork\cacert.pem');
$response = curl_exec($ch);
if ( $response == false){
var_dump(curl_error($ch));
exit;
}
curl_close($ch);
echo nl2br(print_r(json_decode($response, true), true));
?>
うまく動作しました。
ところが、このサイト証明書ですが、定期的に変更されるのだとか。そりゃそうですよね。
とはいえ、ググって出てくるような解決策としては、毎回CRONで取ってくるといった、たいそうな仕組み。
しかもアップロードされているcacert.pem
も、サイズが大きくて、毎回取ってくるにはちょっと時間がかかります。
僕としては、それほど頻繁にローカルサーバを起動しているわけでもなく、開発しているときだけ使いたい。
そこで、前述のサイト証明書ファイルが更新されていたら、ローカルに引っ張ってきて上書きするという仕組みを、同様にcurlを使ってやってみました。
<?php
$pemfilepath = '/var/www/inc/cacert.pem'; //pemファイルが保存されているローカルファイルパス(絶対パス)
$ch = curl_init('http://curl.haxx.se/ca/cacert.pem');
//出力から本文を削除(要らない)
curl_setopt($ch, CURLOPT_NOBODY, true);
//更新日時を取得しようと試みる
curl_setopt($ch, CURLOPT_FILETIME, true);
$result = curl_exec($ch);
if ($result === false) {
die(curl_error($ch)); //失敗
}
$timestamp = curl_getinfo($ch, CURLINFO_FILETIME);
if ($timestamp != -1) {
//更新日時の取得に失敗
}
elseif ( file_exists($pemfilepath) == true){
$dtPem = filemtime($pemfilepath);
//ローカルファイルと、ダウンロード先のファイルの更新日時を比較する
if ( $timestamp > $dtPem){
//新しい場合なら、CA証明書の更新(丸々上書き)
$pem_contents = file_get_contents('http://curl.haxx.se/ca/cacert.pem');
file_put_contents($pemfilepath, $pem_contents);
}
}
curl_close($ch);
?>
たとえば、前述のコードを別ファイル、getca.php
とでもしておいて、
必要なPHPファイルにインクルードして読み込めば便利かもしれません。
<?php
//毎回インクルードして読み込む
require_once('getca.php');
$ch = curl_init();
curl_setopt($ch, CURLOPT_URL, 'https://api.chatwork.com/v1/me');
curl_setopt($ch, CURLOPT_HTTPHEADER, array('X-ChatWorkToken: 発行されたAPI用ハッシュ値'));
curl_setopt($ch, CURLOPT_RETURNTRANSFER, true); //データを直接出力せずに文字列で返す
//CA証明書
curl_setopt($ch, CURLOPT_SSL_VERIFYPEER, true);
curl_setopt($ch, CURLOPT_CAINFO, '/var/www/inc/cacert.pem'); //ローカルでの絶対パス指定
$response = curl_exec($ch);
if ( $response == false){
var_dump(curl_error($ch));
exit;
}
curl_close($ch);
echo nl2br(print_r(json_decode($response, true), true));
?>
とはいえ、mozilla.org から、ぶっこぬいてきたサイト証明書を、しかも、SSLではなく、ただのhttp(平文)でダウンロードしてきて使うっていうのは、セキュリティ上あまり好ましいものではありません。
ローカルサーバで、ちょこっとテストしてみたい、というときだけにお試しください。