Salesforce記録⑤:salesforce RestAPI作成について(202406)

#### 1.Salesforce Oauth の設定
##### ①：インテグレーション用プロファイルでシステム管理者権限の「API の有効化」が有効になっているのを確認します。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3802240/1d5d52d5-71a8-8aca-3062-51b33443f3f7.png)

##### ➁:[設定] - [アプリケーション] - [新規接続アプリケーション]をクリックします。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3802240/12c91874-ffd3-990c-7401-2b46ccee39ac.png)

callback urlは使わないので、デファクトで良い。使う場合は別時間で紹介する
default:https://test.salesforce.com/services/oauth2/success
        or https://login.salesforce.com/services/oauth2/success

##### ③:保存すると、接続アプリケーションの定義の詳細ページが表示されます。ここのコンシューマ鍵とコンシューマの秘密は認証を行う際に必要になります。(このページは [設定] - [オブジェクトマネージャ] から対象の接続アプリケーションの▼ボタンから[参照]をクリックすることで表示できます)
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3802240/342311b0-6ce6-74c3-d383-c84c3305bff2.png)

##### ④:セキュリティトークンの取得
インテグレーションユーサでログインし、[右上のユーザアイコン] - [設定] - [私の個人情報] - [私のセキュリティトークンのリセット]2 の[セキュリティトークンのリセット]をクリックします。※[セキュリティトークンのリセット]が表示されない場合、セキュリティトークンの取得は必要ありません。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3802240/35699bcf-d494-a390-344b-b81cba97545a.png)

##### ユーザーtoken取得(profileにIPの制限cancel)

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3802240/94a38185-29bf-99ce-d794-e1edb4af1340.png)



``` java
ユーザ名パスワード OAuth 認証

リクエストを新規で作成し、下記のように設定を行います。
METHOD: POST
パス: 適切なSalesforce トークン要求エンドポイント
(例: https://login.salesforce.com/services/oauth2/token)
HEADERS
Content-Type: application/x-www-form-urlencoded
BODYにFormを選択し、次のパラメータを設定します。
grant_type=password
client_id=[接続アプリケーションのコンシューマ鍵]
client_secret=[接続アプリケーションのコンシューマの秘密]
username=[インテグレーション用ユーザのSalesforceユーザ名]
password=[インテグレーション用ユーザのSalesforceログインパスワード+セキュリティトークン]

```

##### ⑤:OAuth および OpenID Connect 設定
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3802240/db6d1c4d-d356-4358-0a3f-48767cd1343e.png)

##### ⑥:RESTリクエストを送信するときにレスポンスボディのaccess_tokenを使用し、Apex関数にアクセスする。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3802240/05440336-2476-7f17-f187-61e885525c9f.png)


#### 2.Front側の作成例（JS）

//Token GET
``` JS
// token GET
function getToken() {
  return request
    .post(url.resolve(salesforceApi.endPoint, "/services/oauth2/token"))
    .set("Content-Type", "application/x-www-form-urlencoded")
    .send({
      grant_type: "password",
      client_id: salesforceApi.clientId,
      client_secret: salesforceApi.clientSecret,
      username: salesforceApi.username,
      password: salesforceApi.password ,
      //password: salesforceApi.password + userToken,
    })
    .then(function (res) {
      token = res.body.access_token;
      instanceUrl = res.body.instance_url;
      return {
        token,
        instanceUrl,
      };
    })
    .catch(function (e) {
      return Promise.reject(e);
    });
}
```

// Token Use  ①普通
``` JS

function getApexThings(req, res, next) {
  var reqUrl = url.resolve(
    instanceUrl, //getToken()取得したURL
    `/services/apexrest/application/`
  );
  return request
    .post(reqUrl)
    .set("Authorization", `Bearer ${token}`)//getToken()取得したToken
    .set('Accept', 'application/json')
    .then(function (data) {
      return res.status(200).send(data.body);
    })
    .catch(function (e) {
      if (e.status === 401) {
        if (req.body.isRetry) {
          return res.status(401).send('初期化失敗');
        }

        req.body.isRetry = true
        return getToken().then(function () {
          return getApexThings(req, res, next);
        });
      }

      if (e.status === 404) {
        return res.status(404).send('初期化失敗');
      }

      return res.status(e.status).send('初期化失敗');
    });
}

```
// Token Use　➁ Image blob
``` JS
handleImage() {
      // Salesforce REST API エンドポイント
      const apiUrl = '{instanceUrl}/services/apexrest/application/';

      // Fetch API を使用して POST リクエストを送信
      fetch(apiUrl, {
          method: 'POST',
          headers: {
              'Authorization': 'Bearer  XXXXXXXX',
              'Content-Type': 'image/jpeg'
          },
          body: this.fileBLOB//this.blobdata
      })
      .then(response => {
          if (!response.ok) {
              throw new Error('Network response was not ok');
          }
          return response.json();
      })
      .then(data => {
          console.log('Response data:', data);
      })
      .catch(error => {
          console.error('There was a problem with the request:', error);
          console.error('catch1:'+error+'\n'+' message: '+error.message+'\n'+' stack: '+error.stack);
      });
  }
```


#### 3.backend側の作成例（APEX）

①普通
``` APEX
@RestResource(urlMapping='/application/*')
global with sharing class RestApi {
  @HttpPost
    global static String post() {
        System.debug(' HttpPost');
        //各ロジック処理
        return 'OK';
	}
}
```


➁Image upload 処理 
``` APEX
@RestResource(urlMapping='/application/*')
global with sharing class RestApi {
    
    @HttpPost
    global static String post() {
        //image blobを画像に変更する
        Blob fileContent = RestContext.request.requestBody;
        ContentVersion contentVersionRecord = new ContentVersion();
        contentVersionRecord.VersionData = fileContent;
        contentVersionRecord.Title = '123';
        contentVersionRecord.PathOnClient = '1123.jpeg';
         //  【ファイル】の下に XXXImagesフォルダがある
        ContentWorkspace cw =  [SELECT Id, Name FROM ContentWorkspace WHERE Name = 'XXXImages']; 
        //画像の場所を設定する
        contentVersionRecord.FirstPublishLocationId = cw.Id;
        insert contentVersionRecord;

        return 'OK';
	}
}
```
#### 4.アクセス失敗の場合はどうする

ログイン履歴をチェックする

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3802240/824c5b4d-1620-602f-48fb-7d704f3a6f5d.png)