本指南說明如何使用 Google Chat API,代表使用者建立含有互動式資訊卡的訊息、將資訊卡附加至現有訊息,以及非同步更新這些資訊卡。
建立及更新資訊卡有助於:
- 代表使用者發布代表工作或外部資源的資訊卡。
- 將資訊卡附加至現有的使用者訊息,提供互動式背景資訊或工作流程。
- 根據外部事件更新資訊卡狀態 (例如從「處理中」改為「已完成」),不必等待使用者互動。
- 重新整理使用者訊息中的資訊卡內容,例如連結預覽。
必要條件
Node.js
- 公司或企業專用 Google Workspace 帳戶,且可存取 Google Chat。
- 設定環境:
- 建立 Google Cloud 專案。
- 設定 OAuth 同意畫面。
- 啟用及設定 Google Chat API,並為 Chat 應用程式命名、設定圖示和說明。
- 安裝 Node.js Google API 用戶端程式庫。
- 根據您要在 Google Chat API 要求中驗證的方式,建立存取憑證:
- 如要以 Chat 使用者身分進行驗證,請建立 OAuth 用戶端 ID 憑證,並將憑證儲存至本機目錄中名為
credentials.json的 JSON 檔案。 - 如要以 Chat 應用程式的身分進行驗證,請建立服務帳戶憑證,並將憑證儲存為名為
credentials.json的 JSON 檔案。
- 如要以 Chat 使用者身分進行驗證,請建立 OAuth 用戶端 ID 憑證,並將憑證儲存至本機目錄中名為
- 根據您要以使用者或 Chat 應用程式的身分驗證,選擇授權範圍。
Python
- 公司或企業專用 Google Workspace 帳戶,且可存取 Google Chat。
- 設定環境:
- 建立 Google Cloud 專案。
- 設定 OAuth 同意畫面。
- 啟用及設定 Google Chat API,並為 Chat 應用程式命名、設定圖示和說明。
- 安裝 Python Google API 用戶端程式庫。
- 根據您要在 Google Chat API 要求中驗證的方式,建立存取憑證:
- 如要以 Chat 使用者身分進行驗證,請建立 OAuth 用戶端 ID 憑證,並將憑證儲存至本機目錄中名為
credentials.json的 JSON 檔案。 - 如要以 Chat 應用程式的身分進行驗證,請建立服務帳戶憑證,並將憑證儲存為名為
credentials.json的 JSON 檔案。
- 如要以 Chat 使用者身分進行驗證,請建立 OAuth 用戶端 ID 憑證,並將憑證儲存至本機目錄中名為
- 根據您要以使用者或 Chat 應用程式的身分驗證,選擇授權範圍。
Java
- 公司或企業專用 Google Workspace 帳戶,且可存取 Google Chat。
- 設定環境:
- 建立 Google Cloud 專案。
- 設定 OAuth 同意畫面。
- 啟用及設定 Google Chat API,並為 Chat 應用程式命名、設定圖示和說明。
- 安裝 Java Google API 用戶端程式庫。
- 根據您要在 Google Chat API 要求中驗證的方式,建立存取憑證:
- 如要以 Chat 使用者身分進行驗證,請建立 OAuth 用戶端 ID 憑證,並將憑證儲存至本機目錄中名為
credentials.json的 JSON 檔案。 - 如要以 Chat 應用程式的身分進行驗證,請建立服務帳戶憑證,並將憑證儲存為名為
credentials.json的 JSON 檔案。
- 如要以 Chat 使用者身分進行驗證,請建立 OAuth 用戶端 ID 憑證,並將憑證儲存至本機目錄中名為
- 根據您要以使用者或 Chat 應用程式的身分驗證,選擇授權範圍。
Apps Script
- 公司或企業專用 Google Workspace 帳戶,且可存取 Google Chat。
- 設定環境:
- 建立 Google Cloud 專案。
- 設定 OAuth 同意畫面。
- 啟用及設定 Google Chat API,並為 Chat 應用程式命名、設定圖示和說明。
- 建立獨立的 Apps Script 專案,並開啟進階 Chat 服務。
- 在本指南中,您必須使用使用者或應用程式驗證。如要以 Chat 應用程式的身分進行驗證,請建立服務帳戶憑證。如需步驟,請參閱「以 Google Chat 擴充應用程式身分驗證及授權」。
- 根據您要以使用者或 Chat 應用程式的身分驗證,選擇授權範圍。
代表使用者建立卡片訊息
如要代表使用者建立含有資訊卡的訊息,請使用使用者驗證。
如要建立訊息,請在要求中指定下列項目:
chat.messages.create或chat.messages授權範圍。Message資源中的cardsV2欄位,內含卡片資料。- 每張卡的
cardId,這是非同步更新的必要條件。
以下範例說明如何代表使用者建立含有資訊卡的訊息:
Node.js
/**
* This sample shows how to create a message with a card on behalf of a user.
*/
const {google} = require('googleapis');
const {auth} = require('google-auth-library');
async function main() {
// Create a client
const authClient = await auth.getClient({
scopes: ['https://www.googleapis.com/auth/chat.messages.create']
});
google.options({auth: authClient});
// Initialize the Chat API
const chat = google.chat({version: 'v1'});
// The space to create the message in.
const parent = 'spaces/SPACE_NAME';
// Create the request
const request = {
parent: parent,
requestBody: {
text: 'Here is a card created on my behalf:',
cardsV2: [{
cardId: 'unique-card-id',
card: {
header: {
title: 'Card Title',
subtitle: 'Card Subtitle'
},
sections: [{
widgets: [{
textParagraph: {
text: 'This card is attached to a user message.'
}
}]
}]
}
}]
}
};
// Call the API
const response = await chat.spaces.messages.create(request);
// Handle the response
console.log(response.data);
}
main().catch(console.error);
Python
"""
This sample shows how to create a message with a card on behalf of a user.
"""
from google.oauth2 import service_account
from googleapiclient.discovery import build
import google.auth
def create_message_with_card():
# Create a client
scopes = ["https://www.googleapis.com/auth/chat.messages.create"]
credentials, _ = google.auth.default(scopes=scopes)
# Build the service endpoint for Chat API.
service = build('chat', 'v1', credentials=credentials)
# The space to create the message in.
parent = "spaces/SPACE_NAME"
# Create the request
result = service.spaces().messages().create(
parent=parent,
body={
'text': 'Here is a card created on my behalf:',
'cardsV2': [{
'cardId': 'unique-card-id',
'card': {
'header': {
'title': 'Card Title',
'subtitle': 'Card Subtitle'
},
'sections': [{
'widgets': [{
'textParagraph': {
'text': 'This card is attached to a user message.'
}
}]
}]
}
}]
}
).execute()
print(result)
if __name__ == "__main__":
create_message_with_card()
Java
/**
* This sample shows how to create a message with a card on behalf of a user.
*/
import com.google.api.client.googleapis.javanet.GoogleNetHttpTransport;
import com.google.api.client.http.GenericUrl;
import com.google.api.client.http.HttpRequest;
import com.google.api.client.http.HttpRequestFactory;
import com.google.api.client.http.HttpTransport;
import com.google.api.client.http.json.JsonHttpContent;
import com.google.api.client.json.gson.GsonFactory;
import com.google.auth.http.HttpCredentialsAdapter;
import com.google.auth.oauth2.GoogleCredentials;
import java.util.Arrays;
import java.util.Collections;
import java.util.HashMap;
import java.util.Map;
public class CreateMessageWithCard {
public static void main(String[] args) throws Exception {
HttpTransport transport = GoogleNetHttpTransport.newTrustedTransport();
GsonFactory jsonFactory = GsonFactory.getDefaultInstance();
GoogleCredentials credentials = GoogleCredentials.getApplicationDefault()
.createScoped(Arrays.asList("https://www.googleapis.com/auth/chat.messages.create"));
HttpRequestFactory requestFactory = transport.createRequestFactory(new HttpCredentialsAdapter(credentials));
String parent = "spaces/SPACE_NAME";
GenericUrl url = new GenericUrl("https://chat.googleapis.com/v1/" + parent + "/messages");
// Construct the message body
Map<String, Object> message = new HashMap<>();
message.put("text", "Here is a card created on my behalf:");
Map<String, Object> header = new HashMap<>();
header.put("title", "Card Title");
header.put("subtitle", "Card Subtitle");
Map<String, Object> textParagraph = new HashMap<>();
textParagraph.put("text", "This card is attached to a user message.");
Map<String, Object> widget = new HashMap<>();
widget.put("textParagraph", textParagraph);
Map<String, Object> section = new HashMap<>();
section.put("widgets", Collections.singletonList(widget));
Map<String, Object> card = new HashMap<>();
card.put("header", header);
card.put("sections", Collections.singletonList(section));
Map<String, Object> cardWithId = new HashMap<>();
cardWithId.put("cardId", "unique-card-id");
cardWithId.put("card", card);
message.put("cardsV2", Collections.singletonList(cardWithId));
HttpRequest request = requestFactory.buildPostRequest(url, new JsonHttpContent(jsonFactory, message));
System.out.println(request.execute().parseAsString());
}
}
Apps Script
/**
* This sample shows how to create a message with a card on behalf of a user.
*/
function createMessageWithCard() {
const parent = 'spaces/SPACE_NAME';
const url = `https://chat.googleapis.com/v1/${parent}/messages`;
const message = {
text: 'Here is a card created on my behalf:',
cardsV2: [{
cardId: 'unique-card-id',
card: {
header: {
title: 'Card Title',
subtitle: 'Card Subtitle'
},
sections: [{
widgets: [{
textParagraph: {
text: 'This card is attached to a user message.'
}
}]
}]
}
}]
};
const options = {
method: 'post',
headers: {
Authorization: 'Bearer ' + ScriptApp.getOAuthToken()
},
contentType: 'application/json',
payload: JSON.stringify(message),
muteHttpExceptions: true
};
try {
const response = UrlFetchApp.fetch(url, options);
console.log(response.getContentText());
} catch (err) {
console.log('Failed to create message: ' + err.message);
}
}
代表使用者在現有訊息中附加資訊卡
如要代表使用者將資訊卡附加至現有訊息,請使用使用者驗證呼叫 patch 方法。
如要將資訊卡附加至訊息,請在要求中指定下列項目:
chat.messages授權範圍。- 要更新的訊息
name,格式為spaces/{space}/messages/{message}。 updateMask已設為cards_v2。使用使用者驗證更新訊息時,更新遮罩中只能有cards_v2欄位。您無法在同一個要求中更新訊息text和cards_v2。Message資源中的cardsV2欄位,內含卡片資料。- 每張卡的
cardId,後續非同步更新時需要用到。
以下範例說明如何代表使用者,將資訊卡附加至現有訊息:
Node.js
/**
* This sample shows how to attach a card to an existing message on behalf of a user.
*/
const {google} = require('googleapis');
const {auth} = require('google-auth-library');
async function main() {
// Create a client with user credentials
const authClient = await auth.getClient({
scopes: ['https://www.googleapis.com/auth/chat.messages']
});
google.options({auth: authClient});
// Initialize the Chat API
const chat = google.chat({version: 'v1'});
// The message to update.
const messageName = 'spaces/SPACE_NAME/messages/MESSAGE_ID';
// Create the request
const request = {
name: messageName,
updateMask: 'cards_v2',
requestBody: {
cardsV2: [{
cardId: 'unique-card-id',
card: {
header: {
title: 'Card Title',
subtitle: 'Card Subtitle'
},
sections: [{
widgets: [{
textParagraph: {
text: 'This card was attached to an existing user message.'
}
}]
}]
}
}]
}
};
// Call the API
const response = await chat.spaces.messages.patch(request);
// Handle the response
console.log(response.data);
}
main().catch(console.error);
Python
"""
This sample shows how to attach a card to an existing message on behalf of a user.
"""
from googleapiclient.discovery import build
import google.auth
def attach_card_to_message():
# Create a client with user credentials
scopes = ["https://www.googleapis.com/auth/chat.messages"]
credentials, _ = google.auth.default(scopes=scopes)
# Build the service endpoint for Chat API.
service = build('chat', 'v1', credentials=credentials)
# The message to update.
message_name = "spaces/SPACE_NAME/messages/MESSAGE_ID"
# Create the request
result = service.spaces().messages().patch(
name=message_name,
updateMask="cards_v2",
body={
'cardsV2': [{
'cardId': 'unique-card-id',
'card': {
'header': {
'title': 'Card Title',
'subtitle': 'Card Subtitle'
},
'sections': [{
'widgets': [{
'textParagraph': {
'text': 'This card was attached to an existing user message.'
}
}]
}]
}
}]
}
).execute()
print(result)
if __name__ == "__main__":
attach_card_to_message()
Java
/**
* This sample shows how to attach a card to an existing message on behalf of a user.
*/
import com.google.api.client.googleapis.javanet.GoogleNetHttpTransport;
import com.google.api.client.http.GenericUrl;
import com.google.api.client.http.HttpRequest;
import com.google.api.client.http.HttpRequestFactory;
import com.google.api.client.http.HttpTransport;
import com.google.api.client.http.json.JsonHttpContent;
import com.google.api.client.json.gson.GsonFactory;
import com.google.auth.http.HttpCredentialsAdapter;
import com.google.auth.oauth2.GoogleCredentials;
import java.util.Arrays;
import java.util.Collections;
import java.util.HashMap;
import java.util.Map;
public class AttachCardToMessage {
public static void main(String[] args) throws Exception {
HttpTransport transport = GoogleNetHttpTransport.newTrustedTransport();
GsonFactory jsonFactory = GsonFactory.getDefaultInstance();
GoogleCredentials credentials = GoogleCredentials.getApplicationDefault()
.createScoped(Arrays.asList("https://www.googleapis.com/auth/chat.messages"));
HttpRequestFactory requestFactory = transport.createRequestFactory(new HttpCredentialsAdapter(credentials));
String messageName = "spaces/SPACE_NAME/messages/MESSAGE_ID";
GenericUrl url = new GenericUrl("https://chat.googleapis.com/v1/" + messageName + "?updateMask=cards_v2");
// Construct the card body
Map<String, Object> header = new HashMap<>();
header.put("title", "Card Title");
header.put("subtitle", "Card Subtitle");
Map<String, Object> textParagraph = new HashMap<>();
textParagraph.put("text", "This card was attached to an existing user message.");
Map<String, Object> widget = new HashMap<>();
widget.put("textParagraph", textParagraph);
Map<String, Object> section = new HashMap<>();
section.put("widgets", Collections.singletonList(widget));
Map<String, Object> card = new HashMap<>();
card.put("header", header);
card.put("sections", Collections.singletonList(section));
Map<String, Object> cardWithId = new HashMap<>();
cardWithId.put("cardId", "unique-card-id");
cardWithId.put("card", card);
Map<String, Object> message = new HashMap<>();
message.put("cardsV2", Collections.singletonList(cardWithId));
HttpRequest request = requestFactory.buildPatchRequest(url, new JsonHttpContent(jsonFactory, message));
System.out.println(request.execute().parseAsString());
}
}
Apps Script
/**
* This sample shows how to attach a card to an existing message on behalf of a user.
*/
function attachCardToMessage() {
const messageName = 'spaces/SPACE_NAME/messages/MESSAGE_ID';
const url = `https://chat.googleapis.com/v1/${messageName}?updateMask=cards_v2`;
const message = {
cardsV2: [{
cardId: 'unique-card-id',
card: {
header: {
title: 'Card Title',
subtitle: 'Card Subtitle'
},
sections: [{
widgets: [{
textParagraph: {
text: 'This card was attached to an existing user message.'
}
}]
}]
}
}]
};
const options = {
method: 'patch',
headers: {
Authorization: 'Bearer ' + ScriptApp.getOAuthToken()
},
contentType: 'application/json',
payload: JSON.stringify(message),
muteHttpExceptions: true
};
try {
const response = UrlFetchApp.fetch(url, options);
console.log(response.getContentText());
} catch (err) {
console.log('Failed to attach card: ' + err.message);
}
}
非同步更新資訊卡
使用資訊卡建立訊息或將資訊卡附加至現有訊息後,您可以使用應用程式驗證非同步更新資訊卡。這樣一來,應用程式就能自動重新整理資訊卡內容,不必等待使用者操作。只有將資訊卡新增至使用者訊息的 Chat 應用程式可以取代該資訊卡。如果使用者編輯訊息文字,系統會移除應用程式擁有的資訊卡,您的應用程式也無法再更新這些資訊卡。
如果資訊卡是以非同步方式更新,Google Chat 會在資訊卡的屬性旁顯示「已編輯」指標,讓使用者瞭解資訊卡內容是獨立於訊息更新。
如要更新卡片,請使用下列項目呼叫 replaceCards 方法:
chat.bot授權範圍。- 要更新的訊息
name。 - 新的
cardsV2清單。這會取代訊息中的所有現有資訊卡。 如果提供空白清單,系統會移除卡片。如果移除所有卡片,就無法使用replaceCards重新新增卡片,而是必須使用UpdateMessage搭配使用者驗證來附加新卡片。
以下範例說明如何更新訊息的資訊卡:
Node.js
/**
* This sample shows how to update cards on a message.
*/
const {google} = require('googleapis');
const {auth} = require('google-auth-library');
async function main() {
// Create a client with app credentials
const authClient = await auth.getClient({
scopes: ['https://www.googleapis.com/auth/chat.bot']
});
google.options({auth: authClient});
// Initialize the Chat API
const chat = google.chat({version: 'v1'});
// The message to update.
const messageName = 'spaces/SPACE_NAME/messages/MESSAGE_ID';
// Create the request
const request = {
name: messageName,
requestBody: {
cardsV2: [{
cardId: 'unique-card-id',
card: {
header: {
title: 'Updated Card Title',
subtitle: 'Updated Card Subtitle'
},
sections: [{
widgets: [{
textParagraph: {
text: 'The card content has been updated asynchronously.'
}
}]
}]
}
}]
}
};
// Call the API
await chat.spaces.messages.replaceCards(request);
console.log('Cards updated.');
}
main().catch(console.error);
Python
"""
This sample shows how to update cards on a message.
"""
from google.oauth2 import service_account
from googleapiclient.discovery import build
import google.auth
def replace_message_cards():
# Create a client with app credentials
scopes = ["https://www.googleapis.com/auth/chat.bot"]
credentials, _ = google.auth.default(scopes=scopes)
# Build the service endpoint for Chat API.
service = build('chat', 'v1', credentials=credentials)
# The message to update.
message_name = "spaces/SPACE_NAME/messages/MESSAGE_ID"
# Create the request
result = service.spaces().messages().replaceCards(
name=message_name,
body={
'cardsV2': [{
'cardId': 'unique-card-id',
'card': {
'header': {
'title': 'Updated Card Title',
'subtitle': 'Updated Card Subtitle'
},
'sections': [{
'widgets': [{
'textParagraph': {
'text': 'The card content has been updated asynchronously.'
}
}]
}]
}
}]
}
).execute()
print("Cards updated.")
if __name__ == "__main__":
replace_message_cards()
Java
/**
* This sample shows how to update cards on a message.
*/
import com.google.api.client.googleapis.javanet.GoogleNetHttpTransport;
import com.google.api.client.http.GenericUrl;
import com.google.api.client.http.HttpRequest;
import com.google.api.client.http.HttpRequestFactory;
import com.google.api.client.http.HttpTransport;
import com.google.api.client.http.json.JsonHttpContent;
import com.google.api.client.json.gson.GsonFactory;
import com.google.auth.http.HttpCredentialsAdapter;
import com.google.auth.oauth2.GoogleCredentials;
import java.util.Arrays;
import java.util.Collections;
import java.util.HashMap;
import java.util.Map;
public class ReplaceMessageCards {
public static void main(String[] args) throws Exception {
HttpTransport transport = GoogleNetHttpTransport.newTrustedTransport();
GsonFactory jsonFactory = GsonFactory.getDefaultInstance();
GoogleCredentials credentials = GoogleCredentials.getApplicationDefault()
.createScoped(Arrays.asList("https://www.googleapis.com/auth/chat.bot"));
HttpRequestFactory requestFactory = transport.createRequestFactory(new HttpCredentialsAdapter(credentials));
String messageName = "spaces/SPACE_NAME/messages/MESSAGE_ID";
GenericUrl url = new GenericUrl("https://chat.googleapis.com/v1/" + messageName + ":replaceCards");
// Construct the body
Map<String, Object> header = new HashMap<>();
header.put("title", "Updated Card Title");
header.put("subtitle", "Updated Card Subtitle");
Map<String, Object> textParagraph = new HashMap<>();
textParagraph.put("text", "The card content has been updated asynchronously.");
Map<String, Object> widget = new HashMap<>();
widget.put("textParagraph", textParagraph);
Map<String, Object> section = new HashMap<>();
section.put("widgets", Collections.singletonList(widget));
Map<String, Object> card = new HashMap<>();
card.put("header", header);
card.put("sections", Collections.singletonList(section));
Map<String, Object> cardWithId = new HashMap<>();
cardWithId.put("cardId", "unique-card-id");
cardWithId.put("card", card);
Map<String, Object> body = new HashMap<>();
body.put("cardsV2", Collections.singletonList(cardWithId));
HttpRequest request = requestFactory.buildPostRequest(url, new JsonHttpContent(jsonFactory, body));
request.execute();
System.out.println("Cards updated.");
}
}
Apps Script
/**
* This sample shows how to update cards on a message.
*/
function replaceMessageCards() {
const messageName = 'spaces/SPACE_NAME/messages/MESSAGE_ID';
const url = `https://chat.googleapis.com/v1/${messageName}:replaceCards`;
const request = {
cardsV2: [{
cardId: 'unique-card-id',
card: {
header: {
title: 'Updated Card Title',
subtitle: 'Updated Card Subtitle'
},
sections: [{
widgets: [{
textParagraph: {
text: 'The card content has been updated asynchronously.'
}
}]
}]
}
}]
};
const options = {
method: 'post',
headers: {
Authorization: 'Bearer ' + ScriptApp.getOAuthToken()
},
contentType: 'application/json',
payload: JSON.stringify(request),
muteHttpExceptions: true
};
try {
const response = UrlFetchApp.fetch(url, options);
console.log('Cards updated.');
} catch (err) {
console.log('Failed to update cards: ' + err.message);
}
}
限制
代表使用者建立或更新含有資訊卡的訊息時,Chat 應用程式必須是聊天室成員。這項規定適用於下列情況:
這項規定與其他使用使用者驗證的 API 不同,後者通常不要求應用程式成為聊天室成員。
使用使用者驗證更新訊息時,如果
cards_v2指定於updateMask中,則無法在同一要求中更新其他欄位 (例如text)。replaceCards方法支援更換和移除資訊卡,您可以在更換資訊卡時新增其他資訊卡,但無法將資訊卡新增至沒有資訊卡的訊息。如要將資訊卡附加至沒有資訊卡的訊息,請使用UpdateMessage進行使用者驗證。資訊卡歸因和擁有權:
- 附加至使用者訊息的資訊卡會歸給附加資訊卡的 Chat 應用程式,並由該應用程式擁有,如唯有輸出內容的
CardWithId.owner欄位所示。 - Chat 應用程式只能取代自己附加到訊息的資訊卡,無法取代其他 Chat 應用程式附加的資訊卡。
- 附加至使用者訊息的資訊卡會歸給附加資訊卡的 Chat 應用程式,並由該應用程式擁有,如唯有輸出內容的
如果使用者編輯訊息文字,系統會移除 Chat 應用程式擁有的資訊卡,您也無法再更新這些資訊卡。