ソースコードで学ぶWebプログラミング

[PHP]API接続の基本を確認する[外部サーバ通信]

Web APIとはWebサイトの機能を外部から利用できるようにしたものです。提供された機能で外部の開発者が自発的に新しいサービスを展開するなどの相乗効果が期待されます。このページではPHPでAPI接続をする際の基本となる概念、コーディングのポイントを説明しています。

PHPでGET送信する方法

GET送信とは、ブラウザでURLへアクセスしている状態と同じものになります。PHPでは、file_get_content()で簡単にURLへアクセスし、レスポンスを取得できます。レスポンスのヘッダー情報は、$http_response_headerに代入されています。

<?php /* リクエスト先エンドポイント(URL) */ define('URL','http://example.com/'); /* URLアクセスで取得 */ $res = file_get_contents(URL); /* レスポンスのヘッダー情報が配列で入っている変数 */ $http_response_header

GETリクエストのパラメータは、URLへ繋げることで渡せます。URLとして使えない文字はエスケープする必要があるので、注意が必要です。http_build_query()を使えば簡単にリクエストを構築できます。

/* パラメータを渡す */ $prm = 'name1=value1&name2=value2'; $res = file_get_contents(URL.'?'.$prm); /* keyやvalueをURLエンコードする場合 */ $prm = urlencode($key).'='.urlencode($val); /* 連想配列をリクエストのパラメータに */ $data = array( 'name'=>'value', ); $res = file_get_contents(URL.'?'.http_build_query($data));

ヘッダー情報やリクエストの設定を行ってからGET送信することも出来ます。ヘッダーには、ユーザーエージェントやクッキーなどが設定できます。file_get_contents()では、400番台、500番台の接続エラーとなる場合、Warningエラーとなるため、'ignore_errors'=>trueを設定する必要があります。

/* ヘッダーやコンテキストを設定する */ $data = array( 'name'=>'value', ); $data = http_build_query($data); /* リクエストのヘッダー配列 */ $headers = array( 'User-Agent: Mozilla/5.0 (compatible; MSIE 10.0; Windows NT 6.2; Trident/6.0)' ); /* リクエストのコンテキスト */ $context = array( 'http'=>array( 'method'=>'GET', 'header'=>implode("\r\n",$headers), /* Warningエラー回避 */ 'ignore_errors'=>true ) ); $res = file_get_contents(URL.'?'.$data, false, stream_context_create($context));

PHPでは、cURL関数でも外部サイトへアクセスすることが可能です。file_get_contents()よりもcURLのほうが速く、細かい設定もできるため、頻繁にアクセスする場合は、こちらを使用します。

<?php /* リクエスト先エンドポイント(URL) */ define('URL','http://example.com/'); /* cURLでアクセス */ $ch = curl_init(); /* アクセス先URLを設定 */ curl_setopt($ch, CURLOPT_URL, URL); /* レスポンスを出力せずに受け取る */ curl_setopt($ch, CURLOPT_RETURNTRANSFER, true); /* レスポンスの受け取り */ $res = curl_exec($ch); curl_close($ch);

cURLでよく使われるオプション設定です。サーバにSSL証明書がない場合は、CURLOPT_SSL_VERIFYPEERにfalseを設定することでSSL通信が可能です。

/* レスポンスのヘッダーも取得する */ curl_setopt($ch, CURLOPT_HEADER, true); /* 転送先を取得する */ curl_setopt($ch, CURLOPT_FOLLOWLOCATION, true); /* サーバー証明書の検証をしない */ curl_setopt($ch, CURLOPT_SSL_VERIFYPEER, false); /* リクエストヘッダを設定 */ curl_setopt($ch, CURLOPT_HTTPHEADER, $headers); /* HEADリクエストで送信する */ curl_setopt($ch, CURLOPT_NOBODY, true); /* POSTリクエストで送信する */ curl_setopt($ch, CURLOPT_POST, true); /* POSTするデータを設定 */ curl_setopt($ch, CURLOPT_POSTFIELDS, $data); /* COOKIEをファイル保存する */ curl_setopt($ch, CURLOPT_COOKIEJAR, $file); /* COOKIEのファイルからデータを送信する */ curl_setopt($ch, CURLOPT_COOKIEFILE, $file); /* COOKIEとしてデータを渡す */ curl_setopt($ch, CURLOPT_COOKIE, $data); /* 通信時の詳細情報を取得する */ curl_setopt($ch, CURLOPT_VERBOSE, true); /* 詳細情報をファイル保存する */ curl_setopt($ch, CURLOPT_STDERR, $file);

PHPでPOST送信する方法

file_get_contents()では、POST送信する事も出来ます。注意点としてヘッダーのContent-Typeをapplication/x-www-form-urlencodedにします。multipart/form-dataによるファイル送信も可能ですが、送信データの生成部分をコーディングする必要があります。

<?php /* リクエスト先エンドポイント(URL) */ define('URL','http://example.com/'); /* 送信するデータ */ $data = array( 'name'=>'value', ); $data = http_build_query($data); /* リクエストのヘッダー配列 */ $headers = array( 'Content-Type: application/x-www-form-urlencoded', 'Content-Length: '.strlen($data) ); /* リクエストのコンテキスト */ $context = array( 'http'=>array( 'method'=>'POST', 'header'=>implode("\r\n",$headers), 'content'=>$data, 'ignore_errors'=>true ) ); $res = file_get_contents(URL, false, stream_context_create($context));

cURL関数でPOST送信を行なうには、CURLOPT_POSTをtrueに設定します。application/x-www-form-urlencodedの状態でPOSTリクエストが行われる事になります。multipart/form-dataで送信するには、CURLOPT_POSTFIELDSに連想配列を渡すだけです。

<?php /* リクエスト先エンドポイント(URL) */ define('URL','http://example.com/'); /* 送信するデータ */ $data = array( 'name'=>'value', ); $ch = curl_init(); curl_setopt($ch, CURLOPT_URL, URL); curl_setopt($ch, CURLOPT_RETURNTRANSFER, true); /* POSTリクエストで送信する */ curl_setopt($ch, CURLOPT_POST, true); /* POSTするデータを設定 */ curl_setopt($ch, CURLOPT_POSTFIELDS, http_build_query($data)); /* レスポンスの受け取り */ $res = curl_exec($ch); curl_close($ch);

PHPでCOOKIE送信する方法

Webサイトのログインが必要な画面などでは、クッキーと呼ばれるブラウザの管理データを送受信する必要があります。一般的に必要となるクッキーデータは、ログイン時のレスポンスヘッダーにあります。file_get_contents()では$http_response_headerから取得、受け渡しが可能です。

<?php /* ログイン先URL */ define('URL','http://example.com/login'); /* 送信するデータ */ $data = array( 'id'=>'value', 'pass'=>'value' ); $data = http_build_query($data); $headers = array( 'User-Agent: Mozilla/5.0 (compatible; MSIE 10.0; Windows NT 6.2; Trident/6.0)' ); $context = array( 'http'=>array( 'method'=>'POST', 'header'=>implode("\r\n",$headers), 'content'=>$data, 'ignore_errors'=>true ) ); $res = file_get_contents(URL, false, stream_context_create($context)); /* クッキーを代入する変数 */ $cookie = array(); /* レスポンスヘッダーからクッキーを取り出す */ foreach($http_response_header as $r){ list($key,$val) = explode(' ',$r); if ($key=='Set-Cookie:') { $cookie[] = $val; } } /* ログイン状態でページ遷移 */ $data = array( 'name'=>'value', ); $headers = array( 'User-Agent: Mozilla/5.0 (compatible; MSIE 10.0; Windows NT 6.2; Trident/6.0)', /* クッキーを設定 */ 'Cookie: '.implode('; ',$cookie) ); $context = array( 'http'=>array( 'method'=>'GET', 'header'=>implode("\r\n",$headers), 'ignore_errors'=>true ) ); $res = file_get_contents(URL.'?'.http_build_query($data), false, stream_context_create($context));

cURLでもクッキー情報の送受信は可能です。ログイン時など必要な場面でクッキーをファイル保存し、後は読み込んで送信を行います。この時、クッキーファイルにはログイン領域へのアクセス可能な情報が含まれているため、取り扱いには注意が必要です。

下記では一時ファイルとしてクッキーを保存しています。使い回す場合はファイルを保持するか、レスポンスヘッダーからクッキーデータを取得し、セッションデータとして保持します。

<?php /* ログイン先URL */ define('URL','http://example.com/login'); /* 送信するデータ */ $data = array( 'id'=>'value', 'pass'=>'value' ); /* クッキーを保存するファイル */ $ck_file = tempnam(sys_get_temp_dir(),'CK'); $ch = curl_init(); curl_setopt($ch, CURLOPT_URL, URL); curl_setopt($ch, CURLOPT_RETURNTRANSFER, true); curl_setopt($ch, CURLOPT_POST, true); curl_setopt($ch, CURLOPT_POSTFIELDS, http_build_query($data)); /* COOKIEをファイル保存する */ curl_setopt($ch, CURLOPT_COOKIEJAR, $ck_file); $res = curl_exec($ch); curl_close($ch); /* ログイン状態でページ遷移 */ $data = array( 'name'=>'value', ); $ch = curl_init(); curl_setopt($ch, CURLOPT_URL, URL.'?'.http_build_query($data)); curl_setopt($ch, CURLOPT_RETURNTRANSFER, true); /* COOKIEのファイルからデータを送信する */ curl_setopt($ch, CURLOPT_COOKIEFILE, $ck_file); $res = curl_exec($ch); curl_close($ch);

PHPでBASIC認証する方法

BASIC認証とは、Webサーバで行われるアクセス制限で、一般的に.htaccessと.htpasswdで設定を行います。制限下のディレクトリへアクセスするには、ヘッダーに認証情報を持たせる必要があります。

<?php /* ログイン先URL */ define('URL','http://example.com/login'); /* BASIC認証 ID */ define('BASIC_ID','***'); /* BASIC認証 パスワード */ define('BASIC_PW','***'); $headers = array( 'Authorization: Basic '.base64_encode(BASIC_ID.':'.BASIC_PW) ); $context = array( 'http'=>array( 'method'=>'GET', 'header'=>implode("\r\n",$headers), 'ignore_errors'=>true ) ); $res = file_get_contents(URL, false, stream_context_create($context));

cURL関数でもBASIC認証は可能です。CURLOPT_USERPWDにIDとパスワードを:繋ぎで設定するだけです。

<?php /* ログイン先URL */ define('URL','http://example.com/login'); /* BASIC認証 ID */ define('BASIC_ID','***'); /* BASIC認証 パスワード */ define('BASIC_PW','***'); $ch = curl_init(); curl_setopt($ch, CURLOPT_URL, URL); curl_setopt($ch, CURLOPT_RETURNTRANSFER, true); /* HTTP認証方法 */ curl_setopt($ch, CURLOPT_HTTPAUTH, CURLAUTH_BASIC); /* IDとパスワード */ curl_setopt($ch, CURLOPT_USERPWD, BASIC_ID.':'.BASIC_PW); $res = curl_exec($ch); curl_close($ch);

PHPでOAuth認証する方法

OAuth(オー オース)認証とは、あるWebサイト内にある自己データを対象として、別のアプリケーションにアクセス権限を与えることです。例えば、Twitter内の自分のツイートをidやパスワードを伝えることなく、別のアプリから取得したい場合などに利用されています。

OAuthにはOAuth1.0とOAuth2.0の2つのバージョンがあります。Twitter APIはOAuth1.0がベースになっていて、Facebook APIやYahoo API、Google APIなどはOAuth2.0がベースになっています。

OAuth1.0の処理の流れは1.リクエストトークンを取得→2.認証画面へ遷移→3.アクセストークンを取得となります。OAuth1.0では、リクエスト毎に署名が必要となり、登録を行ったアプリケーションのConsumer Key(APIキー)やConsumer Secret、認証後に取得したSecretなどで作成する事になります。

OAuth2.0の処理の流れは1.認可コードを取得→2.認証画面へ遷移→3.アクセストークンとリフレッシュトークンを取得→4.リフレッシュトークンでアクセストークンを更新となります。OAuth2.0では基本的にトークンに有効期限があるため、更新・再発行処理が必要になります。

以降はOAuth1.0での認証方法を説明します。

/* OAuth Signature を作成 */ function setSignature($method,$req,$url){ $this->method = $method; /* リクエストのキーで並び替え */ ksort($req); /* 暗号化用のトークン */ $token_secret = isset($_SESSION['token_secret']) && $url!=REQ_URL ? $_SESSION['token_secret']: ''; /* 暗号化対象 */ $sig_base = $method.'&'.urlencode($url).'&'.urlencode(http_build_query($req)); /* 暗号化キー */ $sig_key = urlencode(CONSUMER_SECRET).'&'.urlencode($token_secret); /* 署名の作成 */ $req['oauth_signature'] = base64_encode(hash_hmac('sha1',$sig_base,$sig_key,true)); $this->req = $req; }

OAuth1.0では、リクエスト毎に署名(Signature)が必要になります。署名はリクエストのメソッド、リクエストのエンドポイント(URL)、リクエスト(送信データの連想配列)を繋げた文字列を対象として、Consumer SecretとトークンSecretで暗号化したものになります。

作成した署名はリクエスト内に含めます。またリクエストは、ヘッダーAuthorization: OAuth からカンマ区切りで渡すことになります。

/* リクエストの送信 */ function request($url){ $headers = array( 'Authorization: OAuth '.http_build_query($this->req,'',',') ); $context = array( 'http'=>array( 'method'=>$this->method, 'header'=>implode("\r\n",$headers), 'ignore_errors'=>true ) ); $res = file_get_contents($url, false, stream_context_create($context)); if (strpos($res,'errors')===false) { parse_str($res,$res); } return $res; }

今回はTwitterAPIで説明します。OAuth1.0認証で必要となる項目はConsumer Key(APIキー)、Consumer Secret、認証後に戻るURLの3つになります。また認証までにAPIのURLとしてリクエストトークン用URL、認証画面のURL、アクセストークン用URLの3つが必要になります。

/* アプリに発行されたキー */ define('CONSUMER_KEY','***'); /* アプリに発行されたSECRET */ define('CONSUMER_SECRET','***'); /* 戻りURL */ define('CALLBACK_URL','***'); /* リクエストtoken URL */ define('REQUEST_URL','https://api.twitter.com/oauth/request_token'); /* 認証URL */ define('AUTH_URL','https://api.twitter.com/oauth/authorize'); /* アクセスtoken URL */ define('ACCESS_URL','https://api.twitter.com/oauth/access_token');

OAuth1.0認証の処理は、まずリクエストトークンとリクエストトークンSECRETを取得し、後で使うためセッションとして保持します。続いて、取得したリクエストトークンで認証画面にユーザーを遷移させます。

/* 認証画面へ遷移 */ function goAuth(){ $r = $this->request(REQUEST_URL); if (isset($r['oauth_token'])) { /* セッションとして保持 */ $_SESSION['token_secret'] = $r['oauth_token_secret']; /* リクエストトークン付きで認証画面へ */ header('Location: '.AUTH_URL.'?oauth_token='.$r['oauth_token']); } else { echo $r; } exit; }

ユーザーが認証画面から戻ってきたら、レスポンスデータを利用して再度リクエストを作成し、アクセストークンを取得します。このアクセストークンを元に、APIを利用することになるため、DBなどに保存することになります。

/* アクセストークンを取得 */ function getToken(){ $r = $this->request(ACCESS_URL); $_SESSION['token_secret'] = $r['oauth_token_secret']; return $r; }