素のphp5.4でOAuthする(tumblr編)
問題
tumblrにアプリを登録して、APIで投稿できるところまでやってみて!

解答例
OAuthの仕様にはいろんなケースを考慮して細かいところまで書かれているが、用途が限定されていれば、パラメータの並び替えならksort()関数でよいとか、最初から並び替えて書いておけばいいじゃないかとか、話が簡単な部分は結構あると思う。
php5.4だとパラメータのエンコードも標準関数でできるようになっている。
以下、手順。
1、アプリの登録
アカウント作成は済んでいるものとして、アプリの登録はこちら。
http://www.tumblr.com/oauth/apps
2、Consumer Key と Consumer Secret を取得する
OAuth Consumer Key と Secret Key は、1の登録後の画面に表示されている。
Secret Key は 「Show secret key」をクリックすると表示される。

3、Request Token と Secret を取得する
所定のパラメータを作ったり、署名の計算などが必要となる。
request_tokenはパラメータを全部GETで送っても大丈夫なこともあるようだが、仕様の例にあるように、Authorizationヘッダを使って、POSTする方を書いておく。
<?php
//OAuthの Consumer Key and Secret
$consumer_key = 'aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa';
$consumer_secret = 'bbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbb';
//Request Token and Secret 取得先URL
$url = 'http://www.tumblr.com/oauth/request_token';
//POST or GET
$method = 'POST';
//パラメータ(oauth_*のパラメータのみ、他のパラメータは無し)
$parameters = array();
$oauth_parameters = array(
'oauth_consumer_key' => $consumer_key,
'oauth_nonce' => microtime(),
'oauth_signature_method' => 'HMAC-SHA1',
'oauth_timestamp' => time(),
'oauth_version' => '1.0',
);
//署名を作る(署名の計算に使うパラメータは上のoauth_*のみなので、上のアルファベット順のままで並び替え不要)
$base_string = implode('&', array(
rawurlencode($method),
rawurlencode($url),
rawurlencode(http_build_query($oauth_parameters, '', '&', PHP_QUERY_RFC3986))
));
$key = implode('&', array(rawurlencode($consumer_secret), rawurlencode($oauth_token_secret)));
$oauth_parameters['oauth_signature'] = base64_encode(hash_hmac('sha1', $base_string, $key, true));
//APIにリクエスト送信
$options = array(
'http'=>array(
'method' => $method,
'header' => array(
'Authorization: OAuth ' . http_build_query($oauth_parameters, '', ',', PHP_QUERY_RFC3986),
),
'content' => http_build_query($parameters)
)
);
$result = file_get_contents($url, false, stream_context_create($options));
//結果を確認してみる(Request Token and Secret が返ってくる)
var_dump($result);
以下のようなレスポンスが返ってくる(Request Token and Secret)。
string(162) "oauth_token=cccccccccccccccccccccccccccccccccccccccccccccccccc&oauth_token_secret=dddddddddddddddddddddddddddddddddddddddddddddddddd&oauth_callback_confirmed=true"
4、ユーザーにアプリの許可をもらう
ログインしているユーザーに、tumblrの承認画面でアプリを許可してもらう。
Authorize URL に、Request Tokenをパラメータに追加したURLに、ブラウザでアクセスする。
3のRequest Tokenなら、以下のURLになる。
http://www.tumblr.com/oauth/authorize?oauth_token=cccccccccccccccccccccccccccccccccccccccccccccccccc
承認画面が表示されるので、許可する(5へ)。
twitterだと、自分で自分のアプリを承認する場合は、開発者用画面でできてしまうのだが、tumblrにはないようだ。がんばろう。
5、許可されたことを取得する(oauth_verifier または PIN)
4でアプリが許可されると、oauth_tokenとoauth_verifierを引数に付けて、callback URLにリダイレクトされてくる。
特に指定しなければ、tumblrのアプリの設定画面で設定したcallback URLにリダイレクトされる。
一般的なWebサービスなら、サーバー側でこのoauth_tokenとoauth_verifierを取得して次の処理(6)をおこなう。自分で自分のアプリの承認をしたいだけの場合は、ブラウザのアドレスバーのURLからコピー&貼り付けして次の処理すればよい。
tumblrで許可されて、リダイレクト後のアドレス欄から
https://www.softel.co.jp/example/?oauth_token=cccccccccccccccccccccccccccccccccccccccccccccccccc&oauth_verifier=eeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeee
6、Access Token と Secretを取得する
oauth_verifierが取得できたらもうすこし。
Access Token and Secretを取得するためのURLに、Request Token and Secret と oauth_verifierを送る。
これもAuthorizationヘッダでやり取りできる。パラメータは全部ヘッダで送れば、他にGETやPOSTのパラメータはない。仕様の例に沿ってPOSTで送ってみる。
<?php
//OAuthの Consumer Key and Secret, Request Token and Secret, oauth_verifier
$consumer_key = 'aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa';
$consumer_secret = 'bbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbb';
$oauth_token='cccccccccccccccccccccccccccccccccccccccccccccccccc';
$oauth_token_secret='dddddddddddddddddddddddddddddddddddddddddddddddddd';
$oauth_verifier = 'eeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeee';
//Access Token and Secret 取得用URL
$url = 'http://www.tumblr.com/oauth/access_token';
//POST or GET
$method = 'POST';
//パラメータ
$parameters = array();
$oauth_parameters = array(
'oauth_consumer_key' => $consumer_key,
'oauth_nonce' => microtime(),
'oauth_signature_method' => 'HMAC-SHA1',
'oauth_timestamp' => time(),
'oauth_token' => $oauth_token,
'oauth_verifier' => $oauth_verifier,
'oauth_version' => '1.0',
);
//署名を作る(パラメータは上のoauth_*のみなので、上に書いたアルファベット順のままで並び替え不要)
$base_string = implode('&', array(
rawurlencode($method),
rawurlencode($url),
rawurlencode(http_build_query($oauth_parameters, '', '&', PHP_QUERY_RFC3986))
));
$key = implode('&', array(rawurlencode($consumer_secret), rawurlencode($oauth_token_secret)));
$oauth_parameters['oauth_signature'] = base64_encode(hash_hmac('sha1', $base_string, $key, true));
//APIにリクエスト送信
$options = array(
'http'=>array(
'method' => $method,
'header' => array(
'Authorization: OAuth ' . http_build_query($oauth_parameters, '', ',', PHP_QUERY_RFC3986),
),
'content' => http_build_query($parameters)
)
);
$result = file_get_contents($url, false, stream_context_create($options));
//結果を確認してみる(Access Token and Secret が返ってくる)
var_dump($result);
結果例
string(132) "oauth_token=ffffffffffffffffffffffffffffffffffffffffffffffffff&oauth_token_secret=gggggggggggggggggggggggggggggggggggggggggggggggggg"
7、投稿する
Access Token and Secretが取得できたら、ようやくAPIが使える。試しに投稿してみる。
//OAuthのいつもの
$base_hostname = 'softel.tumblr.com';
$consumer_key = 'aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa';
$consumer_secret = 'bbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbb';
$oauth_token = 'ffffffffffffffffffffffffffffffffffffffffffffffffff';
$oauth_token_secret = 'gggggggggggggggggggggggggggggggggggggggggggggggggg';
//どの tumblr API
$url = 'http://api.tumblr.com/v2/blog/' . $base_hostname . '/post';
//POST or GET
$method = 'POST';
//パラメータ
$parameters = array(
'type' => 'link',
'title' => 'タイトルタイトルタイトル',
'url' => 'https://tech.softel.co.jp/blog/',
'description' => '概要概要概要概要概要概要',
);
$oauth_parameters = array(
'oauth_consumer_key' => $consumer_key,
'oauth_nonce' => microtime(),
'oauth_signature_method' => 'HMAC-SHA1',
'oauth_timestamp' => time(),
'oauth_token' => $oauth_token,
'oauth_version' => '1.0',
);
//署名を作る
//署名の計算にはoauth_*とAPIのパラメータを含めて全部使う
//キーと値でソートする仕様なのだが、キーが重複したり英数字以外が混じったりしないのでksort関数で十分
$a = array_merge($oauth_parameters, $parameters);
ksort($a);
$base_string = implode('&', array(
rawurlencode($method),
rawurlencode($url),
rawurlencode(http_build_query($a, '', '&', PHP_QUERY_RFC3986))
));
$key = implode('&', array(rawurlencode($consumer_secret), rawurlencode($oauth_token_secret)));
$oauth_parameters['oauth_signature'] = base64_encode(hash_hmac('sha1', $base_string, $key, true));
//APIにリクエスト送信
$options = array(
'http'=>array(
'method' => $method,
'header' => array(
'Authorization: OAuth ' . http_build_query($oauth_parameters, '', ',', PHP_QUERY_RFC3986),
),
'content' => http_build_query($parameters)
)
);
$result = file_get_contents($url, false, stream_context_create($options));
//結果を確認してみる
var_dump($result);
結果例
"{"meta":{"status":201,"msg":"Created"},"response":{"id":12345678901}}"

以上、アクセストークン取得と、APIでの投稿テストまで。

はじめまして。
Google App Engine for Javaでtumblrに投稿する方法を探していて、
こちらのページに辿り着きました。
tumblr公式のライブラリを使用してもうまくいかず、
APIの情報もほとんど見当たらずに困り果てていたのですが、
こちらのページを参考にJavaの処理を記述することで、
ようやく投稿することができました。
とても貴重な情報をありがとうございました。
お役に立てて何よりです♪コメントありがとうございます。
3、Request Token と Secret を取得する
の26行目は$oauth_token_secretじゃなくて$consumer_secretかな・・・?