PHP+VBS : デスクトップアプリで Twitter API のアクセストークンを取得

  WEBアプリとは多少手順が変わります



WEB アプリでは、データのやり取りを リダイレクトを使ってユーザに手間がかからないようにしますが、デスクトップで動くアプリケーション( この場合は VBScript(WSH) ) では、途中でブラウザ使用して、Twitter のサイトにアクセスし、暗証番号( PIN ) を取得して、それをデスクトップアプリケーションに引き渡す必要があります。

これは、WEB アプリケーションで、oauth_verifier として取得していたものですが、この場合は人が暗記するかクリップボードにコピーする事になるので、桁数の少ない数字となります。

Twitter_pin

Twitter_pin2

さらに、Twitter に対する認証処理は、クライアントからでも良いのですが、元となるアプリケーションのキーとパスワードを公開するわけにはいかないので、アクセストークンを取得する部分の処理を PHP としてホスティングします。

アクセストークン( 秘密のフクセストークンも含む )は、ローカルの PC に保存する事となりますが、そのトークンをキャンセルしたい場合は、自分の Twitter ユーザに登録されている 該当アプリを削除すれば OK です。ですが、そういう内容のものなので、自宅でのみ使う事ように「警告」した上で公開する必要は出てきます。


関連する記事




  PHP ( ホスト側のコード )



プロセスが途中でユーザの手作業が入るので、二つ必要になります

※ 引き渡すデータは単純なテキストで返しています( XML や JSON を使うほどでも無いので )
※ テストは localhost で問題ありません


phase_1.php
<?
// **********************************************************
// Acquiring a request token
// **********************************************************
header( "Content-Type: text/html; Charset=utf-8" );
header( "pragma: no-cache" );
header( "Expires: Wed, 31 May 2000 14:59:58 GMT" );
header( "Cache-control: no-cache" );

// **********************************************************
// OAuth 用の urlencode 関数
// **********************************************************
function url_rfc3986( $str ) {
	// php 5.3.x 〜 ではこの変換は必要無い
	return str_replace('%7E', '~', rawurlencode($str));
}

// **********************************************************
// API ( SSL is recommended )
// **********************************************************
$twitter_url = 'https://api.twitter.com/oauth/request_token';

// **********************************************************
// 認証データ
// **********************************************************
$oauth_consumer_key = "Consumer key"; 
$oauth_consumer_secret = "Consumer secret"; 
$oauth_token = "";
$oauth_secret = "";

// 毎回変化するランダムな文字列
$mt = microtime();
$rand = mt_rand();
$oauth_nonce = md5($mt . $rand);

$oauth_signature_method = "HMAC-SHA1";
$oauth_timestamp = mktime();

$oauth_version = "1.0";

// コールバック url
$oauth_callback = "oob";

// *********************************************************
// シグネチャ用ベース文字列作成
/*
  httpMethod + "&" +
  url_encode(  base_uri ) + "&" +
  sorted_query_params.each  { | k, v |
      url_encode ( k ) + "%3D" +
      url_encode ( v )
  }.join("%26")
*/
// *********************************************************
$base_string = "POST";
$base_string .= "&" . url_rfc3986($twitter_url);
$base_string .= "&";

$base_string .= url_rfc3986("oauth_callback")."%3D".url_rfc3986(url_rfc3986($oauth_callback))."%26";
$base_string .= url_rfc3986("oauth_consumer_key")."%3D".url_rfc3986($oauth_consumer_key)."%26";
$base_string .= url_rfc3986("oauth_nonce")."%3D".url_rfc3986($oauth_nonce)."%26";
$base_string .= url_rfc3986("oauth_signature_method")."%3D".url_rfc3986($oauth_signature_method)."%26";
$base_string .= url_rfc3986("oauth_timestamp")."%3D".url_rfc3986($oauth_timestamp)."%26";
$base_string .= url_rfc3986("oauth_version")."%3D".url_rfc3986($oauth_version);

// *********************************************************
// シグネチャ作成
/*
url_encode( consumer_secret ) + "&" +
url_encode( oauth_token_secret || nil )
*/
// *********************************************************
$oauth_signature = 
base64_encode( hash_hmac(
	"sha1",
	$base_string,
	url_rfc3986($oauth_consumer_secret) . "&",
	true
));
//$postfields['oauth_signature'] = $oauth_signature;

// *********************************************************
// curl 処理
// *********************************************************
$curl = curl_init();
curl_setopt($curl, CURLOPT_CONNECTTIMEOUT, 30);
curl_setopt($curl, CURLOPT_HEADER, false);
curl_setopt($curl, CURLOPT_RETURNTRANSFER, true);
curl_setopt($curl, CURLOPT_BINARYTRANSFER, true);
curl_setopt($curl, CURLOPT_URL, $twitter_url);
curl_setopt($curl, CURLOPT_POST, 1);

// *********************************************************
// http ヘッダ作成
// *********************************************************
$header = array();
$header[] = 'Expect:';

$header[] = 'Authorization: OAuth '.
url_rfc3986("oauth_nonce")."=\"".url_rfc3986($oauth_nonce)."\",".
url_rfc3986("oauth_callback")."=\"".url_rfc3986($oauth_callback)."\",".
url_rfc3986("oauth_signature_method")."=\"".url_rfc3986($oauth_signature_method)."\",".
url_rfc3986("oauth_timestamp")."=\"".url_rfc3986($oauth_timestamp)."\",".
url_rfc3986("oauth_consumer_key")."=\"".url_rfc3986($oauth_consumer_key)."\",".
url_rfc3986("oauth_signature")."=\"".url_rfc3986($oauth_signature)."\",".
url_rfc3986("oauth_version")."=\"".url_rfc3986($oauth_version)."\"";

curl_setopt($curl, CURLOPT_HTTPHEADER, $header);

// *********************************************************
// https 用
// *********************************************************
curl_setopt($curl, CURLOPT_SSL_VERIFYPEER, false);
curl_setopt($curl, CURLOPT_SSL_VERIFYHOST, 1);

// *********************************************************
// 送信
// *********************************************************
$result = curl_exec($curl);


// *********************************************************
// 結果
// *********************************************************

if($result === false) {
	echo 'Curl error: ' . curl_error($curl);
	exit();
}
else {
//	echo 'Operation completed without any errors';
}
curl_close($curl);

parse_str($result,$arr);
print $arr['oauth_token_secret'] . "\n";
print "https://twitter.com/oauth/authorize?oauth_token={$arr['oauth_token']}\n";

?>



phase_2.php
<?
header( "Content-Type: text/html; Charset=utf-8" );
header( "pragma: no-cache" );
header( "Expires: Wed, 31 May 2000 14:59:58 GMT" );
header( "Cache-control: no-cache" );
// **********************************************************
// AOuth 用の urlencode 関数
// **********************************************************
function url_rfc3986( $str ) {
	// php 5.3.x 〜 ではこの変換は必要無い
	return str_replace('%7E', '~', rawurlencode($str));
}

// **********************************************************
// API ( SSL is recommended )
// **********************************************************
$twitter_url = 'https://api.twitter.com/oauth/access_token';

// **********************************************************
// 認証データ
// **********************************************************
$oauth_consumer_key = "Consumer key"; 
$oauth_consumer_secret = "Consumer secret"; 
$oauth_token = $_GET['oauth_token'];
$oauth_secret = $_GET['oauth_token_secret'];

// 毎回変化するランダムな文字列
$mt = microtime();
$rand = mt_rand();
$oauth_nonce = md5($mt . $rand);

$oauth_signature_method = "HMAC-SHA1";
$oauth_timestamp = mktime();

$oauth_version = "1.0";

// *********************************************************
// シグネチャ用ベース文字列作成
/*
  httpMethod + "&" +
  url_encode(  base_uri ) + "&" +
  sorted_query_params.each  { | k, v |
      url_encode ( k ) + "%3D" +
      url_encode ( v )
  }.join("%26")
*/
// *********************************************************
$base_string = "POST";
$base_string .= "&" . url_rfc3986($twitter_url);
$base_string .= "&";

$base_string .= url_rfc3986("oauth_consumer_key")."%3D".url_rfc3986($oauth_consumer_key)."%26";
$base_string .= url_rfc3986("oauth_nonce")."%3D".url_rfc3986($oauth_nonce)."%26";
$base_string .= url_rfc3986("oauth_signature_method")."%3D".url_rfc3986($oauth_signature_method)."%26";
$base_string .= url_rfc3986("oauth_timestamp")."%3D".url_rfc3986($oauth_timestamp)."%26";
$base_string .= url_rfc3986("oauth_token")."%3D".url_rfc3986($oauth_token)."%26";
$base_string .= url_rfc3986("oauth_verifier")."%3D".url_rfc3986($_GET['oauth_verifier']);
$base_string .= url_rfc3986("oauth_version")."%3D".url_rfc3986($oauth_version);

// *********************************************************
// シグネチャ作成
/*
url_encode( consumer_secret ) + "&" +
url_encode( oauth_token_secret || nil )
*/
// *********************************************************
$oauth_signature = 
base64_encode( hash_hmac(
	"sha1",
	$base_string,
	url_rfc3986($oauth_consumer_secret) . "&" . url_rfc3986($oauth_secret),
	true
));
//$postfields['oauth_signature'] = $oauth_signature;

// *********************************************************
// curl 処理
// *********************************************************
$curl = curl_init();
curl_setopt($curl, CURLOPT_CONNECTTIMEOUT, 30);
curl_setopt($curl, CURLOPT_HEADER, false);
curl_setopt($curl, CURLOPT_RETURNTRANSFER, true);
curl_setopt($curl, CURLOPT_BINARYTRANSFER, true);
curl_setopt($curl, CURLOPT_URL, $twitter_url);
curl_setopt($curl, CURLOPT_POST, 1);

// *********************************************************
// http ヘッダ作成
// *********************************************************
$header = array();
$header[] = 'Expect:';
$header[] = 'Authorization: OAuth '.
url_rfc3986("oauth_consumer_key")."=\"".url_rfc3986($oauth_consumer_key)."\",".
url_rfc3986("oauth_nonce")."=\"".url_rfc3986($oauth_nonce)."\",".
url_rfc3986("oauth_signature_method")."=\"".url_rfc3986($oauth_signature_method)."\",".
url_rfc3986("oauth_timestamp")."=\"".url_rfc3986($oauth_timestamp)."\",".
url_rfc3986("oauth_token")."=\"".url_rfc3986($oauth_token)."\",".
url_rfc3986("oauth_verifier")."=\"".url_rfc3986($_GET['oauth_verifier'])."\",".
url_rfc3986("oauth_signature")."=\"".url_rfc3986($oauth_signature)."\",".
url_rfc3986("oauth_version")."=\"".url_rfc3986($oauth_version)."\"";

curl_setopt($curl, CURLOPT_HTTPHEADER, $header);

// *********************************************************
// https 用
// *********************************************************
curl_setopt($curl, CURLOPT_SSL_VERIFYPEER, false);
curl_setopt($curl, CURLOPT_SSL_VERIFYHOST, 1);

// *********************************************************
// 送信
// *********************************************************
$result = curl_exec($curl);

// *********************************************************
// 結果
// *********************************************************

if($result === false) {
	echo 'Curl error: ' . curl_error($curl);
	exit();
}
else {
//	echo 'Operation completed without any errors';
}
curl_close($curl);

parse_str($result,$arr);
print $arr['oauth_token'] . "\n";
print $arr['oauth_token_secret'] . "\n";

?>





  VBScript : クライアントアプリケーション( アクセストークンの取得 )

取得したトークンはテキストファイルに出力しています。実際の処理を行うアプリケーションが
このトークンを使う事になりますので、このコードはその前処理のようなものです。


GetAccessToken.wsf
<JOB>
<OBJECT id="WshShell" progid="WScript.Shell" />
<OBJECT id="Fso" progid="Scripting.FileSystemObject" />
<OBJECT id="objHTTP" progid="MSXML2.XMLHTTP" />

<SCRIPT language=VBScript>
' **********************************************************
' 暗証番号( PIN ) を手に入れる為の URL を取得する
'
' 取得用 URL ( アプリケーションのユーザが用意する )
' **********************************************************
phase_1_url = "http://............/phase_1.php"

' *********************************************************
' 送信準備
' *********************************************************
Call objHTTP.Open( "GET",phase_1_url, False )

' *********************************************************
' 送信
' *********************************************************
Call objHTTP.Send(strData)

' *********************************************************
' URL を取得
' *********************************************************
aRet = Split(objHTTP.responseText,vbLf)

if Ubound(aRet) < 2 then
	Wscript.Echo aRet(0)
	Wscript.Quit
end if

' *********************************************************
' IE で URL にアクセス
' *********************************************************
WshShell.Run( "iexplore.exe " & aRet(1) )

' **********************************************************
' 一時トークン保存
' **********************************************************
Set OutObj1 = Fso.OpenTextFile( "token1.log", 2, True )
Set OutObj2 = Fso.OpenTextFile( "token2.log", 2, True )
aData = Split(aRet(1),"=")
OutObj1.Write aData(1)
OutObj2.Write aRet(0)
OutObj2.Close
OutObj1.Close

PIN = InputBox("暗証番号( PIN )を入力して下さい")

' **********************************************************
' 取得用 URL ( アプリケーションのユーザが用意する )
' **********************************************************
phase_2_url = "http://............/phase_2.php?"
phase_2_url = phase_2_url & "oauth_token=" & aData(1)
phase_2_url = phase_2_url & "&oauth_token_secret=" & aRet(0)
phase_2_url = phase_2_url & "&oauth_verifier=" & PIN

' *********************************************************
' 送信準備
' *********************************************************
Call objHTTP.Open( "GET",phase_2_url, False )

' *********************************************************
' 送信
' *********************************************************
Call objHTTP.Send(strData)

' *********************************************************
' URL を取得
' *********************************************************
aRet = Split(objHTTP.responseText,vbLf)

if Ubound(aRet) < 2 then
	Wscript.Echo aRet(0)
	Wscript.Quit
end if

' **********************************************************
' トークン保存
' **********************************************************
Set OutObj1 = Fso.OpenTextFile( "token1.log", 2, True )
Set OutObj2 = Fso.OpenTextFile( "token2.log", 2, True )
OutObj1.Write aRet(0)
OutObj2.Write aRet(1)
OutObj2.Close
OutObj1.Close

WScript.Echo "処理が終了しました"


</SCRIPT>
</JOB>
















   SQLの窓    create:2010/06/05  update:2015/11/02   管理者用(要ログイン)





フリーフォントWEBサービス

SQLの窓WEBサービス

SQLの窓フリーソフト

素材

一般WEBツールリンク

SQLの窓

フリーソフト

JSライブラリ