使用回呼和 Google 試算表暫停及繼續工作流程


Google 試算表是雲端試算表解決方案,支援即時協作,並提供資料視覺化、處理及傳達工具。

本教學課程示範如何建立及部署工作流程,以建立回呼端點 (或 Webhook)、將回呼網址儲存至 Google 試算表、暫停執行,然後等待使用者透過試算表核准,以重新啟動工作流程。進一步瞭解如何使用回呼

目標

在這個教學課程中,您將執行下列操作:

  1. 在 Google 雲端硬碟中建立新資料夾。這個資料夾用於儲存試算表,並允許工作流程寫入試算表。
  2. 建立 Google 試算表,擷取核准並啟動工作流程的回呼。
  3. 使用 Google Apps Script (雲端 JavaScript 平台,可讓您以程式輔助方式建立、讀取及編輯 Google Workspace 產品),在試算表更新時核准要求後,觸發暫停的工作流程繼續執行。
  4. 建立及部署工作流程,呼叫 Google Sheets API 連接器,將資料附加到試算表。工作流程會執行、暫停,然後在透過試算表核准回呼時繼續執行。進一步瞭解 Workflows 連接器
  5. 測試整個程序,確認工作流程是否如預期進行。

費用

在本文件中,您會使用 Google Cloud的下列計費元件:

如要根據預測用量估算費用,請使用 Pricing Calculator

初次使用 Google Cloud 的使用者可能符合免費試用資格。

本教學課程也會使用 Google Workspace。Google 免費版消費者應用程式未提供的企業級服務,皆須付費。

事前準備

您可以在 Google Cloud 控制台中執行下列部分指令,也可以在終端機或 Cloud Shell 中使用 Google Cloud CLI 執行。

貴機構定義的安全性限制,可能會導致您無法完成下列步驟。如需疑難排解資訊,請參閱「在受限的 Google Cloud 環境中開發應用程式」。

主控台

  1. 在 Google Cloud 控制台的專案選擇器頁面中,選取或建立 Google Cloud 專案

    前往專案選取器

  2. 請確認您已為 Google Cloud 專案啟用計費功能。瞭解如何檢查專案是否已啟用計費功能

  3. 啟用 Compute Engine、Google 試算表和 Workflows API。

    啟用 API

  4. 記下 Compute Engine 預設服務帳戶,因為在本教學課程中,您會將該帳戶與工作流程建立關聯,以進行測試。啟用 Compute Engine API 的新專案會建立這個服務帳戶,並指派 IAM 基本編輯者角色,電子郵件地址格式如下:

    PROJECT_NUMBER-compute@developer.gserviceaccount.com

    您可以在 Google Cloud 控制台的「歡迎」頁面找到專案編號。

    在正式環境中,我們強烈建議建立新的服務帳戶,並授予一或多個包含最低必要權限的 IAM 角色,同時遵循最低權限原則。

gcloud

  1. In the Google Cloud console, activate Cloud Shell.

    Activate Cloud Shell

    At the bottom of the Google Cloud console, a Cloud Shell session starts and displays a command-line prompt. Cloud Shell is a shell environment with the Google Cloud CLI already installed and with values already set for your current project. It can take a few seconds for the session to initialize.

  2. 請確認您已為 Google Cloud 專案啟用計費功能。 瞭解如何檢查專案是否已啟用計費功能

  3. 啟用 Compute Engine、Google 試算表和 Workflows API。

    gcloud services enable \
        compute.googleapis.com \
        sheets.googleapis.com \
        workflows.googleapis.com
  4. 記下 Compute Engine 預設服務帳戶,因為在本教學課程中,您會將該帳戶與工作流程建立關聯,以進行測試。啟用 Compute Engine API 的新專案會建立這個服務帳戶,並指派 IAM 基本編輯者角色,電子郵件地址格式如下:

    PROJECT_NUMBER-compute@developer.gserviceaccount.com

    您可以透過下列方式取得專案編號:

    gcloud projects describe PROJECT_ID

    在正式環境中,我們強烈建議建立新的服務帳戶,並授予一或多個包含最低必要權限的 IAM 角色,同時遵循最低權限原則。

在 Google 雲端硬碟中建立新資料夾

在 Google 雲端硬碟中建立新資料夾。這個資料夾是用來儲存試算表的。設定共用資料夾的權限後,工作流程就能將資料寫入試算表。

  1. 前往 drive.google.com
  2. 依序點選「新增」>「新增資料夾」
  3. 輸入資料夾名稱。
  4. 點選「建立」
  5. 在新資料夾上按一下滑鼠右鍵,然後選取「共用」
  6. 新增 Compute Engine 預設服務帳戶的電子郵件地址。

    這樣一來,服務帳戶就能存取該資料夾。將服務帳戶與工作流程建立關聯後,工作流程就能編輯資料夾中的任何檔案。進一步瞭解如何共用檔案、資料夾和雲端硬碟

  7. 選取「編輯者」角色。

  8. 取消勾選「通知共用對象」核取方塊。

  9. 按一下「共用」

使用 Google 試算表建立試算表

透過 Google 試算表建立的試算表會儲存在 Google 雲端硬碟中。根據預設,試算表會儲存到雲端硬碟的根資料夾。使用 Google 試算表 API 時,無法直接在指定資料夾中建立試算表。不過,您也可以在建立試算表後,將其移至特定資料夾,如本範例所示。詳情請參閱「使用 Google 雲端硬碟資料夾」。

  1. 前往 sheets.google.com

  2. 按一下「新增」圖示 Plus

    即可建立並開啟新的試算表。每份試算表都有專屬的spreadsheetId值,其中包含字母、數字、連字號或底線。您可以在 Google 試算表網址中找到試算表 ID:

    https://docs.google.com/spreadsheets/d/spreadsheetId/edit#gid=0

  3. 請記下這個 ID,建立工作流程時會用到。

  4. 新增欄標題,與下列範例相符:

    用來記錄核准的試算表範例

    請注意,系統會使用「已核准?」(G 欄) 中的值,在工作流程中啟動回呼。

  5. 將試算表移至先前建立的 Google 雲端硬碟資料夾:

    1. 在試算表中,依序選取「檔案」>「移動」
    2. 前往您建立的資料夾。
    3. 按一下 [移動]

您也可以使用 Google 試算表 API 連接器建立試算表。請注意,使用連接器時,可以從 resp 結果擷取 spreadsheetId。例如:

- create_spreadsheet:
    call: googleapis.sheets.v4.spreadsheets.create
    args:
      body:
      connector_params:
        scopes: ${driveScope}
    result: resp
- assign_sheet_id:
    assign:
      - sheetId: ${resp.spreadsheetId}

使用 Apps Script 擴充 Google 試算表功能

您可以使用 Apps Script,以程式輔助方式建立、讀取及編輯 Google 試算表。為 Google 試算表設計的指令碼大多會操控陣列,與試算表中的儲存格、列和欄互動。如要瞭解如何搭配使用 Apps Script 和 Google 試算表,請參閱自訂函式快速入門導覽課程

  1. 從 Google 試算表建立 Apps Script 專案:

    1. 開啟 Google 試算表。
    2. 依序選取「擴充功能」>「Apps Script」
    3. 在指令碼編輯器中,按一下「未命名的專案」
    4. 為專案命名,然後按一下「重新命名」

    您的指令碼現在已繫結至試算表,因此指令碼具備特殊功能,可變更使用者介面,或在試算表開啟時做出回應。

    指令碼專案代表一組 Apps Script 檔案和資源。指令碼專案中的程式碼檔案會採用 .gs 副檔名。

  2. 您可以使用 Apps Script 編寫自訂函式,並在 Google 試算表中使用這些函式,就像使用內建函式一樣。自訂函式是使用標準 JavaScript 建立,建立函式:

    1. 開啟 Apps Script 專案。
    2. 按一下「編輯器」圖示
    3. 指令碼檔案會顯示為名為 Code.gs 的專案檔案。如要編輯檔案,請選取檔案。
    4. 將指令碼編輯器中的任何程式碼,替換為下列程式碼,讀取試算表中的資料,並將資料做為輸入內容傳遞至工作流程執行作業:

      function handleEdit(e) {
        var range = e.range.getA1Notation();
        var sheet = e.source;
      
        if (range.length > 1 && range[0] === 'G') {
          if (e.value == "TRUE") {
            Logger.log("Approved: TRUE");
      
            var row = range.slice(1);
            var url = sheet.getRange('E' + row).getCell(1, 1).getValue();
            var approver = sheet.getRange('F' + row).getCell(1, 1).getValue();
      
            callback(url, approver);
          }
          else {
            Logger.log("Approved: FALSE");
          }
        }
      }
      
      function callback(url, approver) {
        const headers = {
          "Authorization": "Bearer " + ScriptApp.getOAuthToken()
        };
      
        var payload = {
          'approver': approver
        };
      
        const params = {
          "method": 'POST',
          "contentType": 'application/json',
          "headers": headers,
          "payload": JSON.stringify(payload)
        };
      
      
        Logger.log("Workflow callback request to " + url);
        var response = UrlFetchApp.fetch(url, params);
        Logger.log(response);
      }
    5. 按一下「儲存」圖示

  3. Apps Script 的可安裝觸發條件可讓指令碼專案在符合特定條件時執行指定函式,例如開啟或編輯試算表時。建立觸發條件:

    1. 開啟 Apps Script 專案。
    2. 按一下「觸發條件」
    3. 按一下「新增觸發條件」
    4. 在「Add Trigger for YOUR_PROJECT_NAME」(為 YOUR_PROJECT_NAME 新增觸發條件) 對話方塊中,設定觸發條件:
      1. 在「Choose which function to run」(選擇要執行的函式) 清單中,選取「handleEdit」
      2. 在「Choose which deployment should run」(選擇要執行的部署作業) 清單中,選取「Head」
      3. 在「選取事件來源」清單中,選取「從試算表」
      4. 在「選取事件類型」清單中,選取「編輯時」
      5. 在「失敗通知設定」清單中,選取「每天通知我」
    5. 按一下 [儲存]
    6. 如果系統提示你選擇 Google 帳戶,請選取適當的帳戶,然後按一下「允許」

      這樣一來,您的 Apps Script 專案就能查看、編輯、建立及刪除 Google 試算表,並連線至外部服務。

  4. Apps Script 專案的資訊清單檔案是 JSON 檔案,用於指定 Apps Script 順利執行指令碼所需的基本專案資訊。請注意,為保護 Apps Script 專案設定,Apps Script 編輯器預設會隱藏資訊清單檔案。編輯資訊清單檔案:

    1. 開啟 Apps Script 專案。
    2. 按一下「專案設定」
    3. 勾選「在編輯器中顯示『appsscript.json』資訊清單檔案」核取方塊。
    4. 按一下「編輯器」圖示
    5. 資訊清單檔案會顯示為名為 appsscript.json 的專案檔案。如要編輯檔案,請選取檔案。
    6. oauthScopes 欄位會指定字串陣列。如要設定專案使用的授權範圍,請新增包含所需範圍的陣列。例如:

      {
        "timeZone": "America/Toronto",
        "dependencies": {
        },
        "exceptionLogging": "STACKDRIVER",
        "runtimeVersion": "V8",
        "oauthScopes": [
          "https://www.googleapis.com/auth/script.external_request",
          "https://www.googleapis.com/auth/cloud-platform",
          "https://www.googleapis.com/auth/spreadsheets"
        ]
      }

      這會將明確範圍設為:

      • 連線至外部服務
      • 查看、編輯、設定及刪除您的 Google Cloud 資料,以及查看您 Google 帳戶的電子郵件地址
      • 查看、編輯、建立及刪除您的所有 Google 試算表檔案
    7. 按一下「儲存」圖示

部署會寫入試算表並使用回呼的工作流程

部署工作流程,在透過試算表核准回呼時執行、暫停及繼續執行。工作流程會使用 Google Sheets API 連接器,將資料寫入 Google 試算表。

控制台

  1. 前往 Google Cloud 控制台的「Workflows」頁面:

    前往「Workflows」頁面

  2. 按一下「建立」

  3. 輸入新工作流程的名稱:workflows-awaits-callback-sheets

  4. 在「Region」(區域) 清單中,選取「us-central1 (Iowa)」(us-central1 (愛荷華州))

  5. 在「服務帳戶」中,選取 Compute Engine 預設服務帳戶 (PROJECT_NUMBER-compute@developer.gserviceaccount.com)。

  6. 點選「下一步」

  7. 在工作流程編輯器中,輸入下列工作流程定義:

    main:
      steps:
        - init:
            assign:
            # Replace with your sheetId and make sure the service account
            # for the workflow has write permissions to the sheet
            - sheetId: "10hieAH6b-oMeIVT_AerSLNxQck14IGhgi8ign-x2x8g"
        - before_sheets_callback:
            call: sys.log
            args:
              severity: INFO
              data: ${"Execute steps here before waiting for callback from sheets"}
        - wait_for_sheets_callback:
            call: await_callback_sheets
            args:
              sheetId: ${sheetId}
            result: await_callback_result
        - after_sheets_callback:
            call: sys.log
            args:
              severity: INFO
              data: ${"Execute steps here after receiving callback from sheets"}
        - returnResult:
            return: ${await_callback_result}
    
    await_callback_sheets:
        params: [sheetId]
        steps:
            - init:
                assign:
                  - project_id: ${sys.get_env("GOOGLE_CLOUD_PROJECT_ID")}
                  - location: ${sys.get_env("GOOGLE_CLOUD_LOCATION")}
                  - workflow_id: ${sys.get_env("GOOGLE_CLOUD_WORKFLOW_ID")}
                  - execution_id: ${sys.get_env("GOOGLE_CLOUD_WORKFLOW_EXECUTION_ID")}
            - create_callback:
                call: events.create_callback_endpoint
                args:
                  http_callback_method: POST
                result: callback_details
            - save_callback_to_sheets:
                call: googleapis.sheets.v4.spreadsheets.values.append
                args:
                    range: ${"Sheet1!A1:G1"}
                    spreadsheetId: ${sheetId}
                    valueInputOption: RAW
                    body:
                        majorDimension: "ROWS"
                        values:
                          - ["${project_id}", "${location}", "${workflow_id}", "${execution_id}", "${callback_details.url}", "", "FALSE"]
            - log_and_await_callback:
                try:
                  steps:
                    - log_await_start:
                        call: sys.log
                        args:
                          severity: INFO
                          data: ${"Started waiting for callback from sheet " + sheetId}
                    - await_callback:
                        call: events.await_callback
                        args:
                          callback: ${callback_details}
                          timeout: 3600
                        result: callback_request
                    - log_await_stop:
                        call: sys.log
                        args:
                          severity: INFO
                          data: ${"Stopped waiting for callback from sheet " + sheetId}
                except:
                    as: e
                    steps:
                        - log_error:
                            call: sys.log
                            args:
                                severity: "ERROR"
                                text: ${"Received error " + e.message}
            - check_null_await_result:
                switch:
                  - condition: ${callback_request == null}
                    return: null
            - log_await_result:
                call: sys.log
                args:
                  severity: INFO
                  data: ${"Approved by " + callback_request.http_request.body.approver}
            - return_await_result:
                return: ${callback_request.http_request.body}
  8. 請務必將預留位置 sheetId 值替換成您的 spreadsheetId

  9. 按一下 [Deploy] (部署)

gcloud

  1. 為工作流程建立原始碼檔案:

    touch workflows-awaits-callback-sheets.yaml
  2. 在文字編輯器中,將下列工作流程複製到原始碼檔案:

    main:
      steps:
        - init:
            assign:
            # Replace with your sheetId and make sure the service account
            # for the workflow has write permissions to the sheet
            - sheetId: "10hieAH6b-oMeIVT_AerSLNxQck14IGhgi8ign-x2x8g"
        - before_sheets_callback:
            call: sys.log
            args:
              severity: INFO
              data: ${"Execute steps here before waiting for callback from sheets"}
        - wait_for_sheets_callback:
            call: await_callback_sheets
            args:
              sheetId: ${sheetId}
            result: await_callback_result
        - after_sheets_callback:
            call: sys.log
            args:
              severity: INFO
              data: ${"Execute steps here after receiving callback from sheets"}
        - returnResult:
            return: ${await_callback_result}
    
    await_callback_sheets:
        params: [sheetId]
        steps:
            - init:
                assign:
                  - project_id: ${sys.get_env("GOOGLE_CLOUD_PROJECT_ID")}
                  - location: ${sys.get_env("GOOGLE_CLOUD_LOCATION")}
                  - workflow_id: ${sys.get_env("GOOGLE_CLOUD_WORKFLOW_ID")}
                  - execution_id: ${sys.get_env("GOOGLE_CLOUD_WORKFLOW_EXECUTION_ID")}
            - create_callback:
                call: events.create_callback_endpoint
                args:
                  http_callback_method: POST
                result: callback_details
            - save_callback_to_sheets:
                call: googleapis.sheets.v4.spreadsheets.values.append
                args:
                    range: ${"Sheet1!A1:G1"}
                    spreadsheetId: ${sheetId}
                    valueInputOption: RAW
                    body:
                        majorDimension: "ROWS"
                        values:
                          - ["${project_id}", "${location}", "${workflow_id}", "${execution_id}", "${callback_details.url}", "", "FALSE"]
            - log_and_await_callback:
                try:
                  steps:
                    - log_await_start:
                        call: sys.log
                        args:
                          severity: INFO
                          data: ${"Started waiting for callback from sheet " + sheetId}
                    - await_callback:
                        call: events.await_callback
                        args:
                          callback: ${callback_details}
                          timeout: 3600
                        result: callback_request
                    - log_await_stop:
                        call: sys.log
                        args:
                          severity: INFO
                          data: ${"Stopped waiting for callback from sheet " + sheetId}
                except:
                    as: e
                    steps:
                        - log_error:
                            call: sys.log
                            args:
                                severity: "ERROR"
                                text: ${"Received error " + e.message}
            - check_null_await_result:
                switch:
                  - condition: ${callback_request == null}
                    return: null
            - log_await_result:
                call: sys.log
                args:
                  severity: INFO
                  data: ${"Approved by " + callback_request.http_request.body.approver}
            - return_await_result:
                return: ${callback_request.http_request.body}
  3. 請務必將預留位置 sheetId 值替換成您的 spreadsheetId

  4. 輸入下列指令來部署工作流程:

    gcloud workflows deploy workflows-awaits-callback-sheets \
        --source=workflows-awaits-callback-sheets.yaml \
        --location=us-central1 \
        --service-account=PROJECT_NUMBER-compute@developer.gserviceaccount.com

    PROJECT_NUMBER 替換為專案編號。 Google Cloud您可以透過下列方式取得專案編號:

    gcloud projects describe PROJECT_ID

測試端對端流程

執行工作流程,測試端對端流程。執行工作流程時,系統會執行與該工作流程相關聯的目前工作流程定義。

控制台

  1. 前往 Google Cloud 控制台的「Workflows」頁面:

    前往「Workflows」頁面

  2. 在「Workflows」頁面中,選取「workflows-awaits-callback-sheets」工作流程,前往詳細資料頁面。

  3. 在「工作流程詳細資料」頁面中,按一下 「執行」

  4. 再次點按「執行」

    工作流程會開始執行,執行狀態應為「執行中」。記錄檔也會指出工作流程已暫停並等待:

    Execute steps here before waiting for callback from sheets
    ...
    Started waiting for callback from sheet 1JlNFFnqs760M_KDqeeeDc_qtrABZDxoalyCmRE39dpM
  5. 確認工作流程已將回呼詳細資料寫入試算表中的資料列。

    舉例來說,您應該會在「Execution ID」欄中看到工作流程執行 ID,在「Callback URL」欄中看到回呼端點,在「Approved?」欄中看到「FALSE」

  6. 在試算表中,將 FALSE 變更為 TRUE

    一兩分鐘後,執行作業應會繼續,然後以「Succeeded」的執行狀態完成。

gcloud

  1. 開啟終端機。

  2. 執行工作流程:

      gcloud workflows run workflows-awaits-callback-sheets

    工作流程會啟動,輸出內容應會指出工作流程已暫停並等待:

      Waiting for execution [a8361789-90e0-467f-8bd7-ea1c81977820] to complete...working.

  3. 確認工作流程已將回呼詳細資料寫入試算表中的資料列。

    舉例來說,您應該會在「Execution ID」欄中看到工作流程執行 ID,在「Callback URL」欄中看到回呼端點,在「Approved?」欄中看到「FALSE」

  4. 在試算表中,將 FALSE 變更為 TRUE

    一兩分鐘後,執行作業應會繼續,然後以 SUCCEEDED 的執行狀態完成。

清除所用資源

如果您是為了這個教學課程建立新專案,請刪除專案。如果您使用現有專案,並想保留專案,但不要本教學課程新增的變更,請刪除為本教學課程建立的資源

刪除專案

如要避免付費,最簡單的方法就是刪除您為了本教學課程所建立的專案。

如要刪除專案:

  1. In the Google Cloud console, go to the Manage resources page.

    Go to Manage resources

  2. In the project list, select the project that you want to delete, and then click Delete.
  3. In the dialog, type the project ID, and then click Shut down to delete the project.

刪除在本教學課程中建立的資源

  1. 刪除 Google 雲端硬碟中的檔案
  2. 刪除工作流程

後續步驟