令和元年でやること：Google Calendar APIで日本の祝日をGoogleカレンダーからSalesforceカレンダーに読込

こんにちは！
これから記載する内容は、実は2年前にやりたかったものです。
当時の Developer User Group Meetup で、計算式で日本の祝日を登録することが紹介されたが、Google カレンダーのような、専任担当者がメンテナンスを行っているサービスから取り込むことを自動連携できるではないかと思いました。

本記事は、Salesforce Platform Advent Calendar 2019 - Day 18 の投稿になります。

##はじめに
今まで使ったグループウェアの中、使い勝手は一番良いのが G Suite ですね。
日本の祝日のメンテナンスは、GoogleカレンダーよりYahoo！カレンダーのほうがもっと良いですが、予定管理のツールとして一番使いやすいと思いますので、Google API の検証を行いました。

##Google API 認証情報の設定
以下の流れとなります。
１．GCPコンソール ⇒ プロジェクト新規作成
２．プロジェクト選択 ⇒ ライブラリ ⇒ Google Calendar API ⇒ 有効化
３．認証情報 ⇒ 認証情報作成 ⇒ APIキー

####プロジェクト新規作成
#####「新しいプロジェクト」をクリックする
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/309113/fb6bef9b-7a55-6dcf-7ee7-c9453346286e.png)

#####プロジェクト名を入力して「作成」をクリックする
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/309113/e724a198-3c83-31da-3463-13fd2a9923ec.png)

####Google Calendar API 有効化
#####「ライブラリ」をクリックする
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/309113/96878e68-8ed4-7015-0c78-f8d89500ea0a.png)

#####「Google Calendar API」をクリックする
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/309113/66293b07-3d01-b6a3-44e3-305280d8e419.png)

#####「有効にする」をクリックする
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/309113/ddaaba3a-8a2a-e284-13f1-c19b170b3ed9.png)

####APIキーの作成
#####「APIキー」をクリックする
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/309113/0315a3f1-419c-0c6c-6ac3-20586559e1ee.png)

#####キーが作成される
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/309113/96294fa3-47a7-aa24-fe57-53f6bcbc4797.png)

#####「キーを制限」にGoogle Calendar APIを選択して保存する
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/309113/56a99cd1-36dc-5fc2-2254-c392b563b3cf.png)

OAuth認証を利用しないため、Google API の設定は以上です。

##Salesforceの実装 & 設定
Google API キーで認証する場合、カレンダー一覧の取得は意外と簡単です。
JSONクラスでレスポンス本文を解析して必要な情報をEventオブジェクトにセットしてInsertだけです。
ただ、リモートサイトと公開&リソースカレンダーの設定が必要です。
####リモートサイトの設定
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/309113/8197083a-d1e6-5120-e5c7-02790e102a03.png)

####公開 & リソースカレンダーの設定
#####公開カレンダーに<font color="Blue">「日本の祝日」</font>登録
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/309113/9145e177-22cb-f850-c638-1ecb13c6ee99.png)
#####共用権限の設定
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/309113/52a175ef-bb7d-caf2-36b9-4779f8daf479.png)

####APEXコード
```javascript:ExecuteAnonymous
String endpoint = 'https://www.googleapis.com/calendar/v3/calendars/'
                + 'ja.japanese%23holiday%40group.v.calendar.google.com/events?'
                + 'orderBy=startTime&' 
                + 'singleEvents=true&' 
                + 'key=XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX'; //APIキー書き換え
String httpMethod = 'GET';

HttpRequest req = new HttpRequest();
req.setEndpoint(endpoint);
req.setMethod(httpMethod);

Http h = new Http();
HttpResponse res = h.send(req);

if (res.getStatusCode() == 200) {
    List<Event> events =  new List<Event>();
    String calenderId = [select Id from Calendar where Name = '日本の祝日' Limit 1].Id;
    
    Map<String, Object> googleCalenderMap = 
        (Map<String, Object>)JSON.deserializeUntyped(res.getBody());
    List<Object> googleCalenderEvents = (List<Object>) googleCalenderMap.get('items');
    for(Object evt : googleCalenderEvents) {
        Map<String, Object> evtMap = (Map<String, Object>) evt;
        String startDate = String.valueOf(((Map<String, Object>)evtMap
                               .get('start')).get('date'));
        Date evtDate = Date.valueOf(startDate);
        
        Event event = new Event();
        event.ownerId = calenderId;
        event.subject = String.valueOf(evtMap.get('summary'));
        event.ActivityDate = evtDate;
        event.StartDateTime = evtDate;
        event.EndDateTime = evtDate;
        event.IsAllDayEvent = true;
        events.add(event);
    }
    insert events;
}
```

####APEXコード実行後のカレンダー画面
#####カレンダー追加
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/309113/0c246dd2-dace-f841-e0b2-92a2854b7b1e.png)

#####日本の祝日選択
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/309113/a045d1f4-fccd-c65e-3bab-edb8ed5300dc.png)

#####カレンダー画面
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/309113/854c1456-471a-4648-3f8a-890ab4d8058f.png)

Salesforceの実装及び設定は以上です。
比較的に簡単ですが、シンプルすぎる一方、セキュリティ面は多少懸念事項として検討されると思います。
「日本の祝日」だけ取り込むのがまだ良いと思われるかもしれないが、Google API のベストプラクティスをもう少し深堀する必要がありますね。

##さいごに
元々、セキュリティ面を考慮してOAuthの検証もしようと思いましたが、年末の関係でそこまで時間を取れませんでした。
他の Google API の利用や、認証周りなどをもう少し検証したいと思いますので、少しずつこの記事に追記します。

今回の内容は非常にシンプルですが、企業様既存のアセットからして全体の行動管理に対し、Salesforceに取込でなく、逆にGoolgleカレンダーに書き込むことも考えられます。Yahoo！カレンダーの利用も、モバイルプッシュ通知を含めたカスタマーエクスペリエンスなどを検討事項に入れて実用するまでは、これからの先がまだ長いですね。
適切なソリューション検討とアーキテクチャ設計に、ご参考をいただければ幸いです。

【参考】
1. Google Calendar API リファレンス
https://developers.google.com/calendar/v3/reference/calendars/get
2. Google Calendar コンセプト（Calendars and Events）
https://developers.google.com/calendar/concepts/events-calendars
3. API キーの使用
https://cloud.google.com/docs/authentication/api-keys
4. 公開カレンダーまたはリソースカレンダーの作成および管理
https://help.salesforce.com/articleView?id=customize_groupcal.htm&type=5
5. JSONクラスリファレンス
https://developer.salesforce.com/docs/atlas.ja-jp.apexcode.meta/apexcode/apex_class_System_Json.htm
6. Eventオブジェクト項目
https://developer.salesforce.com/docs/atlas.ja-jp.api.meta/api/sforce_api_objects_event.htm
(7. Using OAuth 2.0 to Access Google APIs)
https://developers.google.com/identity/protocols/OAuth2WebServer