LWCからRestAPI呼び出し方法の振り返る

# 目的

ご閲覧ありがとうございます。オレンジ羽のlibra189です。
転職を機におおよそ2年ぶりにSalesforceの案件を担当する事になりました。色々と忘れていたので忘備録として記録していきたいと思います。
今回はLWC(Lightning Web Component)からREST APIを呼び出す設定、実装方法の手順です。

# 前提条件

- SalesforceのDeveloper環境
- APIバージョン：62.0
- SFDX CLIのインストール
- VS CodeとDeveloper環境との連携

# Salesforceの設定

## リモートサイト設定

Salesforceはセキュリティ上、事前にアクセス可能な外部ドメインを許可する必要があります。
今回は簡略化のために認証不要で利用できる PokeAPI(https://pokeapi.co) を利用します。
本来はJWT Web トークンなどで認証する必要があります。

PokeAPIについては下記記事で詳細に説明していただいているのでご参照ください。
[PokeAPIで取得できるポケモンのデータを簡単にまとめてみた - Qiita](https://qiita.com/jinto/items/c953ab25253d8ec82e30)

1. 設定 > セキュリティ > リモートサイト設定 を開く。
2. 「新規リモートサイト」ボタンからAPIの呼び出す外部のベースURL `https://pokeapi.co` を「リモートサイトの URL」に入力。他の項目は適宜入力してください。

# REST API呼び出しのApexクラス作成

## HttpRequestを使ったAPI呼び出し

APIを呼び出すApexクラスを作成します。
今回のAPIは認証不要のため、認証ヘッダーはコメントアウトしています。必要な場合は適宜設定してください。

<details><summary>サンプルコードは長いので、折りたたんでいます。</summary>

```apex
public class PokeApiService {
    @AuraEnabled(cacheable=true) // クライアントにメソッドの結果をキャッシュ
    public static String callExternalApi(Integer id) {
        try {
            // HTTPリクエストを作成
            HttpRequest req = new HttpRequest();
            req.setEndpoint('https://pokeapi.co/api/v2/pokemon/' + String.valueOf(id)); // 外部APIのエンドポイント
            req.setMethod('GET'); // HTTPメソッド
            // req.setHeader('Authorization', 'Bearer YOUR_ACCESS_TOKEN'); // 認証ヘッダー
            req.setHeader('Content-Type', 'application/json'); // 必要なヘッダー
            req.setTimeout(120000); // タイムアウト時間を設定

            // HTTPリクエストを送信
            Http http = new Http();
            HttpResponse res = http.send(req);

            // ステータスコードとレスポンス処理
            if (res.getStatusCode() == 200) {
                System.debug('Response: ' + res.getBody());
                return res.getBody();
            } else {
                System.debug('Error: ' + res.getStatusCode() + ' ' + res.getStatus());
                return null;
            }
        } catch (Exception e) {
            System.debug('Exception: ' + e.getMessage());
            return null;
        }
    }
}
```
</details>

## API呼び出しのテスト

設定ボタンから開発者コンソールを開き、「Ctrl + E」を押して、「Execute Anonymous Window」に移ります。
下記のコードを入力し、ログにレスポンスが出ていれば動作テスト完了です。

```apex
Integer id = 1;
String response = PokeApiService.callExternalApi(id);
System.debug('API Response: ' + response);
```

# LWCの作成

## LWCの実装

<details><summary>サンプルコードは長いので、折りたたんでいます。</summary>

```html:FetchPokemon
<template>
    <div class="external-api-container">
        <lightning-card title="External API Data" icon-name="standard:record">
            <div class="slds-p-around_medium">
                <template if:true={apiResponse}>
                    <pre class="response-display">{apiResponse}</pre>
                </template>

                <template if:true={errorMessage}>
                    <div class="slds-theme_error">
                        <p>{errorMessage}</p>
                    </div>
                </template>

                <template if:false={apiResponse}>
                    <lightning-spinner alternative-text="Loading" size="medium">
                    </lightning-spinner>
                </template>
            </div>
        </lightning-card>
    </div>
</template>
```

```javascript:fetchPokemon.js
import { LightningElement, wire } from 'lwc';
import callExternalApi from "@salesforce/apexPokeApiService.callExternalApi";

export default class FetchPokemon extends LightningElement {
    apiResponse;
    errorMessage;

    @wire(callExternalApi, {
        id: 1, // 簡略化のため固定値
    })
    wiredAPIData({ error, data }) {
        if (data) {
            this.apiResponse = data;
        } else if (error) {
            this.errorMessage = error;
        }
    }
}
```

```xml:fetchPokemon.js-meta.xml
<?xml version="1.0" encoding="UTF-8"?>
<LightningComponentBundle xmlns="http://soap.sforce.com/2006/04/metadata">
    <apiVersion>62.0</apiVersion>
    <isExposed>true</isExposed>
    <targets>
        <target>lightning__RecordPage</target>
        <target>lightning__AppPage</target>
        <target>lightning__HomePage</target>
    </targets>
    <targetConfigs>
        <targetConfig targets="lightning__RecordPage">
            <objects>
                <object>Account</object>
                <object>Contact</object>
            </objects>
        </targetConfig>
    </targetConfigs>
</LightningComponentBundle>

```
</details>

## コンポーネントの配置

今回はアプリケーションページ、ホームページまたは、取引先(Account)、取引先責任者(Contact)のレコード詳細ページに配置できるようにXMLの設定をしたので、いづれかにコンポーネントを配置し、動作を確認すれば完了です。

# まとめ

以上で大まかな流れと実装は完了です。
今回は簡略化のために認証不要としましたが、本来であれば認証は必須です。呼び出す外部APIの認証方法に合わせてカスタマイズが必要です。
外部システムとの連携にはREST API以外に連携ツールとしてSalesforce社の`MuleSoft`があります。
価格面で難ありと聞いているので、案件があるかは不明ですが、キャッチアップを続けて、資格取得を目指したいです。

# 参考

- [リモートサイトの設定の追加 - Apex 開発者ガイド](https://developer.salesforce.com/docs/atlas.ja-jp.apexcode.meta/apexcode/apex_callouts_remote_site_settings.htm)
- [Lightning Web コンポーネントの作成 - Trailhead](https://trailhead.salesforce.com/ja/content/learn/trails/build-lightning-web-components)
- [Salesforce LWCの設定情報について - Qiita](https://qiita.com/kakakaori830/items/134e32f15c64c892810a)