初めに
この記事は記事投稿キャンペーン
の参加記事です。
今僕はシェアハウスをしており、共通で使う消耗品などを毎月決算する運用をしています。
費用の計算を毎回手で行うのは手間だなと思ったので、いい感じに計算を行うための仕組みを作りました。
自動で計算をする上で、家計簿アプリのZaimを使い、以下のような仕組みを実現したので記事にします。
- Zaimに使った費用を記録する
- 毎日前日に使った費用の一覧をSlackに自動投稿する
- 毎月の締め日に、先月使った費用の合計数、費用一覧、一人当たりの費用をSlackに自動投稿する
この仕組みを作るにあたり、Zaim APIを簡単に使えるようにするためのRubyクライアントを作成したので紹介します。
なぜZaimなのか
僕は普段はマネーフォワード MEを使って口座管理をしています。
しかし今回はZaimを採用しました。
なぜZaimを利用したかというと、ZaimにはAPIが公式で提供されているという特徴があるからです。
Zaim APIを使うことで、簡単に使った費用データの取得と加工を行うことができます。
作ったもの
早速ですが実装したコードを紹介します。
の記事を参考にして、以下のようなコードでクライアントを実装しました。
なお、GitHubにも公開しています。
# 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
# 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/ から取得を行うようにお願いします。
コンシューマーキーを取得するまでの流れは以下の記事などが参考になるかもしれません。
zaim/verifier.rb
zaim/verifier.rb
は認証を行うためのクラスです。
Zaim APIはOAuth1.0aによる認証をサポートしているので、コンシューマーキー、コンシューマーシークレットキー、コールバックURLをもとに、認証→アクセストークンを取得するところまでの処理をメソッドとして用意しました。
使い方は以下のような形になると思います。
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へリクエストを送ることができるようにしています。
使い方は以下のようなイメージです。
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トークからぜひ「話したい」をお願いします!