「だいじょぶだぁ」と言うとSAP CP Workflow Serviceで購買依頼登録が承認されるiOSアプリを実装する(2/2)で紹介したいソースコードが長くなったのでこちらにまとめました。
※ SAP API Business Hubで"Code Snippet"ボタンを押すと各種言語によるAPIの呼び方が出てくるので、基本的にはそこからのコピペベースで書けるのですが、Swiftの場合はSnippetのソースのバージョンが古く、現在の最新バージョンであるSwift5ではエラーになりました。下記はSwift5.0.1でのHTTPリクエストの呼び方です。
## だっふんだ!と言ってPOSTメソッド(Start a new instance)を使用しWorkflow Instanceを開始する
//だっふんだの認識に成功していた場合のメソッド
func dafundaRecognized() {
//認証情報の暗号化
let originalString = "POOO123456:xxxxxxxxxx" //ユーザ名とパスワードを「:」でつなぐ
let originalData = originalString.data(using: .utf8)
let encodedString = originalData?.base64EncodedString()
print(encodedString!)
//Tokenを取るためのリクエストURLをセット
let httpUrl = "https://bpmworkflowruntimewfs-p2000123456trial.hanatrial.ondemand.com/workflow-service/rest/v1/xsrf-token"
guard let url = URL(string: httpUrl) else {
return
}
//リクエストHeaderを設定
var fetchTokenRequest = URLRequest(url: url)
fetchTokenRequest.setValue("Fetch", forHTTPHeaderField: "X-CSRF-Token")
fetchTokenRequest.setValue("application/json", forHTTPHeaderField: "Content-Type")
fetchTokenRequest.setValue("application/json", forHTTPHeaderField: "Accept")
fetchTokenRequest.setValue("Basic " + encodedString!, forHTTPHeaderField: "Authorization")
fetchTokenRequest.httpMethod = "GET"
//HTTPリクエスト
let fetchToken = URLSession.shared.dataTask(with: fetchTokenRequest) { (data, response, error) in
if let data = data, let response = response as? HTTPURLResponse {
print(response)
print(data)
do {
//Tokenの取得に成功した場合、POSTメソッドへ進む
let token = response.allHeaderFields["X-CSRF-Token"]
print (token as Any)
//POSTメソッドのURLをセット
let httpUrl = "https://bpmworkflowruntimewfs-p2000123456trial.hanatrial.ondemand.com/workflow-service/rest/v1/workflow-instances"
guard let url = URL(string: httpUrl) else {
return
}
//リクエストHeaderを設定
var updateUserTaskRequest = URLRequest(url: url)
updateUserTaskRequest.setValue(token as? String, forHTTPHeaderField: "X-CSRF-Token") //取得したTokenをセット
updateUserTaskRequest.setValue("application/json", forHTTPHeaderField: "Content-Type")
updateUserTaskRequest.setValue("application/json", forHTTPHeaderField: "Accept")
updateUserTaskRequest.setValue("Basic " + encodedString!, forHTTPHeaderField: "Authorization") //暗号化した認証情報をセット
updateUserTaskRequest.httpMethod = "POST"
//リクエストbodyを準備
let parameter : [String: Any] = [
"definitionId": "mydafundaworkflow", //Workflow定義のID
"context": [ //Workflow Instanceに反映されるWorkflow Context
"odata":[
"request":[ //Service Task実行時に渡されるパラメータ。使用するODataの仕様に合わせて設定
"Matnr": "300280", //「ドリフ大爆笑DVD」のS/4HANA上の品目コード
"Menge": 1, //「ドリフ大爆笑DVD」の個数
"Meins": "EA" //「ドリフ大爆笑DVD」の単位
],
"response":[]
]
]
]
let jsonData = try JSONSerialization.data(withJSONObject: parameter, options: [])
let jsonString = String(data: jsonData, encoding: String.Encoding.ascii)!
print (jsonString)
//リクエストbodyを設定
updateUserTaskRequest.httpBody = jsonData
//POSTリクエスト
let updateUserTask = URLSession.shared.dataTask(with: updateUserTaskRequest) { (data, response, error) in
if let data = data, let response = response as? HTTPURLResponse {
print(data)
print(response)
print(response.statusCode)
//成功していた場合、成功ダイアログを表示(別途実装が必要)
self.displayDialog()
} else {
print(error ?? "Error")
}
}
updateUserTask.resume()
} catch {
print("Error")
}
} else {
print(error ?? "Error")
}
}
fetchToken.resume()
}
## GETメソッド(Retrieve task by ID)を使用しWorkflow Instanceを取得する
@objc private func refreshData(_ sender: UIRefreshControl?) -> Void{
//処理中くるくるマーク表示開始(別途設定が必要)
DispatchQueue.main.async {
self.activityIndicatorView.startAnimating()
}
//認証情報の暗号化
let originalString = "POOO123456:xxxxxxxxxx" //ユーザ名とパスワードを「:」でつなぐ
let originalData = originalString.data(using: .utf8)
let encodedString = originalData?.base64EncodedString()
print(encodedString!)
//フィルタをかけて特定のTask Instanceの情報のみ取得
let httpUrl = "https://bpmworkflowruntimewfs-p2000123456trial.hanatrial.ondemand.com/workflow-service/rest/v1/task-instances?%24skip=0&%24top=100&%24inlinecount=none&%24orderby=createdAt%20asc&workflowDefinitionId=mydafundaworkflow&status=READY"
//分かりにくいですが、上記のURLのなかでWorkflow定義IDとTask Instance Statusをフィルタ用パラメータとして指定しました。
guard let url = URL(string: httpUrl) else {
return
}
//リクエストHeaderをセット
var request = URLRequest(url: url)
request.setValue("application/json", forHTTPHeaderField: "Content-Type")
request.setValue("application/json", forHTTPHeaderField: "Accept")
request.setValue("Basic " + encodedString!, forHTTPHeaderField: "Authorization")
let task = URLSession.shared.dataTask(with: request) { (data, response, error) in
if let data = data, let response = response {
print(data)
print(response)
do {
let json = try JSONSerialization.jsonObject(with: data, options: JSONSerialization.ReadingOptions.allowFragments)
print(json)
//配列を初期化(あらかじめ配列の宣言が必要)
self.localMaster = []
//取得した情報の一部を配列に格納
let jsonArray = json as? NSArray
for item in jsonArray!{
if let item = item as? NSDictionary{
var workflowTaskParameter = WorkflowTask()
workflowTaskParameter.taskID = (item["id"] as? String)! //Task Instance ID
workflowTaskParameter.applicantName = (item["createdBy"] as? String)!
self.localMaster.append(workflowTaskParameter)
}
}
DispatchQueue.main.async {
//テーブルをリロードする
self.tableView.reloadData()
// senderがある場合(テーブルを下に引っ張ってリフレッシュした場合)は、リフレッシュ完了させる
if sender != nil {
sender?.endRefreshing()
print("refresh")
}
//処理中くるくるマーク表示終了
self.activityIndicatorView.stopAnimating()
}
} catch {
print("Serialize Error")
}
} else {
print(error ?? "Error")
}
}
task.resume()
}
話は逸れますが、データ取得処理中に表示するくるくるマークはかわいくて便利です。実装方法は例えばこちらの記事を参照ください。
## だいじょぶだぁ!と言ってPATCHメソッド(Update task by ID)を使用しUser TaskのStatusをCOMPLETEDにする
private func completeUserTask (taskID: String, approved: String){
//認証情報の暗号化
activityIndicatorView.startAnimating()
let originalString = "P2000123456:xxxxxx"
let originalData = originalString.data(using: .utf8)
let encodedString = originalData?.base64EncodedString()
print(encodedString!)
//Tokenを取得するためのURLをセット
let httpUrl = "https://bpmworkflowruntimewfs-p2000123456trial.hanatrial.ondemand.com/workflow-service/rest/v1/xsrf-token"
guard let url = URL(string: httpUrl) else {
return
}
//リクエストHeaderをセット
var fetchTokenRequest = URLRequest(url: url)
fetchTokenRequest.setValue("Fetch", forHTTPHeaderField: "X-CSRF-Token")
fetchTokenRequest.setValue("application/json", forHTTPHeaderField: "Content-Type")
fetchTokenRequest.setValue("application/json", forHTTPHeaderField: "Accept")
fetchTokenRequest.setValue("Basic " + encodedString!, forHTTPHeaderField: "Authorization")
fetchTokenRequest.httpMethod = "GET"
//Tokenを取得する
let fetchToken = URLSession.shared.dataTask(with: fetchTokenRequest) { (data, response, error) in
if let data = data, let response = response as? HTTPURLResponse {
print(response)
print(data)
do {
let token = response.allHeaderFields["X-CSRF-Token"]
print (token as Any)
print ("selected task id is " + taskID)
//Tokenの取得に成功した場合、PATCHリクエストへ進む
//URLにWorkflow Instance IDを含める
let httpUrl = "https://bpmworkflowruntimewfs-p2000123456trial.hanatrial.ondemand.com/workflow-service/rest/v1/task-instances/" + taskID
guard let url = URL(string: httpUrl) else {
return
}
//リクエストbodyを準備
let parameter : [String: Any] = [
//引数のapprovedはBool変数。承認or否認に応じてtrue or falseをWorkflow Contextに渡す
"context": ["approved" : approved],
"status": "COMPLETED", //Task InstanceのStatusをCOMPLETEDに。他のパラメータは使わない。
// "subject": "string",
// "description": "string",
// "recipientUsers": "string",
// "recipientGroups": "string",
// "processor": "string",
// "dueDate": "2019-06-12T14:06:52.892Z",
// "priority": "VERY_HIGH"
]
let jsonData = try JSONSerialization.data(withJSONObject: parameter, options: [])
let jsonString = String(data: jsonData, encoding: String.Encoding.ascii)!
print (jsonString)
//リクエストHeaderをセット
var updateUserTaskRequest = URLRequest(url: url)
updateUserTaskRequest.setValue(token as? String, forHTTPHeaderField: "X-CSRF-Token")
updateUserTaskRequest.setValue("application/json", forHTTPHeaderField: "Content-Type")
updateUserTaskRequest.setValue("application/json", forHTTPHeaderField: "Accept")
updateUserTaskRequest.setValue("Basic " + encodedString!, forHTTPHeaderField: "Authorization")
updateUserTaskRequest.httpMethod = "PATCH"
updateUserTaskRequest.httpBody = jsonData
//PATCHリクエスト
let updateUserTask = URLSession.shared.dataTask(with: updateUserTaskRequest) { (data, response, error) in
if let data = data, let response = response as? HTTPURLResponse {
print(data)
print(response)
print(response.statusCode)
self.refreshData(nil)
} else {
print(error ?? "Error")
}
}
updateUserTask.resume()
} catch {
print("Error")
}
} else {
print(error ?? "Error")
}
}
fetchToken.resume()
}