GASからZaim APIを利用する

# はじめに
- 個人向け家計簿サービスでAPIが提供されているものを探していたが、有名なところだとZaimくらいしか見つからなかった
- ググってもZaim APIについての情報が少なかった
- [GAS(Google Apps Script)](https://developers.google.com/apps-script/)からZaimをあれこれする方法を探って見つけたのでメモ

# Zaimに登録する
- [https://zaim.net/](https://zaim.net/)
  - Zaim使ったこと無いならAPI叩く前にいくらか使って理解を深めておいたほうが良い(自戒)
- [https://dev.zaim.net/](https://dev.zaim.net/)
  - 開発者登録(ログイン)もしておく


# Zaimアプリケーションの作成
[Zaim Developer Center](https://dev.zaim.net/home/clients/add) から自分のZaimの情報にアクセスするためのアプリケーションを作成する。
![image.png](https://qiita-image-store.s3.amazonaws.com/0/40264/174f4311-6c96-2891-93bf-edad231b12e3.png)
↑実際はちゃんと入力しましょう。

また、「家計簿へのアクセスを永続的に許可する」にチェックを入れないと24時間ごとに認証が必要になるようです。
> "Permanently accessible to your account book" means that a user once permits using Zaim, you can access user's data whenever until the user withdraws from Zaim or revokes the permission. If you don't check it, the permission expires in 24 hours.

引用: https://dev.zaim.net/home/api/authorize

アプリケーションの作成が完了すると以下の情報が手に入ります。

|名称|値|
|:---|:---|
|コンシューマ ID|長い文字列|
|コンシューマシークレット|長い文字列|
|リクエストトークン取得 URL|https://api.zaim.net/v2/auth/request|
|認証 URL|https://auth.zaim.net/users/auth|
|アクセストークン取得 URL|https://api.zaim.net/v2/auth/access|

# GASからOAuth認証をしてZaimの情報を取得する

作成したZaimアプリケーションは、OAuth認証をすることでユーザの代わりにユーザの情報にアクセスすることが出来ます。なお、OAuth以外の認証方法は提供されていないので、必ずOAuthで認証する必要があります。

なお、開発者サイトにもあるようにOAuthの認証形式はTwitterと非常に似ているので、ここではTwitterのOAuth認証のサンプルを参考にGASから認証を試みます。
> Check the format of OAuth 1.0a in this page: http://oauth.net/core/1.0a/
> Zaim OAuth format is nearly the same with Twitter API: https://dev.twitter.com/docs/auth/oauth

引用: https://dev.zaim.net/home/api/authorize

## OAuth1 for Apps Script
- https://github.com/googlesamples/apps-script-oauth1
- **OAuth1で認証・認可を行うためのGAS Library**
- Google公式のLibraryで、サンプルも豊富
- 今回はTwitterのサンプルを改造して使う
- 参考: https://sites.google.com/site/gasgaidobukku/scon/raiburari/oauth1raiburariwo-shi-yongshitetwitterniakusesu

## GASプロジェクトを作成し、ライブラリを導入する
主な流れは以下の通りです。

1. 新規GASプロジェクトを作成する
2. 上記ライブラリ(ID: `1CXDCY5sqT9ph64fFwSzVtXnbjpSfWdRymafDrtIZ7Z_hwysTY7IIhi7s`)をGASプロジェクトに導入する
3. [Twitter用のサンプル](https://raw.githubusercontent.com/googlesamples/apps-script-oauth1/master/samples/Twitter.gs) をGASプロジェクトにコピペして適宜書き換える
4. 初回実行(OAuth認証を求められる)
5. 再度実行(サンプルが動く)

### 1. 新規GASプロジェクトの作成
GASプロジェクトの作成は様々なサイトで解説されていますが、例えば [こちら](https://qiita.com/yabaiwebyasan/items/cbb9832d42dc627800fb) の一番最初の項目が参考になるかと思います。

### 2. ライブラリの追加
作成したGASプロジェクトに前述のOAuth1ライブラリを追加します。これを追加することで、プロジェクト内で `OAuth1` というオブジェクトが使用可能になります。
![image.png](https://qiita-image-store.s3.amazonaws.com/0/40264/3d5ad670-3261-b1e3-8153-f9b489c0f89d.png)

OAuth1ライブラリのID `1CXDCY5sqT9ph64fFwSzVtXnbjpSfWdRymafDrtIZ7Z_hwysTY7IIhi7s` を入力することで追加できます。
![image.png](https://qiita-image-store.s3.amazonaws.com/0/40264/02e6eb35-7b04-26df-a0f2-fa53593505d6.png)

追加後に選択できる「バージョン」はなるべく新しい方が良いかと思いますが、ここでは「15」を利用しています。

### 3. Twitter用のサンプルを書き換える
参考リンク: https://sites.google.com/site/gasgaidobukku/scon/raiburari/oauth1raiburariwo-shi-yongshitetwitterniakusesu

Twitter用のサンプルを [ここ](https://raw.githubusercontent.com/googlesamples/apps-script-oauth1/master/samples/Twitter.gs) からコピーして、GASプロジェクトに貼り付ける。
![image.png](https://qiita-image-store.s3.amazonaws.com/0/40264/6ff561ab-a269-0e47-e6a7-ac9ed68ecb05.png)

コンシューマID、コンシューマシークレット、リクエストトークン取得URL、APIエンドポイントなど、各種文字列をZaim用に書き換える。

```JavaScript
var CONSUMER_KEY = '取得したコンシューマID';
var CONSUMER_SECRET = '取得したコンシューマシークレット';

/**
 * Authorizes and makes a request to the Zaim API.
 */
function run() {
  var service = getService();
  if (service.hasAccess()) {
    var url = 'https://api.zaim.net/v2/home/money';
    var response = service.fetch(url, {
      method: 'get'
    });
    var result = JSON.parse(response.getContentText());
    Logger.log(JSON.stringify(result, null, 2));
  } else {
    var authorizationUrl = service.authorize();
    Logger.log('次のURLを開いてZaimで認証したあと、再度スクリプトを実行してください。: %s',
        authorizationUrl);
  }
} 

/**
 * Reset the authorization state, so that it can be re-tested.
 */
function reset() {
  var service = getService();
  service.reset();
}

/**
 * Configures the service.
 */
function getService() {
  return OAuth1.createService('Zaim')
      // Set the endpoint URLs.
      .setAccessTokenUrl('https://api.zaim.net/v2/auth/access')
      .setRequestTokenUrl('https://api.zaim.net/v2/auth/request')
      .setAuthorizationUrl('https://auth.zaim.net/users/auth')
  
      // Set the consumer key and secret.
      .setConsumerKey(CONSUMER_KEY)
      .setConsumerSecret(CONSUMER_SECRET)

      // Set the name of the callback function in the script referenced
      // above that should be invoked to complete the OAuth flow.
      .setCallbackFunction('authCallback')

      // Set the property store where authorized tokens should be persisted.
      .setPropertyStore(PropertiesService.getUserProperties());
}

/**
 * Handles the OAuth callback.
 */
function authCallback(request) {
  var service = getService();
  var authorized = service.handleCallback(request);
  if (authorized) {
    return HtmlService.createHtmlOutput('認証できました！このページを閉じて再びスクリプトを実行してください。');
  } else {
    return HtmlService.createHtmlOutput('認証に失敗');
  }
}
```

### 4. 初回実行とOAuth認証
GAS上部タブから「関数を選択」→「run」を選択して「▶」ボタンを押すことでrun関数を実行します。
初めて実行する場合はGoogleの認証が求めらるので許可しておきましょう。なお、これはGASが外部サービスへアクセスする許可であって、ZaimのOAuth認証とは異なります。
![image.png](https://qiita-image-store.s3.amazonaws.com/0/40264/552f2cb3-7dda-82b1-2c35-de5e5e69fd82.png)
許可をするとrun関数が実行されますが、何も変化がないように思えます。
初回実行時はログにZaimのOAuth認証用URLが表示されていますので、**「表示」→「ログ」**からログを開きます。
![image.png](https://qiita-image-store.s3.amazonaws.com/0/40264/c747169f-c542-a0cb-d099-44a29fd09c09.png)

ログに表示されたURLを開くといわゆるTwitter認証のようなページが開きます。「許可する」を選択します。
![image.png](https://qiita-image-store.s3.amazonaws.com/0/40264/12ec8b9b-4fbb-b74c-9526-0068b1128fbc.png)

本来であればコールバックURLに自動で遷移するはずですが、なぜか遷移しません。（Zaim側のバグ？）
そこでページのソースを見てみると、

```
<div class="callback">https://script.google.com/macros/d/XXXXXXXXXXX/usercallback?state=XXXXXXXXX&oauth_token=xxxxxxxx&oauth_verifier=xxxxxxxx<div class="callback_end"></div></div>
```

というコールバックURLが見つかるので、この `https://script～` のURLをブラウザに直接貼り付けて移動します。
![image.png](https://qiita-image-store.s3.amazonaws.com/0/40264/efb4146f-64da-7492-83b5-627f618f0019.png)
↑サンプルを書き換えていればこのように表示される

### 5. 再びスクリプトを実行する
再びGASのプロジェクト画面に戻り、run関数を実行します。GASのログに今度は以下のような支払い履歴が表示される。

```javascript
[18-03-05 07:42:14:572 PST] {
  "money": [
    {
      "id": ******,
      "user_id": *****,
      "date": "2018-03-04",
      "mode": "payment",
      "category_id": ***,
      "genre_id": *****,
      "from_account_id": ******,
      "to_account_id": 0,
      "amount": 299,
      "comment": "",
      "active": 1,
      "created": "2018-03-04 18:42:42",
      "currency_code": "JPY",
      "name": "ベーコン",
      "receipt_id": *********,
      "place_uid": "*************",
      "place": "hogehogeコンビニ"
    }, ... 
  "requested": *****
}
```

これらの値の意味は [ZaimのAPIドキュメント](https://dev.zaim.net/home/api) に書いてあります。
あとはログに出力するところをSlackに送信するようにするなり、SpreadSheetに記録するようにするなり、特殊な計算をするなり。


# おわりに
久しぶりにGASもAPIも触ったのでちょっと大変でした。あとZaimのAPI情報少なすぎですね。。

実際はこのあとSlackのbotを作ってbotに現在の利用金額などを喋らせるようにしたのですが、さすがにここでは文量的に書けません。（ZaimのAPIを動かすことよりSlackのAPI理解とGASからのSlack発言に時間を取られました…）