目的
Salesforceには、標準でSalesforce Filesというファイル管理機能がありますが、
- それとは別にファイル管理関連のAppExchangeを導入している
- 他のファイルサービスを併用している
という声を聞くことが多い気がします。(あくまでも主観ですが)
他のファイルサービスとの連携に関しては、標準でSalesforce Files Connectという機能があり、主要なファイルサービスとの連携は、ほぼほぼこの機能の範疇で出来てしまいます。ただ、基本的には、連携したファイルサービス側のファイルをSalesforceからダウンロードしたり、逆にSalesforceからアップロードしたり、一覧表示できたり、程度のオーソドックスな機能のみとなっています。
なので、もう少し込み入った事をしたい場合、各ファイルサービスが公開しているAPIを使用する形になると思いますが、直近でそのような要望をいただく事があったので、今回、GoogleDriveAPIを題材としてAPI連携時に必要な作業を備忘録的に記載しておきます。
前提
- Googleアカウント取得済み
- Salesforceアカウント取得済み
- GoogleDriveAPI v3
手順
1. Google側の設定
1. プロジェクト作成
Google Developer Consoleにアクセスし、Googleアカウントでログイン後、プロジェクトを作成をクリックします。

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

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

| 項目 | 値 | 
|---|---|
| アプリケーション名 | 任意 | 
| サポートメール | あなたのメールアドレス | 
| 承認済みドメイン | Salesforce.com | 
4. 認証情報作成
認証情報から認証情報を作成をクリックし、OAuthクライアントIDを選択します。

| 項目 | 値 | 
|---|---|
| アプリケーションの種類 | ウェブアプリケーション | 
| 名前 | 任意 | 
作成されたクライアントの詳細からJSONをダウンロードをクリックします。

ダウンロードされたファイルを開くと、クライアントIDを始め、認証エンドポイントやトークンエンドポイントの情報が記載されているので、これらの情報を元にSalesforce側の設定を行います。
{
    "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. 認証プロバイダ作成
| 項目 | 値 | 
|---|---|
| プロバイダタイプ | 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が払い出されます。

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

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

| 項目 | 値 | 
|---|---|
| 表示ラベル | 任意 | 
| 名前 | 任意 | 
| URL | https://www.googleapis.com/drive/v3/files | 
| ID 種別 | 指定ユーザ | 
| 認証プロトコル | OAuth 2.0 | 
| 認証プロバイダ | 手順2-1.で作成した認証プロバイダ | 
| 範囲 | https://www.googleapis.com/auth/drive | 
| 保存時に認証フローを開始 | true | 
※URLと範囲は、GoogleDriveAPI v3のリファレンス記載の内容を指定する
4. Apexトリガにコールアウト処理を実装
非常にシンプルですが、取引先作成時に取引先名のフォルダーをGoogleDriveのマイドライブに作成する処理を実装します。
※ガバナ制限等、全く考慮していません
trigger AccountTrigger on Account(after insert) {
    AccountTriggerHandler handler = new AccountTriggerHandler();
    if (Trigger.isInsert && Trigger.isAfter) {
        handler.onAfterInsert(Trigger.newMap);
    }
}
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);
        }
    }
}
GoogleDriveに取引先名のフォルダが作成されていることを確認します。

まとめ
サービス連携という側面では、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








