Salesforce External Services: OpenAPIを活用したローコード連携の効率化

背景とアプリケーションシナリオ

Salesforceと外部システム間の連携は、現代のビジネスプロセスにおいて不可欠な要素です。多くの場合、顧客データ、注文情報、財務データなどが複数のシステムに分散しており、これらをリアルタイムで連携させることで、業務の効率化と顧客体験の向上が実現します。しかし、従来の連携手法では、カスタムApexコードの開発や複雑なAPI処理が必要となることが多く、開発コストとメンテナンスの負担が課題でした。

ここでExternal Services(外部サービス)の出番です。SalesforceのExternal Servicesは、OpenAPI(旧Swagger)仕様に基づいて外部Webサービスを登録し、宣言的な手法でSalesforceからこれらのサービスを呼び出せるようにする強力な機能です。Salesforce 統合エンジニアとして、私たちは、この機能が開発リソースを節約しつつ、堅牢な統合ソリューションを構築するためのゲームチェンジャーであると考えています。

具体的なアプリケーションシナリオは多岐にわたります。例えば、以下のようなケースでExternal Servicesが活躍します。

  • 顧客データ同期: 外部のマスターデータ管理(MDM)システムから顧客の最新情報を取得し、Salesforceの取引先レコードをリアルタイムで更新します。
  • 与信チェック: 商談のフェーズが特定の段階に進んだ際に、外部の与信評価サービスを呼び出し、顧客の信用情報を確認します。この処理はFlow(フロー)から簡単に実行できます。
  • ERP連携: Salesforceで作成された受注情報を、外部の基幹業務システム(ERP)に自動的に送信し、出荷処理を開始させます。
  • AI/MLサービス連携: 外部のAIサービス(例えば、感情分析や画像認識)を呼び出し、Salesforceのデータ(例えば、ケースの説明文)を分析し、結果をレコードに反映させます。
  • 在庫確認: 商品の詳細ページから外部の在庫管理システムに問い合わせ、リアルタイムの在庫状況を表示します。
これらのシナリオでは、External ServicesがSalesforceと外部システム間のシームレスなデータフローを可能にし、手作業によるエラーを減らし、ビジネスプロセスの自動化を大きく推進します。特に、開発者が不足している場合や、迅速なプロトタイピングが求められる場合に、その真価を発揮します。

原理説明

External Servicesの核となるのは、外部APIの記述に用いられるOpenAPI Specification(OpenAPI仕様)です。この仕様は、RESTful APIの構造、利用可能なエンドポイント、操作(メソッド)、入力パラメータ、出力レスポンスなどを機械可読な形式で記述する標準的な方法を提供します。Salesforceは、OpenAPI 2.0または3.0のJSONスキーマを受け入れます。

登録プロセス

SalesforceでExternal Servicesを利用する最初のステップは、外部サービスを登録することです。これは「設定(Setup)」メニューから簡単に行えます。統合エンジニアは以下の手順を実行します。

  1. OpenAPIスキーマの準備: 連携したい外部APIのOpenAPI JSONスキーマファイルを用意します。このファイルは、APIのエンドポイント、HTTPメソッド(GET、POSTなど)、リクエストとレスポンスのデータ構造を正確に定義している必要があります。
  2. 名前付き認証情報の設定: 外部サービスへの安全な認証を確立するために、Named Credentials(名前付き認証情報)を設定します。これにより、ApexコードやFlowに認証情報を直接記述することなく、安全に外部システムと接続できます。Basic認証、OAuth 2.0、APIキーなど、さまざまな認証方式に対応しています。
  3. 外部サービスの登録: Salesforceの設定画面で「外部サービス」を選択し、「新しい外部サービス」をクリックします。サービス名、説明、そして先に準備したOpenAPIスキーマのURLまたはファイルを指定します。認証には、作成済みのNamed Credentialsを選択します。
  4. 操作の生成: スキーマが正常に解析されると、Salesforceはスキーマに記述されている各API操作(メソッド)に対して、対応するApexクラスを自動的に生成します。これらの生成されたApexクラスは、FlowやApexコードから呼び出すためのインターフェースとして機能します。

生成されたApexクラスと呼び出し

External Servicesが登録されると、Salesforceは内部的に特定の命名規則に従ってApexクラスを生成します。これらのクラスは、外部サービスの各操作に対応しており、入力パラメータを保持するクラス(_INで終わる)と、出力レスポンスを保持するクラス(_OUTで終わる)が通常セットで生成されます。例えば、MyBankという外部サービスにtransferFundsという操作がある場合、ExternalService.MyBank.transferFunds_INExternalService.MyBank.transferFunds_OUTといったクラスが生成されます。

これらの生成されたサービスは、主に以下の方法で呼び出されます。

  • Flow(フロー): 最も一般的で宣言的な方法です。Flow Builderの「アクション(Action)」要素から、登録された外部サービス操作を選択し、入力と出力をドラッグ&ドロップでマッピングするだけで、複雑なコーディングなしに外部サービスを呼び出すことができます。これはSalesforce管理者やビジネスアナリストにとっても非常に強力なツールです。
  • Apex: 統合エンジニアや開発者は、生成されたApexクラスを直接Apexコードから呼び出すこともできます。これにより、より複雑なビジネスロジック内で外部サービスを統合したり、既存のApexベースのソリューションに外部機能を組み込んだりすることが可能になります。
  • Einstein Bots(アインシュタインボット): Einstein BotsもExternal Servicesを利用して、外部システムと対話することができます。例えば、ボットが顧客からの問い合わせを受けて、外部のデータベースから情報を検索したり、予約システムにアクセスしたりする際に使用されます。
データのマッピングは、スキーマで定義されたデータ型に基づいてSalesforceのデータ型と自動的に行われますが、複雑なオブジェクトや配列の場合は、FlowやApexで適切な変換が必要になることもあります。

サンプルコード

External Servicesの主な利点はFlowから宣言的に利用できる点にありますが、Salesforce 統合エンジニアの視点からは、生成されたApexクラスを直接操作する場面も少なくありません。例えば、より複雑なエラーハンドリングを実装する場合や、既存のApexサービスに外部機能を組み込む場合などです。

以下に、登録された外部サービスをApexコードから呼び出す例を示します。この例では、MyBankという外部サービスが登録されており、その中にtransferFundsという操作(送金処理)があると仮定しています。この操作は、送金元の口座、送金先の口座、金額、通貨を入力として受け取り、取引IDを返すとします。

public class BankIntegrationService {

    public static String initiateFundTransfer(Decimal amount, String fromAccount, String toAccount, String currency) {
        // Step 1: 外部サービスによって生成された入力クラスのインスタンスを作成します。
        // ここでは、サービス名 'MyBank' と操作名 'transferFunds' が仮定されています。
        // 実際のサービス名と操作名に置き換えてください。
        // _IN サフィックスは入力パラメータを表すクラスです。
        ExternalService.MyBank.transferFunds_IN transferRequest = new ExternalService.MyBank.transferFunds_IN();

        // Step 2: 入力パラメータを設定します。
        // これらのプロパティ名は、OpenAPIスキーマで定義された外部APIのパラメータ名に対応します。
        transferRequest.amount = amount;
        transferRequest.fromAccount = fromAccount;
        transferRequest.toAccount = toAccount;
        transferRequest.currency = currency;

        // Step 3: 外部サービス操作を呼び出します。
        // 新しい ExternalService..() インスタンスを作成し、
        // その invoke() メソッドに入力オブジェクトを渡します。
        // invoke() メソッドは、外部サービスから返されたデータを含む出力オブジェクトを返します。
        // _OUT サフィックスは出力レスポンスを表すクラスです。
        try {
            ExternalService.MyBank.transferFunds_OUT transferResponse = 
                new ExternalService.MyBank.transferFunds().invoke(transferRequest);

            // Step 4: レスポンスを処理します。
            // 外部サービスからの応答が null でないか、または特定の成功指標があるかを確認します。
            if (transferResponse != null && transferResponse.transactionId != null) {
                System.debug('Funds transfer successful. Transaction ID: ' + transferResponse.transactionId);
                // 必要に応じて、Salesforceのレコードを更新するなどの追加処理を実行します。
                return transferResponse.transactionId;
            } else {
                System.debug('Funds transfer failed or returned no transaction ID.');
                // エラー処理または予期しないレスポンスの処理
                throw new CalloutException('Fund transfer failed: No transaction ID received.');
            }
        } catch (Exception e) {
            // コールアウトエラー(ネットワークの問題、外部サービスのエラーなど)をキャッチします。
            System.debug('Error calling external service for fund transfer: ' + e.getMessage());
            // エラーを適切にログに記録し、ユーザに通知するか、再試行ロジックを実装します。
            throw new CalloutException('Failed to initiate fund transfer: ' + e.getMessage());
        }
    }

    // このサービスをテストするための例:
    public static void testTransfer() {
        try {
            String transactionId = BankIntegrationService.initiateFundTransfer(100.50, 'A123', 'B456', 'JPY');
            System.debug('Transaction initiated with ID: ' + transactionId);
        } catch (CalloutException ce) {
            System.debug('Test transfer failed: ' + ce.getMessage());
        }
    }
}

上記のコードは、ExternalService.MyBank.transferFunds_INExternalService.MyBank.transferFunds_OUTという自動生成されたクラスをどのように使用するかを示しています。これらのクラスのプロパティは、OpenAPIスキーマで定義されたAPIの入力と出力のペイロード構造に直接マッピングされます。invoke()メソッドは、外部サービスへの実際のコールアウトを実行します。エラーハンドリングは、堅牢な統合の重要な側面であり、try-catchブロックを使用して、ネットワークの問題や外部サービスからのエラー応答を適切に処理する必要があります。


注意事項

External Servicesは強力なツールですが、統合エンジニアとして以下の重要な考慮事項を理解しておく必要があります。

認証(Authentication)

外部サービスへの安全な接続は最優先事項です。Named Credentials(名前付き認証情報)を使用することで、認証情報をハードコードすることなく、安全に管理できます。Named Credentialsは、URLのホワイトリスト化、認証情報の暗号化、OAuth 2.0やBasic認証などの標準プロトコルへの対応を提供し、本番環境でのセキュリティを大幅に向上させます。

API制限(API Limits)

External Servicesによる外部サービスへのコールアウトは、SalesforceのAPIコールアウト制限の対象となります。通常、24時間あたりの組織ごとの制限や、同期コールアウトの合計タイムアウト(通常120秒)などの制限が存在します。これらの制限を超過すると、外部サービス呼び出しは失敗します。大規模な統合を設計する際には、これらの制限を考慮し、バッチ処理や非同期処理の利用を検討する必要があります。

ペイロードサイズ制限(Payload Size Limits)とタイムアウト(Timeout Limits)

リクエストとレスポンスのペイロードサイズには制限があります(通常、リクエスト/レスポンスボディで約6MB)。また、単一のコールアウト操作のタイムアウトも制限されています(デフォルトで10秒)。大規模なデータ転送が必要な場合は、これらの制限を考慮し、データを分割して送信したり、より効率的なデータ形式を使用したりする必要があります。

エラー処理(Error Handling)

外部サービスとの統合において、エラーは常に発生し得ます。ネットワークの問題、外部サービス側のダウンタイム、不正なデータ形式、認証エラーなどが考えられます。

  • Flow: Flowでは、「障害パス(Fault Path)」を設定することで、外部サービスアクションが失敗した場合の代替処理やエラー通知ロジックを定義できます。
  • Apex: Apexでは、try-catchブロックを使用して、CalloutExceptionやその他の関連する例外を捕捉し、エラーメッセージのログ記録、ユーザーへの通知、再試行メカニズムの実装などを行う必要があります。また、外部サービスからのHTTPステータスコード(例: 400 Bad Request, 500 Internal Server Error)を解析し、適切なビジネスロジックを実行することが重要です。

スキーマ進化(Schema Evolution)とバージョン管理

外部APIが変更されると、登録済みのOpenAPIスキーマも更新する必要があります。外部サービスのスキーマに変更があった場合、Salesforceに再登録することで、生成されたApexクラスが最新の状態に更新されます。これは、特に外部APIが頻繁に更新される場合に、計画的なメンテナンス作業として考慮する必要があります。APIのバージョン管理戦略(例: URLにバージョンを含める)は、スムーズな移行のために役立ちます。

データ型(Data Types)のマッピング

OpenAPIスキーマで定義されたデータ型とSalesforceのデータ型との間のマッピングには注意が必要です。特に、日付/時刻形式、複雑なオブジェクト、配列などは、Salesforceで期待される形式に合うように、外部サービス側で調整したり、FlowやApexで変換ロジックを追加したりする必要がある場合があります。

権限セット(Permission Sets)

ユーザーがExternal Servicesを呼び出すFlowやApexコードを実行できるようにするには、適切な権限が必要です。通常、「フローの実行(Run Flows)」権限と、登録された外部サービスを呼び出すための特定の権限セットの割り当てが必要になります。統合のセキュリティモデルの一部として、最小限の特権の原則に従って権限を付与してください。


まとめとベストプラクティス

Salesforce External Servicesは、複雑な統合タスクを簡素化し、開発者がコードを書くことなく外部システムとの連携を可能にする革新的なツールです。Salesforce 統合エンジニアの視点から見ると、これはビジネスプロセスを迅速に自動化し、Salesforceの機能を外部エコシステムに拡張するための、非常に効率的でスケーラブルなアプローチを提供します。

まとめ:

  • 宣言的な統合: 主にFlowを通じて、ローコード/ノーコードでの外部サービス連携を可能にします。
  • OpenAPI標準の活用: 業界標準のOpenAPI仕様を使用することで、APIの記述と管理が容易になります。
  • Apexクラスの自動生成: 登録されたスキーマに基づいてApexクラスが自動生成され、FlowだけでなくApexからも利用できます。
  • セキュリティの強化: Named Credentialsによる安全な認証情報の管理を提供します。

ベストプラクティス:

  • OpenAPIスキーマの正確性: 登録するOpenAPIスキーマが外部APIの仕様と完全に一致していることを確認してください。不正確なスキーマは、生成されるApexクラスの誤動作や予期しないエラーの原因となります。
  • Named Credentialsの徹底利用: 認証情報を直接コードに埋め込むのではなく、常にNamed Credentialsを使用して、セキュリティとメンテナンス性を向上させます。
  • 堅牢なエラーハンドリング: Flowの障害パスやApexのtry-catchブロックを積極的に利用し、外部サービスからのエラー応答を適切に処理するロジックを実装します。再試行メカニズムやエラー通知も検討してください。
  • テストと監視: 統合が正しく機能することを確認するために、徹底的なテストを実施します。本番稼働後は、APIコールアウトの制限、エラーログ、および外部サービスのパフォーマンスを継続的に監視します。
  • バージョン管理と変更管理: 外部APIの変更に対応するため、OpenAPIスキーマとSalesforceの外部サービス登録を同期させるための明確なプロセスを確立します。
  • 非同期処理の検討: 長時間実行される外部サービスや、大量のデータを処理するサービスの場合、ApexのFutureメソッドやキューブルApex、Platformイベントと組み合わせることで、非同期処理を検討し、Salesforceのコールアウト制限やガバナ制限を回避します。
  • 最小限の権限の原則: ユーザーやプロファイルに、外部サービスを呼び出すために必要な最小限の権限のみを付与し、セキュリティリスクを低減します。

External Servicesを効果的に活用することで、Salesforceは単なるCRMシステムから、ビジネスプロセス全体をオーケストレーションする強力な統合ハブへと進化します。統合エンジニアとして、この技術を習得し、ビジネス価値を最大化するソリューションを提供することが私たちの使命です。

コメント