3
1

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

More than 5 years have passed since last update.

「だいじょぶだぁ」と言うとSAP CP Workflow Serviceで購買依頼登録が承認されるiOSアプリを実装する(Appendix)

Last updated at Posted at 2019-06-17

「だいじょぶだぁ」と言うと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を開始する

ViewController.swift
//だっふんだの認識に成功していた場合のメソッド
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を取得する

TableViewController
    @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にする

TableViewController
    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()
    }
3
1
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
3
1

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?