はじめに
前回の記事の続きです。今回はいよいよ UiPath から S/4HANA の OData API /A_PurchaseOrder
を呼び出してみます。
本記事で作成するワークフローは Studio 23.10.4 で作成しています。
SAP OData API 呼び出しで知っておきたいこと
前回は、内部(SAP GUI)から OData API を呼び出しましたが、今回は外部(UiPath)からの呼び出しとなります。外部から OData API を呼び出す場合は下記2点を考慮する必要があります。
1. 認証が必要
2. GET, HEAD 以外の呼び出し (POST, PUT, PATCH, MERGE, DELETE) には CSRF トークンが必要
それぞれ見ていきましょう。
1. 認証が必要
当然と言えば当然ですが、API 呼び出しには認証が必要になります。SAP Business Accelerator Hub の該当 API ページ の Authentication Methods を見るとどの認証方法を使えるか確認できます。
今回は Basic Authentication(Basic 認証)を使います。
認証が通るとセッションIDが払い出されます。後続の API 呼び出し時に払い出されたセッションIDを付与する必要があります。
2. GET, HEAD 以外の呼び出し (POST, PUT, PATCH, MERGE, DELETE) には CSRF トークンが必要
CSRF トークンを取得するには、リクエスト HTTP ヘッダーに x-csrf-token : Fetch
を含めて GET または HEAD メソッドで API を呼び出す必要があります。
呼び出しに成功すると、レスポンス HTTP ヘッダーの x-csrf-token
に CSRF トークンが設定されるので取得します。以降の GET 以外の呼び出し時にこの CSRF トークンをリクエストヘッダーに設定します。
ワークフローを実装する
依存関係の追加
UiPath から S/4HANA の OData API を呼び出しは、HTTP 要求
アクティビティを使います。このアクティビティは UiPath.WebAPI.Activities
に含まれています。
プロジェクトを新規に作成して、プロジェクトの依存関係に追加します。
セッション ID と CSRF トークンの取得
POST の /A_PurchaseOrder
の呼び出しで必要となるセッション ID と CSRF トークンを取得します。専用エンドポイントは用意されていないので、今回は GET で /A_PurchaseOrder
を呼び出してエンドポイントのメタデータを取得することでトークンを取得します。
呼び出すエンドポイントの URI は以下となります。クエリパラメータとして $metadata
を付けることでエンドポイントのメタデータが取得できます。
https://{host}:{port}/sap/opu/odata/sap/API_PURCHASEORDER_PROCESS_SRV/A_PurchaseOrder?$metadata
はじめに、以下の変数を定義します。
変数 | 型 |
---|---|
strUri | String |
strClient | String |
disResHeader | Dictionary |
strSapSessionId | String |
strCsrfToken | String |
regexResult | IEnumerable<Match> |
strResContent | String |
intStsCode | int32 |
jsonResContent | JObject |
strUri
と strClient
に 代入
アクティビティで値を指定します。
変数 | 値 |
---|---|
strUri |
https://{host}:{port}/sap/opu/odata/sap/API_PURCHASEORDER_PROCESS_SRV/A_PurchaseOrder {host} {port} は実際の値を指定します。 |
strClient | クライアントID |
続いて HTTP 要求
アクティビティを配置します。以下のプロパティを指定します。
プロパティ | 値 |
---|---|
エンドポイント | strUri + "?$metadata" |
要求メソッド | GET |
HTTP ヘッダー |
sap-client : strClient x-csrf-token : "Fetch" |
認証 |
簡易 HTTP ユーザー名、パスワード |
出力 - ヘッダー | dicResHeader |
応答コンテンツ | strResContent |
応答ステータス | intStsCode |
エンドポイントを呼び出したら、レスポンスヘッダーから CSRF トークンを取得します。CSRF トークンはレスポンスヘッダーに x-csrf-token
として格納されています。
HTTP 要求
アクティビティでの API 呼び出しがうまくいかないときは、 プロパティ 応答コンテンツ
と 応答ステータス
に設定された値を確認すると、呼び出しの失敗原因を特定できる可能性があるので活用してください。
strCsrfToken = dicResHeader("x-csrf-token")
続いて、レスポンスヘッダーからセッション ID を取得します。セッション ID はレスポンスヘッダーに含まれる Cookie で SAP_SESSIONID_<sid>_<client>
という形式のキーに格納されています。
一致する文字列を取得
アクティビティを使ってセッション ID を取得します。このアクティビティは正規表現を使って文字列を抽出することが出来ます。
プロパティはこちらです。
プロパティ | 値 |
---|---|
結果 | regexResult |
パターン | SAP_SESSIONID_(.*?)=(.*?)(?:;|,(?!\s)) |
入力 | dicResHeader("Set-Cookie") + ";" |
抽出結果を変数 strSapSessionId
に格納します。
strSapSessionId = regexResult(0).Groups(2).ToString
以上でセッション ID と CSRF トークンを利用できるようになりました。
購買発注の呼び出し
リクエストデータの構築
/A_PurchaseOrder
に渡すリクエストデータを用意します。
リクエストデータは JSON 形式で渡します。JSON の作成は Dictionary 型の変数にキーと値を設定していき、最後に JsonConvert
クラスの SerializeObject(Dictionary型変数)
メソッドを使って Dictionary 型から JSON 文字列に変換します。
リクエストデータの構築には下記変数を使います。
変数名 | 型 |
---|---|
dicPayload | Dictionary<Of String, Object> |
lstItems | List<Of Object> |
dicItem | Dictionary<Of String, String> |
strPayload | String |
代入
または 複数代入
アクティビティで購買発注に必要な情報を設定していきます。
上記実装を VB.NET のコードで表現すると以下のようになります。
' ヘッダ情報を作成
Dim dicPayload As New Dictionary(Of String, Object)
dicPayload("CompanyCode") = "1710"
dicPayload("PurchaseOrderType") = "NB"
dicPayload("PurchasingGroup") = "001"
dicPayload("PurchasingOrganization") = "1710"
dicPayload("Supplier") = "17300001"
' 明細情報を作成
Dim dicItem As New Dictionary(Of String, String)
dicItem("Material") = "TG11"
dicItem("NetPriceAmount") = "130.00"
dicItem("NetPriceQuantity") = "1"
dicItem("OrderQuantity") = "1"
dicItem("Plant") = "1710"
dicItem("PurchaseOrderItemCategory") = "0"
Dim lstItems As New List(Of Object)
lstItems.Add(dicItem)
' ヘッダに明細を追加
dicPayload("to_PurchaseOrderItem") = lstItems
' JSON 文字列に変換
strPayload = JsonConvert.SerializeObject(dicPayload)
実行すると以下の JSON 文字列が strPayload
変数に格納されます。
{"CompanyCode":"1710","PurchaseOrderType":"NB","PurchasingGroup":"001","PurchasingOrganization":"1710","Supplier":"17300001","to_PurchaseOrderItem":[{"Material":"TG11","NetPriceAmount":"130.00","NetPriceQuantity":"1","OrderQuantity":"1","Plant":"1710","PurchaseOrderItemCategory":"0"}]}
HTTP 要求アクティビティの構築
続いて HTTP 要求
アクティビティを配置します。以下のプロパティを指定します。
プロパティ | 値 |
---|---|
エンドポイント | strUri |
要求メソッド | POST |
HTTP ヘッダー |
sap-client : strClient x-csrf-token : strCsrfToken |
Cookie |
SAP_SESSIONID_S4H_804 : strSapSessionId セッション ID 名は ``SAP_SESSIONID_<sid>_<client>`` の形式で、<sid>と<client>の部分は環境により異なります。ご利用の環境に合わせてセッション ID 名を設定してください。 |
本文形式 | application/json |
本文 | strPayload |
受け入れ形式 | JSON |
応答コンテンツ | strResContent |
応答ステータス | intStsCode |
最後に、HTTP 呼び出し結果から伝票番号を取得します。レスポンスデータは JSON 形式となっているので、JSON を逆シリアル化
アクティビティを使って JObject 型に変換します。プロパティは次の通りです。
プロパティ | 値 |
---|---|
TypeArgument | Newtonsoft.Json.Linq.JObject |
JSON 文字列 | strResContent |
Json オブジェクト | jsonResContent |
JObject の変数 jsonResContent
から伝票番号を取得します。今回はメッセージボックスに結果を表示させてみます。
実行してみる
完成したワークフローを実行してみましょう。発注伝票が登録され、以下のように伝票番号が表示されれば成功です。
おわりに
UiPath から SAP の OData を呼び出すことが出来ました。UiPath では画面の自動化だけでなく、HTTP ベースの API 呼び出しも簡単に実装することが出来ます。
皆様の開発の一助になれば幸いです。
UiPath から SAP S/4HANA の OData を呼び出すシリーズ