Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
- Loading branch information
kudotk
committed
Dec 24, 2018
0 parents
commit 181f62f
Showing
9 changed files
with
320 additions
and
0 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,2 @@ | ||
node_modules | ||
config/development.json |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,49 @@ | ||
# Zaim Rest API Sample | ||
|
||
## Overview | ||
|
||
ZaimのREST API実行サンプルです | ||
|
||
## Requirement | ||
|
||
* node v10.13.0 | ||
* npm 6.4.1 | ||
|
||
## Install | ||
|
||
### 1. Zaim認証ID取得 | ||
|
||
https://dev.zaim.net/users/login にログイン | ||
[新しいアプリケーションを追加]で適当に入力 | ||
コンシューマID、コンシューマシークレットをconfig/default.jsonに追記 | ||
|
||
### 2. ユーザートークン取得 | ||
|
||
``` | ||
$ npm install | ||
$ npm run start | ||
``` | ||
ブラウザで http://127.0.0.1 を開く | ||
OAuthの[認証実行]をクリック | ||
Zaimの認証画面に移動するので許可する | ||
完了画面に移動するがリダイレクトされないので、Chrome開発者ツールなどでソースを表示 | ||
div.callbackのURL`http://127.0.0.1:4000/auth/callback?〜`をブラウザで開く | ||
表示されたtoken、token secretをconfig/default.jsonに追記 | ||
|
||
## Usage | ||
|
||
Install後、`npm run start`で再起動 | ||
ブラウザで http://127.0.0.1 を開き、ユーザー情報の取得、合計金額の取得を実行すると、Zaimに入力しているデータが表示される | ||
|
||
## Reference | ||
|
||
* [RubyでZaim APIを利用する](https://qiita.com/seteen/items/12f535228e2a3453764b) | ||
* [GASからZaim APIを利用する](https://qiita.com/shutosg/items/6845057432bca551024b) | ||
|
||
## Licence | ||
|
||
[MIT](https://github.com/tcnksm/tool/blob/master/LICENCE) | ||
|
||
---- | ||
|
||
(c) 2018 kudotk |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,8 @@ | ||
{ | ||
"zaim": { | ||
"consumerId": "<put your app id>", | ||
"consumerSecret": "<put your app secret>", | ||
"userToken": "<put your user-token>", | ||
"userTokenSecret": "<put your user-token-secret>" | ||
} | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,25 @@ | ||
{ | ||
"name": "zaim-rest-api-sample", | ||
"version": "1.0.0", | ||
"description": "", | ||
"main": "index.js", | ||
"scripts": { | ||
"start": "NODE_ENV=development node server.js", | ||
"test": "echo \"Error: no test specified\" && exit 1" | ||
}, | ||
"keywords": [], | ||
"author": "", | ||
"license": "MIT", | ||
"dependencies": { | ||
"body-parser": "^1.18.3", | ||
"config": "^3.0.1", | ||
"cors": "^2.8.5", | ||
"express": "^4.16.4", | ||
"express-session": "^1.15.6", | ||
"morgan": "^1.9.1", | ||
"oauth": "^0.9.15", | ||
"passport": "^0.4.0", | ||
"passport-oauth1": "^1.1.0", | ||
"pug": "^2.0.3" | ||
} | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,176 @@ | ||
const express = require('express') | ||
const cors = require('cors') | ||
const passport = require('passport') | ||
const OAuth1Strategy = require('passport-oauth1') | ||
const session = require('express-session') | ||
const morgan = require('morgan') | ||
const oauth = require('oauth').OAuth | ||
const config = require('config') | ||
const bodyParser = require('body-parser'); | ||
|
||
/** | ||
* Environment | ||
*/ | ||
|
||
// zaim OAuthパラメータ | ||
const zaimOauthOptions = { | ||
requestTokenURL: 'https://api.zaim.net/v2/auth/request', | ||
accessTokenURL: 'https://api.zaim.net/v2/auth/access', | ||
consumerKey: config.get('zaim.consumerId'), | ||
consumerSecret: config.get('zaim.consumerSecret'), | ||
signatureMethod: "HMAC-SHA1", | ||
} | ||
|
||
// zaim他パラメータ | ||
const zaim = { | ||
oauth1StrategyOptions: Object.assign(zaimOauthOptions, | ||
{ | ||
userAuthorizationURL: 'https://auth.zaim.net/users/auth', | ||
callbackURL: "http://127.0.0.1:4000/auth/callback", | ||
}), | ||
|
||
// Zaim user oauth token which passport sets | ||
userToken: config.get('zaim.userToken'), | ||
userTokenSecret: config.get('zaim.userTokenSecret') | ||
} | ||
|
||
|
||
/** | ||
* Express | ||
*/ | ||
const app = express() | ||
app.use(cors()) | ||
app.use(morgan('short')) | ||
app.use(bodyParser.urlencoded({extended: true})) | ||
app.set('view engine', 'pug') | ||
|
||
|
||
/** | ||
* Passport | ||
*/ | ||
passport.serializeUser((user, done) => done(null, user)) | ||
passport.deserializeUser((user, done) => done(null, user)) | ||
passport.use(new OAuth1Strategy(zaimOauthOptions, | ||
function (token, tokenSecret, profile, done) { | ||
zaim.userToken = token | ||
zaim.userTokenSecret = tokenSecret | ||
return done(null, profile) | ||
} | ||
)); | ||
app.use(passport.initialize()) | ||
app.use(passport.session()) | ||
|
||
|
||
/** | ||
* Session | ||
*/ | ||
const sessionOptions = { | ||
secret: 'keyboard cat', | ||
cookie: {}, | ||
resave: false, | ||
saveUninitialized: true | ||
} | ||
if (app.get('env') === 'production') { | ||
app.set('trust proxy', 1) // trust first proxy | ||
sessionOptions.cookie.secure = true // serve secure cookies | ||
} | ||
app.use(session(sessionOptions)) | ||
|
||
|
||
/** | ||
* Routing | ||
*/ | ||
|
||
// index | ||
app.get('/', (req, res) => { | ||
res.render('index', {}) | ||
}); | ||
|
||
// 認証 | ||
app.get('/auth', passport.authenticate('oauth')); | ||
|
||
app.get('/auth/callback', | ||
passport.authenticate('oauth', {failureRedirect: '/'}), | ||
function (req, res) { | ||
res.render('auth-callback', { | ||
token: zaim.userToken, | ||
tokenSecret: zaim.userTokenSecret | ||
}) | ||
}); | ||
|
||
|
||
// zaim OAuth認証情報ヘッダ | ||
const oauthHeader = new oauth( | ||
zaimOauthOptions.requestTokenURL, | ||
zaimOauthOptions.accessTokenURL, | ||
zaimOauthOptions.consumerKey, | ||
zaimOauthOptions.consumerSecret, | ||
'1.0A', | ||
null, | ||
zaimOauthOptions.signatureMethod | ||
); | ||
|
||
// ユーザー情報取得 | ||
app.get('/user/info', (req, res) => { | ||
oauthHeader.get( | ||
'https://api.zaim.net/v2/home/user/verify', | ||
zaim.userToken, | ||
zaim.userTokenSecret, | ||
function (e, data, zaimRes) { | ||
if (e) console.error(e); | ||
res.render('result', { | ||
result: JSON.stringify(JSON.parse(data), null, ' ') | ||
}) | ||
}); | ||
}) | ||
|
||
// 指定カテゴリの合計金額取得 | ||
app.post('/category/total', (req, res) => { | ||
const category = req.body.category | ||
|
||
oauthHeader.get( | ||
'https://api.zaim.net/v2/home/category', | ||
zaim.userToken, | ||
zaim.userTokenSecret, | ||
function (e, data, zaimRes) { | ||
if (e) { | ||
console.log(e) | ||
return | ||
} | ||
|
||
const json = JSON.parse(data) | ||
let categoryId | ||
json.categories.some((elm) => { | ||
if (elm.name === category) { | ||
categoryId = elm.id | ||
return true | ||
} | ||
return false | ||
}) | ||
if (!categoryId) { | ||
res.render('result', { | ||
result: "カテゴリが見つかりませんでした" | ||
}) | ||
return | ||
} | ||
|
||
let total = 0 | ||
const params = '?mapping=1&category_id=' + categoryId + '&mode=payment' | ||
oauthHeader.get( | ||
'https://api.zaim.net/v2/home/money' + params, | ||
zaim.userToken, | ||
zaim.userTokenSecret, | ||
function (e, data, zaimRes) { | ||
const json = JSON.parse(data) | ||
json.money.forEach((elm) => { | ||
total += elm.amount | ||
}) | ||
res.render('result', { | ||
result: JSON.stringify(JSON.parse('{ "totalAmount": ' + total + '}'), null, ' ') | ||
}) | ||
}) | ||
|
||
}); | ||
}) | ||
|
||
app.listen(4000) |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,18 @@ | ||
html(lang="en") | ||
head | ||
<!-- Required meta tags --> | ||
meta(charset="utf-8") | ||
meta(name="viewport" content="width=device-width, initial-scale=1, shrink-to-fit=no") | ||
title | ||
| Zaim Rest API Sample | ||
link(rel="stylesheet" href="https://stackpath.bootstrapcdn.com/bootstrap/4.2.1/css/bootstrap.min.css" integrity="sha384-GJzZqFGwb1QTTN6wy59ffF1BuGJpLSa9DkKMp0DgiMDm4iYMj70gZWKYbI706tWS" crossorigin="anonymous") | ||
body | ||
div.container.p-0.m-4 | ||
h1.font-weight-light Zaim Rest API Sample | ||
block content | ||
|
||
script(src="https://code.jquery.com/jquery-3.3.1.slim.min.js" integrity="sha384-q8i/X+965DzO0rT7abK41JStQIAqVgRVzpbzo5smXKp4YfRvH+8abtTE1Pi6jizo" crossorigin="anonymous") | ||
script(src="https://cdnjs.cloudflare.com/ajax/libs/popper.js/1.14.6/umd/popper.min.js" integrity="sha384-wHAiFfRlMFy6i5SRaxvfOCifBUQy1xHdJ/yoi7FRNXMRBu5WHdZYu1hA6ZOblgut" crossorigin="anonymous") | ||
script(src="https://stackpath.bootstrapcdn.com/bootstrap/4.2.1/js/bootstrap.min.js" integrity="sha384-B0UglyR+jN6CkvvICOB2joaf5I4l3gm9GU6Hc1og6Ls7i6U/mkkaduKaBhlAXv9k" crossorigin="anonymous") | ||
|
||
|
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,8 @@ | ||
extends _layout | ||
|
||
block content | ||
div.container.mt-5 | ||
h2.font-weight-light.mt-4 token | ||
span= token | ||
h2.font-weight-light.mt-4 token secret | ||
span= tokenSecret |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,27 @@ | ||
extends _layout | ||
|
||
block content | ||
div.container.mt-5.mr-0.mb-0.ml-0 | ||
h2.font-weight-light OAuth | ||
a.mt-2.btn.btn-primary(href="/auth" role="button") 認証実行 | ||
div.row.mt-2.ml-0.mr-0.mb-0.p-0 | ||
small.text-muted.w-100 | ||
| [認証が完了]画面でリダイレクトされない場合、 | ||
br | ||
| Chromeの開発者ツールなどでソースを開き、 | ||
span.text-success.font-weight-bold div.callbackのURL | ||
| をブラウザで開いてOAuthトークンを取得してください。 | ||
div.container.mt-5.mr-0.mb-0.ml-0 | ||
div.container.p-0.m-0 | ||
h2.font-weight-light ユーザー情報の取得 | ||
a.btn.btn-primary.mt-2(href="/user/info" role="button") 実行 | ||
div.container.mt-5.mr-0.mb-0.ml-0 | ||
div.container.p-0.m-0 | ||
h2.font-weight-light 合計金額の取得 | ||
form(action="/category/total" method="POST") | ||
.form-group | ||
label(for="category") | ||
input.form-control.w-25(type="text" name="category" placeholder="カテゴリを入力" aria-describedby="categoryHelp") | ||
small#categoryHelp.form-text.text-muted | ||
| 合計金額を取得したいカテゴリを入力 | ||
button.btn.btn-primary.mt-2(type="submit") 実行 |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,7 @@ | ||
extends _layout | ||
|
||
block content | ||
div.container.mt-5 | ||
h2.font-weight-light.mt-4 レスポンス | ||
pre | ||
code=result |