SYNCER

SYNCER

Twitter REST APIの使い方

9件

公開日: 2017/01/22 / 更新日:

今や「インフラ」と表現しても過言ではないほど、多くの日本人が当たり前のように利用しているミニブログサービス、Twitter。この記事では、Twitterが提供するAPIの使い方を、初心者向けに説明しています。ぜひ、素敵なウェブサービスを作って下さいね。

Twitter Developers
Twitter Developers
Twitter APIなどを利用する開発者のためのページ。公式リファレンスの確認や、アプリケーションの作成など。

アプリケーションの登録

APIを利用するために必要な「アプリケーションの登録方法」を紹介します。APIキーとAPIシークレットを取得できます。

アプリケーションとは?

よくAPIを利用するのに「アプリケーションを登録して」という言葉が出てきます。このアプリケーションって何でしょう。これは、SNSでいう「ユーザーアカウント」と同じようなものだと考えると、イメージを掴みやすいと思います。

アプリケーションの例(診断メーカー)
アプリケーションの例(診断メーカー)

アプリケーションは「API Key」「API Secret」という、言わばIDとPASSの組み合わせで成り立っています。Twitter側は「どのアプリケーションが、どれだけAPIを利用しているか?」「どのユーザーがどのアプリケーションにアカウントを接続しているか?」などを把握する必要があり、個々のアプリケーションを「API Key」によって識別するわけです。

あなたがTwitterを始めるのにユーザーアカウントを作成したのと同じで、APIの利用は、この「アプリケーションの登録(API Keyの新規作成)」から始まります。

ユーザーアカウントの用意

Twitter APIを利用するには、ユーザーアカウントが必要です。普段、ツイートをしている人はそのアカウントをそのまま利用して下さい。もし、ユーザーアカウントをまだお持ちじゃない場合は、下記記事を参考に作成して下さい。なお、2015年1月頃より、「メールアドレス認証」と「電話番号認証」を完了していないユーザーは、アプリケーションの作成、編集ができなくなりました。新規登録後、これらの情報も併せて、登録しておいて下さいね。電話番号はアプリケーションの作成、編集をする時以外は削除しておいてかまいません。

デベロッパー・センター

これからアプリケーションを登録する手順を紹介していきます。初心者の人は、深く考えずに、まずはこの記事の内容通りに操作して下さい。真似しながら動かしていくことで、内容をだんだんと理解していくことができるはずです。

Developers Twitter
Twitter Developers

まずは、この記事冒頭で紹介した「Twitter Developers」にアクセスしてみて下さい。ここはTwitterの機能を使ってwebサービスを作る、開発者たちの拠点となるページです。永く利用していくことになるので、ここをブックマークしておきましょう。まだログインしていない場合は、普段のTwitter上でログインしておいて下さいね。

Apps」をクリックする Your 「Manage
「Manage Your Apps」をクリックする

デベロッパー・センターのページ下、フッター部分にあるメニューの中から「Manage Your Apps」というリンクを探して下さい。アプリケーションを作成するには、ここから「アプリケーションの管理画面」に移動できます。

アプリケーションの管理画面
アプリケーションの管理画面

「Twitter Apps」という画面に移動しました。ここは、あなたが作成したアプリケーションを管理する画面です。ここも頻繁にアクセスする場所なので、ブックマークしておくことをお勧めします。この記事を読んでいる人はまだアプリケーションを1つも作成していないと思うので、図のように何も表示されていないはずです。新しくアプリケーションを登録するには、「Create New App」というボタンをクリックして下さい。

Twitter Apps
Twitter Apps
Twitter Developers内の、アプリケーションを作成、管理するためのページ。

アプリケーションの登録

ここから本格的な登録作業に進みます。本格的といっても、やることは簡単です。

アプリケーションの情報を入力する
アプリケーションの情報を入力する

アプリケーション情報の登録画面に移動します。用意されたフォームに、アプリケーションの名前や概要などを入力して下さい。日本語の利用が可能です。案内はありませんが、アプリケーションは1日に何個も新規作成することができません。が、1つくらいなら削除して作り直しても大丈夫です。なので最初は練習用として適当なものを作ってみましょう。入力後、一番下にある「Create your Twitter application」をクリックして下さい。電話番号を登録していないとエラーが起こります。

アプリケーション情報の入力例
アプリケーション情報の入力例

ここで躓くポイントは「Callback URL(コールバックURL)」だと思います。これって何のことか分からないですよね?これは後ほど、アクセストークンを取得する作業で使います。いつでも編集することができるので、ここではとりあえず上の図のように空白にしておいて、後で理解した時に設定して下さい。「Callback URLという設定項目がある」ということだけは覚えておいて下さいね。

項目説明
Nameアプリケーションの名称。webサービスを作るんだったら、その名前など。全ユーザーの全アプリケーションの中で重複しない必要があります。
Descriptionアプリケーションの概要。
Websiteアプリケーションを動かすウェブサイトのトップページのURLアドレス。
Callback URLコールバックURL。ユーザーが認証(アプリ連携)作業をした後の、戻り先となるURLアドレス。裏方で情報を収集するだけなど、不特定多数のユーザーの認証が必要ないアプリケーションの場合は関係ありません。
Developer Rules of the RoadAPIの利用規約。「Yes,I agree(同意)」にチェックして下さい。

アプリケーションの確認

アプリケーションの情報を入力する
アプリケーションの情報を入力する

入力に問題がなければ、アプリケーションが作成され、自動的にそのアプリケーションを管理する画面へ遷移します。

管理画面に追加されている
管理画面に追加されている

アプリケーションの管理画面に戻って下さい。作成したアプリケーションが加わっているはずです。ここの名前の部分をクリックすると、このアプリケーションを管理する画面に移動することができます。設定を編集するのに再度、訪れる時はここからどうぞ。

APIキーの確認

作成したアプリケーション
作成したアプリケーション

作成したアプリケーションの管理画面へと戻りましょう。さて…、色々と情報が掲載されていますが、日が暮れるので全てを見る必要はありません。この記事で指定するところだけを見れば大丈夫です。繰り返しますが、とりあえず動かすことを通して、だんだんと各項目の意味が分かるようになってきます。分からなくなったらいつでも、このページに戻ってきて下さい(:

アプリケーションの管理メニュー
アプリケーションの管理メニュー

それではアプリケーションを作成した主目的である「APIキー(API KeyとAPI Secretの総称)」を確認しましょう。アプリケーション名のすぐ下にタブ式のメニューがあります。この中の「Keys and Access Tokens」をクリックして下さい。

APIキーを確認する
APIキーを確認する

「Keys and Access Tokens」の画面に移動しました。ここにはAPIキーや、後ほど説明するアクセストークンの情報があります。まずは赤枠内のConsumer Key (API Key)とConsumer Secret (API Secret)を、メモして下さい。これらは、冒頭でも説明した通り、ユーザーアカウントにおけるIDとPASSのようなものです。API Keyは他ユーザーが知り得る(隠す必要のない)情報ですが、API Secretは絶対に知られてはいけません。

パーミッションの設定

続いて、開発者としてのあなたは「パーミッション(権限)」という概念を覚える必要があります。これは簡単に言うと「あなたのアプリケーションができること」です。例えば、アプリケーションに「書込権限」のパーミッションを付与していないのに、APIを通してツイートをしようとすると、エラーが発生してしまいます。

Application Permission Model
Application Permission Model
Twitter Developers内のページ。各パーミッションについてのドキュメントです。
「Permissions」をクリックする
「Permissions」をクリックする

パーミッションを設定するには、上部メニューの中から「Permissions」をクリックして下さい。

パーミッション(権限)を選択する
パーミッション(権限)を選択する

パーミッションの設定画面に移動します。3つの権限の中から、1つを選択し、「Update Settings」をクリックして下さい。APIをテスト用として利用するなら、一番強力な「Read,Write and Access direct messages」を選択しておきましょう。いつでも設定を変更することができます。

項目説明
Read Onlyタイムラインやプロフィールなどのデータを取得することができる読み取り権限。
Read and Write読み取り権限に加えて、ツイートの投稿、リツイート、お気に入り、ミュート、ブロック、プロフィールの変更など、ダイレクトメッセージに関すること以外の操作ができる書き込み権限。
Read,Write and Access direct messages読み取り権限、書き込み権限に加えて、ダイレクトメッセージの内容を取得したり、ダイレクトメッセージを送ることが可能。一番強力な権限。

登録情報の変更

「Settings」をクリックする
「Settings」をクリックする

アプリケーション名や、Callback URLの設定を変更したい時は、上部メニューの「Settings」をクリックして下さい。

アプリケーションの設定を変更する
アプリケーションの設定を変更する

アプリケーションの登録時にはなかった、アイコンの設定なども、この画面で行なうことができます。

APIキーの変更

Consumer Key Secret」をクリックする and 「Regenerate
「Regenerate Consumer Key and Secret」をクリックする

もしAPIキーの情報を公表するなどして、他人に知られてしまった、または知られた可能性があって心配な場合は、上部メニューから「Keys and Access Tokens」のページにアクセスして下さい。下部にある「Regenerate Consumer Key and Secret」をクリックすれば、いつでも変更することができます。

アプリケーションの削除

「Details」をクリックする
「Details」をクリックする

「アプリケーションをもう使わなくなったので削除したい」という場合は、上部メニューの「Details」をクリックして下さい。

Application」をクリックする 「Delete
「Delete Application」をクリックする

ページ下にある「Delete Application」をクリックすると、そのアプリケーションを削除することができます。

この章のまとめ

無事にアプリケーションを作成することができましたか?アプリケーションの作成が完了したら、通常は続いて「アクセストークン」、または「ベアラートークン」を取得するためのプログラムの作成に取りかかります。主に必要な情報は下記の通りとなっているので、確認しておきましょう。

API Key
アプリケーションのIDにあたる。
API Secret
アプリケーションのパスワードにあたる。
Callback URL
ユーザーが認証画面から戻るURLアドレス。アクセストークンを取得する際に利用します。

アクセストークンの取得

Twitter APIで、あるユーザーの情報を読み取ったり、そのユーザーとして書き込みをする、すなわち、アカウントのデータにアクセスするにはそのユーザーのアクセストークンが必要です。この章ではAPIを利用するのに必要な「アクセストークン」を取得する方法を紹介します。

アクセストークンとは?

Twitterのアクセストークンは、ユーザーアカウントにおけるIDとPASSのように、「Access Token Key」「Access Token Secret」という2種類の文字列を指します。これは、アプリケーションが、ユーザーの代わりに、ユーザーデータにアクセスするための「通行許可証」のようなものです。言わば、第三者(webサービスなど)用に用意されたユーザーID、ユーザーPASSと言ってもいいでしょう。例えば、「Twilog」などのwebサービス(アプリケーション)は、アクセストークンを利用して、あなたの"代わり"に、Twitterからあなたのデータを取得してくれます。

もし、アクセストークンが存在しなかったら、リスクだらけになってしまうと思いませんか?考えてもみて下さい。webサービスを利用するためには、自分のユーザーIDとPASSを預けなければいけなくなります。webサービス側がその気になれば、あなたのIDとPASSで勝手にログインし、アカウントを削除することだって可能な状況を作ってしまいます。

こういったリスクを防ぐために、第三者が、限られた範囲で、あなたのデータにアクセスするための「アクセストークン」が存在しているというわけです。これならば、webサービス側が例え悪意を持ったとしても、APIを通してできる範囲(せいぜい、つぶやいたりフォローする程度)のことしかできません。そういった安全などが確保されるというわけです。

アクセストークンを取得するには?

アプリケーションの認証画面
アプリケーションの認証画面

アクセストークンを取得するには、当然ながら、対象となるユーザー自身が認証作業をする必要があります。図のような認証画面を、誰もが見たことがあると思います。この画面でユーザーが「連携アプリを認証」をクリックすることで、アプリケーション側がそのユーザーのアクセストークンを取得できるという仕組みです。この、一連の認証作業をユーザーに行なわせるには、サービス提供側(今回はTwitter)の指定通りに、プログラミングをする必要があります。Twitterの場合、OAuth1.0という認証方式になります。そのプログラミングをどうすればいいか、がこの章のメインです。

認証作業を体験してみる

Twitterの認証作業
Twitterの認証作業

「認証作業が何のことだか、よく分からない…」という人のために、アクセストークンを取得するサンプルデモを用意してみました。一連の作業をぜひ、行なってみて下さい。このアプリケーションは、あなたの操作なしに、勝手に、アカウントのデータにアクセスすることはありません。

プログラミングなしで取得する

アクセストークンを取得するには、基本的に対象となるユーザーによる認証作業と、その認証作業をさせるためのプログラミングが必要です。しかし、アプリケーションの開発者自身のアクセストークンなら、アプリケーションの管理画面から、ワンタッチで発行することが可能です。何故、認証作業がいらないのかというと、自分のアクセストークンを自分が悪用する心配がないからです。

要するに、Twitter側の、「面倒なことしなくてもいいよ」という気遣いですね。この方法では、他ユーザーのデータにアクセスできない点にご注意下さい。Twitter Botなど、他ユーザーのアクセストークンが必要ないコンテンツを作る場合は、この方法で十分ですね。下記方法で取得して下さい。

アプリケーションの認証画面
アプリケーションの認証画面

アプリケーションの管理画面の「Keys and Access Tokens」に移動して下さい。ページ下にある「Create my access token」をクリックします。

アクセストークンが発行される
アクセストークンが発行される

すると、同画面に「Your Access Token」という項目が追加されます。この中にある「Access Token」と「Access Token Secret」の2種類がアクセストークンとなります。自分のアカウントをAPIで操作するだけなら、アクセストークンの取得はとっても簡単だということです。

準備編

ここからは、OAuth1.0に準じたプログラミングを通して認証システムを作成し、対象ユーザーのアクセストークンを取得する方法を紹介していきます。繰り返しになりますが、前項のお手軽な方法で済むなら、プログラミングをする必要はありません。

必要なもの

まず、取得に必要な要素を整理しておきましょう。揃っているか、確認してみて下さい。また、Callback URLは、この記事で作るサンプルプログラムを設置するURLアドレスと一致するよう、設定して下さいね。

API Key
アプリケーション作成時に発行されたAPI Key。
API Secret
アプリケーション作成時に発行されたAPI Secret。
Callback URL
アプリケーション作成時に設定した、認証画面からユーザーが戻って来るURLアドレス。この記事のサンプルプログラムを設置するURLアドレスでもある。

プログラミングの流れ

続いて、アクセストークンを取得するまでの流れを紹介します。この通りに、プログラムを作成していくので、なんとなく意識してみて下さい。初めての人にとっては長い戦いになると思いますが、コーヒーでも飲みながらゆっくりと進めていきましょう。

  1. リクエストトークンを取得する。
  2. リクエストトークンをパラメータに付けて、ユーザーを認証画面に飛ばす。
  3. ユーザーが、認証画面でアプリ連携を許可する。
  4. 許可証となるコードをパラメータに付けて、ユーザーがCallback URLで設定したURLアドレスに飛ばされてくる。
  5. 許可証となるコードを利用して、アクセストークンを取得する。

プログラムを始める前に、時間がちょっとかかります。OAuth1.0認証では、リクエストをするごとに「署名」を作成する必要があります。その署名はどのように作るのか、下記ページで仕組みを解説しているので、一度目を通しておいて下さい。Twitter APIの利用は、道のりが長いのです…。

OAuth1.0の署名(Signature)を作成する方法
OAuth1.0の署名(Signature)を作成する方法
OAuth1.0のSignature(署名)を、ライブラリを使わずに1から作成する方法を初心者向けに解説。サンプル言語はPHP。

[手順1] リクエストトークンの取得

はじめにユーザーを、Twitterのサーバー上にある認証画面へ移動させるのですが、移動の際には、指定されたパラメータが付いている必要があります。そのパラメータの一部となる数十桁のコードがリクエストトークンです。リクエストトークンとは、言わば、認証画面の入場チケット代わりのコードと言えます。リクエストトークンの取得方法に関する公式ドキュメント(英語)は下記ページをご参考下さい。

POST oauth/request_token
POST oauth/request_token
Twitter Developersのページ。リクエストトークンの取得方法の案内。

リクエスト方法

公式ドキュメントを読み、リクエスト方法をまとめてみました。まず、下記のエンドポイントに、POSTメソッドでリクエストを送ります。

https://api.twitter.com/oauth/request_token

リクエスト時に必要なパラメータが下記の通りです。種類は多いですが、そのほとんどは決まった指定方法なので、そこまで難しいことはありません。

oauth_callback
「Callback URL」に設定したURLアドレスを指定する。認証画面で作業を終えたユーザーが戻ってくるURLアドレス。
oauth_consumer_key
アプリケーション作成時に取得したAPI Key。
oauth_signature_method
署名の種類を指定。HMAC-SHA1を指定すればいい。
oauth_signature
作成した署名を指定する。
oauth_timestamp
リクエストを送る際のUNIX TIMESTAMPの値を指定する。具体的には、PHPでtime()の値をそのまま指定すればいい。
oauth_nonce
任意で用意したランダムな文字列を指定する。PHPなら、例えばmicrotime()などの値をそのまま指定すればいい。
oauth_version
認証に利用する規格であるOAuthのバージョンを指定する。1.0を指定すればいい。

設定項目

それでは、リクエストトークンを取得してみましょう。まずは、取得に必要となるデータを変数にセットしておきましょう。

PHP

<?php
// 設定項目
$api_key = "" ;	// API Key
$api_secret = "" ;	// API Secret
$callback_url = "" ;	// Callback URL (このプログラムのURLアドレス)

署名を作成する

まずはoauth_signatureの値となる、署名を作成しなければいけません。署名の作成方法については、参考記事を章の冒頭で紹介しましたね。それに沿って進めていきます。

キーを作成する

署名を作成する材料となる「キー」を作成します。キーは、API KeyとAccess Token Secretの値を&で繋ぎます。この時点ではAccess Token Secretがまだ存在しないため、Access Token Secretはなし(空の文字列)として扱います。具体的には次のように処理します。

PHP

/*** [手順1] リクエストトークンの取得 ***/

// [アクセストークンシークレット] (まだ存在しないので「なし」)
$access_token_secret = "" ;

// エンドポイントURL
$request_url = "https://api.twitter.com/oauth/request_token" ;

// リクエストメソッド
$request_method = "POST" ;

// キーを作成する (URLエンコードする)
$signature_key = rawurlencode( $api_secret ) . "&" . rawurlencode( $access_token_secret ) ;
データを作成する

署名の、もう1つの材料となる「データ」を作成しましょう。先ほどのプログラムに書き足していって下さい。

PHP

// パラメータ([oauth_signature]を除く)を連想配列で指定
$params = array(
	"oauth_callback" => $callback_url ,
	"oauth_consumer_key" => $api_key ,
	"oauth_signature_method" => "HMAC-SHA1" ,
	"oauth_timestamp" => time() ,
	"oauth_nonce" => microtime() ,
	"oauth_version" => "1.0" ,
) ;

// 各パラメータをURLエンコードする
foreach( $params as $key => $value ) {
	// コールバックURLはエンコードしない
	if( $key == "oauth_callback" ) {
			continue ;
	}

	// URLエンコード処理
	$params[ $key ] = rawurlencode( $value ) ;
}

// 連想配列をアルファベット順に並び替える
ksort( $params ) ;

// パラメータの連想配列を[キー=値&キー=値...]の文字列に変換する
$request_params = http_build_query( $params , "" , "&" ) ;
 
// 変換した文字列をURLエンコードする
$request_params = rawurlencode( $request_params ) ;
 
// リクエストメソッドをURLエンコードする
$encoded_request_method = rawurlencode( $request_method ) ;
 
// リクエストURLをURLエンコードする
$encoded_request_url = rawurlencode( $request_url ) ;
 
// リクエストメソッド、リクエストURL、パラメータを[&]で繋ぐ
$signature_data = $encoded_request_method . "&" . $encoded_request_url . "&" . $request_params ;
キーとデータを「署名」に変換する

キーとデータを作成することができました。この2つを利用して、署名を作成しましょう。$signatureに署名が代入されます。

PHP

// キー[$signature_key]とデータ[$signature_data]を利用して、HMAC-SHA1方式のハッシュ値に変換する
$hash = hash_hmac( "sha1" , $signature_data , $signature_key , TRUE ) ;

// base64エンコードして、署名[$signature]が完成する
$signature = base64_encode( $hash ) ;

リクエストトークンを取得する

署名($signature)が完成して、リクエストに必要なパラメータが全て揃いました。後は、POSTメソッドでリクエストを送るだけですね。パラメータはAuthorizationというカスタムヘッダーの中に、次のように含めます。

Authorization: OAuth パラメータ名=値,パラメータ名=値,パラメータ名=値,...

「OAuth」という文字列の次に半角スペースを入れて、その後にパラメータを「キー=値,キー=値,...」の形で入れていきます。そして「キー=値」と「キー=値」の間には半角カンマを挟んで下さい。また、値はURLエンコードされている必要があります。この形式に従うと次の通りになりますね。

Authorization: OAuth oauth_callback=http%3A%2F%2Fsyncer.jp%2Foauth.php,oauth_consumer_key=:APIキー,oauth_signature_method=HMAC-SHA1,oauth_signature=...

以上を踏まえて、cURLを利用して次のようにPOSTリクエストを送信しましょう。リクエストの返り値を$responseという変数に代入します。この$responseの中に、リクエストトークンとなる値が含まれています。

PHP

// パラメータの連想配列、[$params]に、作成した署名を加える
$params["oauth_signature"] = $signature ;

// パラメータの連想配列を[キー=値,キー=値,...]の文字列に変換する
$header_params = http_build_query( $params , "" , "," ) ;

// リクエスト用のコンテキストを作成する
$context = array(
	"http" => array(
		"method" => $request_method , // リクエストメソッド (POST)
		"header" => array(			  // カスタムヘッダー
			"Authorization: OAuth " . $header_params ,
		) ,
	) ,
) ;

// cURLを使ってリクエスト
$curl = curl_init() ;
curl_setopt( $curl, CURLOPT_URL , $request_url ) ;	// リクエストURL
curl_setopt( $curl, CURLOPT_HEADER, true ) ;	// ヘッダーを取得する
curl_setopt( $curl, CURLOPT_CUSTOMREQUEST , $context["http"]["method"] ) ;	// メソッド
curl_setopt( $curl, CURLOPT_SSL_VERIFYPEER , false ) ;	// 証明書の検証を行わない
curl_setopt( $curl, CURLOPT_RETURNTRANSFER , true ) ;	// curl_execの結果を文字列で返す
curl_setopt( $curl, CURLOPT_HTTPHEADER , $context["http"]["header"] ) ;	// リクエストヘッダーの内容
curl_setopt( $curl, CURLOPT_TIMEOUT , 5 ) ;	// タイムアウトの秒数
$res1 = curl_exec( $curl ) ;
$res2 = curl_getinfo( $curl ) ;
curl_close( $curl ) ;

// 取得したデータ
$response = substr( $res1, $res2["header_size"] ) ;	// 取得したデータ(JSONなど)
$header = substr( $res1, 0, $res2["header_size"] ) ;	// レスポンスヘッダー (検証に利用したい場合にどうぞ)

// [cURL]ではなく、[file_get_contents()]を使うには下記の通りです…
// $response = file_get_contents( $request_url , false , stream_context_create( $context ) ) ;

返ってきた値の確認

リクエストが成功すると、下記の文字列が$responseに代入されます。分かりやすくするため色を付けました。ちょうど、URLアドレスに付けるパラメータみたいになっていますね。

oauth_token=5mb9VtYwa27HTVjK5OhoyyI503dWoPndDQ9G4V8yCI&oauth_token_secret=4dW4gGLic6oItvd0YySWRU5aLjBQsw1N9xDC3Wkqw&oauth_callback_confirmed=true

この文字列のoauth_tokenの値がリクエストトークン、そしてoauth_token_secretの値がリクエストトークン・シークレットです。

oauth_token
リクエストトークン。ユーザーが認証画面にアクセスする時のパラメータに必要な値です。
oauth_token_secret
リクエストトークンシークレット。後ほどアクセストークンを取得する際に必要です。
oauth_callback_confirmed
oauth_callbackの値をサービス提供側(Twitter)が受信したか?trueになっているはずです。特に使わないので無視しても大丈夫です。

値は、次のように$queryという変数の配列に整理します。例えば、$query["oauth_token"]でリクエストトークンを取り出すことができます。

PHP

// リクエストトークンを取得できなかった場合
if( !$response ) {
	echo "<p>リクエストトークンを取得できませんでした…。$api_keyと$callback_url、そしてTwitterのアプリケーションに設定しているCallback URLを確認して下さい。</p>" ;
	exit ;
}

// $responseの内容(文字列)を$query(配列)に直す
// aaa=AAA&bbb=BBB → [ "aaa"=>"AAA", "bbb"=>"BBB" ]
$query = [] ;
parse_str( $response, $query ) ;

// 配列の内容を出力する (本番では不要)
foreach ( $query as $key => $value ) {
	echo "<b>" . $key . "</b>: " . $value . "<BR>" ;
}

// レスポンスヘッダーを出力 (本番では不要)
echo "<BR>" . $header ;

サンプルプログラム

ここまで説明してきたコードを1つにまとめたサンプルプログラムが下記です。

PHP (request_token.php)

<?php
// 設定項目
$api_key = "" ;	// API Key
$api_secret = "" ;	// API Secret
$callback_url = "" ;	// Callback URL (このプログラムのURLアドレス)

/*** [手順1] リクエストトークンの取得 ***/

// [アクセストークンシークレット] (まだ存在しないので「なし」)
$access_token_secret = "" ;

// エンドポイントURL
$request_url = "https://api.twitter.com/oauth/request_token" ;

// リクエストメソッド
$request_method = "POST" ;

// キーを作成する (URLエンコードする)
$signature_key = rawurlencode( $api_secret ) . "&" . rawurlencode( $access_token_secret ) ;

// パラメータ([oauth_signature]を除く)を連想配列で指定
$params = array(
	"oauth_callback" => $callback_url ,
	"oauth_consumer_key" => $api_key ,
	"oauth_signature_method" => "HMAC-SHA1" ,
	"oauth_timestamp" => time() ,
	"oauth_nonce" => microtime() ,
	"oauth_version" => "1.0" ,
) ;

// 各パラメータをURLエンコードする
foreach( $params as $key => $value ) {
	// コールバックURLはエンコードしない
	if( $key == "oauth_callback" ) {
			continue ;
	}

	// URLエンコード処理
	$params[ $key ] = rawurlencode( $value ) ;
}

// 連想配列をアルファベット順に並び替える
ksort( $params ) ;

// パラメータの連想配列を[キー=値&キー=値...]の文字列に変換する
$request_params = http_build_query( $params , "" , "&" ) ;
 
// 変換した文字列をURLエンコードする
$request_params = rawurlencode( $request_params ) ;
 
// リクエストメソッドをURLエンコードする
$encoded_request_method = rawurlencode( $request_method ) ;
 
// リクエストURLをURLエンコードする
$encoded_request_url = rawurlencode( $request_url ) ;
 
// リクエストメソッド、リクエストURL、パラメータを[&]で繋ぐ
$signature_data = $encoded_request_method . "&" . $encoded_request_url . "&" . $request_params ;

// キー[$signature_key]とデータ[$signature_data]を利用して、HMAC-SHA1方式のハッシュ値に変換する
$hash = hash_hmac( "sha1" , $signature_data , $signature_key , TRUE ) ;

// base64エンコードして、署名[$signature]が完成する
$signature = base64_encode( $hash ) ;

// パラメータの連想配列、[$params]に、作成した署名を加える
$params["oauth_signature"] = $signature ;

// パラメータの連想配列を[キー=値,キー=値,...]の文字列に変換する
$header_params = http_build_query( $params , "" , "," ) ;

// リクエスト用のコンテキストを作成する
$context = array(
	"http" => array(
		"method" => $request_method , // リクエストメソッド (POST)
		"header" => array(			  // カスタムヘッダー
			"Authorization: OAuth " . $header_params ,
		) ,
	) ,
) ;

// cURLを使ってリクエスト
$curl = curl_init() ;
curl_setopt( $curl, CURLOPT_URL , $request_url ) ;	// リクエストURL
curl_setopt( $curl, CURLOPT_HEADER, true ) ;	// ヘッダーを取得する
curl_setopt( $curl, CURLOPT_CUSTOMREQUEST , $context["http"]["method"] ) ;	// メソッド
curl_setopt( $curl, CURLOPT_SSL_VERIFYPEER , false ) ;	// 証明書の検証を行わない
curl_setopt( $curl, CURLOPT_RETURNTRANSFER , true ) ;	// curl_execの結果を文字列で返す
curl_setopt( $curl, CURLOPT_HTTPHEADER , $context["http"]["header"] ) ;	// リクエストヘッダーの内容
curl_setopt( $curl, CURLOPT_TIMEOUT , 5 ) ;	// タイムアウトの秒数
$res1 = curl_exec( $curl ) ;
$res2 = curl_getinfo( $curl ) ;
curl_close( $curl ) ;

// 取得したデータ
$response = substr( $res1, $res2["header_size"] ) ;	// 取得したデータ(JSONなど)
$header = substr( $res1, 0, $res2["header_size"] ) ;	// レスポンスヘッダー (検証に利用したい場合にどうぞ)

// [cURL]ではなく、[file_get_contents()]を使うには下記の通りです…
// $response = @file_get_contents( $request_url , false , stream_context_create( $context ) ) ;

// リクエストトークンを取得できなかった場合
if( !$response ) {
	echo "<p>リクエストトークンを取得できませんでした…。$api_keyと$callback_url、そしてTwitterのアプリケーションに設定しているCallback URLを確認して下さい。</p>" ;
	exit ;
}

// $responseの内容(文字列)を$query(配列)に直す
// aaa=AAA&bbb=BBB → [ "aaa"=>"AAA", "bbb"=>"BBB" ]
$query = [] ;
parse_str( $response, $query ) ;

// 配列の内容を出力する (本番では不要)
foreach ( $query as $key => $value ) {
	echo $key . ": " . $value . "<BR>" ;
}

// レスポンスヘッダーを出力 (本番では不要)
echo $header ;

[手順2] ユーザーを認証画面に飛ばす

続いて、ユーザーを認証画面に移動させます。

URLアドレスを組み立てる

認証画面のURLアドレスは2種類あります。コンテンツの性質に合わせてURLを選んで下さい。パラメータのoauth_tokenの値には、先ほど取得したリクエストトークンを指定します。

毎回認証が必要な場合

ユーザーは認証の度に連携のボタンをクリックする必要があります。

https://api.twitter.com/oauth/authorize?oauth_token={リクエストトークン}
GET oauth/authorize
GET oauth/authorize
Twitter Developers内のページ。毎回ボタンを押す必要がない認証画面、に関する情報があります。
再認証を省略する場合

過去に認証を完了したユーザーには認証画面が表示されません。

https://api.twitter.com/oauth/authenticate?oauth_token={リクエストトークン}
GET oauth/authenticate
GET oauth/authenticate
Twitter Developers内のページ。毎回ボタンを押す必要がある認証画面、に関する情報があります。

リクエストトークン・シークレットの記録

ユーザーを認証画面へ飛ばす前に、oauth_token_secret(リクエストトークン・シークレット)の値を保存しておかなければいけません。何故なら、このoauth_token_secretは、ユーザーがこのページを離れて認証画面へアクセスした後、再び、このプログラムのURLに戻ってきた時に必要になるからです。それにはセッションを利用して、次のように保存します。

PHP

// セッション[$_SESSION["oauth_token_secret"]]に[oauth_token_secret]を保存する
session_start() ;
session_regenerate_id( true ) ;
$_SESSION["oauth_token_secret"] = $query["oauth_token_secret"] ;

こうしておくことで、再び、ユーザーが認証画面からこのプログラムのURLに戻ってきた時に、$_SESSION["oauth_token_secret"]oauth_token_secretの値を取り出すことができます。

認証画面へ移動させる

準備ができたので、ユーザーを認証画面に移動させましょう。それには、一般的には、次のようにheader()を利用して、ユーザーを強制的にリダイレクトさせます。次のコードを、これまでのプログラムに書き足して下さいね。これで、このプログラムにアクセスすると、自動的にリクエストトークンを取得して認証画面に移動するようになりました。

PHP

// ユーザーを認証画面へ飛ばす (毎回ボタンを押す場合)
header( "Location: https://api.twitter.com/oauth/authorize?oauth_token=" . $query["oauth_token"] ) ;

// ユーザーを認証画面へ飛ばす (二回目以降は認証画面をスキップする場合)
// header( "Location: https://api.twitter.com/oauth/authenticate?oauth_token=" . $query["oauth_token"] ) ;

理解を深めるために捕捉しておきますが、次のようにリンクを用意してユーザー自身にアクセスしてもらっても同じだということを意識して下さいね。

PHP

echo '<p><a href="https://api.twitter.com/oauth/authenticate?oauth_token=' . $query["oauth_token"] . '">認証画面へ移動する</a></p>' ;

サンプルプログラム

ここまでをまとめたサンプルプログラムが下記です。Twitterの認証画面に移動しますが、そこでの操作は不要なのでウィンドウを閉じてしまって下さい。

PHP (redirect.php)

<?php
// 設定項目
$api_key = "" ;	// API Key
$api_secret = "" ;	// API Secret
$callback_url = "" ;	// Callback URL (このプログラムのURLアドレス)

// 認証画面のURLを[.../authenticate]にした時にリダイレクトループを防ぐ処理
if ( isset( $_GET['oauth_token'] ) || isset($_GET["oauth_verifier"]) ) {
	echo "認証画面から帰ってきました。" ;
	exit ;
}

/*** [手順1] リクエストトークンの取得 ***/

// [アクセストークンシークレット] (まだ存在しないので「なし」)
$access_token_secret = "" ;

// エンドポイントURL
$request_url = "https://api.twitter.com/oauth/request_token" ;

// リクエストメソッド
$request_method = "POST" ;

// キーを作成する (URLエンコードする)
$signature_key = rawurlencode( $api_secret ) . "&" . rawurlencode( $access_token_secret ) ;

// パラメータ([oauth_signature]を除く)を連想配列で指定
$params = array(
	"oauth_callback" => $callback_url ,
	"oauth_consumer_key" => $api_key ,
	"oauth_signature_method" => "HMAC-SHA1" ,
	"oauth_timestamp" => time() ,
	"oauth_nonce" => microtime() ,
	"oauth_version" => "1.0" ,
) ;

// 各パラメータをURLエンコードする
foreach( $params as $key => $value ) {
	// コールバックURLはエンコードしない
	if( $key == "oauth_callback" ) {
			continue ;
	}

	// URLエンコード処理
	$params[ $key ] = rawurlencode( $value ) ;
}

// 連想配列をアルファベット順に並び替える
ksort( $params ) ;

// パラメータの連想配列を[キー=値&キー=値...]の文字列に変換する
$request_params = http_build_query( $params , "" , "&" ) ;
 
// 変換した文字列をURLエンコードする
$request_params = rawurlencode( $request_params ) ;
 
// リクエストメソッドをURLエンコードする
$encoded_request_method = rawurlencode( $request_method ) ;
 
// リクエストURLをURLエンコードする
$encoded_request_url = rawurlencode( $request_url ) ;
 
// リクエストメソッド、リクエストURL、パラメータを[&]で繋ぐ
$signature_data = $encoded_request_method . "&" . $encoded_request_url . "&" . $request_params ;

// キー[$signature_key]とデータ[$signature_data]を利用して、HMAC-SHA1方式のハッシュ値に変換する
$hash = hash_hmac( "sha1" , $signature_data , $signature_key , TRUE ) ;

// base64エンコードして、署名[$signature]が完成する
$signature = base64_encode( $hash ) ;

// パラメータの連想配列、[$params]に、作成した署名を加える
$params["oauth_signature"] = $signature ;

// パラメータの連想配列を[キー=値,キー=値,...]の文字列に変換する
$header_params = http_build_query( $params , "" , "," ) ;

// リクエスト用のコンテキストを作成する
$context = array(
	"http" => array(
		"method" => $request_method , // リクエストメソッド (POST)
		"header" => array(			  // カスタムヘッダー
			"Authorization: OAuth " . $header_params ,
		) ,
	) ,
) ;

// cURLを使ってリクエスト
$curl = curl_init() ;
curl_setopt( $curl, CURLOPT_URL , $request_url ) ;	// リクエストURL
curl_setopt( $curl, CURLOPT_HEADER, true ) ;	// ヘッダーを取得する
curl_setopt( $curl, CURLOPT_CUSTOMREQUEST , $context["http"]["method"] ) ;	// メソッド
curl_setopt( $curl, CURLOPT_SSL_VERIFYPEER , false ) ;	// 証明書の検証を行わない
curl_setopt( $curl, CURLOPT_RETURNTRANSFER , true ) ;	// curl_execの結果を文字列で返す
curl_setopt( $curl, CURLOPT_HTTPHEADER , $context["http"]["header"] ) ;	// リクエストヘッダーの内容
curl_setopt( $curl, CURLOPT_TIMEOUT , 5 ) ;	// タイムアウトの秒数
$res1 = curl_exec( $curl ) ;
$res2 = curl_getinfo( $curl ) ;
curl_close( $curl ) ;

// 取得したデータ
$response = substr( $res1, $res2["header_size"] ) ;	// 取得したデータ(JSONなど)
$header = substr( $res1, 0, $res2["header_size"] ) ;	// レスポンスヘッダー (検証に利用したい場合にどうぞ)

// [cURL]ではなく、[file_get_contents()]を使うには下記の通りです…
// $response = @file_get_contents( $request_url , false , stream_context_create( $context ) ) ;

// リクエストトークンを取得できなかった場合
if( !$response ) {
	echo "<p>リクエストトークンを取得できませんでした…。$api_keyと$callback_url、そしてTwitterのアプリケーションに設定しているCallback URLを確認して下さい。</p>" ;
	exit ;
}

// $responseの内容(文字列)を$query(配列)に直す
// aaa=AAA&bbb=BBB → [ "aaa"=>"AAA", "bbb"=>"BBB" ]
$query = [] ;
parse_str( $response, $query ) ;

// セッション[$_SESSION["oauth_token_secret"]]に[oauth_token_secret]を保存する
session_start() ;
session_regenerate_id( true ) ;
$_SESSION["oauth_token_secret"] = $query["oauth_token_secret"] ;

/*** [手順2] ユーザーを認証画面へ飛ばす ***/

// ユーザーを認証画面へ飛ばす (毎回ボタンを押す場合)
header( "Location: https://api.twitter.com/oauth/authorize?oauth_token=" . $query["oauth_token"] ) ;

// ユーザーを認証画面へ飛ばす (二回目以降は認証画面をスキップする場合)
// header( "Location: https://api.twitter.com/oauth/authenticate?oauth_token=" . $query["oauth_token"] ) ;

[手順3] ユーザーによる認証作業

アプリケーションの認証画面
アプリケーションの認証画面

この手順はサービス提供(Twitter)側での操作なのでプログラムの作成はありません。ここでユーザーは、あなたのアプリケーションが自分のデータにアクセスして読み込んだり書き込んだりするのを許可するか、拒否するかを選択します。

左部分に「この連携アプリを認証すると、次の動作が許可されます。」という項目がありますが、ここにアプリケーションの登録時に設定したパーミッションの内容が反映されています。強い権限を持つアプリケーションは、ユーザーに警戒され、許可されにくいので、webサービスの機能を満たす最低限の権限を設定するようにしましょう。ちょっと話が逸れてしまいましたね。

URLが2種類ありましたが、ここでもう一度説明します。authorizeのURLは毎回、ユーザーがこの画面でボタンを押さなければいけません。authenticateのURLはユーザーが過去にボタンを押している場合に、この画面(手順)がスキップされます。

さて、開発者は、ユーザーが「連携アプリを認証」をクリックした時と、「キャンセル」をクリックした時の2通りに備えておく必要があります。次に進みましょう。

[手順4] ユーザーが戻ってくる

さて、処理も後半、ユーザーが認証画面での操作を終えたところです。ユーザーが認証画面で「連携アプリを認証」、または「キャンセル」をクリックすると、こちらが認証画面へ飛ばしたのと同じように、今度はTwitter側が、ユーザーをこちらの指定したURL(Callback URL)に飛ばしてきます。

OAuth認証において、このようにユーザーはまるでドッジボールのボールみたいにアプリケーション側とサービス提供側の間で投げつけられ合います。

許可と拒否

「連携アプリを認証」をクリックした場合

ユーザーがアプリケーションの連携を許可した場合、Callback URLで指定したアドレスにoauth_tokenoauth_verifier、2つのパラメータを付けて戻ってきます。これらは次の行程で利用するので意識しておいて下さいね。

http://syncer.jp/oauth.php?oauth_token=mFyphbOybZCKfoZWurAU7dbcTnFoUeksGfVyFauFWM&oauth_verifier=TGUMMyQWCSJGKiXlUlQmgRQEYMv8mkIt5cHPERUgvw
「キャンセル」をクリックした場合

ユーザーが、アプリケーションの連携を拒否した場合、deniedというパラメータを付けて戻ってきます。

http://syncer.jp/oauth.php?denied=Dtqzw56YZ7HhFkQgYbvnwmgX0iwTK06ntHQ2TYCoo

条件分けの例

条件分けのプログラムは、次のようになりますね。そして、この条件分けは、OAuth1.0認証のプログラムを1つのファイルにまとめるのなら、リクエストトークンを取得する処理よりも、前に記述する必要がありますよね。もし、後に記述していたら、まるでジョジョのゴールドエクスペリエンスを受けたかのように、ユーザーが認証作業をしては認証画面に飛ばされて…、の繰り返しになってしまいます。この理屈を意識してみて下さい。

PHP

// 「連携アプリを認証」をクリックして帰ってきた時
if( isset( $_GET["oauth_token"] ) && isset( $_GET["oauth_verifier"] ) ) {
	// アクセストークンを取得するための処理
	// ...
	exit ;

// 「キャンセル」をクリックして帰ってきた時
} elseif ( isset( $_GET["denied"] ) ) {
	// エラーメッセージを出力して終了
	echo "連携を拒否しました。" ;
	exit ;

}

[手順5] アクセストークンを取得する

いよいよ最後の手順です。ここまでに取得できた材料を元に「アクセストークン」を取得しましょう。下記ページに公式ドキュメント(英語)があります。

POST oauth/access_token
POST oauth/access_token
Twitter Developers内のページ。OAuth認証の最後の手順、アクセストークンを取得するためのエンドポイントについての説明。

リクエスト方法

アクセストークンの取得は、リクエストトークンの取得の時と、その仕組みは同じです。エンドポイントは下記です。

https://api.twitter.com/oauth/access_token

リクエストに必要なパラメータは下記の通りです。リクエストトークンの取得時とは微妙に違っていますので、確認してみて下さいね。

oauth_consumer_key
アプリケーション作成時に取得したAPI Key。
oauth_token
ユーザーが認証作業を終えて戻ってきた時、URLに付けているパラメータのoauth_tokenの値。
oauth_signature_method
署名の種類を指定。HMAC-SHA1を指定すればいい。
oauth_signature
作成した署名を指定する。
oauth_timestamp
リクエストを送る際のUNIX TIMESTAMPの値を指定する。具体的には、PHPでtime()の値をそのまま指定すればいい。
oauth_verifier
ユーザーが認証作業を終えて戻ってきた時、URLに付けているパラメータのoauth_verifierの値。
oauth_nonce
任意で用意したランダムな文字列を指定する。PHPなら、microtime()の値をそのまま指定すればいい。
oauth_version
認証に利用する規格であるOAuthのバージョンを指定する。1.0を指定すればいい。

署名を作成する

それでは署名を作成していきましょう。繰り返しになりますが、作成方法はリクエストトークンの時とほぼ同じです。ここからのプログラミングは、ユーザーが許可をして戻ってきた時の条件分岐内に記述していきます。

リクエストトークン・シークレットを呼び出す

セッションを利用して、ユーザーの端末に記憶させていたリクエストトークン・シークレットを呼び出しましょう。

PHP

//[リクエストトークン・シークレット]をセッションから呼び出す
session_start() ;
$request_token_secret = $_SESSION["oauth_token_secret"] ;
キーを作成する

署名の材料となる「キー」の作成です。キーは、API KeyとAccess Token Secretの値を&で繋ぐのでしたね。リクエストトークンを取得する時は、Access Token Secretを空にしていましたが、今回は、手順1で、リクエストトークンと一緒に取得したリクエストトークン・シークレットを利用します。このリクエストトークン・シークレットは、手順2でユーザーを認証画面に飛ばす時、セッションに保存していました。

PHP

// リクエストURL
$request_url = "https://api.twitter.com/oauth/access_token" ;

// リクエストメソッド
$request_method = "POST" ;

// キーを作成する
$signature_key = rawurlencode( $api_secret ) . "&" . rawurlencode( $request_token_secret ) ;
データを作成する

続いて、もう1つの署名の材料である「データ」を作成しましょう。

PHP

// パラメータ([oauth_signature]を除く)を連想配列で指定
$params = array(
	"oauth_consumer_key" => $api_key ,
	"oauth_token" => $_GET["oauth_token"] ,
	"oauth_signature_method" => "HMAC-SHA1" ,
	"oauth_timestamp" => time() ,
	"oauth_verifier" => $_GET["oauth_verifier"] ,
	"oauth_nonce" => microtime() ,
	"oauth_version" => "1.0" ,
) ;

// 配列の各パラメータの値をURLエンコード
foreach( $params as $key => $value ) {
	$params[ $key ] = rawurlencode( $value ) ;
}

// 連想配列をアルファベット順に並び替え
ksort($params) ;

// パラメータの連想配列を[キー=値&キー=値...]の文字列に変換
$request_params = http_build_query( $params , "" , "&" ) ;

// 変換した文字列をURLエンコードする
$request_params = rawurlencode($request_params) ;

// リクエストメソッドをURLエンコードする
$encoded_request_method = rawurlencode( $request_method ) ;

// リクエストURLをURLエンコードする
$encoded_request_url = rawurlencode( $request_url ) ;

// リクエストメソッド、リクエストURL、パラメータを[&]で繋ぐ
$signature_data = $encoded_request_method . "&" . $encoded_request_url . "&" . $request_params ;
キーとデータを「署名」に変換する

作成した「キー」と「データ」を利用して、署名を作成します。

PHP

// キー[$signature_key]とデータ[$signature_data]を利用して、HMAC-SHA1方式のハッシュ値に変換する
$hash = hash_hmac( "sha1" , $signature_data , $signature_key , TRUE ) ;

// base64エンコードして、署名[$signature]が完成する
$signature = base64_encode( $hash ) ;
アクセストークンを取得する

署名が作成できたら、リクエストを行ないましょう。ここでも、リクエストトークンの時と処理は同じです。$responseに取得するデータを代入します。

PHP

// パラメータの連想配列、[$params]に、作成した署名を加える
$params["oauth_signature"] = $signature ;

// パラメータの連想配列を[キー=値,キー=値,...]の文字列に変換する
$header_params = http_build_query( $params, "", "," ) ;

// リクエスト用のコンテキストを作成する
$context = array(
	"http" => array(
		"method" => $request_method ,	//リクエストメソッド
		"header" => array(	//カスタムヘッダー
			"Authorization: OAuth " . $header_params ,
		) ,
	) ,
) ;

// cURLを使ってリクエスト
$curl = curl_init() ;
curl_setopt( $curl , CURLOPT_URL , $request_url ) ;
curl_setopt( $curl , CURLOPT_HEADER, 1 ) ; 
curl_setopt( $curl , CURLOPT_CUSTOMREQUEST , $context["http"]["method"] ) ;	// メソッド
curl_setopt( $curl , CURLOPT_SSL_VERIFYPEER , false ) ;	// 証明書の検証を行わない
curl_setopt( $curl , CURLOPT_RETURNTRANSFER , true ) ;	// curl_execの結果を文字列で返す
curl_setopt( $curl , CURLOPT_HTTPHEADER , $context["http"]["header"] ) ;	// ヘッダー
curl_setopt( $curl , CURLOPT_TIMEOUT , 5 ) ;	// タイムアウトの秒数
$res1 = curl_exec( $curl ) ;
$res2 = curl_getinfo( $curl ) ;
curl_close( $curl ) ;

// 取得したデータ
$response = substr( $res1, $res2["header_size"] ) ;	// 取得したデータ(JSONなど)
$header = substr( $res1, 0, $res2["header_size"] ) ;	// レスポンスヘッダー (検証に利用したい場合にどうぞ)

// [cURL]ではなく、[file_get_contents()]を使うには下記の通りです…
// $response = file_get_contents( $request_url , false , stream_context_create( $context ) ) ;
返ってきた値の確認

リクエストが成功すると下記の文字列が$responseに代入されます。この中に念願の「アクセストークン(oauth_token)」「アクセストークンシークレット(oauth_token_secret)」が含まれています。

oauth_token=1528352858-UUCjYDVcLC4V34xHob5XTxboEgJWLwp9aIGSrBC&oauth_token_secret=VNhCQye7rX4P4u2OIuDHOgdSBATgZV3qWvJ8uSLkXqP25&user_id=1528352858&screen_name=arayutw

それぞれのパラメータは次の意味を持っています。

oauth_token
アクセストークン。oauth token、access tokenなどとも表現される。
oauth_token_secret
アクセストークン・シークレット。oauth token secret、access token secretなどとも表現される。
user_id
ユーザーアカウントに割り当てられた一意のID。スクリーンネーム(@arayutw)が外見せ用のIDなのに対し、こちらは絶対に変わらない、内部管理用のID。
screen_name
ユーザーアカウントに割り当てられた、外見せ用のID。一意だがユーザーが好きな時に変更できる。

最後は、リクエストトークンを取得した時と同じように、取得したデータを配列に変換して$queryに保存し、最後にブラウザに出力するなり、データベースに保存するなりして下さい。

PHP

// $responseの内容(文字列)を$query(配列)に直す
// aaa=AAA&bbb=BBB → [ "aaa"=>"AAA", "bbb"=>"BBB" ]
$query = [] ;
parse_str( $response, $query ) ;

// 配列の内容を出力する (本番では不要)
foreach ( $query as $key => $value ) {
	echo "<b>" . $key . "</b>: " . $value . "<BR>" ;
}

サンプルプログラム

ここまでの説明を踏まえて作成したアクセストークンを取得するサンプルプログラムです。よろしければお使い下さいね。リクエストトークンの取得とアクセストークンの取得で、ほとんど同じ処理をしています。流れを分かりやすくするため、あえて、分けて記述してあることをご了承下さい。

PHP (access_token.php)

<?php
// 設定項目
$api_key = "" ;	// API Key
$api_secret = "" ;	// API Secret
$callback_url = "" ;	// Callback URL (このプログラムのURLアドレス)

/*** [手順4] ユーザーが戻ってくる ***/

// 認証画面から戻ってきた時 (認証OK)
if ( isset( $_GET['oauth_token'] ) || isset($_GET["oauth_verifier"]) ) {
	/*** [手順5] [手順5] アクセストークンを取得する ***/

	//[リクエストトークン・シークレット]をセッションから呼び出す
	session_start() ;
	$request_token_secret = $_SESSION["oauth_token_secret"] ;

	// リクエストURL
	$request_url = "https://api.twitter.com/oauth/access_token" ;

	// リクエストメソッド
	$request_method = "POST" ;

	// キーを作成する
	$signature_key = rawurlencode( $api_secret ) . "&" . rawurlencode( $request_token_secret ) ;

	// パラメータ([oauth_signature]を除く)を連想配列で指定
	$params = array(
		"oauth_consumer_key" => $api_key ,
		"oauth_token" => $_GET["oauth_token"] ,
		"oauth_signature_method" => "HMAC-SHA1" ,
		"oauth_timestamp" => time() ,
		"oauth_verifier" => $_GET["oauth_verifier"] ,
		"oauth_nonce" => microtime() ,
		"oauth_version" => "1.0" ,
	) ;

	// 配列の各パラメータの値をURLエンコード
	foreach( $params as $key => $value ) {
		$params[ $key ] = rawurlencode( $value ) ;
	}

	// 連想配列をアルファベット順に並び替え
	ksort($params) ;

	// パラメータの連想配列を[キー=値&キー=値...]の文字列に変換
	$request_params = http_build_query( $params , "" , "&" ) ;

	// 変換した文字列をURLエンコードする
	$request_params = rawurlencode($request_params) ;

	// リクエストメソッドをURLエンコードする
	$encoded_request_method = rawurlencode( $request_method ) ;

	// リクエストURLをURLエンコードする
	$encoded_request_url = rawurlencode( $request_url ) ;

	// リクエストメソッド、リクエストURL、パラメータを[&]で繋ぐ
	$signature_data = $encoded_request_method . "&" . $encoded_request_url . "&" . $request_params ;

	// キー[$signature_key]とデータ[$signature_data]を利用して、HMAC-SHA1方式のハッシュ値に変換する
	$hash = hash_hmac( "sha1" , $signature_data , $signature_key , TRUE ) ;

	// base64エンコードして、署名[$signature]が完成する
	$signature = base64_encode( $hash ) ;

	// パラメータの連想配列、[$params]に、作成した署名を加える
	$params["oauth_signature"] = $signature ;

	// パラメータの連想配列を[キー=値,キー=値,...]の文字列に変換する
	$header_params = http_build_query( $params, "", "," ) ;

	// リクエスト用のコンテキストを作成する
	$context = array(
		"http" => array(
			"method" => $request_method ,	//リクエストメソッド
			"header" => array(	//カスタムヘッダー
				"Authorization: OAuth " . $header_params ,
			) ,
		) ,
	) ;

	// cURLを使ってリクエスト
	$curl = curl_init() ;
	curl_setopt( $curl, CURLOPT_URL , $request_url ) ;
	curl_setopt( $curl, CURLOPT_HEADER, 1 ) ; 
	curl_setopt( $curl, CURLOPT_CUSTOMREQUEST , $context["http"]["method"] ) ;	// メソッド
	curl_setopt( $curl, CURLOPT_SSL_VERIFYPEER , false ) ;	// 証明書の検証を行わない
	curl_setopt( $curl, CURLOPT_RETURNTRANSFER , true ) ;	// curl_execの結果を文字列で返す
	curl_setopt( $curl, CURLOPT_HTTPHEADER , $context["http"]["header"] ) ;	// ヘッダー
	curl_setopt( $curl, CURLOPT_TIMEOUT , 5 ) ;	// タイムアウトの秒数
	$res1 = curl_exec( $curl ) ;
	$res2 = curl_getinfo( $curl ) ;
	curl_close( $curl ) ;

	// 取得したデータ
	$response = substr( $res1, $res2["header_size"] ) ;	// 取得したデータ(JSONなど)
	$header = substr( $res1, 0, $res2["header_size"] ) ;	// レスポンスヘッダー (検証に利用したい場合にどうぞ)

	// [cURL]ではなく、[file_get_contents()]を使うには下記の通りです…
	// $response = file_get_contents( $request_url , false , stream_context_create( $context ) ) ;

	// $responseの内容(文字列)を$query(配列)に直す
	// aaa=AAA&bbb=BBB → [ "aaa"=>"AAA", "bbb"=>"BBB" ]
	$query = [] ;
	parse_str( $response, $query ) ;

	// アクセストークン
	// $query["oauth_token"]

	// アクセストークン・シークレット
	// $query["oauth_token_secret"]

	// ユーザーID
	// $query["user_id"]

	// スクリーンネーム
	// $query["screen_name"]

	// 配列の内容を出力する (本番では不要)
	echo '<p>下記の認証情報を取得しました。(<a href="' . explode( "?", $_SERVER["REQUEST_URI"] )[0] . '">もう1回やってみる</a>)</p>' ;

	foreach ( $query as $key => $value ) {
		echo "<b>" . $key . "</b>: " . $value . "<BR>" ;
	}

// 認証画面から戻ってきた時 (認証NG)
} elseif ( isset( $_GET["denied"] ) ) {
	// エラーメッセージを出力して終了
	echo "連携を拒否しました。" ;
	exit ;

// 初回のアクセス
} else {
	/*** [手順1] リクエストトークンの取得 ***/

	// [アクセストークンシークレット] (まだ存在しないので「なし」)
	$access_token_secret = "" ;

	// エンドポイントURL
	$request_url = "https://api.twitter.com/oauth/request_token" ;

	// リクエストメソッド
	$request_method = "POST" ;

	// キーを作成する (URLエンコードする)
	$signature_key = rawurlencode( $api_secret ) . "&" . rawurlencode( $access_token_secret ) ;

	// パラメータ([oauth_signature]を除く)を連想配列で指定
	$params = array(
		"oauth_callback" => $callback_url ,
		"oauth_consumer_key" => $api_key ,
		"oauth_signature_method" => "HMAC-SHA1" ,
		"oauth_timestamp" => time() ,
		"oauth_nonce" => microtime() ,
		"oauth_version" => "1.0" ,
	) ;

	// 各パラメータをURLエンコードする
	foreach( $params as $key => $value ) {
		// コールバックURLはエンコードしない
		if( $key == "oauth_callback" ) {
			continue ;
		}

		// URLエンコード処理
		$params[ $key ] = rawurlencode( $value ) ;
	}

	// 連想配列をアルファベット順に並び替える
	ksort( $params ) ;

	// パラメータの連想配列を[キー=値&キー=値...]の文字列に変換する
	$request_params = http_build_query( $params , "" , "&" ) ;
 
	// 変換した文字列をURLエンコードする
	$request_params = rawurlencode( $request_params ) ;
 
	// リクエストメソッドをURLエンコードする
	$encoded_request_method = rawurlencode( $request_method ) ;
 
	// リクエストURLをURLエンコードする
	$encoded_request_url = rawurlencode( $request_url ) ;
 
	// リクエストメソッド、リクエストURL、パラメータを[&]で繋ぐ
	$signature_data = $encoded_request_method . "&" . $encoded_request_url . "&" . $request_params ;

	// キー[$signature_key]とデータ[$signature_data]を利用して、HMAC-SHA1方式のハッシュ値に変換する
	$hash = hash_hmac( "sha1" , $signature_data , $signature_key , TRUE ) ;

	// base64エンコードして、署名[$signature]が完成する
	$signature = base64_encode( $hash ) ;

	// パラメータの連想配列、[$params]に、作成した署名を加える
	$params["oauth_signature"] = $signature ;

	// パラメータの連想配列を[キー=値,キー=値,...]の文字列に変換する
	$header_params = http_build_query( $params , "" , "," ) ;

	// リクエスト用のコンテキストを作成する
	$context = array(
		"http" => array(
			"method" => $request_method , // リクエストメソッド (POST)
			"header" => array(			  // カスタムヘッダー
				"Authorization: OAuth " . $header_params ,
			) ,
		) ,
	) ;

	// cURLを使ってリクエスト
	$curl = curl_init() ;
	curl_setopt( $curl, CURLOPT_URL , $request_url ) ;	// リクエストURL
	curl_setopt( $curl, CURLOPT_HEADER, true ) ;	// ヘッダーを取得する
	curl_setopt( $curl, CURLOPT_CUSTOMREQUEST , $context["http"]["method"] ) ;	// メソッド
	curl_setopt( $curl, CURLOPT_SSL_VERIFYPEER , false ) ;	// 証明書の検証を行わない
	curl_setopt( $curl, CURLOPT_RETURNTRANSFER , true ) ;	// curl_execの結果を文字列で返す
	curl_setopt( $curl, CURLOPT_HTTPHEADER , $context["http"]["header"] ) ;	// リクエストヘッダーの内容
	curl_setopt( $curl, CURLOPT_TIMEOUT , 5 ) ;	// タイムアウトの秒数
	$res1 = curl_exec( $curl ) ;
	$res2 = curl_getinfo( $curl ) ;
	curl_close( $curl ) ;

	// 取得したデータ
	$response = substr( $res1, $res2["header_size"] ) ;	// 取得したデータ(JSONなど)
	$header = substr( $res1, 0, $res2["header_size"] ) ;	// レスポンスヘッダー (検証に利用したい場合にどうぞ)

	// [cURL]ではなく、[file_get_contents()]を使うには下記の通りです…
	// $response = file_get_contents( $request_url , false , stream_context_create( $context ) ) ;

	// リクエストトークンを取得できなかった場合
	if( !$response ) {
		echo "<p>リクエストトークンを取得できませんでした…。$api_keyと$callback_url、そしてTwitterのアプリケーションに設定しているCallback URLを確認して下さい。</p>" ;
		exit ;
	}

	// $responseの内容(文字列)を$query(配列)に直す
	// aaa=AAA&bbb=BBB → [ "aaa"=>"AAA", "bbb"=>"BBB" ]
	$query = [] ;
	parse_str( $response, $query ) ;

	// セッション[$_SESSION["oauth_token_secret"]]に[oauth_token_secret]を保存する
	session_start() ;
	session_regenerate_id( true ) ;
	$_SESSION["oauth_token_secret"] = $query["oauth_token_secret"] ;

	/*** [手順2] ユーザーを認証画面へ飛ばす ***/

	// ユーザーを認証画面へ飛ばす (毎回ボタンを押す場合)
	header( "Location: https://api.twitter.com/oauth/authorize?oauth_token=" . $query["oauth_token"] ) ;

	// ユーザーを認証画面へ飛ばす (二回目以降は認証画面をスキップする場合)
	// header( "Location: https://api.twitter.com/oauth/authenticate?oauth_token=" . $query["oauth_token"] ) ;
}

ベアラートークンの取得

アクセストークンではなく、ベアラートークンを取得する方法を説明します。

Application-only authentication
Application-only authentication
Twitter Developersの公式ドキュメント。アプリケーション認証についての説明が掲載されています。

ベアラートークンとは?

ベアラートークンという言葉は、なかなか馴染み深くないかもしれません。アクセストークンが「ユーザー認証」なのに対して、ベアラートークンは「アプリケーション認証」です。この違いは、例えば、現実にある「証明書」を想像すると分かりやすいと思います。ここでは「映画チケット」がベアラートークン、「運転免許証」がアクセストークンとしましょう。

映画チケットと運転免許証

映画館のチケットを思い浮かべて下さい。映画館のチケットは、映画を観るために必要です。持っていなければ、映画館に入ることはできません。次に、運転免許証を思い浮かべて下さい。運転免許証は、運転をするために必要です。持っていなければ、運転をすることはできません。

映画チケットと運転免許証、一見、同じチケットのようですが、明確な違いがあります。それは、「他人が利用できるか?」という点です。Aさんが買った映画チケットをBさんが使っても問題はありませんが、Aさんが取得した運転免許証をBさんが使うことはできません。運転免許証には、個人を識別できる効力があるというわけです。対して、映画チケットは、チケット自体があれば、それを使う人が誰でもかまいません。

アクセストークンとベアラートークンの違い

さて、アクセストークン(運転免許証)とベアラートークン(映画チケット)ですが、アクセストークンは「誰が認証したのか」がTwitter側に確認されるので、認証したユーザーのデータにアクセスすることができます。Twitter側からすれば、「本人が運転免許証を出したんだから、その本人の個人情報を渡したり、操作してもいい」というわけです。アクセストークンを用いてリクエストすれば、そのユーザーに代わってツイートを投稿したり、そのユーザーが非公開ユーザーであってもツイートを取得できたりします。

対して、ベアラートークンは「誰が認証したのか」をTwitter側が確認できません。Twitter側からすれば、「映画チケットを見せられても、誰が買った映画チケットなのか分からないから、特定の個人に関する情報は渡せないし操作させられない」ということです。そのため、誰でも見られるパブリックな情報にしかアクセスできません。例えば、ツイートを公開しているユーザーのツイートを取得する、などですね。Aさん、Bさん、Cさん…、誰でも平等にできることしかできないわけです。

お手軽だけど、できることが限られる

例え話が下手で混乱してしまった人はすいません…。要は、「リクエストの度に署名とか作らないで簡単、お手軽に使えるんだけど、できることが限られてしまう」のがベアラートークンだと考えて下さい。ベアラートークンでは、POSTメソッドのリクエスト全般が利用できません。APIを通して、ツイートを投稿したり、他人をフォローしたりする必要がある場合は、アクセストークンを利用しましょう。

ベアラートークンの取得

ベアラートークンを取得していきましょう。お手軽で拍子抜けしてしまうかもしれません。

リクエスト方法

下記のURLに、POSTメソッドでリクエストを送ります。

https://api.twitter.com/oauth2/token

クレデンシャルの作成

ベアラートークンを取得するには、APIキーとAPIシークレットが必要です。コロン(:)を区切り文字にして、APIキーとAPIシークレットを繋げて下さい。

{APIキー}:{APIシークレット}

そして、できた文字列をbase64エンコードします。PHPだと次のようになります。

PHP

<?php
// 設定項目
$api_key = "" ;	// APIキー
$api_secret = "" ;	// APIシークレット

// クレデンシャルを作成
$credential = base64_encode( $api_key . ":" . $api_secret ) ;

ヘッダーの作成

先ほど作成した文字列を、ヘッダーのAuthorizationという項目に、Basicを付けて指定します。

Authorization: Basic {クレデンシャル}

加えて、次のヘッダーも追加して下さい。

Content-Type: application/x-www-form-urlencoded;charset=UTF-8

ボディの作成

また、POSTフィールドには、grant_typeを指定します。

grant_type=client_credentials

リクエストを送る

準備ができたら、リクエストを送ってみましょう。次のようにプログラミングしてみました。cURLを利用しています。

PHP

// リクエストURL
$request_url = "https://api.twitter.com/oauth2/token" ;

// リクエスト用のコンテキストを作成する
$context = array(
	"http" => array(
		"method" => "POST" , // リクエストメソッド
		"header" => array(			  // ヘッダー
			"Authorization: Basic " . $credential ,
			"Content-Type: application/x-www-form-urlencoded;charset=UTF-8" ,
		) ,
		"content" => http_build_query(	// ボディ
			array(
				"grant_type" => "client_credentials" ,
			)
		) ,
	) ,
) ;

// cURLを使ってリクエスト
$curl = curl_init() ;
curl_setopt( $curl, CURLOPT_URL , $request_url ) ;	// リクエストURL
curl_setopt( $curl, CURLOPT_HEADER, true ) ;	// ヘッダーを取得する 
curl_setopt( $curl, CURLOPT_CUSTOMREQUEST , $context["http"]["method"] ) ;	// メソッド
curl_setopt( $curl, CURLOPT_SSL_VERIFYPEER , false ) ;	// 証明書の検証を行わない
curl_setopt( $curl, CURLOPT_RETURNTRANSFER , true ) ;	// curl_execの結果を文字列で返す
curl_setopt( $curl, CURLOPT_HTTPHEADER , $context["http"]["header"] ) ;	// ヘッダー
curl_setopt( $curl, CURLOPT_POSTFIELDS , $context["http"]["content"] ) ;	// リクエストボディ
curl_setopt( $curl, CURLOPT_TIMEOUT , 5 ) ;	// タイムアウトの秒数
$res1 = curl_exec( $curl ) ;
$res2 = curl_getinfo( $curl ) ;
curl_close( $curl ) ;

// 取得したデータ
$response = substr( $res1, $res2["header_size"] ) ;	// 取得したデータ(JSONなど)
$header = substr( $res1, 0, $res2["header_size"] ) ;	// レスポンスヘッダー (検証に利用したい場合にどうぞ)

// [cURL]ではなく、[file_get_contents()]を使うには下記の通りです…
// $response = file_get_contents( $request_url , false , stream_context_create( $context ) ) ;

取得できるJSON

リクエストに成功すると、下記内容のJSONを取得することができます。access_tokenの値が、求めているベアラートークンです。

JSON

{"token_type":"bearer","access_token":"AAAAAAAAAAAAAAAAAAAALbagwAAAAAA4Cj2nDhfUcC%2VceMMosEkn1cloxs%3DrDxvakqv2H3NGGxz27AAwYl21gXtDGnAX0gySpGkornNeJnxjz"}

サンプルプログラム

これまでの説明を踏まえた、ベアラートークンを取得するサンプルプログラムを用意しました。APIキーとAPIシークレットをセットして、起動してみて下さいね。

PHP (bearer_token.php)

<?php
// 設定項目
$api_key = "" ;	// APIキー
$api_secret = "" ;	// APIシークレット

// クレデンシャルを作成
$credential = base64_encode( $api_key . ":" . $api_secret ) ;

// リクエストURL
$request_url = "https://api.twitter.com/oauth2/token" ;

// リクエスト用のコンテキストを作成する
$context = array(
	"http" => array(
		"method" => "POST" , // リクエストメソッド
		"header" => array(			  // ヘッダー
			"Authorization: Basic " . $credential ,
			"Content-Type: application/x-www-form-urlencoded;charset=UTF-8" ,
		) ,
		"content" => http_build_query(	// ボディ
			array(
				"grant_type" => "client_credentials" ,
			)
		) ,
	) ,
) ;

// cURLを使ってリクエスト
$curl = curl_init() ;
curl_setopt( $curl, CURLOPT_URL , $request_url ) ;	// リクエストURL
curl_setopt( $curl, CURLOPT_HEADER, true ) ;	// ヘッダーを取得する 
curl_setopt( $curl, CURLOPT_CUSTOMREQUEST , $context["http"]["method"] ) ;	// メソッド
curl_setopt( $curl, CURLOPT_SSL_VERIFYPEER , false ) ;	// 証明書の検証を行わない
curl_setopt( $curl, CURLOPT_RETURNTRANSFER , true ) ;	// curl_execの結果を文字列で返す
curl_setopt( $curl, CURLOPT_HTTPHEADER , $context["http"]["header"] ) ;	// ヘッダー
curl_setopt( $curl, CURLOPT_POSTFIELDS , $context["http"]["content"] ) ;	// リクエストボディ
curl_setopt( $curl, CURLOPT_TIMEOUT , 5 ) ;	// タイムアウトの秒数
$res1 = curl_exec( $curl ) ;
$res2 = curl_getinfo( $curl ) ;
curl_close( $curl ) ;

// 取得したデータ
$response = substr( $res1, $res2["header_size"] ) ;	// 取得したデータ(JSONなど)
$header = substr( $res1, 0, $res2["header_size"] ) ;	// レスポンスヘッダー (検証に利用したい場合にどうぞ)

// [cURL]ではなく、[file_get_contents()]を使うには下記の通りです…
// $response = file_get_contents( $request_url , false , stream_context_create( $context ) ) ;

// JSONを配列に変換する
$arr = json_decode( $response, true ) ;

// 配列の内容を出力する (本番では不要)
echo '<p>下記の認証情報を取得しました。(<a href="' . explode( "?", $_SERVER["REQUEST_URI"] )[0] . '">もう1回やってみる</a>)</p>' ;

foreach ( $arr as $key => $value ) {
	echo "<b>" . $key . "</b>: " . $value . "<BR>" ;
}

データの取得 (GETメソッド)

ここからは、これまでに取得したAPIキー、APIシークレット、アクセストークン(またはベアラートークン)を使って、リクエストする方法を説明していきます。3種類のリクエスト方法を覚えておけば、ほぼ全てのAPIを利用できます。まずは、GETメソッドによるリクエスト方法を説明します。GETメソッドは主に「情報の取得」に利用します。

ツイートを取得してみよう

なんでもいいのですが、試しにツイートを取得してみましょう。まずはリクエストの条件を整理しておきます。下記のURLに、GETメソッドでリクエストを送ります。

https://api.twitter.com/1.1/statuses/user_timeline.json

また、オプションとして、下記パラメータを指定します。

screen_name
スクリーンネーム。
count
取得件数。

ベアラートークンの場合

ベアラートークンを使ったリクエスト方法を説明します。ここで注意点なのですが、取得する対象のユーザーが非公開ユーザーの場合、ベアラートークンでは取得できません。先ほどの運転免許証と映画チケットの例を思い出して下さい。映画チケットのベアラートークンでは、あなたがその非公開ユーザーのフォロワーであることを、Twitter側が確認できないからです。

パラメータの付与

GETメソッドの場合、リクエストURLに、パラメータを付けます。

https://api.twitter.com/1.1/statuses/user_timeline.json?screen_name=arayutw&count=10

ヘッダーの作成

ベアラートークンでリクエストするには、ヘッダーのAuthorizationという項目に、Bearerと一緒にベアラートークンを付けて下さい。やることはこれだけです。

Authorization: Bearer {ベアラートークン}

サンプルプログラム

以上を考慮したサンプルプログラムが下記です。試してみて下さいね。JSONを取得できれば成功です。このJSONを変換して、ツイートを表示をしたりできます。

PHP (get-oauth2.php)

<?php
/**************************************************

	GETメソッドのリクエスト [ベアラートークン]

**************************************************/

// 設定
$bearer_token = "" ;	// ベアラートークン
$request_url = 'https://api.twitter.com/1.1/statuses/user_timeline.json' ;	// リクエストURL

// パラメータ
$params = array(
	'screen_name' => '@arayutw' ,
	'count' => 10 ,
) ;

// パラメータがある場合
if ( $params ) {
	$request_url .= '?' . http_build_query( $params ) ;
}

// リクエスト用のコンテキスト
$context = array(
	'http' => array(
		'method' => 'GET' , // リクエストメソッド
		'header' => array(			  // ヘッダー
			'Authorization: Bearer ' . $bearer_token ,
		) ,
	) ,
) ;

// cURLを使ってリクエスト
$curl = curl_init() ;
curl_setopt( $curl, CURLOPT_URL, $request_url ) ;	// リクエストURL
curl_setopt( $curl, CURLOPT_HEADER, true ) ;	// ヘッダーを取得する
curl_setopt( $curl, CURLOPT_CUSTOMREQUEST, $context['http']['method'] ) ;	// メソッド
curl_setopt( $curl, CURLOPT_SSL_VERIFYPEER, false ) ;	// 証明書の検証を行わない
curl_setopt( $curl, CURLOPT_RETURNTRANSFER, true ) ;	// curl_execの結果を文字列で返す
curl_setopt( $curl, CURLOPT_HTTPHEADER, $context['http']['header'] ) ;	// ヘッダー
curl_setopt( $curl, CURLOPT_TIMEOUT, 5 ) ;	// タイムアウトの秒数
$res1 = curl_exec( $curl ) ;
$res2 = curl_getinfo( $curl ) ;
curl_close( $curl ) ;

// 取得したデータ
$json = substr( $res1, $res2['header_size'] ) ;	// 取得したデータ(JSONなど)
$header = substr( $res1, 0, $res2['header_size'] ) ;	// レスポンスヘッダー (検証に利用したい場合にどうぞ)

// [cURL]ではなく、[file_get_contents()]を使うには下記の通りです…
// $json = @file_get_contents( $request_url , false , stream_context_create( $context ) ) ;

// JSONを変換
// $obj = json_decode( $json ) ;	// オブジェクトに変換
// $arr = json_decode( $json, true ) ;	// 配列に変換

// HTML用
$html = '' ;

// 検証用にレスポンスヘッダーを出力 [本番環境では不要]
$html .= '<h2>取得したデータ</h2>' ;
$html .= '<p>下記のデータを取得できました。</p>' ;
$html .= 	'<h3>ボディ(JSON)</h3>' ;
$html .= 	'<p><textarea rows="8">' . $json . '</textarea></p>' ;
$html .= 	'<h3>レスポンスヘッダー</h3>' ;
$html .= 	'<p><textarea rows="8">' . $header . '</textarea></p>' ;

// HTMLを出力
echo $html ;

デモを開く

アクセストークンの場合

アクセストークンでGETメソッドのリクエストを送ってみましょう。アクセストークンの場合、ユーザーとして認証するので、非公開ユーザーのツイートを本人、またはフォロワーの場合に取得できるなど、ベアラートークンと比べてより多くの情報を取得できます。ただし、OAuth1.0方式の、署名を用いた認証が必要です。

パラメータの付与

GETメソッドの場合、リクエストURLに、パラメータを付けます。この点はベアラートークンの場合と同じです。ここに付けるのは、オプションとなるパラメータのみで、署名用のパラメータは含みません。

https://api.twitter.com/1.1/statuses/user_timeline.json?screen_name=arayutw&count=10

署名の作成

さぁ、悪夢の再来です。署名を作らなければいけません。署名の材料には、オプションとして指定したcountscreen_nameも含む点にご注意下さい。オプションとなるパラメータが増えればその分、材料も増えます。oauth_callbackは不要です。

oauth_consumer_key
アプリケーション作成時に取得したAPI Key。
oauth_token
取得したアクセストークン。
oauth_signature_method
署名の種類を指定。HMAC-SHA1を指定すればいい。
oauth_signature
作成した署名を指定する。
oauth_timestamp
リクエストを送る際のUNIX TIMESTAMPの値を指定する。具体的には、PHPでtime()の値をそのまま指定すればいい。
oauth_nonce
任意で用意したランダムな文字列を指定する。PHPなら、microtime()の値をそのまま指定すればいい。
oauth_version
認証に利用する規格であるOAuthのバージョンを指定する。1.0を指定すればいい。
count
オプションとして指定したcount
screen_name
オプションとして指定したscreen_name

ヘッダーの作成

署名を含めたAuthorizationの指定が必要です。

Authorization: OAuth count=10,oauth_consumer_key={APIキー},oauth_nonce=0.09787400+1439033304,oauth_signature_method=HMAC-SHA1,oauth_timestamp=1439033304,oauth_token={アクセストークン},oauth_version=1.0,screen_name=%40arayutw,oauth_signature={作成した署名}

サンプルプログラム

アクセストークンを用いたGETメソッドのリクエストのサンプルプログラムが下記です。署名の作成方法などは「アクセストークンの取得」の章で説明したので割愛します。デモでは、あなたのユーザーアカウントを利用してデータを取得します。

PHP (get-oauth1.php)

<?php
/**************************************************

	GETメソッドのリクエスト [アクセストークン]

**************************************************/

// 設定
$api_key = "" ;	// APIキー
$api_secret = "" ;	// APIシークレット
$access_token = "" ;	// アクセストークン
$access_token_secret = "" ;	// アクセストークンシークレット
$request_url = 'https://api.twitter.com/1.1/statuses/user_timeline.json' ;	// エンドポイント
$request_method = 'GET' ;

// パラメータA (リクエストのオプション)
$params_a = array(
	'screen_name' => '@arayutw' ,
	'count' => 10 ,
) ;

// キーを作成する (URLエンコードする)
$signature_key = rawurlencode( $api_secret ) . '&' . rawurlencode( $access_token_secret ) ;

// パラメータB (署名の材料用)
$params_b = array(
	'oauth_token' => $access_token ,
	'oauth_consumer_key' => $api_key ,
	'oauth_signature_method' => 'HMAC-SHA1' ,
	'oauth_timestamp' => time() ,
	'oauth_nonce' => microtime() ,
	'oauth_version' => '1.0' ,
) ;

// パラメータAとパラメータBを合成してパラメータCを作る
$params_c = array_merge( $params_a , $params_b ) ;

// 連想配列をアルファベット順に並び替える
ksort( $params_c ) ;

// パラメータの連想配列を[キー=値&キー=値...]の文字列に変換する
$request_params = http_build_query( $params_c , '' , '&' ) ;

// 一部の文字列をフォロー
$request_params = str_replace( array( '+' , '%7E' ) , array( '%20' , '~' ) , $request_params ) ;

// 変換した文字列をURLエンコードする
$request_params = rawurlencode( $request_params ) ;

// リクエストメソッドをURLエンコードする
// ここでは、URL末尾の[?]以下は付けないこと
$encoded_request_method = rawurlencode( $request_method ) ;
 
// リクエストURLをURLエンコードする
$encoded_request_url = rawurlencode( $request_url ) ;
 
// リクエストメソッド、リクエストURL、パラメータを[&]で繋ぐ
$signature_data = $encoded_request_method . '&' . $encoded_request_url . '&' . $request_params ;

// キー[$signature_key]とデータ[$signature_data]を利用して、HMAC-SHA1方式のハッシュ値に変換する
$hash = hash_hmac( 'sha1' , $signature_data , $signature_key , TRUE ) ;

// base64エンコードして、署名[$signature]が完成する
$signature = base64_encode( $hash ) ;

// パラメータの連想配列、[$params]に、作成した署名を加える
$params_c['oauth_signature'] = $signature ;

// パラメータの連想配列を[キー=値,キー=値,...]の文字列に変換する
$header_params = http_build_query( $params_c , '' , ',' ) ;

// リクエスト用のコンテキスト
$context = array(
	'http' => array(
		'method' => $request_method , // リクエストメソッド
		'header' => array(			  // ヘッダー
			'Authorization: OAuth ' . $header_params ,
		) ,
	) ,
) ;

// パラメータがある場合、URLの末尾に追加
if( $params_a ) {
	$request_url .= '?' . http_build_query( $params_a ) ;
}

// cURLを使ってリクエスト
$curl = curl_init() ;
curl_setopt( $curl, CURLOPT_URL , $request_url ) ;	// リクエストURL
curl_setopt( $curl, CURLOPT_HEADER, true ) ; 	// ヘッダーを取得
curl_setopt( $curl, CURLOPT_CUSTOMREQUEST , $context['http']['method'] ) ;	// メソッド
curl_setopt( $curl, CURLOPT_SSL_VERIFYPEER , false ) ;	// 証明書の検証を行わない
curl_setopt( $curl, CURLOPT_RETURNTRANSFER , true ) ;	// curl_execの結果を文字列で返す
curl_setopt( $curl, CURLOPT_HTTPHEADER , $context['http']['header'] ) ;	// ヘッダー
curl_setopt( $curl, CURLOPT_TIMEOUT , 5 ) ;	// タイムアウトの秒数
$res1 = curl_exec( $curl ) ;
$res2 = curl_getinfo( $curl ) ;
curl_close( $curl ) ;

// 取得したデータ
$json = substr( $res1, $res2['header_size'] ) ;	// 取得したデータ(JSONなど)
$header = substr( $res1, 0, $res2['header_size'] ) ;	// レスポンスヘッダー (検証に利用したい場合にどうぞ)

// [cURL]ではなく、[file_get_contents()]を使うには下記の通りです…
// $json = @file_get_contents( $request_url , false , stream_context_create( $context ) ) ;

// JSONを変換
// $obj = json_decode( $json ) ;	// オブジェクトに変換
// $arr = json_decode( $json, true ) ;	// 配列に変換

// HTML用
$html = '' ;

// 検証用にレスポンスヘッダーを出力 [本番環境では不要]
$html .= '<h2>取得したデータ</h2>' ;
$html .= '<p>下記のデータを取得できました。</p>' ;
$html .= 	'<h3>ボディ(JSON)</h3>' ;
$html .= 	'<p><textarea rows="8">' . $json . '</textarea></p>' ;
$html .= 	'<h3>レスポンスヘッダー</h3>' ;
$html .= 	'<p><textarea rows="8">' . $header . '</textarea></p>' ;

// アプリケーション連携の解除
$html .= '<h2 style="color:red">アプリケーション連携の解除</h2>' ;
$html .= '<p>このアプリケーションとの連携を解除するには、下記ページより、行なって下さい。</p>' ;
$html .= '<p><a href="https://twitter.com/settings/applications" target="_blank">https://twitter.com/settings/applications</a></p>' ;

// HTMLを出力
echo $html ;

デモを開く

データの更新 (POSTメソッド)

次はPOSTメソッドのリクエストに挑戦してみましょう。GETメソッドの「情報の取得」に対して、POSTメソッドは主に「情報の更新」をするためのメソッドです。ユーザーデータを操作するため、ユーザー認証を経ないベアラートークンでは利用できません。

ツイートを投稿してみよう

それではPOSTメソッドで最もメジャーな「ツイートの投稿」をしてみましょう。ツイートを投稿するには、下記のエンドポイントに、POSTメソッドでリクエストを送ります。

https://api.twitter.com/1.1/statuses/update.json

このエンドポイントには色々なオプションがありますが、とりあえずはstatusのオプションだけを付けましょう。

status
ツイート本文。
media_ids
メディアID。複数指定するには、カンマ(,)で区切る。ツイートに画像を添付するには、その画像のメディアIDをここで指定する必要がある。この章では使いません。

アクセストークンの場合

アクセストークンを使ってリクエストをする手順です。基本的な部分はGETメソッドの時と変わりません。

パラメータの付与

POSTメソッドの場合、リクエストURLの末尾にはパラメータを付けません。

https://api.twitter.com/1.1/statuses/update.json

代わりに、リクエストボディに指定します。

status=APIを通して投稿してみました。投稿元→https://syncer.jp/twitter-api-matome

署名の作成

署名の作成方法は、GETメソッドの時と同じです。指定したオプションを材料に加えることを意識して下さい。

oauth_consumer_key
アプリケーション作成時に取得したAPI Key。
oauth_token
取得したアクセストークン。
oauth_signature_method
署名の種類を指定。HMAC-SHA1を指定すればいい。
oauth_signature
作成した署名を指定する。
oauth_timestamp
リクエストを送る際のUNIX TIMESTAMPの値を指定する。具体的には、PHPでtime()の値をそのまま指定すればいい。
oauth_nonce
任意で用意したランダムな文字列を指定する。PHPなら、microtime()の値をそのまま指定すればいい。
oauth_version
認証に利用する規格であるOAuthのバージョンを指定する。1.0を指定すればいい。
status
オプションとして指定したstatus

ヘッダーの作成

リクエストトークンやアクセストークンの時と同様に、署名を含めたAuthorizationの指定が必要です。ツイート本文はURLエンコードしています。

Authorization: OAuth oauth_consumer_key={APIキー},oauth_nonce=0.42393700+1439044803,oauth_signature_method=HMAC-SHA1,oauth_timestamp=1439044803,oauth_token={アクセストークン},oauth_version=1.0,status=API%E3%82%92%E9%80%9A%E3%81%97%E3%81%A6%E6%8A%95%E7%A8%BF%E3%81%97%E3%81%A6%E3%81%BF%E3%81%BE%E3%81%97%E3%81%9F%E3%80%82%E6%8A%95%E7%A8%BF%E5%85%83%E2%86%92https%3A%2F%2Fsyncer.jp%2Ftwitter-api-matome,oauth_signature={作成した署名}

サンプルプログラム

アクセストークンを用いたGETメソッドのリクエストのサンプルプログラムが下記です。署名の作成方法などは「アクセストークンの取得」の章で説明したので割愛します。なお、投稿するにはアプリケーションに「書込権限のパーミッション」が必要です。デモでは、あなたのユーザーアカウントを利用して実際に、このツイートと同じ内容を投稿します。ご利用後は、お手数ですが投稿されたツイートを削除して下さい。

PHP (post-oauth1.php)

<?php
/**************************************************

	POSTメソッドのリクエスト [アクセストークン]

**************************************************/

// 設定
$api_key = '' ;		// APIキー
$api_secret = '' ;		// APIシークレット
$access_token = '' ;		// アクセストークン
$access_token_secret = '' ;		// アクセストークンシークレット[_TWITTER_OAUTH_1_]
$request_url = 'https://api.twitter.com/1.1/statuses/update.json' ;		// エンドポイント
$request_method = 'POST' ;

// パラメータA (リクエストのオプション)
$params_a = array(
	'status' => 'APIを通して投稿してみました。' . "\n\n" . '投稿時間: ' . date( 'Y/m/d H:i' ) . "\n" . '投稿元: https://syncer.jp/Web/API/Twitter/Rest_API/' ,
//	'media_ids' => "" ,	// 添付する画像のメディアID
) ;

// キーを作成する (URLエンコードする)
$signature_key = rawurlencode( $api_secret ) . '&' . rawurlencode( $access_token_secret ) ;

// パラメータB (署名の材料用)
$params_b = array(
	'oauth_token' => $access_token ,
	'oauth_consumer_key' => $api_key ,
	'oauth_signature_method' => 'HMAC-SHA1' ,
	'oauth_timestamp' => time() ,
	'oauth_nonce' => microtime() ,
	'oauth_version' => '1.0' ,
) ;

// パラメータAとパラメータBを合成してパラメータCを作る
$params_c = array_merge( $params_a , $params_b ) ;

// 連想配列をアルファベット順に並び替える
ksort( $params_c ) ;

// パラメータの連想配列を[キー=値&キー=値...]の文字列に変換する
$request_params = http_build_query( $params_c , '' , '&' ) ;

// 一部の文字列をフォロー
$request_params = str_replace( array( '+' , '%7E' ) , array( '%20' , '~' ) , $request_params ) ;

// 変換した文字列をURLエンコードする
$request_params = rawurlencode( $request_params ) ;

// リクエストメソッドをURLエンコードする
// ここでは、URL末尾の[?]以下は付けないこと
$encoded_request_method = rawurlencode( $request_method ) ;
 
// リクエストURLをURLエンコードする
$encoded_request_url = rawurlencode( $request_url ) ;
 
// リクエストメソッド、リクエストURL、パラメータを[&]で繋ぐ
$signature_data = $encoded_request_method . '&' . $encoded_request_url . '&' . $request_params ;

// キー[$signature_key]とデータ[$signature_data]を利用して、HMAC-SHA1方式のハッシュ値に変換する
$hash = hash_hmac( 'sha1' , $signature_data , $signature_key , TRUE ) ;

// base64エンコードして、署名[$signature]が完成する
$signature = base64_encode( $hash ) ;

// パラメータの連想配列、[$params]に、作成した署名を加える
$params_c['oauth_signature'] = $signature ;

// パラメータの連想配列を[キー=値,キー=値,...]の文字列に変換する
$header_params = http_build_query( $params_c , '' , ',' ) ;

// リクエスト用のコンテキスト
$context = array(
	'http' => array(
		'method' => $request_method , // リクエストメソッド
		'header' => array(			  // ヘッダー
			'Authorization: OAuth ' . $header_params ,
		) ,
	) ,
) ;

// オプションがある場合、コンテキストにPOSTフィールドを作成する
if ( $params_a ) {
	$context['http']['content'] = http_build_query( $params_a ) ;
}

// cURLを使ってリクエスト
$curl = curl_init() ;
curl_setopt( $curl, CURLOPT_URL , $request_url ) ;	// リクエストURL
curl_setopt( $curl, CURLOPT_HEADER, true ) ;	// ヘッダーを取得
curl_setopt( $curl, CURLOPT_CUSTOMREQUEST, $context['http']['method'] ) ;	// メソッド
curl_setopt( $curl, CURLOPT_SSL_VERIFYPEER, false ) ;	// 証明書の検証を行わない
curl_setopt( $curl, CURLOPT_RETURNTRANSFER, true ) ;	// curl_execの結果を文字列で返す
curl_setopt( $curl, CURLOPT_HTTPHEADER, $context['http']['header'] ) ;	// ヘッダー
if( isset( $context['http']['content'] ) && !empty( $context['http']['content'] ) ) {
	curl_setopt( $curl, CURLOPT_POSTFIELDS, $context['http']['content'] ) ;	// リクエストボディ
}
curl_setopt( $curl, CURLOPT_TIMEOUT, 5 ) ;	// タイムアウトの秒数
$res1 = curl_exec( $curl ) ;
$res2 = curl_getinfo( $curl ) ;
curl_close( $curl ) ;

// 取得したデータ
$json = substr( $res1, $res2['header_size'] ) ;	// 取得したデータ(JSONなど)
$header = substr( $res1, 0, $res2['header_size'] ) ;	// レスポンスヘッダー (検証に利用したい場合にどうぞ)

// [cURL]ではなく、[file_get_contents()]を使うには下記の通りです…
// $json = @file_get_contents( $request_url , false , stream_context_create( $context ) ) ;

// JSONを変換
// $obj = json_decode( $json ) ;	// オブジェクトに変換
// $arr = json_decode( $json, true ) ;	// 配列に変換

// HTML用
$html = '' ;

// 検証用にレスポンスヘッダーを出力 [本番環境では不要]
$html .= '<h2>取得したデータ</h2>' ;
$html .= '<p>下記のデータを取得できました。実際に更新されているかを、Twitterのアカウントで確認して下さい。</p>' ;
$html .= 	'<h3>ボディ(JSON)</h3>' ;
$html .= 	'<p><textarea rows="8">' . $json . '</textarea></p>' ;
$html .= 	'<h3>レスポンスヘッダー</h3>' ;
$html .= 	'<p><textarea rows="8">' . $header . '</textarea></p>' ;

// アプリケーション連携の解除
$html .= '<h2 style="color:red">アプリケーション連携の解除</h2>' ;
$html .= '<p>このアプリケーションとの連携を解除するには、下記ページより、行なって下さい。</p>' ;
$html .= '<p><a href="https://twitter.com/settings/applications" target="_blank">https://twitter.com/settings/applications</a></p>' ;

// HTMLの出力
echo $html ;

デモを開く

メディアアップロード (POSTメソッド)

取得(GET)と更新(POST)を使えるようになれば、9割のエンドポイントを利用できます。残る1つはメディアアップロード、すなわち、画像や動画の投稿です。こちらは、multipart POSTという形式をとり、POSTメソッドのリクエストなんですが、その内容は前章とは全く違います。

画像をアップロードしてみよう

それでは、お手軽に、画像を投稿してみましょう。画像を投稿するには、下記のエンドポイントにPOSTメソッドでリクエストを送ります。

https://upload.twitter.com/1.1/media/upload.json

オプションには、画像データを示すmedia_dataを指定します。

media_data
base64エンコードをした画像のデータ。

画像をbase64エンコードする

画像を投稿するのに、base64エンコードをして文字列化します。文字列化という表現が正確かは分かりませんが、ニュアンスは伝わると思います。例えば次の画像を投稿するとしましょう。

SYNCERのロゴ
SYNCERのロゴ

このファイル名がsyncer.jpgだとして、PHPでは、base64_encode()という関数を使って、画像に変換することができます。

PHP

// [syncer.jpg]をbase64エンコード
$image = base64_encode( @file_get_contents( "./syncer.jpg" ) ) ;

参考までに上記の画像をbase64エンコードをすると次のようなデータに変換されます。文字数が多過ぎるので途中を省略しています。

/9j/4AAQSkZJRgA...eOVTLia9T/9k=

バウンダリーの定義

各データを区切るための文字列をバウンダリーといい、リクエストの際にこのバウンダリーを定義します。一般的には次のように定義します。

------------------------1ae47d990b354d1b00a4eea60e6b5b72

末尾のランダムな文字列を作るには、mt_rand()の関数などを使うといいでしょう。

PHP

// バウンダリーを定義
$boundary = "---------------" . md5( mt_rand() ) ;

リクエストボディの作成

ここが一番面倒くさいのですが、張り切っていきましょう。バウンダリーでデータを区切りながら、リクエストボディを作成していきます。なお、ここでは次の文字列をバウンダリーとして定義したと仮定します。sで始まって、5で終わっているのだけ覚えておいて下さい。

s-y-n-c-e-r---------------d9aa2a5566fbaee2d2522514c321fce5

区切り文字

区切り文字は、定義したバウンダリーの先頭にハイフン2つ(--)を付けるというルールになっています。区切り文字の後には、1つの改行(\r\n)を挟んで下さい。

--{バウンダリー}

サンプルのバウンダリーをあてはめると、次の通りです。

--s-y-n-c-e-r---------------d9aa2a5566fbaee2d2522514c321fce5

データ内容の定義

続いては、どのようなデータを送信するのかという情報を加えていきます。まず、オプションの内容を振り返ってみましょう。次の通りでしたね。

media_data
base64エンコードをした画像のデータ。

キーと値は次のように指定して下さい。改行の数を守って下さいね。

{区切り文字}\r\nContent-Disposition: form-data; name="{キー}"; \r\n\r\n{値}\r\n

これに実際のデータをあてはめると次のようになります。

--s-y-n-c-e-r---------------d9aa2a5566fbaee2d2522514c321fce5\r\nContent-Disposition: form-data; name="media_data"; \r\n\r\n/9j/4AAQSkZJRgA...eOVTLia9T/9k=\r\n

仮に複数のキーと値のペアがある場合は、同じパターンで繰り返すだけでOKです。

{区切り文字}\r\nContent-Disposition: form-data; name="{キー1}"; \r\n\r\n{値1}\r\n{区切り文字}\r\nContent-Disposition: form-data; name="{キー2}"; \r\n\r\n{値2}\r\n{区切り文字}\r\nContent-Disposition: form-data; name="{キー3}"; \r\n\r\n{値3}\r\n...

ボディのフッター

最後に、リクエストボディにフッターを付けます。定義したバウンダリーの先頭と末尾にそれぞれハイフン2つ(--)を付けて、さらに改行を2つ(\r\n\r\n)付けて下さい。

--{バウンダリー}--\r\n\r\n

完成したリクエストボディ

次が、ルールに則って完成したリクエストボディです。

--s-y-n-c-e-r---------------d9aa2a5566fbaee2d2522514c321fce5\r\nContent-Disposition: form-data; name="media_data"; \r\n\r\n/9j/4AAQSkZJRgA...eOVTLia9T/9k=\r\n--s-y-n-c-e-r---------------d9aa2a5566fbaee2d2522514c321fce5--\r\n\r\n

なお、画像データにはContent-Type、Content-Transfer-Encoding、filenameなどを指定するのが通常ですが、Twitterの場合、それらを省略しても受け入れてくれるので、ここでは省略してしまっています。

署名の作成

メディアアップロードの際にも、もちろん署名が必要です。署名の材料にご注意下さい。というのもmultipart POSTの場合、オプションパラメータ(この例ではmedia_data)は署名の材料に加えません。

oauth_consumer_key
アプリケーション作成時に取得したAPI Key。
oauth_token
取得したアクセストークン。
oauth_signature_method
署名の種類を指定。HMAC-SHA1を指定すればいい。
oauth_signature
作成した署名を指定する。
oauth_timestamp
リクエストを送る際のUNIX TIMESTAMPの値を指定する。具体的には、PHPでtime()の値をそのまま指定すればいい。
oauth_nonce
任意で用意したランダムな文字列を指定する。PHPなら、microtime()の値をそのまま指定すればいい。
oauth_version
認証に利用する規格であるOAuthのバージョンを指定する。1.0を指定すればいい。

ヘッダーの作成

最後にヘッダーを作成します。従来の、署名を含めたヘッダーは変わりません。繰り返しになりますが、署名の材料から外したオプションパラメータのデータはここには含まれません。

Authorization: OAuth oauth_consumer_key=[APIキー],oauth_nonce=0.34590000+1439080710,oauth_signature_method=HMAC-SHA1,oauth_timestamp=1439080710,oauth_token=[アクセストークン],oauth_version=1.0,oauth_signature=[作成した署名]

また、次のヘッダーを加えて下さい。

Content-Type: multipart/form-data; boundary={定義したバウンダリー}

実際の値をあてはめると、次の通りとなります。

Content-Type: multipart/form-data; boundary=s-y-n-c-e-r---------------d9aa2a5566fbaee2d2522514c321fce5

送信方法のまとめ

multipart POSTと、通常のPOSTメソッドとの違いは次の2点です。ルールさえ意識すれば、すぐに慣れると思います。

  • リクエストボディを作成する。
  • 署名の材料に、オプションパラメータは含めない。
  • ヘッダーを2種類(AuthorizationContent-Type)、指定する。

サンプルプログラム

これまでの説明を踏まえた、メディアファイルをアップロードするサンプルプログラムを用意しました。ここでは画像をアップロードするだけで、ツイートは投稿されません。アップロードして取得できるメディアID、これを別途、ツイートを投稿する時にパラメータに指定することで画像付きのツイートを投稿できるというわけです。利用するには、アプリケーションに「書込権限のパーミッション」が必要です。

PHP (multipart-post-oauth1.php)

<?php
/**************************************************

	メディアアップロード

	// 下記のエンドポイントに対応
	https://api.twitter.com/1.1/account/update_profile_background_image.json	(背景画像)
	https://api.twitter.com/1.1/account/update_profile_image.json	(アイコン画像)
	https://api.twitter.com/1.1/account/update_profile_banner.json	(バナー画像)
	https://upload.twitter.com/1.1/media/upload.json	(画像、動画のメディアアップロード)

**************************************************/

// 設定
$api_key = '' ;		// APIキー
$api_secret = '' ;		// APIシークレット
$access_token = '' ;		// アクセストークン
$access_token_secret = '' ;		// アクセストークンシークレット[_TWITTER_OAUTH_2_]
$request_url = 'https://upload.twitter.com/1.1/media/upload.json' ;		// エンドポイント
$request_method = 'POST' ;

// パラメータA (リクエストのオプション)
$params_a = array(
	'media_data' => base64_encode( @file_get_contents( './image.png' ) ) ,
) ;

// キーを作成する (URLエンコードする)
$signature_key = rawurlencode( $api_secret ) . '&' . rawurlencode( $access_token_secret ) ;

// パラメータB (署名の材料用)
$params_b = array(
	'oauth_token' => $access_token ,
	'oauth_consumer_key' => $api_key ,
	'oauth_signature_method' => 'HMAC-SHA1' ,
	'oauth_timestamp' => time() ,
	'oauth_nonce' => microtime() ,
	'oauth_version' => '1.0' ,
) ;

// リクエストURLにより、メディアを指定するパラメータが違う
switch ( $request_url ) {
	case( 'https://api.twitter.com/1.1/account/update_profile_background_image.json' ) :
	case( 'https://api.twitter.com/1.1/account/update_profile_image.json' ) :
		$media_param = 'image' ;
	break ;

	case( 'https://api.twitter.com/1.1/account/update_profile_banner.json' ) :
		$media_param = 'banner' ;
	break ;

	case( 'https://upload.twitter.com/1.1/media/upload.json' ) :
		$media_param = ( isset($params_a['media']) && !empty($params_a['media']) ) ? 'media' : 'media_data' ;
	break ;
}

// イメージデータの取得
$media_data = ( isset( $params_a[ $media_param ] ) ) ? $params_a[ $media_param ] : '' ;

// 署名の材料から、動画データを除外する
if( isset( $params_a[ $media_param ] ) ) unset( $params_a[ $media_param ] ) ;

// バウンダリーの定義
$boundary = 's-y-n-c-e-r---------------' . md5( mt_rand() ) ;

// POSTフィールドの作成 (まずはメディアのパラメータ)
$request_body = '' ;
$request_body .= '--' . $boundary . "\r\n" ;
$request_body .= 'Content-Disposition: form-data; name="' . $media_param . '"; ' ;
// $request_body .= 'filename="' . time() . '"' ;	// [filename]は指定不要なので、おサボり…
$request_body .= "\r\n" ;
// [Content-Type]と[Content-Transfer-Encoding]は指定不要なので、おサボり…
// $mimetype = 〜	//Mime/Typeを調べる処理
// $request_body .= "Content-Type: " . $mimetype . "\r\n" ;
// $request_body .= "Content-Transfer-Encoding: \r\n" ;
$request_body .= "\r\n" . $media_data . "\r\n" ;

// POSTフィールドの作成 (その他のオプションパラメータ)
foreach( $params_a as $key => $value ) {
	$request_body .= '--' . $boundary . "\r\n" ;
	$request_body .= 'Content-Disposition: form-data; name="' . $key . '"' . "\r\n\r\n" ;
	$request_body .= $value . "\r\n" ;
}

// リクエストボディの作成
$request_body .= '--' . $boundary . '--' . "\r\n\r\n" ;

// リクエストヘッダーの作成
$request_header = "Content-Type: multipart/form-data; boundary=" . $boundary ;

// パラメータAとパラメータBを合成してパラメータCを作る → ×
//	$params_c = array_merge( $params_a , $params_b ) ;
$params_c = $params_b ;		// 署名の材料にオプションパラメータを加えないこと

// 連想配列をアルファベット順に並び替える
ksort( $params_c ) ;

// パラメータの連想配列を[キー=値&キー=値...]の文字列に変換する
$request_params = http_build_query( $params_c , '' , '&' ) ;

// 一部の文字列をフォロー
$request_params = str_replace( array( '+' , '%7E' ) , array( '%20' , '~' ) , $request_params ) ;

// 変換した文字列をURLエンコードする
$request_params = rawurlencode( $request_params ) ;

// リクエストメソッドをURLエンコードする
// ここでは、URL末尾の[?]以下は付けないこと
$encoded_request_method = rawurlencode( $request_method ) ;
 
// リクエストURLをURLエンコードする
$encoded_request_url = rawurlencode( $request_url ) ;
 
// リクエストメソッド、リクエストURL、パラメータを[&]で繋ぐ
$signature_data = $encoded_request_method . '&' . $encoded_request_url . '&' . $request_params ;

// キー[$signature_key]とデータ[$signature_data]を利用して、HMAC-SHA1方式のハッシュ値に変換する
$hash = hash_hmac( 'sha1' , $signature_data , $signature_key , TRUE ) ;

// base64エンコードして、署名[$signature]が完成する
$signature = base64_encode( $hash ) ;

// パラメータの連想配列、[$params]に、作成した署名を加える
$params_c['oauth_signature'] = $signature ;

// パラメータの連想配列を[キー=値,キー=値,...]の文字列に変換する
$header_params = http_build_query( $params_c, '', ',' ) ;

// リクエスト用のコンテキスト
$context = array(
	'http' => array(
		'method' => $request_method ,	// リクエストメソッド
		'header' => array(	// ヘッダー
			'Authorization: OAuth ' . $header_params ,
			'Content-Type: multipart/form-data; boundary= ' . $boundary ,
		) ,
		'content' => $request_body ,
	) ,
) ;

// cURLを使ってリクエスト
$curl = curl_init() ;
curl_setopt( $curl, CURLOPT_URL , $request_url ) ;	// リクエストURL
curl_setopt( $curl, CURLOPT_HEADER, true ) ;	// ヘッダーを取得
curl_setopt( $curl, CURLOPT_CUSTOMREQUEST, $context['http']['method'] ) ;	// メソッド
curl_setopt( $curl, CURLOPT_SSL_VERIFYPEER, false ) ;	// 証明書の検証を行わない
curl_setopt( $curl, CURLOPT_RETURNTRANSFER, true ) ;	// curl_execの結果を文字列で返す
curl_setopt( $curl, CURLOPT_HTTPHEADER, $context['http']['header'] ) ;	// ヘッダー
if( isset( $context['http']['content'] ) && !empty( $context['http']['content'] ) ) {
	curl_setopt( $curl, CURLOPT_POSTFIELDS, $context['http']['content'] ) ;	// リクエストボディ
}
curl_setopt( $curl, CURLOPT_TIMEOUT, 5 ) ;	// タイムアウトの秒数
$res1 = curl_exec( $curl ) ;
$res2 = curl_getinfo( $curl ) ;
curl_close( $curl ) ;

// 取得したデータ
$json = substr( $res1, $res2['header_size'] ) ;	// 取得したデータ(JSONなど)
$header = substr( $res1, 0, $res2['header_size'] ) ;	// レスポンスヘッダー (検証に利用したい場合にどうぞ)

// [cURL]ではなく、[file_get_contents()]を使うには下記の通りです…
// $json = @file_get_contents( $request_url , false , stream_context_create( $context ) ) ;

// JSONを変換
// $obj = json_decode( $json ) ;	// オブジェクトに変換
// $arr = json_decode( $json, true ) ;	// 配列に変換

// HTML用
$html = '' ;

// 検証用にレスポンスヘッダーを出力 [本番環境では不要]
$html .= '<h2>取得したデータ</h2>' ;
$html .= '<p>下記のデータを取得できました。実際に更新されているかを、Twitterのアカウントで確認して下さい。</p>' ;
$html .= 	'<h3>ボディ(JSON)</h3>' ;
$html .= 	'<p><textarea rows="8">' . $json . '</textarea></p>' ;
$html .= 	'<h3>レスポンスヘッダー</h3>' ;
$html .= 	'<p><textarea rows="8">' . $header . '</textarea></p>' ;

// アプリケーション連携の解除
$html .= '<h2 style="color:red">アプリケーション連携の解除</h2>' ;
$html .= '<p>このアプリケーションとの連携を解除するには、下記ページより、行なって下さい。</p>' ;
$html .= '<p><a href="https://twitter.com/settings/applications" target="_blank">https://twitter.com/settings/applications</a></p>' ;

// HTMLの出力
echo $html ;

デモを開く

ツイートに画像を添付するには?

さて、ツイートに画像を付けて投稿するにはどうすればいいでしょうか?メディアファイルのアップロードに成功すると返り値で次のJSONを取得できるでしょう。media_id_stringの値が、目的のメディアIDです。

JSON

{"media_id":824814167332827136,"media_id_string":"824814167332827136","size":987,"expires_after_secs":86400,"image":{"image_type":"image\/png","w":96,"h":96}}

前章で紹介した「ツイート投稿」のエンドポイントを思い出して下さい。先ほどは、オプションにstatus(ツイート内容)しか指定しませんでした。これにmedia_idsというパラメータを加えて、値にメディアIDを指定すれば、ツイートにこの画像が添付されるという仕組みです。

ツイートに画像を添付するには、最低でも二回のリクエストが必要というわけです。例えば、3つの画像を付けたツイートを投稿する流れは次の通りです。

  1. 画像をアップロードしてメディアID(その1)を取得する。
  2. 画像をアップロードしてメディアID(その2)を取得する。
  3. 画像をアップロードしてメディアID(その3)を取得する。
  4. 3つのメディアIDをmedia_idsの値に指定して、ツイートを投稿する。
Twitter Rest APIで画像付きツイートを投稿する方法
Twitter Rest APIで画像付きツイートを投稿する方法
Twitter APIで画像を付けてツイートをする方法を説明します。サンプルコード、デモなど。

動画をアップロードするには?

画像と同じように動画をアップロードすることも、もちろん可能です。動画の場合は、INIT、APPEND、FINALIZEという3段階のリクエストをすることになるのですが、ここでは説明が長くなりすぎてしまうので割愛します。基本的には画像の場合と変わりません。ツイートに添付する手順も前項と同じで、動画をアップロードすることでその動画のメディアIDを取得し、これをパラメータに指定して、ツイートを投稿します。

  1. INIT(POST)のリクエストを実行する。アップロードする動画の情報(サイズとMIME TYPE)をTwitter側に知らせる。
  2. APPEND(multipart POST)のリクエストを実行する。動画をアップロードする。分割してアップロードするには、その回数だけリクエストが必要。
  3. FINALIZE(POST)のリクエストを実行する。動画のアップロードが完了したことをTwitter側に知らせる。ここで動画のメディアIDを取得できる。
  4. 動画のメディアIDをmedia_idsの値に指定して、ツイートを投稿する。
Twitter Rest APIで動画付きツイートを投稿する方法
Twitter Rest APIで動画付きツイートを投稿する方法
Twitter APIで動画を付けてツイートをする方法を説明します。サンプルコード、デモなど。

エンドポイントの一覧

この章では、Twitter Rest APIで利用できる全てのエンドポイントを紹介します。情報は2017年1月時点のものです。各項目名をクリックすると、詳しい説明ページに移動します。

REST APIs
REST APIs
Twitterの公式ドキュメント。全てのエンドポイントを確認することができます。

account - アカウント

アカウント設定のデータを取り扱うカテゴリです。

メソッドエンドポイント説明
GETaccount/settings認証ユーザーのアカウント設定を取得する。
GETaccount/verify_credentials認証ユーザーのアカウントが有効な状態か確認する。
POSTaccount/remove_profile_bannerバナー画像を削除する。
POSTaccount/settingsアカウントの設定を更新する。
POSTaccount/update_profileプロフィールを更新する。
POSTaccount/update_profile_background_imageプロフィールの背景画像を更新する。
POSTaccount/update_profile_bannerプロフィールのバナー画像を更新する。
POSTaccount/update_profile_imageプロフィールのアイコン画像を更新する。

application - レートリミット

レートリミットの情報を取り扱うカテゴリです。

メソッドエンドポイント説明
GETapplication/rate_limit_statusレートリミット設定と使用状況を取得する。

blocks - ブロック

ブロック関係のデータを取り扱うカテゴリです。

メソッドエンドポイント説明
GETblocks/idsブロックしているユーザーを、ユーザーIDで取得する。
GETblocks/listブロックしているユーザーを、ユーザーオブジェクトで取得する。
POSTblocks/createブロックを実行する。
POSTblocks/destroyブロックを解除する。

collections - コレクション

コレクション関係のデータを取り扱うカテゴリです。

メソッドエンドポイント説明
GETcollections/entriesコレクションをタイムライン付きで取得する。
GETcollections/listユーザーが作成したコレクション、またはツイートが含まれるコレクションを検索する。
GETcollections/showコレクションを取得する。
POSTcollections/createコレクションを作成する。
POSTcollections/destroyコレクションを削除する。
POSTcollections/entries/addコレクションにツイートを追加する。
POSTcollections/entries/curateコレクションをまとめて編集する。
POSTcollections/entries/moveコレクションのツイートの位置を変更する。
POSTcollections/entries/removeコレクションからツイートを削除する。
POSTcollections/updateコレクションの設定を更新する。

direct_messages - ダイレクトメッセージ

ダイレクトメッセージのデータを取り扱うカテゴリです。

メソッドエンドポイント説明
GETdirect_messages受信したダイレクトメッセージを取得する。
GETdirect_messages/sent送信したダイレクトメッセージを取得する。
GETdirect_messages/show個別のダイレクトメッセージの内容を取得する。
POSTdirect_messages/destroyダイレクトメッセージを削除する。
POSTdirect_messages/newダイレクトメッセージを送信する。

favorites - お気に入り

お気に入り関係のデータを取り扱うカテゴリです。

メソッドエンドポイント説明
GETfavorites/list対象ユーザーがお気に入りに登録したツイートの一覧を取得する。
POSTfavorites/create対象ツイートにいいねを付ける。
POSTfavorites/destroy対象ツイートのいいねを取り消す。

followers - フォロワー

フォロワー関係のデータを取り扱うカテゴリです。

メソッドエンドポイント説明
GETfollowers/ids対象ユーザーのフォロワーを、IDの一覧で取得する。
GETfollowers/list対象ユーザーのフォロワーを、オブジェクトの一覧で取得する。

friends - フォロー

フォロー関係のデータを取り扱うカテゴリです。

メソッドエンドポイント説明
GETfriends/ids対象ユーザーがフォローしているユーザーを、IDの一覧で取得する。
GETfriends/list対象ユーザーがフォローしているユーザーを、オブジェクトの一覧で取得する。

friendships - ユーザー間の関係

ユーザー間の関係、に関するデータを取り扱うカテゴリです。

メソッドエンドポイント説明
GETfriendships/incoming自分に対してフォローリクエストを送っているユーザーを取得する。
GETfriendships/lookup自分と対象ユーザーとの関係を取得する。
GETfriendships/no_retweets/ids自分がRT非表示中のユーザーを取得する。
GETfriendships/outgoing自分がフォローリクエストを送っているユーザーを取得する。
GETfriendships/show2人のユーザーの関係を取得する。
POSTfriendships/createフォローする。
POSTfriendships/destroyフォローを解除する。
POSTfriendships/updateリツイート非表示、ツイート通知の設定を更新する。

geo - 場所

場所や位置座標の情報を取り扱うカテゴリです。

メソッドエンドポイント説明
GETgeo/id/:place_id場所の情報を取得する。
GETgeo/reverse_geocode緯度、経度から場所の情報を取得する。
GETgeo/search場所を検索する。

help - ヘルプ

Twitterのルール関係のデータを取り扱うカテゴリです。

メソッドエンドポイント説明
GEThelp/configurationTwitterの内部設定を取得する。
GEThelp/languagesTwitterが対応している言語の一覧を取得する。
GEThelp/privacyTwitterのプライバシーポリシーを取得する。
GEThelp/tosTwitterのサービス利用規約を取得する。

lists - リスト

リスト関係のデータを取り扱うカテゴリです。

メソッドエンドポイント説明
GETlists/list対象ユーザーのリスト一覧を取得する。
GETlists/members対象のリストにメンバー(発言者)として加えられているユーザーの一覧を取得する。
GETlists/members/show対象のリストに、対象のユーザーがメンバーとして加わっているか否かを確認する。
GETlists/membershipslists/members/memberships(GETメソッド)は、対象ユーザーが、メンバー(発言者)として加えられているリストの一覧を取得するエンドポイントです。
GETlists/ownerships対象ユーザーが作成したリストの一覧を取得する。
GETlists/show対象のリストを取得する。
GETlists/statusesリストのタイムラインを取得する。
GETlists/subscribersリストの購読者を取得する。
GETlists/subscriptionsユーザーが購読しているリストを取得する。
POSTlists/createリストを作成する。
POSTlists/destroyリストを削除する。
POSTlists/members/createリストにメンバーを追加する。
POSTlists/members/create_allリストに複数のメンバーを追加する。
POSTlists/members/destroyリストからメンバーを削除する。
POSTlists/members/destroy_allリストから複数のメンバーを削除する。
POSTlists/subscribers/createリストを保存する。
POSTlists/subscribers/destroyリストの購読を取り消す。
POSTlists/updateリストの設定を更新する。

media - メディアアップロード

メディアアップロードをするカテゴリです。

メソッドエンドポイント説明
POSTmedia/upload画像をアップロードする。
POSTmedia/upload (APPEND)動画のアップロードを実行する。
POSTmedia/upload (FINALIZE)動画のアップロードを完了する。
POSTmedia/upload (INIT)動画のアップロードを準備する。

mutes - ミュート

ミュート関係のデータを取り扱うカテゴリです。

メソッドエンドポイント説明
GETmutes/users/ids自分がミュートしているユーザーを、ユーザーIDの一覧で取得する。
GETmutes/users/list自分がミュートしているユーザーを、オブジェクトの一覧で取得する。
POSTmutes/users/createミュートを実行する。
POSTmutes/users/destroyミュートを解除する。

saved_searches - 検索メモ

検索メモ関係のデータを取り扱うカテゴリです。

メソッドエンドポイント説明
GETsaved_searches/list検索メモを一覧で取得する。
GETsaved_searches/show/:id検索メモを個別に取得する。
POSTsaved_searches/create検索メモを保存する。
POSTsaved_searches/destroy/:id検索メモを削除する。

search - 検索

ツイートの検索APIを利用できます。

メソッドエンドポイント説明
GETsearch/tweetsツイートを検索する。

statuses - ツイート

ツイート関係のデータを取り扱うカテゴリです。

メソッドエンドポイント説明
GETstatuses/home_timelineホームタイムラインを取得する。
GETstatuses/lookupツイートを任意の数だけ取得する。
GETstatuses/mentions_timelineメンションタイムラインを取得する。
GETstatuses/oembed対象ツイートの埋め込み用コードを取得する。
GETstatuses/retweeters/ids対象ツイートをリツイートしたユーザーを、ユーザーIDの一覧で取得する。
GETstatuses/retweets/:id対象ツイートをリツイートしたユーザーを、オブジェクトの一覧で取得する。
GETstatuses/retweets_of_meリツイートされたツイートの一覧を取得する。
GETstatuses/show/:idツイートを個別に取得する。
GETstatuses/user_timelineユーザータイムラインを取得する。
POSTstatuses/destroy/:idツイートを削除する。
POSTstatuses/retweet/:idリツイートを実行する。
POSTstatuses/unretweet/:idリツイートを取り消す。
POSTstatuses/updateツイートを投稿する。

trends - トレンド

トレンドの情報を取り扱うカテゴリです。

メソッドエンドポイント説明
GETtrends/availableトレンドの集計対象となっている地域の一覧を取得する。
GETtrends/closest位置座標からWOEIDを取得する。
GETtrends/placeトレンドワードを取得する。

users - ユーザー

ユーザープロフィールに関係するデータを取り扱うカテゴリです。

メソッドエンドポイント説明
GETusers/lookup複数のユーザーの情報を取得する。
GETusers/profile_bannerプロフィールのバナー画像を取得する。
GETusers/searchユーザーを検索する。
GETusers/showユーザーのプロフィールを取得する。
GETusers/suggestionsサジェストのカテゴリを取得する。
GETusers/suggestions/:slugおすすめユーザーを取得する。
GETusers/suggestions/:slug/membersおすすめユーザーをツイート付きで取得する。
POSTusers/report_spamスパム報告を実行する。

JSONの説明

取得できるJSONの各プロパティがどのような意味を持つのかをまとめてあります。

オブジェクト名説明
ユーザーオブジェクトユーザーの情報を含むオブジェクトです。
ツイートオブジェクトツイートの情報を含むオブジェクトです。
エンティティオブジェクトテキストをリッチテキスト化したり、画像や動画を表示するための情報を含むオブジェクト。ツイートオブジェクトやユーザーオブジェクトに含まれています。
リストオブジェクトリストの情報を含むオブジェクトです。
場所オブジェクト場所の情報を含むオブジェクトです。
ダイレクトメッセージオブジェクトダイレクトメッセージの情報を含むオブジェクトです。
検索メモオブジェクト検索メモの情報を含むオブジェクトです。
トレンドオブジェクトトレンドの情報を含むオブジェクトです。