端っこプログラマーの手帳

主にプログラムに関する手記です

PHPでWunderlist API を叩いてみる

こんにちは~。kzhishuです。

早速なのですが、自分はタスク管理に、Wunderlistを使っています。
タスク登録を一部自動化してみたかったので、APIを調べました。
ドキュメントが簡潔に書かれているため、「英語無理~」という自分のような人間でも比較的簡単にできました。 TwitterとかでAPIに触れたことがあるという方はドキュメントをみてパッパッと料理できてしまうと思います。 ですが、日本語の情報が少ないので、まとめてみます。 なお、Wunderlistのアカウントは既に持っていることを前提に話を進めています。
Wunderlist ドキュメント

APIキーの取得

まずはAPIキーを取得のため、Wunderlistへのアプリーケーション登録が必要です。 「アプリーケーション登録」というと大げさに聞こえますが、アプリケーション名とコールバックURLを登録すればOKです。

Wunderlist開発者用ページ の MY APP > Create New App から以下の情報を入力しました。Name は適当に、App Url と Auth Callback URL を実行環境と合わせれば問題ないと思います。ちなみに、この2項目は、後から変更可能です。

Name
 wnuderlist util
Description
 未入力
App Icon
 未入力
App Url
 http://localhost
Auth Callback URL
 http://localhost/wunderlist

SAVEボタンを押した後、「Client Id」「Client Secret」が表示されます。
この2つがAPIでアクセスする際に必要になります。これをメモっておきましょう。

アクセストークンの取得

APIを使用するために、アクセストークンを取得します。 ドキュメントでのリクエスト手順をPHPで記述してみます。 流れは、

1、初回リクエスト(GET)
2、リダイレクト(code値の取得)
3、code値とAPIキー情報をPOSTでリクエスト
4、3のレスポンスでアクセストークンが返ってくる

といった具合。

<?php
// 1 設定の定義
$client_id = '/* Client Id */';
$client_secret = '/* Client Secret */';
$redirect_url = '/* Auth Callback URL */';
$state = '/* STATE */';    

if(!isset($_GET['code'])){
    // 2 初回のアクセス
    header("Location: https://www.wunderlist.com/oauth/authorize?redirect_uri={$redirect_url}&client_id={$client_id}&state={$state}");
    exit();
}
else{
    // 3 リダイレクト後 アクセストークンの取得
    $code = $_GET['code'];
    $rdstate = $_GET['state'];
    
    if($rdstate != $state){
        exit('stateの内容が違います');
    }
    
    $params = array(
        'client_id' => $client_id,
        'client_secret' => $client_secret,
        'code' => $code
    );
    
    $token_url = 'https://www.wunderlist.com/oauth/access_token';
    $context = array(
        "http" => array(
            "method"  => "POST",
            "content" => http_build_query($params)
        )
    );
    $response = file_get_contents($token_url, false, stream_context_create($context));
    $json = json_decode($response);
    $access_token = $json->access_token;
    /* 以下タスク取得などの処理が続きます */
}
?>

1 設定の定義
先ほど取得した「Client Id」「Client Secret」と登録した「Auth Callback URL」を変数で定義します。 state についてはCSRF対策のために必要なようです。 リダイレクト時の実行プログラムが正しいかどうかを保障するためと理解しました。「リクエスト前のstate」と「リダイレクト後のstate」が同一であるか調べることでその判定ができそうです。予測しづらい文字列を書いておけばよいかと思います。

2 初回のアクセス
client_id, redirect_url, stateをパラメータに https://www.wunderlist.com/oauth/authorize へGETリクエストしています。 初回の実行はここで終了なので、exit(); しています。 成功するとredirect_url に「code」と「state」の2つパラメータと共にリクエストが帰ってきます。このとき、redirect_url と登録した「Auth Callback URL」が異なる場合は失敗します。リダイレクトかどうかは、GETパラメータ「code」の有無で判断しました。

3 リダイレクト後 アクセストークンの取得
リダイレクトの「state」が正しいか検証した後、「code」の値を取得します。 その値を、client_id, client_secret と共に今度はPOSTで https://www.wunderlist.com/oauth/access_token にリクエストします。 処理には file_get_contents() を使いました。(file_get_contents() ってヘッダーつけたり、POSTでリクエストできるんですね) レスポンスはJSON形式で返って来るためそれを取得します。これでアクセストークンを取得できました。

APIを叩く(リスト取得とタスク登録)

これでやっと準備が整いました。ここからリストを取得したりタスクを登録したりというAPIを叩いていくのですが、リクエスト時に2つ決まりがあります。

・リクエストヘッダーにアクセストークンとクライアントIDをつける(X-Access-Token、X-Client-ID)
・パラメータはJSON形式で送る
(またリクエストヘッダーにも Content-Type: application/json; をつける)

以上を元に取得してみます。プログラムは、上の /* 以下タスク取得などの処理が続きます */の部分に書いていきます。まずはリストの取得。 $json に自分のWunderlist のリストがしっかりと含まれ無事成功しました。

<?php
    $header = array(
         "X-Client-ID: {$client_id}",
         "X-Access-Token: {$access_token}",
         "Content-Type: application/json; charset=utf-8",
    );
    
    $list_url = 'https://a.wunderlist.com/api/v1/lists';
    $context = array(
         "http" => array(
              "method"  => "GET",
              "header"  => implode("\r\n", $header)
         )
    );
    $response = file_get_contents($list_url, false, stream_context_create($context));
    $json = json_decode($response);
?>

リストが取得できれば、list_id がわかりますので、そのidを指定することで、タスクの登録ができます。一つ注意点として、パラメータを送る際は Content-Length: [文字数] をリクエストヘッダーに含める必要があるようです。これで無事にタスクを登録することができました。

<?php
    $data = json_encode($params);

    $header = array(
         "X-Client-ID: {$client_id}",
         "X-Access-Token: {$access_token}",
         "Content-Type: application/json; charset=utf-8",
         "Content-Length: ".strlen($data)
    );
    
    $task_url = 'https://a.wunderlist.com/api/v1/tasks';
    $params = array(
        'list_id' => '/* list_id */',
        'title' => 'テスト タスク'
    );
    
    $context = array(
         "http" => array(
              "method"  => "POST",
              "header"  => implode("\r\n", $header),
              "content" => $data
         )
    );
    $response = file_get_contents($task_url, false, stream_context_create($context));
    $json = json_decode($response);
?>

クラス化してみる

記述したコードを上から眺めていると、同じような処理が重複しており、頭がクラクラしてきますので、クラス化してリスト名を指定してタスクが登録できるようなサンプルコードを書いてみました。インスタンス生成後、URLとリクエストメソッドとパラメータを指定すればAPIを叩けるようになっています。 詳細は以下のGitHubにコードを載せておきました。これでだいぶスッキリです。
Wunderlist API · GitHub