PythonからOAuthを使ってZaimのAPIを叩きます。
Slackから決まった物をZaimに登録できれば、家計簿の管理がかなり簡略化できます。
まずは、[ここ](https://dev.zaim.net)からZaimの開発者APIをたたくための登録をします。
URLを登録する場所がありますが、なんでもOKなのでhttp://example.comなどを入力しておきます。
その時に発行されるコンシューマIDや認証URLなどを一通り控えておきます。
### 環境
* Python 2.7.9
### 必要なモジュールのインストール
まずはPythonでOAuth認証するためのモジュールをインストールします。
Pythonでの実装は[ここ](https://remotestance.com/blog/1037/)を参考にしました。
```bash
$ sudo pip install oauth2
$ sudo pip install urllib
```
## APIを実行するまでの流れ
APIを実行するには下記の手順を踏む必要があります。
(1度行えば、次回からは不要になります。)
1. OAuth Token, OAuth Token Secretを取得する
2. 上記を使って、ブラウザで認証を行い、OAuth Verifierを取得する
3. Access Token, Access Token Secretを取得する
4. 1から3までの情報を使ってAPIを使用する
## 認証用のRequest, Tokenを取得する
まずは、OAuth認証するためには、一回ブラウザで認証をする必要があります。
OAuth Token, OAuth Token Secretを取得します。
```python
# coding: utf-8
import urllib
import oauth2 as oauth
request_token_url = 'https://api.zaim.net/v2/auth/request'
access_token_url = 'https://api.zaim.net/v2/auth/access'
authenticate_url = 'https://auth.zaim.net/users/auth'
callback_url = 'https://www.zaim.net/'
consumer_key = 'consumerkeyxxxxxxxxxxxxxxxxxxxxxxxxxxxxx'
consumer_secret = 'consumenrsecretxxxxxxxxxxxxxxxxxxxxxxxxx'
def get_request_token():
consumer = oauth.Consumer(key=consumer_key, secret=consumer_secret)
client = oauth.Client(consumer)
# get the request_token
resp, content = client.request('%s?&oauth_callback=%s' % (request_token_url, callback_url))
request_token = dict(parse_qsl(content))
print 'OAuth Token Secret: %s' % request_token['oauth_token_secret']
print 'OAuth Token : %s' % request_token['oauth_token']
return request_token['oauth_token']
def parse_qsl(url):
param = {}
for i in url.split('&'):
_p = i.split('=')
param.update({_p[0]: _p[1]})
return param
def get_access_token(oauth_token, oauth_verifier):
customer = oauth.Consumer(key=consumer_key, secret=consumenr_secret)
token = oauth.Token(oauth_token, oauth_verifier)
client = oauth.Client(consumer, token)
resp, content = client.request(access_token_url, "POST", body="oauth_verifier={0}".format(oauth_verifier))
return content
# main
## request tokenを取得
request_token = get_request_token()
## request_tokenを認証URLにつけて認証URLを生成する
authorize_url = '%s?oauth_token=%s' % (authenticate_url, request_token)
print 'Authorize url: %s' % authorize_url
```
## ブラウザを使ってOAuth Verifierを取得する
上記で作成したURLを使ってブラウザでアクセスします。
認証を行ったら、そのページ内の"oauth_verifier"を控えておきます。
(HTMLのソースを表示でソースないに表示されます)
これが後々の通信に必要になります。
## Access Token, Access Token Secretの取得
下記のコードで取得します。
これで取得したAccess Token, Access Token Secretも控えておきましょう。
```python
# coding: utf-8
import urllib
import oauth2 as oauth
import urlparse
request_token_url = 'https://api.zaim.net/v2/auth/request'
access_token_url = 'https://api.zaim.net/v2/auth/access'
authenticate_url = 'https://auth.zaim.net/users/auth'
callback_url = 'https://www.zaim.net/'
consumer_key = 'consumer key'
consumer_secret = 'consumer secret'
request_token = 'reequest token'
request_token_secret = 'request token secret'
oauth_verifier = 'oauth verifier'
def main():
consumer = oauth.Consumer(key=consumer_key, secret=consumer_secret)
token = oauth.Token(request_token, request_token_secret)
token.set_verifier(oauth_verifier)
client = oauth.Client(consumer, token)
resp, content = client.request(access_token_url, 'POST')
access_token = dict(urlparse.parse_qsl(content))
print 'Access Token: %s' % access_token['oauth_token']
print 'Access Token Secret: %s' % access_token['oauth_token_secret']
if __name__ == '__main__':
main()
```
ここまでで、APIにアクセスするための情報が全て集まりました。
## 通信サンプル
ここまでの情報を使って通信するサンプルになります。
ユーザー情報を引っ張ってきます。
結果はcontentにJSON形式で入ります。
リクエストパラメーターがある場合はparamsにkey:valueで登録します。
```python
# coding: utf-8
from urllib import urlencode
import oauth2 as oauth
import urlparse
request_token_url = 'https://api.zaim.net/v2/auth/request'
access_token_url = 'https://api.zaim.net/v2/auth/access'
authenticate_url = 'https://auth.zaim.net/users/auth'
callback_url = 'https://www.zaim.net/'
consumer_key = 'consumer key'
consumer_secret = 'consumer secret'
request_token = 'request token'
request_token_secret = 'request token secret'
oauth_verifier = 'oauth verifier'
access_token = 'access token'
access_token_secret = 'access token secret'
base_hostname = 'https://api.zaim.net'
def main():
url = base_hostname + '/v2/home/user/verify'
token = oauth.Token(key=access_token, secret=access_token_secret)
consumer = oauth.Consumer(key=consumer_key, secret=consumer_secret)
params = {}
#
# paramsがある場合は params = {'key':'valye'} で登録する
#
client = oauth.Client(consumer, token)
resp, content = client.request(url, method='GET', body=urlencode(params))
print resp
print content
if __name__ == '__main__':
main()
```
あとはAPIのリファレンスを見ながら投稿できます。
## 支出を登録するサンプル
支出を登録するコードのサンプルです。
```python
# coding: utf-8
import sys
from urllib import urlencode
import oauth2 as oauth
import urlparse
request_token_url = 'https://api.zaim.net/v2/auth/request'
access_token_url = 'https://api.zaim.net/v2/auth/access'
authenticate_url = 'https://auth.zaim.net/users/auth'
callback_url = 'https://www.zaim.net/'
consumer_key = 'consumer key'
consumer_secret = 'consumer secret'
request_token = 'request token'
request_token_secret = 'request token secret'
oauth_verifier = 'oauth verifier'
access_token = 'access token'
access_token_secret = 'access token token secret'
base_hostname = 'https://api.zaim.net'
#
# ZaimのAPIでアクセスする
#
def access_zaim_api(api, method, params):
url = base_hostname + api
token = oauth.Token(key=access_token, secret=access_token_secret)
consumer = oauth.Consumer(key=consumer_key, secret=consumer_secret)
client = oauth.Client(consumer, token)
resp, content = client.request(url, method=method, body=urlencode(params))
# print resp
# print content
return resp
def input_payment_data(category_id, genre_id, amount, date, from_account_id, comment, name, place):
params = {
'mapping' : 1,
'category_id' : category_id,
'genre_id' : genre_id,
'amount' : amount,
'date' : date,
'from_account_id' : from_account_id,
'comment' : comment,
'name' : name,
'place' : place
}
return access_zaim_api('/v2/home/money/payment', 'POST', params)
if __name__ == '__main__':
# 保育料の設定
input_payment_data(109, 11111111, 1111, '2017-12-22', 1111111, '保育料', '', '')
```
amountに金額を設定します。
genre_idなどは、取得するAPIがあるので、そちらで取得してどのIDで登録するか事前に調べておきます。
取得したJSONの文字列はUnicodeでエンコードされているので、jqコマンドを使って読めるようにして調べると良いです。
resp, content = client.request(url, method='GET', body=urlencode(params))でエンコードのエラーがでたので、変えました。TypeError: Unicode-objects must be encoded before hashing
返信削除resp, content = client.request(url, method='GET', body=urlencode(params).encode('UTF-8'))