Twitter gemを使用せずにツイート機能を実装

こんにちは、デザイン・システム室の菅野です。

先日、ツイート機能を実装したので、実装までの流れをまとめてみました。
拙い文章ですが、お許しください。

ツイート機能はtwitter gemを使用すると簡単にできるのですが、今回はgemを使えない状況だったので、仕方なくgemを使わず実装しました。。。

実装までの流れは以下の通りです。
1.Twitter APIの利用申請
2.APIキー、アクセストークンを取得
3.ツイート機能実装


1.Twitter APIの利用申請

英文で申請する必要があるのでちょっとめんどくさい大変ですが、申請方法をについては紹介してくれる記事がたくさんあるので、そちらを参考にしてササッと終わらせました。


2.APIキー、アクセストークンを取得

こちらも内容を埋めるだけで、簡単にできます。
手順は以下の通りです。

1.create an app を押下

2.各内容を埋めて、create を押下後、利用規約が出てくるので、create 押下

3.Keys and tokensタブを押下すると、Consumer API keys(APIキーとAPIシークレットキー)を確認できます。
アクセストークンはAccess token & access token secretのGenerateを押下することで取得できます。


3.ツイート機能実装

Authorization ヘッダーを加えてHTTPリクエストを行うことで認証されるとのことなので、Authorization ヘッダーを作る必要があります。
必要な情報は以下の通りです。
ーーーーーーーーーーーーーーーーーーーーーーーーーーーー
・oauth_consumer_key   :APIキー
・oauth_nonce      :ランダムな文字列
・oauth_signature    :署名を設定
・oauth_signature_method:署名の種類を指定。”HMAC-SHA1″を指定。
・oauth_timestamp :リクエスト時のタイムスタンプ
・oauth_token      :アクセストークン
・oauth_version     :OAuthのバージョンを設定。”1.0″を指定。
ーーーーーーーーーーーーーーーーーーーーーーーーーーーー

署名の作成

oauth_signatureには署名を設定する必要があります。
署名作成の流れは以下の通りです。
1.シグネチャーベースを作成
2.シグネチャーキーを作成
3.シグネチャーベースとシグネチャーキーをHMAC-SHA1を用いて署名に変換

サンプルコード(※リファクタリング必要)

<APIkey等を記載したファイルを読み込む>
# ymlファイル読み込み
File = File.read("config/api/twitter.yml")
# 環境ごとに読み込む箇所を変更し、Configに格納
Config = YAML.safe_load(File, [], [], true)[Rails.env].symbolize_keys

def self.per_enc(str, enc=nil)
  URI.encode_www_form_component(str, enc=nil)
end

def self.tweet(params = {})
  # ツイートを投稿するエンドポイントを設定
  url = "https://api.twitter.com/1.1/statuses/update.json"
  # uri生成
  uri = URI.parse(url)
  # HTTP接続の設定
  https = Net::HTTP.new(uri.host, uri.port)
  # httpsで通信のため必要
  https.use_ssl = true
  # ヘッダーを設定
  request = Net::HTTP::Post.new(uri.request_uri, self.create_authorization_header(url, params))
  # requestにparamsをつける
  request.set_form_data(params)
  # リクエスト送信及びレスポンス受信
  response = https.request(request)
end

def self.create_authorization_header(url, params)
  <1.シグネチャーベースを作成>
  # タイムスタンプ作成
  time_stamp = Time.parse(Time.current.strftime("%Y-%m-%d %H:%M:%S")).to_i
  # ランダムな文字列作成
  random_str = Base64.encode64(SecureRandom.hex()).gsub!(/[^0-9A-Za-z]/, '')
  # クエリデータ生成
  query_data = "#{per_enc("oauth_consumer_key")}=#{per_enc(Config[:api_key])}&#{per_enc("oauth_nonce")}=#{per_enc(random_str)}&#{per_enc("oauth_signature_method")}=#{per_enc("HMAC-SHA1")}&#{per_enc("oauth_timestamp")}=#{per_enc(time_stamp)}&#{per_enc("oauth_token")}=#{per_enc(Config[:access_token])}&#{per_enc("oauth_version")}=#{per_enc("1.0")}&#{per_enc("status")}=#{per_enc(params[:status])}"
  # パーセントエンコードする
  encoded_query_data = per_enc(query_data, enc=nil)
  # シグネシャーベースの計算
  request_method = "POST"
  encode_after_url =  per_enc(url, enc=nil)
  # リクエストメソッド・url・クエリデータを&で連結する
  signature_base = request_method + "&" + encode_after_url + "&" + encoded_query_data

  <2.シグネチャーキーを作成>
  # APIシークレットキーとアクセストークンシークレットをパーセントエンコードしてクエリ文字列にする
  signature_key = per_enc(Config[:api_secret_key]) + "&" +  per_enc(Config[:access_token_secret])

  <3.シグネチャーベースとシグネチャーキーをHMAC-SHA1を用いて署名に変換>
  # 「シグネチャベース」と「シグネチャキー」から HMAC-SHA1 ハッシュ値を計算
  hash = OpenSSL::HMAC.digest("sha1", signature_key, signature_base)

 <Authorizationヘッダーを作成>
  # Base64エンコード
  signature_base64_enc = Base64.encode64(hash).chomp
  # パーセントエンコード
  signature_per_enc = per_enc(signature_base64_enc, enc=nil)
  # シグネチャーベースクエリにシグネチャークエリを追加
  request_header = {Authorization: 'OAuth ' + per_enc("oauth_consumer_key") + '="' + "#{Config[:api_key]}" + '", ' + per_enc("oauth_nonce") + '="' + "#{per_enc(random_str)}" + '", ' + per_enc("oauth_signature") + '="'+ "#{signature_per_enc}"+ '", ' +  per_enc("oauth_signature_method") + '="' + per_enc("HMAC-SHA1") +'", ' + per_enc("oauth_timestamp") +  '="' + "#{per_enc(time_stamp)}" + '", ' + per_enc("oauth_token") + '="' + "#{Config[:access_token]}" + '", ' + per_enc("oauth_version") + '="' + per_enc("1.0") + '"'}
  return request_header
end

あとはtweetメソッドを呼ぶ時に引数に{status: “ツイートしたい内容”}を設定すればツイートできます。


まとめ

twitter gemを使用しないで実装している記事があまりなく、認証のところで何回も失敗して泣きそうになりましたが、なんとか実装できてよかったです。
こんなめんどくさいことをgemを使うだけで簡単にできてしまうんですから、gemを作る人には本当に尊敬しかありません。自分もgemを作れるような人になりたいものです。

ファンデリー デザイン・システム室では現在メンバーを募集しています。
私のような入社まもない方でも開発案件につくことができますし、自分のやりたいことにチャレンジできる環境があります。
少しでも興味を持たれた方、ぜひご応募ください。
お待ちしております!

デザイン・システム室へのご質問 >

募集要項およびエントリーフォーム >