はじめに
サイボウズにはkintoneの他にもGaroonというグループウェア製品があります。
※ これら以外にも製品はあります。
そして、このGaroonにはREST APIが搭載されているので、
kintoneと連携(俗にこれを ガルキン連携 といいます)することもできます!!
ってことで、この記事ではシンプルに
kintone → Garoon
のスケジュール連携を実装してみました。
コーディング前
「同じ会社の製品だし簡単に連携できるっしょ!」って思っていました。
なので、コーディングする前は「わざわざ記事化する必要ないだろう」とも思っていました。
しかし、世の中そんな甘くはないなーってことがコーディング中にあったので記事化しますw
引っかかったところ
では、さっそく何があったのか。
- エンドポイントの構成が異なる
- ユーザー(アカウント)情報の構成が異なる
- 認証がいい感じにできない
-
日時のフォーマットが異なる<-記事作ってる間になんかできるようになった(謎) - ドキュメントの量が異なる
エンドポイント問題
kintoneのendpointは https://{subdomain}.cybozu.com/k/v1/〇〇.json
という形で、
kintone JavaScript APIを使えば kintone.api.url('/k/v1/〇〇');
と書けます。
ここは調べずにおおちゃくした自分が悪いのですが、
「Garoonの場合は kintone.api.url('/g/api/v1/〇〇');
でいけるやろ!」ってことで書いて実行したところ、、、
{"error":{"errorCode":"GRN_REST_API_00101","message":"入力内容が正しくありません。","cause":"指定されたURIパスが見つかりません。"}}
なんだって!?!?
どうやらGaroonは、
https://{subdomain}.cybozu.com/g/api/v1/〇〇
で最後に「.json」は必要ないらしい。
kintone.api.url();は「.json」も補完する。余計なお世話や!
ユーザー情報問題
ここは普通にハマったのですが、
kintoneのユーザー選択フィールドのデータは
{
"value" : [{
"code": "<ログインID>",
"name": "<ユーザー名>"
}]
}
となっています。複数人いた場合は
{
"value" : [{
"code": "aa",
"name": "AA"
},
{
"code": "bb",
"name": "BB"
},
{
"code": "cc",
"name": "CC"
}]
}
となります。
しかし、これをそのままGaroonに突っ込もうとするとエラーがでます。
"{"error":{"errorCode":"GRN_REST_API_00201","message":"パラメーターの指定が正しくありません。","cause":"attendees.typeは必須パラメーターです。"}}"
Oh...
Garoonの場合はユーザーと施設と2種類アカウント(のようなもの)があるので、TYPEが別途必要!!
{
"value" : [{
"code": "aa",
"name": "AA",
"type": "USER"
},
{
"code": "bb",
"name": "BB",
"type": "USER"
},
{
"code": "cc",
"name": "CC",
"type": "USER"
}]
}
ってことでkintoneのユーザー選択フィールドの値を取得した後に、ちょっとごにょごにょしないといけません
認証問題
今回、kintoneとGaroonは同じドメインでやっているため、セッション認証を使えればいいなと思ったのですが、Garoon→kintone ならCSRFトークンが使えますが、kintone→Garoon はCSRFトークンは使えませんでした。Oh...
→ GaroonにはCSRFトークンを取得するJavaScript APIがあるんですが、kintoneにはそのAPIはありませんでした。。
ってことで、今回はログパス認証になります。(Grにトークン認証はないため)
参考)kintone連携用トークンを取得する
https://developer.cybozu.io/hc/ja/articles/115005294843
日時問題 (なんか解決済)
記事を書き始める前はフォーマットが違ったので、Garoon側に合うように修正しないときちんと入らなかったのですが、なんか記事書いている間にもう一度試したら、普通にいけましたw
でもフォーマットは異なるのでそこだけご紹介。
- kintoneの日時フィールドは
2019-01-01T12:50:00Z
のような形で UTC
-> リンク - Garoonのスケジュールの日時は
2019-01-01T21:50:00+09:00
のような形で JST
-> リンク
日時フォーマットはややこしい。。。
ドキュメント問題 (問題ってレベルでもないけど)
devnetしかり、世の中一般しかり、Garoonのカスタマイズをしているところが圧倒的に少ない!!
-> kintoneのカスタマイズはググればたくさん出てくるのに。。。つД`)グスン
だから、参考にできるものも少なくて、1から自分で調べないといけない。辛い。。
まぁこんな背景もあって、この記事を書こうって決心したのもあります (´・∀・`)
コード
上記のトラップに引っかかりながらも作成したコードがこちらです。
(function() {
'use strict';
// kintoneのフィールドコード
var common = {
text: 'Text',
user: 'User',
startDate: 'Start',
endDate: 'End',
memo: 'Memo'
};
// Garoonの認証
var auth = {
'X-Cybozu-Authorization': 'ログ:パス Base64エンコード',
'Content-Type': 'application/json'
};
// editは一旦放置。Garoon予定の更新も放置。
kintone.events.on('app.record.create.submit', function(event) {
// kintoneのユーザー選択フィールドにはtypeがないので追加する
event.record[common.user].value = event.record[common.user].value.map(function(element) {
return {
code: element.code,
name: element.name,
type: 'USER'
};
});
// GaroonのスケジュールREST API に必要なパラメータ (施設は今回省略)
var params = {
'eventType': 'REGULAR',
'subject': event.record[common.text].value,
'start': {
'dateTime': event.record[common.startDate].value, // UTCの変換
'timeZone': 'Asia/Tokyo'
},
'end': {
'dateTime': event.record[common.endDate].value, // UTCの変換
'timeZone': 'Asia/Tokyo'
},
'attendees': event.record[common.user].value,
'notes': event.record[common.memo].value
};
return kintone.proxy('https://<subdomain>.cybozu.com/g/api/v1/schedule/events', 'POST', auth, JSON.stringify(params))
.then(function(resp) {
if (resp[1] !== 201) {
return Promise.reject(resp);
}
window.alert('登録に成功しました!');
}).catch(function(err) {
console.log(err);
window.alert('登録に失敗しました!');
return false;
});
});
})();
動きのイメージ
- kintoneに登録すると、

- Garoonにも入った!以上!

- 複数人も登録できます

おわりに
やはり一度触ってみないとわからないものですね〜
kintoneだけでなく、Garoonも便利カスタマイズがたくさんできるので、どんどん記事化していこうと思います!
まぁそもそも論、このkintone→Garoonスケジュール連携ってニーズあるのかな・・・^^;
それでは!≧(+・` ཀ・´)≦