鎌形 稔 12月/ 1/ 2019 | 0
kintone から MF クラウド請求書 API の PATCH メソッドを実行する
はじめに
kintone から外部 API を仕様する際は、kintone.proxy() で実行します。
これは JavaScript で外部 API を実行するのに超えなきゃいけない CORS の壁に対する救済措置として存在しています。
このkintone.proxy()で実行できるHTTPメソッドは「GET,POST,PUT,DELETE」の4つです。
しかし、MFクラウド請求書APIでデータの変更をする場合は、PATCH でやらないといけないという事実を最近知りました。。。
MFクラウド請求書 API ドキュメント
PATCH メソッドとは?
恥ずかしながら初めて見ました。。。。
kintone の REST API も変更は PUT メソッドだったので、MFクラウド請求書APIも PUT だろうと勝手に思い込んでましたが。。。
実際作ろうと取り掛かった時に気づきました。。。
なんなんでしょうか?PATCH メソッドって?
MDN web doc より
HTTP PATCH リクエストメソッド はリソースへの部分的変更を適用します。
HTTP PUT メソッドは、ドキュメントの完全な置換のみを許可します。PUT とは違って、PATCH はべき等ではありません。すなわち、同一の PATCH リクエストが連続しておこなわれると、異なる効果が得られる可能性があります。ただし PATCH リクエストがべき等になるようにリクエストすることは可能です。
ほー。部分的変更の場合に使うんですね。
kintone の REST API は完全な置き換えだったんだ。
なるほど。
どうにかする
とにかく、どうにかしないといけない。
取引先マスタを変更したいのです。
それには CORS のやっかいな壁をどうにかしたい。
考えた結果、外部サーバにリクエストを代わりに実行してもらうしかないなと思い、
プロキシサーバを作ってみました。
リクエストの流れとしては、以下のようになります。
kintone ⇒ POST ⇒ プロキシサーバ ⇒ PATCH ⇒ MFクラウド請求書
これなら kintone.proxy() でも実行できますね。
プロキシサーバを Node.js で書いてみる
こんな感じです。
var express = require('express');
var request = require('request');
var app = express();
/** kintoneリクエストトークン */
var authToken = 'xxxxxx';
/** MFクラウド請求書 API URL */
var mfApiUrl = 'https://invoice.moneyforward.com/api/v2/partners';
/** 取引先変更用 オプション設定 */
var patchOptions = {
url: null,
method: 'PATCH',
headers: {
'Content-Type': 'application/json',
'Authorization': null
},
json: {}
}
/**
* express 初期設定
*/
app.set('port', (process.env.PORT || 5000));
app.use(express.json());
/**
* 簡易接続制限
*/
app.use(function (req, res, next) {
if (req.header('Authorization') === authToken && req.header('X-MF-App') !== undefined) {
next();
} else {
console.log('Authorization: ', req.header('Authorization'));
res.send({
status: 'Access Denied'
});
}
});
/**
* Top Page
*/
app.get('/', function (req, res) {
res.send('kintone App Space!!')
});
/**
* MFクラウド請求書
* 取引先 変更
*/
app.post('/api/mf/partners/change', (req, res) => {
// Authorizationヘッダにアクセストークン設定
patchOptions.headers.Authorization = req.header('X-MF-App');
patchOptions.url = mfApiUrl + '/' + req.query.id + '.json'
patchOptions.json = req.body;
// 取引先作成(PATCH)
request(patchOptions, function (error, response, body) {
res.send(body);
});
});
/**
* Webサーバ開始
*/
app.listen(app.get('port'), function () {
console.log("Node app is running at localhost:" + app.get('port'))
});
補足
- POST で受け取ったデータを request オブジェクトで PATCH リクエスト実行。
- PATCH リクエストのレスポンスをそのまま POST リクエストのレスポンスで返す。
- Authorizationヘッダに REST API 認証トークンがセットされている想定。
- 独自ヘッダ (X-MF-App) の方に MFクラウド請求書側のアクセストークンがセットされている想定。
kintone からプロキシサーバを利用した取引先マスタ変更
利用する kintone 側のコードは以下のような感じ。
/** MF請求書プロキシ URL */
const PROXY_URL = 'https://xxxxx.com/api/mf/partners/change?id=';
/** MFクラウド請求書側の取引先マスタ変更(プロキシ実行) */
const patchMfPartners = (partnerId, patchData, tokens) => {
return kintone.proxy(PROXY_URL + partnerId,
'POST',
{
'Authorization': tokens.proxyToken.value,
'Content-Type': 'application/json',
'X-MF-App': tokens.writeToken.value
},
patchData
).then((resp) => {
if (resp[1] === 200) {
var ret = JSON.parse(resp[0]);
return Promise.resolve(ret.data);
} else {
return Promise.reject(JSON.parse(resp[0]));
}
}).catch((err) => {
console.log('取引先変更エラー');
return Promise.reject(err);
});
}
補足
- kintone.proxy() の使い方については こちら。
- callback 引数の省略して、kintone.Promise オブジェクト形式で実行。
- プロキシサーバ側の認証情報をヘッダにセットするため、Authorization ヘッダを追加。
- MFクラウド請求書APIを実行するための認証情報は「X-MF-App」という独自ヘッダにセット。
どうにか出来ました
-
kintone.proxy() が PATCH メソッドに対応していなかったため、自前でプロキシサーバを作って PATCH メソッドを実行できる環境を作ってみました。
-
kintone.proxy() 自体も今回書いたような事を裏でやっているのかなぁ、と思いました。
-
そういえば プロキシサーバ のアクセス制限をトークン的なものでやっていますが、本来ならアクセス元をちゃんと制限しておくべきでしたね。トークンだと基本的にどっからでもアクセス出来てしまいますね。そこは課題という事で。

