建立 Classroom 外掛程式

這是 Classroom 外掛程式逐步操作說明系列中的第一個逐步操作說明。

在這個逐步操作說明中,您會奠定開發網頁應用程式的基礎,並將其發布為 Classroom 外掛程式。此應用程式的後續逐步操作說明。

在本逐步操作說明中,您將完成下列操作:

  • 為網頁應用程式建立新的 Google Cloud 專案。
  • 以預留位置登入按鈕建立基本架構網頁應用程式。
  • 為網頁應用程式發布私人 Google Workspace Marketplace (GWM) 商店資訊。

完成後,您就可以安裝外掛程式,並將外掛程式載入 Classroom 外掛程式 iframe。

必要條件

請選擇下方任一語言,查看適當的需求條件:

Python

我們的 Python 範例使用 Flask 架構。您可以從「總覽」頁面下載所有逐步操作說明的完整原始碼。您可以在 /flask/01-basic-app/ 目錄中找到此逐步操作說明的程式碼。

如有需要,請安裝 Python 3.7+,並確認 pip 可用。

python -m ensurepip --upgrade

我們也建議您設定並啟用新的 Python 虛擬環境。

python3 -m venv .classroom-addon-env
source .classroom-addon-env/bin/activate

下載範例中的每個逐步操作說明子目錄都包含 requirements.txt。您可以使用 pip 快速安裝所需的程式庫。請使用下列指令安裝本逐步操作說明所需的程式庫。

cd flask/01-basic-app
pip install -r requirements.txt

Node.js

我們的 Node.js 範例使用 Express 架構。您可以從「總覽」頁面下載所有逐步操作說明的完整原始碼

如有必要,請安裝 NodeJS v16.13+

使用 npm 安裝必要的節點模組。

npm install

Java

我們的 Java 範例使用 Spring Boot 架構。您可以從「總覽」頁面下載所有逐步操作說明的完整原始碼

如果您尚未在機器上安裝 Java 11+,請先安裝。

Spring Boot 應用程式可以使用 Gradle 或 Maven 處理建構作業及管理依附元件。這個範例包含的 Maven 包裝函式可確保建構成功,而不必安裝 Maven。

如要執行我們提供的範例,請在您下載專案的目錄中執行下列指令,確保您具備執行專案的必要條件。

java --version
./mvnw --version

或在 Windows 執行下列指令:

java -version
mvnw.cmd --version

設定 Google Cloud 專案

Classroom API 的存取權和必要驗證方法是由 Google Cloud 專案控制。以下操作說明可引導您完成基本步驟,以建立及設定新專案,以便與外掛程式搭配使用。

建立專案

前往專案建立頁面建立新的 Google Cloud 專案。您可以提供新專案的任何名稱。按一下「建立」

新專案需要一些時間才會建立完成。完成後,請務必選取專案;您可以在畫面頂端的專案選取器下拉式選單中選擇專案,或在右上方的通知選單中按一下 [選取專案]

在 Google Cloud 控制台中選取專案

將 GWM SDK 附加至 Google Cloud 專案

前往「API Library」(API 程式庫) 瀏覽器。搜尋 Google Workspace Marketplace SDK。您應該會在結果清單中看到 SDK。

Google Workspace Marketplace SDK 資訊卡

選取 Google Workspace Marketplace SDK 資訊卡,然後按一下「啟用」

設定 GWM SDK

GWM 會提供清單,使用者和管理員可透過哪些管道安裝您的外掛程式。如要繼續操作,請先設定 OAuth 同意畫面和 GWM SDK 的「應用程式設定」「商店資訊」。

使用者首次授權應用程式時,會顯示 OAuth 同意畫面。系統會根據您啟用的範圍,提示使用者允許應用程式存取個人和帳戶資訊。

前往 OAuth 同意畫面建立頁面。提供下列資訊:

  • 將「使用者類型」設為「外部」。點選「建立」
  • 在下一頁中,填寫必要的應用程式詳細資料和聯絡資訊。 在「授權網域」底下,提供任何代管您應用程式的網域。按一下「儲存並繼續」
  • 新增網頁應用程式所需的任何 OAuth 範圍。如要深入瞭解範圍和用途,請參閱 OAuth 設定指南

    您必須至少要求下列其中一個範圍,Google 才能傳送 login_hint 查詢參數。如要進一步瞭解這個行為,請參閱 OAuth 設定指南

    • https://www.googleapis.com/auth/userinfo.email (已納入)
    • https://www.googleapis.com/auth/userinfo.profile (已納入)

    Classroom 外掛程式專用的範圍如下:

    • https://www.googleapis.com/auth/classroom.addons.teacher
    • https://www.googleapis.com/auth/classroom.addons.student

    以及使用者應用程式需要的任何其他 Google API 範圍

    按一下 [儲存並繼續]。

  • 在「測試使用者」頁面上列出所有測試帳戶的電子郵件地址。 按一下「儲存並繼續」

確認您的設定正確無誤,然後返回資訊主頁。

應用程式設定

前往 GWM SDK 的「App Configuration」頁面。提供下列資訊:

  • 將「App Visibility」設為 Private。此設定適用於測試與開發用途,也是這類逐步操作說明的合適選項。除非您準備好開放一般大眾使用外掛程式,否則請勿選擇 Public

  • 如要限制只有網域管理員才能安裝,請將「Installation Settings」設為 Admin Only install

  • 在「應用程式整合」下方,選取「Classroom 外掛程式」。系統會提示您使用安全的連結設定 URI,也就是當使用者開啟您的外掛程式時,您希望載入的網址。為進行本逐步操作說明,這個欄位應為 https://<your domain>/addon-discovery

  • 允許的附件 URI 前置字串會使用 courses.*.addOnAttachments.createcourses.*.addOnAttachments.patch 方法,驗證 AddOnAttachment 中設定的 URI。驗證是文字字串前置字串比對,目前不允許使用萬用字元。目前這些資料可以暫時留空。

  • 新增與上個步驟 OAuth 同意畫面中提供的相同 OAuth 範圍

  • 在「Developer Links」(開發人員連結) 下方,視需要填寫貴機構適用的欄位。

商店資訊

前往 GWM SDK 的「商店資訊」頁面。 提供下列資訊:

  • 在「App Details」下方,新增語言或在已列出的語言旁邊展開下拉式選單。提供應用程式名稱和說明;這些資訊會顯示在外掛程式的 GWM 商店資訊頁面中。點按「完成」儲存設定。
  • 選擇外掛程式的「類別」
  • 在「Graphics Assets」下方,為必填欄位提供圖片。您日後可以變更這些設定,而且在上一個步驟中將應用程式瀏覽權限設為私人時,也能做為預留位置。
  • 在「支援連結」底下提供要求的網址。如果您在上一個步驟中將應用程式瀏覽權限設為私人,就可能是預留位置。

按一下「發布」儲存設定。如果您在上一個步驟中將應用程式瀏覽權限設為「私人」,應用程式便可立即安裝。如果將應用程式瀏覽權限設為「公開」,您的應用程式會先送交 GWM 團隊審查,再開放安裝。

安裝外掛程式

您現在可以使用 GWM SDK「商店資訊」頁面頂端的連結安裝外掛程式。按一下頁面頂端的「App URL」(應用程式網址) 查看清單,然後選擇「Install」

建立基本的網頁應用程式

設定具有兩條路徑的基本架構網頁應用程式。此應用程式的逐步操作說明將擴展,因此現在只需要為 /addon-discovery 外掛程式建立到達網頁,並為「公司網站」建立模擬索引頁面 /

iframe 中的網頁應用程式範例

實作這兩個端點:

  • /:顯示歡迎訊息,以及用於關閉目前分頁和外掛程式 iframe 的按鈕。
  • /addon-discovery:顯示歡迎訊息和兩個按鈕:一個用於關閉外掛程式 iframe,另一個則是在新分頁中開啟網站。

請注意,我們將新增用於建立和關閉視窗或 iframe 的按鈕。這些示範方法可在後續逐步操作說明中,安全地將使用者彈出新分頁進行授權。

建立公用程式指令碼

建立 static/scripts 目錄。建立新檔案 addon-utils.js。新增以下兩個函式。

/**
 *   Opens a given destination route in a new window. This function uses
 *   window.open() so as to force window.opener to retain a reference to the
 *   iframe from which it was called.
 *   @param {string} destinationURL The endpoint to open, or "/" if none is
 *   provided.
 */
function openWebsiteInNewTab(destinationURL = '/') {
  window.open(destinationURL, '_blank');
}

/**
 *   Close the iframe by calling postMessage() in the host Classroom page. This
 *   function can be called directly when in a Classroom add-on iframe.
 *
 *   Alternatively, it can be used to close an add-on iframe in another window.
 *   For example, if an add-on iframe in Window 1 opens a link in a new Window 2
 *   using the openWebsiteInNewTab function above, you can call
 *   window.opener.closeAddonIframe() from Window 2 to close the iframe in Window
 *   1.
 */
function closeAddonIframe() {
  window.parent.postMessage({
    type: 'Classroom',
    action: 'closeIframe',
  }, '*');
};

建立路徑

實作 /addon-discovery/ 端點。

Python

設定應用程式目錄

為達這個範例的目的,請將應用程式邏輯建構為 Python 模組。這是我們提供的範例中的 webapp 目錄。

建立伺服器模組的目錄,例如 webapp。將 static 目錄移至模組目錄。請一併在模組目錄中建立 template 目錄,HTML 檔案則位於此處。

建構伺服器模組*

在模組目錄中建立 __init__.py 檔案,並新增以下匯入和宣告內容。

from flask import Flask
import config

app = Flask(__name__)
app.config.from_object(config.Config)

# Load other module script files. This import statement refers to the
# 'routes.py' file described below.
from webapp import routes

接著建立檔案來處理網頁應用程式的路徑。這是我們提供的範例中的 webapp/routes.py。在這個檔案中導入兩個路徑。

from webapp import app
import flask

@app.route("/")
def index():
    return flask.render_template("index.html",
                                message="You've reached the index page.")

@app.route("/classroom-addon")
def classroom_addon():
    return flask.render_template(
        "addon-discovery.html",
        message="You've reached the addon discovery page.")

請注意,我們的路徑都會將 message 變數傳遞至各自的 Jinja 範本。這項資訊有助於找出使用者到達的網頁。

建立設定和啟動檔案

在應用程式的根目錄中建立 main.pyconfig.py 檔案。請在 config.py 中設定密鑰。

import os

class Config(object):
    # Note: A secret key is included in the sample so that it works.
    # If you use this code in your application, replace this with a truly secret
    # key. See https://flask.palletsprojects.com/quickstart/#sessions.
    SECRET_KEY = os.environ.get(
        'SECRET_KEY') or "REPLACE ME - this value is here as a placeholder."

main.py 檔案中,匯入模組並啟動 Flask 伺服器。

from webapp import app

if __name__ == "__main__":
    # Run the application over HTTPs with a locally stored certificate and key.
    # Defaults to https://localhost:5000.
    app.run(
        host="localhost",
        ssl_context=("localhost.pem", "localhost-key.pem"),
        debug=True)

Node.js

路徑已在 app.js 檔案中登錄,如下所示。

const websiteRouter = require('./routes/index');
const addonRouter = require('./routes/classroom-addon');

app.use('/', websiteRouter);
app.use('/addon-discovery', addonRouter);

開啟 /01-basic-app/routes/index.js 並查看程式碼。當使用者造訪公司網站時,就會到達這個路徑。路徑會使用 index 控制列範本轉譯回應,並將含有 titlemessage 變數的資料物件傳遞給範本。

router.get('/', function (req, res, next) {
  res.render('index', {
    title: 'Education Technology',
    message: 'Welcome to our website!'
  });
});

開啟第二條路線 /01-basic-app/routes/classroom-addon.js 並查看程式碼。當使用者造訪外掛程式時,就會到達這個路徑。請注意,這個路徑會使用 discovery 控制列範本和 addon.hbs 版面配置,以與公司網站不同的方式轉譯頁面。

router.get('/', function (req, res, next) {
  res.render('discovery', {
    layout: 'addon.hbs',
    title: 'Education Technology Classroom add-on',
    message: `Welcome.`
  });
});

Java

Java 程式碼範例使用模組來封裝逐步逐步操作說明步驟。由於這是第一個逐步操作說明,程式碼位於 step_01_basic_app 模組下。您不應該使用模組實作專案。在逐步操作說明中的每個步驟中,建議您以單一專案為基礎建構程式碼。

在本範例專案中,建立控制器類別 Controller.java 以定義端點。在這個檔案中,從 spring-boot-starter-web 依附元件匯入 @GetMapping 註解。

import org.springframework.web.bind.annotation.GetMapping;

在類別定義上方加入 Spring 架構控制器註解,以表示類別的用途。

@org.springframework.stereotype.Controller
public class Controller {

然後導入兩個路徑和另一個路徑來處理錯誤。

/** Returns the index page that will be displayed when the add-on opens in a
*   new tab.
*   @param model the Model interface to pass error information that's
*   displayed on the error page.
*   @return the index page template if successful, or the onError method to
*   handle and display the error message.
*/
@GetMapping(value = {"/"})
public String index(Model model) {
  try {
    return "index";
  } catch (Exception e) {
    return onError(e.getMessage(), model);
  }
}

/** Returns the add-on discovery page that will be displayed when the iframe
*   is first opened in Classroom.
*   @param model the Model interface to pass error information that's
*   displayed on the error page.
*   @return the addon-discovery page.
*/
@GetMapping(value = {"/addon-discovery"})
public String addon_discovery(Model model) {
  try {
    return "addon-discovery";
  } catch (Exception e) {
    return onError(e.getMessage(), model);
  }
}

/** Handles application errors.
*   @param errorMessage message to be displayed on the error page.
*   @param model the Model interface to pass error information to display on
*   the error page.
*   @return the error page.
*/
@GetMapping(value = {"/error"})
public String onError(String errorMessage, Model model) {
  model.addAttribute("error", errorMessage);
  return "error";
}

測試外掛程式

啟動伺服器。接著,以老師測試的其中一位人員登入 Google Classroom。前往「課堂作業」分頁,建立新的「作業」。按一下文字區域下方的「Add-ons」按鈕,然後選取外掛程式。該 iframe 會開啟,外掛程式會載入您在 GWM SDK「App Configuration」頁面中指定的連結設定 URI

恭喜!您可以開始進行下一個步驟:透過 Google 單一登入 (SSO) 登入使用者