kintoneからMFクラウド請求書APIのPATCHメソッドを実行する
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() 自体も今回書いたような事を裏でやっているのかなぁ、と思いました。
-
そういえば プロキシサーバ のアクセス制限をトークン的なものでやっていますが、本来ならアクセス元をちゃんと制限しておくべきでしたね。トークンだと基本的にどっからでもアクセス出来てしまいますね。そこは課題という事で。