Zaim APIを使うためにRubyでAPIクライアントを作った

## 初めに
この記事は記事投稿キャンペーン

https://qiita.com/official-events/6d31965c499a69377c0b

の参加記事です。

今僕はシェアハウスをしており、共通で使う消耗品などを毎月決算する運用をしています。
費用の計算を毎回手で行うのは手間だなと思ったので、いい感じに計算を行うための仕組みを作りました。

自動で計算をする上で、家計簿アプリの[Zaim](https://zaim.net/)を使い、以下のような仕組みを実現したので記事にします。

1. Zaimに使った費用を記録する
1. 毎日前日に使った費用の一覧をSlackに自動投稿する
1. 毎月の締め日に、先月使った費用の合計数、費用一覧、一人当たりの費用をSlackに自動投稿する

この仕組みを作るにあたり、Zaim APIを簡単に使えるようにするためのRubyクライアントを作成したので紹介します。

## なぜZaimなのか
僕は普段はマネーフォワード MEを使って口座管理をしています。
しかし今回はZaimを採用しました。
なぜZaimを利用したかというと、ZaimにはAPIが公式で提供されているという特徴があるからです。
Zaim APIを使うことで、簡単に使った費用データの取得と加工を行うことができます。

https://dev.zaim.net/

## 作ったもの
早速ですが実装したコードを紹介します。

https://qiita.com/seteen/items/12f535228e2a3453764b

の記事を参考にして、以下のようなコードでクライアントを実装しました。
なお、[GitHub](https://github.com/getty104/zaim_client_ruby)にも公開しています。

```rb:zaim/client.rb
# frozen_string_literal: true

require 'json'
require 'oauth'
require 'uri'

module Zaim
  class Client
    API_URL = 'https://api.zaim.net'

    private attr_reader :access_token

    def initialize(consumer_key:, consumer_secret:, access_key:, access_secret:)
      consumer = OAuth::Consumer.new(
        consumer_key,
        consumer_secret,
        site: 'https://api.zaim.net',
        request_token_path: '/v2/auth/request',
        authorize_url: 'https://auth.zaim.net/users/auth',
        access_token_path: '/v2/auth/access'
      )

      @access_token = OAuth::AccessToken.new(consumer, access_key, access_secret)
    end

    def request(http_method:, endpoint:, params: {})
      unless %i(get post put delete patch).include?(http_method)
        raise NotPermittedValueError, 'Only :get, :post, :put, :delete, :patch are allowed for http_method'
      end

      uri = URI.parse("#{API_URL}#{endpoint}")
      uri.query = nil
      request_url = uri.to_s

      response = if %i(get delete).include?(http_method)
        formatted_params = params.map { |key, value| "#{key}=#{value}" }.join('&')
        request_url = "#{request_url}?#{formatted_params}" if formatted_params.present?
        access_token.get(request_url)
      else
        access_token.send(http_method, request_url, params)
      end

      JSON.parse(response.body, symbolize_names: true)
    end

    class NotPermittedValueError < StandardError; end
  end
end

```

```rb:zaim/verifier.rb
# frozen_string_literal: true

require 'oauth'
require 'json'

module Zaim
  class Verifier
    private attr_reader :request_token

    def initialize(consumer_key:, consumer_secret:, oauth_callback:)
      consumer = OAuth::Consumer.new(
        consumer_key,
        consumer_secret,
        site: 'https://api.zaim.net',
        request_token_path: '/v2/auth/request',
        authorize_url: 'https://auth.zaim.net/users/auth',
        access_token_path: '/v2/auth/access'
      )
      @request_token = consumer.get_request_token(oauth_callback:)
    end

    def authorize_url
      request_token.authorize_url
    end

    def get_access_token(oauth_verifier:)
      access_token = request_token.get_access_token(oauth_verifier:)
      {
        access_key: access_token.token,
        access_secret: access_token.secret
      }
    end
  end
end

```

## 使い方
今回は`zaim/client.rb`と`zaim/verifier.rb`という二つのクラスを作っています。
それぞれの役割は以下の通りです。

- zaim/verifier.rb → 認証を行うためのクラス
- zaim/client.rb → 実際にZaim APIへリクエストを送るためのクラス

それぞれのクラスについての具体ていな説明を行っていきます。
なお、説明はコンシューマーキーを取得している前提で話を進めます。

https://dev.zaim.net/ から取得を行うようにお願いします。
コンシューマーキーを取得するまでの流れは以下の記事などが参考になるかもしれません。

https://qiita.com/seteen/items/12f535228e2a3453764b

### zaim/verifier.rb
`zaim/verifier.rb`は認証を行うためのクラスです。
Zaim　APIはOAuth1.0aによる認証をサポートしているので、コンシューマーキー、コンシューマーシークレットキー、コールバックURLをもとに、認証→アクセストークンを取得するところまでの処理をメソッドとして用意しました。
使い方は以下のような形になると思います。

```rb
require_relative 'zaim/verifier'

verifier = Zaim::Verifier.new(
  consumer_key: ENV['CONSUMER_KEY'],
  consumer_secret: ENV['CONSUMER_SECRET'],
  oauth_callback: 'https://example.com'
)

puts verifier.authorize_url #=>認証用のURLを発行
print "Verifier:"
oauth_verifier = gets.chomp.strip #=> authorize_urlからログインをした後に取得できるverifierを入力
pp verifier.get_access_token(oauth_verifier:) #=> verifierからアクセストークンを発行
```

### zaim/client.rb
`zaim/client.rb`は実際にZaim APIを叩くためのクラスです。
今回は横着してHTTPメソッドとエンドポイント、リクエストパラメータを渡すことでAPIへリクエストを送ることができるようにしています。

使い方は以下のようなイメージです。

```rb
require 'json'
require_relative 'zaim/client'

client = Zaim::Client.new(
  consumer_key: ENV['CONSUMER_KEY'],
  consumer_secret: ENV['CONSUMER_SECRET'],
  access_key: ENV['ACCESS_KEY'],
  access_secret: ENV['ACCESS_SECRET']
)

response = client.request(http_method: :get, endpoint: '/v2/home/user/verify') #=>認証ができているかどうかのチェック

if response[:error] #=> 認証ができていない時
...
else #=>認証ができているとき
...
end
```

## 最後に

今回実装したコードを用いて、毎月の費用計算を楽にできるようにしました。

もし筆者の僕と雑談をしてみたい方がいれば、↓のDevトークからぜひ「話したい」をお願いします！

https://jobs.qiita.com/employers/qiita-inc/dev_talks/27