XojoでTwitterアプリを作る

2017.11.10  投稿者: moongift
開発

Web APIを使えば多彩なアプリケーションが作れるようになります。ユーザがいなくともWebサービスがすでに持っているユーザベースを活用できたり、画像加工のような複雑な機能もWeb APIで簡単に実現できます。

今回はWeb APIの中でも人気なTwitterを使ってみたいと思います。特に認証周りはライブラリも存在しないので参考になるかと思います。

用意するもの

まずTwitter Application Managementにてアプリを作成します。Callback URLをあらかじめ指定しておくのが肝で、Xojoの場合は http://localhost:8080/callback としておきます。

今回はツイートを投稿するところまで実装するので、読み取り(Read)だけでなく書き込み(Write)権限も得るようにしておきます。

アプリを作った結果、Consumer KeyとConsumer Secretが手に入ります。

画面について

今回はWeb版として作成します。次のような画面になります。Consumer KeyとConsumer SecretはWeb画面上で指定できるようにしておきます。

認証の流れ

認証は次のような流れになります。

  1. Consumer KeyとConsumer Secretから認証用URLを呼び出す
  2. 認証用URLが取得できたらWebブラウザをリダイレクトさせる
  3. 認証後、 /callback が呼び出されるので、認証した際のデータを使ってアクセストークンを取得する

署名を作る処理

TwitterのWeb APIでは署名を作成する処理が必要になります。これは殆ど同じパターンなので一度作ってしまえば苦労しないでしょう。

まず認証用URLを作る場合の必須情報は以下になります。

  • HTTPメソッド
  • リクエスト先のURL

例えば認証用URLを得る場合は次のようになります。

Dim method as string = "POST"
Dim requestUrl as String = "https://api.twitter.com/oauth/request_token"

そして署名を作るために必要な基本的パラメータを取得します。これはすべてのWeb APIリクエストで共通です。Unixタイムスタンプについては、Xojoでは1970年からの数値ではないので2082844800を引いて調整します(via Date value to unix timestamp - Xojo Forum)。

Dim params as Dictionary = new Dictionary
Dim timestamp as new Date
Dim unix as Integer = timestamp.TotalSeconds - 2082844800
params.Value("oauth_consumer_key") = Self.consumerKey
params.Value("oauth_signature_method") = "HMAC-SHA1"
params.Value("oauth_timestamp") = unix
params.Value("oauth_nonce") = Microseconds.ToText
params.Value("oauth_version") = "1.0"

そして認証URLはここにもう一つ oauth_callback を追加します。

params.Value("oauth_callback") = ""

この params の各値をURLエンコードし、ソートします。

Dim aryParams() as String
Dim value as string
Dim k as String
For each k in params.Keys
  value = params.Value(k)
  value = EncodeURLComponent(value)
  aryParams.Append(k + "=" + value)
Next

aryParams.Sort

メソッド(method)、リクエストURL(requestUrl)そしてaryParamsを使って署名を生成します。これはaryParamsの各値を & で連結し、URLエンコードします。さらにその結果をメソッド、リクエストURLと & で連結します。署名に用いるキーは Twitter で作成した Consumer Secret と アクセストークンシークレット(ある場合)になります。これらを使ってSHA1でハッシュ化し、さらにBase64エンコードしたのが署名となります。

Dim requestParams as String = Join(aryParams, "&")
requestParams = EncodeURLComponent(requestParams)

Dim signatureData as String = EncodeURLComponent(method) + "&" + EncodeURLComponent(requestUrl) + "&" + requestParams

DIm signatureKey as String = EncodeURLComponent(Self.consumerSecret) + "&" + EncodeURLComponent(accessTokenSecret)

EncodeBase64(Crypto.HMAC(signatureKey, signatureData, Crypto.Algorithm.SHA1), 0)

この署名を元々のaryParamsに oauth_signature として追加します。

aryParams.Append("oauth_signature=" + EncodeURLComponent(Self.generateSignature(method, requestUrl, aryParams, "")))

Web APIの呼び出し

この署名を含めた aryParamsはHTTPヘッダーのAuthorizationとして適用し、HTTPメソッドに従ってWeb APIを呼び出します。

Dim http as HTTPSecureSocket = new HTTPSecureSocket
http.SetRequestHeader("Authorization", "OAuth " + Join(aryParams, ","))

http.Post(requestUrl, 10)

ここまでが処理の流れになります。

認証用URLの取得

認証用URLを取得する場合は前述の通り、メソッドとURLが次のようになります。

Dim method as string = "POST"
Dim requestUrl as String = "https://api.twitter.com/oauth/request_token"

さらにパラメータは基本的なものに加えて oauth_callback (空文字)を追加します。

params.Value("oauth_callback") = ""

レスポンスとして文字列が返ってきます。

oauth_token=aaa&oauth_token_secret=bbb

これらを & と = で分割してデータを得ます。

Dim responses() as String = response.Split("&")
Dim queries as Dictionary = new Dictionary
Dim values() as String
Dim i as Integer
For i = 0 to UBound(responses)
  values = responses(i).split("=")
  queries.Value(values(0)) = values(1)
Next

そして oauth_token をパラメータとして付与してリダイレクトさせます。

showURL("https://api.twitter.com/oauth/authenticate?oauth_token=" + queries.Value("oauth_token")

ここまでで認証用URLの流れが完了です。

コールバックの扱い & アクセストークン取得

Twitterからのコールバック先は /callback になります。そこでhandleURLを使います。クエリストリングには次のような文字列が入ります。

oauth_token=aaa&oauth_verifier=bbb

これらの上記の認証時と同じように分解し、Dictionary型にします。そして次にアクセストークンを取得します。この処理でのHTTPメソッド、URLは次のようになります。

Dim method as string = "POST"
Dim requestUrl as String = "https://api.twitter.com/oauth/access_token"

アクセストークンの取得では基本的なパラメータに加えて、次のデータが必要です。基本的にコールバックから取得できるデータになります。

params.Value("oauth_token") = Self.oauthToken
params.Value("oauth_consumer_key") = Self.consumerKey
params.Value("oauth_verifier") = Self.oauthVerifier

これらのデータを加えて署名を作り、上記のURLにアクセスすることでレスポンスが得られます。

oauth_token=aaa&user_id=ccc&screen_name=ddd&x_auth_expires=0

これでアクセストークンが得られました。

ツイートする

ツイートについても基本的に処理は同じです。HTTPメソッド、URLは次のようになります。

Dim method as string = "POST"
Dim requestUrl as String = "https://api.twitter.com/1.1/statuses/update.json"

違いはリクエスト時にステータス(ツイート内容)をはじめとするデータが追加されることでしょう。

Dim body as Dictionary = new Dictionary
body.Value("status") = tweet

リクエスト時にこれらのデータはSetFormDataに適用します。

http.SetFormData(body)

この方法さえ覚えてしまえばTwitterとXojoアプリの連携も難しくないはずです。


TwitterのWeb APIを扱う際に一番問題になるのが署名を生成する部分になるかと思います。そこさえ正しく生成できれば、後はHTTPアクセスする流れは普通のWeb APIと変わりません。また、コールバック先のURLを用意しておく必要があるので、Webアプリケーション向きかも知れません。

今回のコードはgoofmint/Xojo_Twitter_OAuth: Twitter auth demo app with Xojoにアップロードしてあります。実装時の参考にしてください。