PHPでOAuth

PEARが嫌いというわけでもないけど、短く書けるものは短く書きたいということで。
いろいろ参考にしながら書いてみました。

PHP(5.3.xの機能は使ってません)のクライアントアプリです。
依存ライブラリとかはありません。
でも、エラー処理とかもありません。
ごちゃごちゃした仕様書よりも、
5.2.x以前では動くが5.3.xでは(たまに)動かないコードよりも、
ちゃんと動くコードを読むのが早いよね、っていう方、是非。
(なんでPHPなんだ、というのは、聞かないでください...)

実行するとURLが表示されるので、(ユーザに)このURLにアクセスしてもらいます。
「許可」ボタンを押すと数字が表示されるので、
Enter verifier code:の後に続けて数字を打ち込んでEnterを押します。

そうすると、user_id, screen_name, oauth_token, oauth_token_secretが表示されます。

今回はここまで。
次回はこれを使ってtwitter clientでも作ってみようと思います。

<?php

$api = new oauth_consumer();
$api->consumer_key = "*********************";
$api->consumer_secret = "****************************************";

$request_token = $api->get_request_token();

$confirm_url = "http://twitter.com/oauth/authenticate?oauth_token=".$request_token['oauth_token'];

print "Let's access to $confirm_url\n";
print "\n";

print "Enter verifier code: ";
$stdin = fopen('php://stdin', 'r');
$verifier = trim(fgets($stdin));

$access_token = $api->get_access_token($request_token, $verifier);

print $access_token['user_id']."\n";
print $access_token['screen_name']."\n";
print $access_token['oauth_token']."\n";
print $access_token['oauth_token_secret']."\n";

class oauth_consumer {
        function http_build_query($h) {
                return join('&', array_map(array($this, 'pair'), array_keys($h), array_values($h)));
        }

        function pair($k, $v) {
                return join('=', array_map(array($this, 'encode'), array($k, $v)));
        }

        function encode($str) {
                return preg_replace('/([^a-zA-Z0-9_\.~-])/e', '"%".strtoupper(join("", unpack("H2", \'$1\')))', $str);
        }

        function sign($method, $url, $param, $secret="") {
                $param['oauth_signature_method'] = 'HMAC-SHA1';
                $param['oauth_timestamp'] = time();
                $param['oauth_nonce'] = md5(microtime() . mt_rand());
                $param['oauth_version'] = '1.0';

                ksort($param, SORT_STRING);
                $qstring = $this->http_build_query($param);

                $txt = join('&', array_map(array($this, 'encode'), array($method, $url, $qstring)));
                $key = join('&', array_map(array($this, 'encode'), array($this->consumer_secret, $secret)));

                $param['oauth_signature'] = base64_encode(hash_hmac('sha1', $txt, $key, true));

                return $param;
        }

        function get_request_token() {
                $method = "GET";
                $url = 'http://twitter.com/oauth/request_token';
                $param = array(
                        'oauth_consumer_key' => $this->consumer_key,
                        'oauth_callback' => 'oob',
                );
                $param = $this->sign($method, $url, $param);
                $q = $this->http_build_query($param);

                $result = file_get_contents("$url?$q");
                parse_str($result, $result);

                return $result;
        }

        function get_access_token($request_token, $verifier) {
                $method = "GET";
                $url = 'http://twitter.com/oauth/access_token';
                $param = array(
                        'oauth_consumer_key' => $this->consumer_key,
                        'oauth_token' => $request_token['oauth_token'],
                        'oauth_verifier' => $verifier,
                );
                $param = $this->sign($method, $url, $param, $request_token['oauth_token_secret']);
                $q = $this->http_build_query($param);

                $result = file_get_contents("$url?$q");
                parse_str($result, $result);

                return $result;
        }
}