Dartでhttpライブラリのみを利用してTwitter API v2を使う

3 min読了の目安(約3200字TECH技術記事

必要なもの

  • APIキー
  • APIシークレットキー

手順としては

  1. APIキーとAPIシークレットキーBase64化する
  2. OAuth 2.0 Bearer Tokenを取得する
  3. 取得したBearer Tokenの情報を付与してAPIアクセス

※現地点でユーザに紐づくAPIのv2は存在しないようです。
※デベロッパーサイトでOAuth 2.0 Bearer Tokenを直接取得することもできます。

APIキーとAPIシークレットキーBase64化する

  final base64encoded =  base64.encode(latin1.encode('${API_KEY}:${API_KEY_SECRET}'));

Tokenを取得するためのAPIはBasic認証が掛けられていますので、APIキーとAPIシークレットキーを:で結合してBase64化します。
base64化コードはhttp_authライブラリを参考にしました。

OAuth 2.0 Bearer Tokenを取得する

https://api.twitter.com/oauth2/token
に対して、リクエストを投げます。
投げる内容は、リクエストヘッダーに「Authorization」とリクエストボディに「grant_type」を指定します。

  final response = await http.post(
    'https://api.twitter.com/oauth2/token',
    headers: {'Authorization': 'Basic $base64encoded'},
    body: {'grant_type': 'client_credentials'},
  );

レスポンスが以下(例)のように返ってきて、AAAA%2FAAA%3DAAAAAAAAがBearer Tokenになります。

{"token_type":"bearer","access_token":"AAAA%2FAAA%3DAAAAAAAA"}

取得したBearer Tokenの情報を付与してAPIアクセス

ここでは、例として、
/2/users/by/username/:username
にアクセスしてみます。
投げる内容は、「:username」に組み込みパラメータとしてLuecy1(私のtwitterアカウントです)リクエストヘッダーに「Authorization」を指定します。

  final result = await http.get(
    'https://api.twitter.com/2/users/by/username/Luecy1',
    headers: {'Authorization': 'Bearer ${oauthToken.accessToken}'},
  );

Bearerとtokenの間はスペース1つ分です!(一回はまった)

これで以下のレスポンスが返却されます。
従来のAPIよりレスポンス量が物足りないですが、Twitter API v2では欲しい情報を指定する方針となったようです。

{"data":{"id":"285498667","name":"youhei@( ˘ω˘)スヤァ…☃️","username":"Luecy1"}}

完成版コード

いままで紹介したコードとは少しことなる箇所があります。

import 'dart:convert';

import 'package:http/http.dart' as http;

void main() async {
  final base64encoded =
      base64.encode(latin1.encode('${API_KEY}:${API_KEY_SECRET}'));

  final response = await http.post(
    'https://api.twitter.com/oauth2/token',
    headers: {'Authorization': 'Basic $base64encoded'},
    body: {'grant_type': 'client_credentials'},
  );

  print(response.body);

  final oauthToken = OauthToken.fromJson(jsonDecode(response.body));

  // Map<String,List<String>>
  final queryParameters = {
    'expansions': ['pinned_tweet_id'],
    'user.fields': [
      'name',
      'created_at',
      'description',
    ],
  };

  // join request queryParameters
  final params = queryParameters.entries.map((paramEntry) {
    final value = paramEntry.value.join(',');
    return '${paramEntry.key}=$value';
  }).reduce((param1, param2) {
    return '${param1}&${param2}';
  });

  final result = await http.get(
    'https://api.twitter.com/2/users/by/username/Luecy1?$params',
    headers: {'Authorization': 'Bearer ${oauthToken.accessToken}'},
  );

  print(result.body);
}

class OauthToken {
  final String tokenType;
  final String accessToken;

  OauthToken(this.tokenType, this.accessToken);

  OauthToken.fromJson(Map<String, dynamic> json)
      : tokenType = json['token_type'],
        accessToken = json['access_token'];
}

まとめ

従来のOauth1.0aのときはoauthライブラリを使わないとhmac-sha1というアルゴリズムで署名する必要があり、かなりハードルが高かった印象がありました。
今回のv2ではヘッダーやボディにbase64やあるいはそのまま指定するだけで利用でき、かなり簡単に使えました☺️

参考

https://techbookfest.org/product/5734388805402624?productVariantID=5699465224650752
とらい!Twitter新API
APIキーやAPIキーシークレットを取得するのは若干ハードルが高いです。
有料書籍ですがその流れが記載されているので、おすすめです。