Qiita Teams that are logged in
You are not logged in to any team

Log in to Qiita Team
Community
OrganizationAdvent CalendarQiitadon (β)
Service
Qiita JobsQiita ZineQiita Blog
Help us understand the problem. What is going on with this article?

ApexトリガからGoogleDriveAPIをコールアウト

More than 1 year has passed since last update.

目的

Salesforceには、標準でSalesforce Filesというファイル管理機能がありますが、

  • それとは別にファイル管理関連のAppExchangeを導入している
  • 他のファイルサービスを併用している

という声を聞くことが多い気がします。(あくまでも主観ですが)

他のファイルサービスとの連携に関しては、標準でSalesforce Files Connectという機能があり、主要なファイルサービスとの連携は、ほぼほぼこの機能の範疇で出来てしまいます。ただ、基本的には、連携したファイルサービス側のファイルをSalesforceからダウンロードしたり、逆にSalesforceからアップロードしたり、一覧表示できたり、程度のオーソドックスな機能のみとなっています。

なので、もう少し込み入った事をしたい場合、各ファイルサービスが公開しているAPIを使用する形になると思いますが、直近でそのような要望をいただく事があったので、今回、GoogleDriveAPIを題材としてAPI連携時に必要な作業を備忘録的に記載しておきます。

前提

  • Googleアカウント取得済み
  • Salesforceアカウント取得済み
  • GoogleDriveAPI v3

手順

1. Google側の設定

1. プロジェクト作成

Google Developer Consoleにアクセスし、Googleアカウントでログイン後、プロジェクトを作成をクリックします。
1.png

プロジェクト名を入力し、作成をクリックします。
2.png

2. GoogleDriveAPIの有効化

作成したプロジェクトのダッシュボードから以下の内容を入力し、APIとサービスを有効化をクリックします。
3.png

有効にするをクリックします。
4.png

3. OAuth同意画面の設定

OAuth同意画面から以下の内容を入力し、保存をクリックします。
5.png

項目
アプリケーション名 任意
サポートメール あなたのメールアドレス
承認済みドメイン Salesforce.com

4. 認証情報作成

認証情報から認証情報を作成をクリックし、OAuthクライアントIDを選択します。
6.png

以下の内容を入力し、作成をクリックします。
7.png

項目
アプリケーションの種類 ウェブアプリケーション
名前 任意

作成されたクライアントの詳細からJSONをダウンロードをクリックします。
8.png

ダウンロードされたファイルを開くと、クライアントIDを始め、認証エンドポイントやトークンエンドポイントの情報が記載されているので、これらの情報を元にSalesforce側の設定を行います。

client_secret_〜.json
{
    "web": {
        "client_id": [client_id],
        "project_id": "salesforceconnect-258102",
        "auth_uri": "https://accounts.google.com/o/oauth2/auth",
        "token_uri": "https://oauth2.googleapis.com/token",
        "auth_provider_x509_cert_url": "https://www.googleapis.com/oauth2/v1/certs",
        "client_secret": [client_secret]
    }
}

2. Salesforce側の設定

1. 認証プロバイダ作成

設定 > 認証プロバイダから新規をクリックします。
9.png

以下の内容を入力し、保存をクリックします。
10.png

項目
プロバイダタイプ Open ID Connect
名前 任意
URL 接尾辞 任意
コンシューマ鍵 Google認証情報JSONのclient_id
コンシューマの秘密 Google認証情報JSONのclient_secret
承認エンドポイント URL Google認証情報JSONのauth_uri
トークンエンドポイント URL Google認証情報JSONのtoken_uri

2. GoogleプロジェクトのコールバックURL更新

認証プロバイダを作成すると、Googleアカウントで認証された後の遷移先となるコールバックURLが払い出されます。
11.png

これを手順1-4.で作成した認証情報の承認済みのリダイレクトURIに貼付し、保存をクリックします。
12.png

3. 指定ログイン情報を作成

Apexからコールアウトする際は、通常リモートサイトの設定をしなければいけませんが、指定ログイン情報を登録することでこれをスキップできます。また、指定ログイン情報に、手順2-1.で作成した認証プロバイダの設定とエンドポイント、スコープを登録しておくことで、プログラムでのアクセストークン取得〜対象APIへのリクエスト作成部分を省略することができます。

設定 > 指定ログイン情報から新規指定ログイン情報をクリックします。
13.png

以下の内容を入力し、保存をクリックします。
14.png

項目
表示ラベル 任意
名前 任意
URL https://www.googleapis.com/drive/v3/files
ID 種別 指定ユーザ
認証プロトコル OAuth 2.0
認証プロバイダ 手順2-1.で作成した認証プロバイダ
範囲 https://www.googleapis.com/auth/drive
保存時に認証フローを開始 true

※URLと範囲は、GoogleDriveAPI v3のリファレンス記載の内容を指定する

認証が完了すると、認証状況が認証済みに変わります。
16.png

4. Apexトリガにコールアウト処理を実装

非常にシンプルですが、取引先作成時に取引先名のフォルダーをGoogleDriveのマイドライブに作成する処理を実装します。
※ガバナ制限等、全く考慮していません

AccountTrigger.trigger
trigger AccountTrigger on Account(after insert) {
    AccountTriggerHandler handler = new AccountTriggerHandler();
    if (Trigger.isInsert && Trigger.isAfter) {
        handler.onAfterInsert(Trigger.newMap);
    }
}
AccountTriggerHandler.cls
public with sharing class AccountTriggerHandler {

    public void onAfterInsert(Map<Id, Account> newAccMap) {
        String targetAccName = '';
        for(Account acc : newAccMap.values()){
            targetAccName = acc.Name;
        }
        createGoogleDriveFolder(targetAccName);
    }

    @Future(callout=true)
    public static void createGoogleDriveFolder(String folderName) {

        Http http = new Http();
        HttpRequest req = new HttpRequest();

        // 指定ログイン情報を使用
        String reqPath = 'callout:google_driveapi';
        req.setEndpoint(reqPath);
        req.setMethod('POST');
        req.setHeader('content-type', 'application/json');
        JSONGenerator gen = JSON.createGenerator(true);
        gen.writeStartObject();
        // フォルダーに指定されるmimeTypeを指定
        gen.writeStringField('mimeType', 'application/vnd.google-apps.folder');
        // フォルダー名を指定
        gen.writeStringField('name', folderName);
        gen.writeEndObject();
        String reqBody = gen.getAsString();
        req.setBody(reqBody);

        HttpResponse res = http.send(req);

        if (res.getStatusCode() == 200) {
            Map<String, Object> results = (Map<String, Object>) JSON.deserializeUntyped(res.getBody());
            System.debug(results);
        }

    }
}

取引先を作成します。
17.png
18.png

GoogleDriveに取引先名のフォルダが作成されていることを確認します。
19.png

まとめ

サービス連携という側面では、GoogleDrive側の公開範囲設定と、Salesforce側のロジック(どこにフォルダを作成するのか)で足並みを揃えれば、公開範囲等も、ある程度柔軟にコントロールすることができそうだし、
GoogleDriveのローカル同期を可能にするドライブ ファイル ストリームを併用することでGoogleDrive⇔Salsforce⇔ローカルが繋がるので、やり方次第では非常に効率の良い作業環境が作れるのでは、と思いました。

技術的な側面では、今回、認証設定とエンドポイントを一纏めに定義する指定ログイン情報というものを使い、ロジックを簡略化できたのが良かったのですが(今まで普通にURL組み立ててた)、画面に表示されているようにアクセストークンの有効期限切れに関するWarningが出力されました。

認証プロバイダが更新トークンを提供しませんでした。アクセストークンの有効期限が切れると、組織からこの指定ログイン情報にアクセスできなくなります。

これが設定漏れ/誤りの影響ではない場合、定期的にこの指定ログイン情報を再保存(認証フローを再度行う)必要があるので、どうするのが正解なのか疑問が残りました。

参考サイト

https://web.plus-idea.net/2017/01/salesforce-google-calendar-rest/
https://himakan.net/websites/how_to_google_oauth

Why not register and get more from Qiita?
  1. We will deliver articles that match you
    By following users and tags, you can catch up information on technical fields that you are interested in as a whole
  2. you can read useful information later efficiently
    By "stocking" the articles you like, you can search right away