【SAP Cloud Integration】BTP ABAP環境のODataサービスを呼ぶ

## はじめに
この記事では、BTP ABAP環境 (Trial)で作成したODataサービスをCPIから呼ぶ方法について説明します。一見簡単そうですが、認証の仕方がちょっと特殊なので、そこがこの記事のテーマとなります。

### BTP ABAP環境での認証方法
BTP ABAP環境のODataサービスを呼ぶには、[OAuth 2.0 Password Grant Type](https://developer.okta.com/blog/2018/06/29/what-is-the-oauth2-password-grant)を使い、ログインユーザとしてアクセスする必要があります。CPIのSecurity MaterialにはPassword Grantは用意されていないので、トークンを取得する処理を自分で実装する必要があります。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/276021/e6c67006-f96f-6d42-1f2a-b7a698aad9b7.png)

## 事前準備
トークンを取得するために、XSUAAのサービスインスタンスを作成しておきます。プランは"apiaccess"とします。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/276021/53a72ddc-d41d-9c7a-c6a3-51f49bf8ce7c.png)

```
cf create-service xsuaa apiaccess <access_name> //サービスインスタンスの作成
cf create-service-key <access_name> <key_name>     //サービスキーの作成
```

## Postmanから呼んでみる
呼び出すODataサービスは何でもよいですが、今回は自分で作ったサービスを呼んでみます。URLは、abap-trialのサービスキーの中にあるurlと、
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/276021/fcaa61fc-bf79-9ad9-fea5-5486e9af232a.png)
"Service URL"に表示されている以下の部分を結合したものになります。
例：`https://e70506aa-ddc0-435c-aab6-7abc40008538.abap.eu10.hana.ondemand.com/sap/opu/odata/sap/ZUI_A_SALESORDER_O2`
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/276021/ab805c98-f89e-9626-9ab3-5785e648fed4.png)


### 1. トークンを取得
以下のパラメータを設定し、トークンを取得します。

|項目  |  |設定値  |
|---|---|---|
|URL| |XSUAAのサービスキーに記載のurl + /oauth/token  |
|ヘッダ|Content-Type |application/x-www-form-urlencoded  |
|パラメータ|grant_type |password  |
||username  |BTPログイン用のメールアドレス  |
||password |BTPログイン用のパスワード  |
||client_id  |XSUAAのサービスキーに記載のclient_id  |
||client_secret  |XSUAAのサービスキーに記載のclient_secret  |

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/276021/c31ff629-f2f5-1823-260c-9f8d1b588c84.png)

### 2. サービスを呼ぶ
続いて、ODataサービスのメタデータを取得してみます。

|項目  |  |設定値  |
|---|---|---|
|URL| |上記で確認したURL + /$metadata  |
|ヘッダ|Authorization |Bearer + 1.で取得したaccess_token  |

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/276021/2f687a75-c283-fe0a-f911-065e8d6c3068.png)

## フローの作成
Postmanで確認した通り、BTP ABAP環境のODataサービスを呼ぶステップは大まかには以下になります。
1. トークンを取得する
2. ODataサービスを呼ぶ
フローを見やすくするために、1.を別のフローとして作成し、2.のフローから呼び出す形とします。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/276021/2fc7795d-64c6-2201-2789-882117c3b424.png)

### トークン取得用のフロー
以下がトークン取得用のフローです。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/276021/8531b9da-ecab-95e7-084e-352f29347dcf.png)

#### 1. ProcessDirect
[ProcessDirect Adapter](https://help.sap.com/viewer/368c481cd6954bdfa5d0435479fd4eaf/Cloud/en-US/74457187451f431298355fbbf807d086.html?q=processdirect)は外部のフローからこのフローを呼びだすためのアダプターです。設定内容はアドレスのみです。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/276021/42933f70-0b2f-c065-911e-51d6c233c0e3.png)

#### 2. Set Header & Body [Content Modifier]
トークン取得用のエンドポイントに渡すヘッダとボディを編集します。

ヘッダにはcontent-typeとして`application/x-www-form-urlencoded`を設定します。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/276021/f787a2f1-b5bd-0ef8-cec3-83a7aabe3698.png)

ボディには固定値で以下を設定します。
`username=<BTPログイン用のメールアドレス>&password=<BTPログイン用のパスワード>&client_id=<XSUAAのサービスキーに記載のclient_id>&client_secret=<XSUAAのサービスキーに記載のclient_secret>`
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/276021/4d1617e1-693a-d7ab-3058-5806760af5a7.png)
※本来これらは直接フローに書かずにSecurity Materialから取得したほうがよいのですが、簡単にするためにベタ書きしています。

#### 3. Get Token [HTTP Adapter]
以下のHTTPリクエストでトークンを取得します。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/276021/b23fe9fb-ec15-ad09-718e-9b197688f54c.png)

#### 4. JSON to XML Converter
取得したトークンを次のステップで取得しやすくするため、レスポンスをXML形式に変換します。以下の設定はデフォルトのままです。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/276021/0f76c4a6-cf66-d093-821a-be27afd28ba5.png)

#### 5. Extract Token [Content Modifier]
このフローは、最終的にボディにトークンを設定して返します。このために、このステップでは以下のことを行います。

1. トークンをプロパティに格納 
1. プロパティからトークンを取得し、ボディに設定

トークンをプロパティに格納
XMLに変換しておいたので、XPathを使ってトークンにアクセスできます。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/276021/0d8ccbc6-26af-04d1-0226-3f48d14eb5d7.png)

プロパティからトークンを取得し、ボディに設定
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/276021/cf17f03c-512f-6926-3692-55d4b0e0e29c.png)

#### アウトプット
最初のProcessDirectを一時的にHTTPアダプターに変えてテストしてみると、以下のレスポンスが返ってきます。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/276021/c514db13-4ed4-8a8a-3b08-93b09f7cb59d.png)

### メインのフロー
以下がメインのフローです。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/276021/0faac5a5-1a83-a13f-d17b-8e542344d448.png)

#### 1. HTTP Sender Adapter
HTTPリクエストでフローを呼ぶため、HTTP Sender Adapterを使用します。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/276021/86bef586-85c1-042a-e7f8-f0c21e26dcf2.png)

#### 2. Get Token [ProcessDirect]
トークン取得用のフローを呼びだします。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/276021/83193e79-63ed-9fdb-70f5-fb2779c8962c.png)

#### 3. Set Headers
取得したトークン（ボディに入っている）を、Authorizationヘッダに`Bearer <token>`の形で設定します。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/276021/5bcd6180-6383-b602-a59a-afcac41d8efb.png)

#### 4. Call RAP OData [OData V2 Adapter]
RAPのODataサービスに対してGETリクエストを投げます。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/276021/b5937120-cbc7-7c38-eda0-72e9b1aaf685.png)
Request Headersに前のステップで作成した`Authorization`を設定します。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/276021/3695817b-be5c-543f-13d5-807341012b2f.png)

#### アウトプット
フローをデプロイし、Postmanからリクエストを投げます。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/276021/58cb25b0-5fa1-542e-0464-de809cf5160f.png)
以下のように結果が返ってくれば成功です。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/276021/ada69228-6399-6fd1-5119-15b2c743f1af.png)