Skip to content

Commit

Permalink
initial commit
Browse files Browse the repository at this point in the history
  • Loading branch information
kudotk committed Dec 24, 2018
0 parents commit 181f62f
Show file tree
Hide file tree
Showing 9 changed files with 320 additions and 0 deletions.
2 changes: 2 additions & 0 deletions .gitignore
@@ -0,0 +1,2 @@
node_modules
config/development.json
49 changes: 49 additions & 0 deletions README.md
@@ -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
8 changes: 8 additions & 0 deletions config/default.json
@@ -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>"
}
}
25 changes: 25 additions & 0 deletions package.json
@@ -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"
}
}
176 changes: 176 additions & 0 deletions server.js
@@ -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)
18 changes: 18 additions & 0 deletions views/_layout.pug
@@ -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")


8 changes: 8 additions & 0 deletions views/auth-callback.pug
@@ -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
27 changes: 27 additions & 0 deletions views/index.pug
@@ -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") 実行
7 changes: 7 additions & 0 deletions views/result.pug
@@ -0,0 +1,7 @@
extends _layout

block content
div.container.mt-5
h2.font-weight-light.mt-4 レスポンス
pre
code=result

0 comments on commit 181f62f

Please sign in to comment.