PHPで2-legged OAuthによるAPIアクセス

OAuthの実装の仕組みを理解するためにPHPでMyOAuthクラスなるものを自分で作った。
mixiの「2-legged OAuthによるAPIアクセス」を参考にしてるよ。
http://developer.mixi.co.jp/appli/spec/mob/2-legged-oauth
※「こうして生成されたパラメータをAuthorizationヘッダに追加して、APIリクエストを送信します。」ってどうやるねん!と思った。
※2-legged OAuthはTwitterで採用してるOAuthなんかと違って「ユーザが認証する」プロセスがないようです。
※追記 : クエリパラメータに ?fields=birthday,gender みたいに , 区切りがあると失敗する。なぜだ。
     ⇒ どうやらパラメータの , はエンコードしてはいけないらしい。というか最初にエンコードしとらしい。なので , だけはわざと二重エンコードするようにした。

my_oauth.class.php

<?php
/**
 * OAuth認証でAPIにリクエストを送信するライブラリ
 *
 * 2010-10-28
 * @author Tanny
 */
require_once 'HTTP/Request.php' ;

class MyOAuth {
    const OAUTH_SIGNATURE_METHOD = 'HMAC-SHA1',
          OAUTH_VERSION          = '1.0';

    private $oauth_consumer_key;        //事前に発行されたconsumer_keyを設定
    private $oauth_consumer_secret_key; //事前に発行されたconsumer_secret_keyを設定
    private $oauth_nonce;               //ランダムな文字列。必ずリクエストごとに違う値を設定してください。
    private $oauth_signature;           //APIリクエストの妥当性を検証するための署名
    private $oauth_signature_method;    //署名方式。’HMAC-SHA1′固定
    private $oauth_version;             //1.0
    private $oauth_timestamp;           //UNIXタイムスタンプ。時刻がずれているとエラーになるので、サーバの時刻設定を確認ください。
    private $xoauth_requestor_id;       //ViewerのIDを設定

    /**
     * コンストラクタ
     *
     * @param $oauth_consumer_key 事前に発行されたconsumer_key
     * @param $oauth_consumer_secret_key 事前に発行されたconsumer_secret_key
     * @param $xoauth_requestor_id ViewerのID
     */
    public function __construct($oauth_consumer_key, $oauth_consumer_secret_key, $xoauth_requestor_id) {
        $this->oauth_consumer_key        = $oauth_consumer_key;
        $this->oauth_consumer_secret_key = $oauth_consumer_secret_key;
        $this->xoauth_requestor_id       = $xoauth_requestor_id;
        $this->oauth_signature_method    = self::OAUTH_SIGNATURE_METHOD;
        $this->oauth_version             = self::OAUTH_VERSION;
    }

    /**
     * get
     * GETでOAuth認証をして、APIにリクエストを送信する
     *
     * @param $api_url APIのURL
     * @param $query_params クエリパラメータの配列
     * @return APIからのレスポンス
     */
    public function get($api_url, $query_params = array()) {
        return $this->request('GET', $api_url, $query_params);
    }

    /**
     * post
     * POSTでOAuth認証をして、APIにリクエストを送信する
     *
     * @param $api_url APIのURL
     * @param $query_params クエリパラメータの配列
     * @return APIからのレスポンス
     */
    public function post($api_url, $query_params = array()) {
        return $this->request('POST', $api_url, $query_params);
    }

    /**
     * request
     * OAuth認証をして、APIにリクエストを送信する
     *
     * @param $method リクエストの送信方法(GET or POST)
     * @param $api_url APIのURL
     * @param $query_params クエリパラメータの配列
     * @return APIからのレスポンス
     */
    private function request($method, $api_url, $query_params) {
        $this->oauth_nonce     = uniqid();  //TODO この乱数生成は微妙かもしれない
        $this->oauth_timestamp = time();

        $query_params = $this->fix_query_params($query_params);
        $this->oauth_signature = $this->create_oauth_signature($method, $api_url, $query_params);

        $request = new HTTP_Request();
        $request->setUrl($api_url . '?' . $this->join_param('&', $query_params));
        $request->addHeader('Authorization', $this->create_authorization_header());
        if ($method === 'POST') {
            $request->setMethod(HTTP_REQUEST_METHOD_POST);
        }
        $response = $request->sendRequest();

        if (PEAR::isError($response)) {
            return false;
        }

        return $request->getResponseBody();
    }

    /**
     * fix_query_params
     * クエリパラメータにVIEWERのIDを付属させる
     *
     * @param $query_params クエリパラメータの配列
     * @return VIEWERのIDを付属させたクエリパラメータの配列
     */
    private function fix_query_params($query_params) {
        $query_params['xoauth_requestor_id'] = $this->xoauth_requestor_id;
        return $query_params;
    }

    /**
     * create_oauth_signature
     * OAuth認証のためのシグニシャを生成する
     *
     * @param $method リクエストの送信方法(GET or POST)
     * @param $api_url APIのURL
     * @param $query_params クエリパラメータの配列
     * @return OAuth認証のためのシグニシャ
     */
    private function create_oauth_signature($method, $api_url, $query_params) {
        if (!$method || !$api_url) {
            return false;
        }

        $oauth_signature_params = array(
                'oauth_consumer_key'     => $this->oauth_consumer_key,
                'oauth_nonce'            => $this->oauth_nonce,
                'oauth_signature_method' => $this->oauth_signature_method,
                'oauth_timestamp'        => $this->oauth_timestamp,
                'oauth_version'          => $this->oauth_version,
                );
        if ($query_params) {
            foreach ($query_params as $key => $val) {
                $oauth_signature_params[$key] = $val;
            }
        }
        ksort($oauth_signature_params);
        $oauth_signature_param = $this->join_param('&', $oauth_signature_params);
        $base_params = array(
                rawurlencode($method),
                rawurlencode($api_url),
                rawurlencode($oauth_signature_param),
                );
        $base_str   = join('&', $base_params);
        $secret_key = $this->oauth_consumer_secret_key . '&';
        return base64_encode(hash_hmac('sha1', $base_str, $secret_key, true));
    }

    /**
     * create_authorization_header
     * Authorizationヘッダーにつける値を生成
     *
     * @return Authorizationヘッダーにつける値
     */
    private function create_authorization_header() {
        $headers = array(
                'oauth_consumer_key'     => $this->oauth_consumer_key,
                'oauth_signature_method' => $this->oauth_signature_method,
                'oauth_signature'        => $this->oauth_signature,
                'oauth_timestamp'        => $this->oauth_timestamp,
                'oauth_nonce'            => $this->oauth_nonce,
                'oauth_version'          => $this->oauth_version,
                );
        ksort($headers);
        $authorization_header = 'OAuth realm=""';
        foreach ($headers as $key => $val) {
            $authorization_header .= ", {$key}=\"{$val}\"";
        }
        return $authorization_header;
    }

    /**
     * 配列のキーと値を「=」で繋ぎ、それらを$glueで指定された文字で連結する
     *
     * @param $glue 連結文字
     * @param $params 連結する連想配列
     * @return @配列のキーと値を「=」で繋ぎ、それらを$glueで指定された文字で連結した配列
     */
    private function join_param($glue, $params) {
        $ary = array();
        foreach ($params as $key => $val) {
            $ary[] = "{$key}={$val}";
        }
        return join($glue, $ary);
    }
}
?>
MyOAuthを使用する側

<?php
    require_once 'my_oauth.class.php';

    $oauth    = new MyOAuth(OAUTH_CONSUMER_KEY, OAUTH_CONSUMER_SECRET_KEY, VIEWER_ID);
    $response = $oauth->get('APIURL', ARRAY_PARAM);
?>