Tạo và cập nhật thẻ tương tác

Hướng dẫn này giải thích cách sử dụng Google Chat API để tạo tin nhắn có chứa thẻ tương tác thay cho người dùng, đính kèm thẻ vào tin nhắn hiện có và cập nhật các thẻ đó một cách không đồng bộ.

Việc tạo và cập nhật thẻ sẽ hữu ích khi bạn muốn làm những việc sau:

  • Đăng thẻ đại diện cho một việc cần làm hoặc tài nguyên bên ngoài thay cho người dùng.
  • Đính kèm thẻ vào một tin nhắn hiện có của người dùng để cung cấp ngữ cảnh hoặc quy trình tương tác.
  • Cập nhật trạng thái của thẻ (ví dụ: "Đang tiến hành" thành "Đã hoàn tất") dựa trên các sự kiện bên ngoài mà không cần chờ lượt tương tác của người dùng.
  • Làm mới nội dung của thẻ trong tin nhắn của người dùng, chẳng hạn như bản xem trước đường liên kết.

Điều kiện tiên quyết

Node.js

Python

Java

Apps Script

Tạo tin nhắn dạng thẻ thay cho người dùng

Để tạo một thông báo có thẻ thay cho người dùng, hãy sử dụng xác thực người dùng.

Để tạo thông báo, hãy chỉ định những thông tin sau trong yêu cầu của bạn:

  • Phạm vi uỷ quyền chat.messages.create hoặc chat.messages.
  • Trường cardsV2 trong tài nguyên Message, chứa dữ liệu thẻ.
  • cardId cho mỗi thẻ, bắt buộc phải có để cập nhật không đồng bộ.

Ví dụ sau đây cho thấy cách tạo một thông báo có thẻ thay cho người dùng:

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);
  }
}

Đính kèm thẻ vào một tin nhắn hiện có thay mặt cho người dùng

Để đính kèm thẻ vào một thông báo hiện có thay cho người dùng, hãy gọi phương thức patch bằng cách sử dụng xác thực người dùng.

Để đính kèm thẻ vào một thông báo, hãy chỉ định những thông tin sau trong yêu cầu của bạn:

  • Phạm vi uỷ quyền chat.messages.
  • name của thông báo cần cập nhật, ở định dạng spaces/{space}/messages/{message}.
  • Đã đặt updateMask thành cards_v2. Khi cập nhật một thông báo bằng tính năng xác thực người dùng, cards_v2 phải là trường duy nhất trong mặt nạ cập nhật. Bạn không thể cập nhật thông báo textcards_v2 trong cùng một yêu cầu.
  • Trường cardsV2 trong tài nguyên Message, chứa dữ liệu thẻ.
  • cardId cho mỗi thẻ, bắt buộc phải có để cập nhật không đồng bộ sau này.

Ví dụ sau đây cho thấy cách đính kèm thẻ vào một thông báo hiện có thay cho người dùng:

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);
  }
}

Cập nhật thẻ không đồng bộ

Sau khi tạo một thông báo có thẻ hoặc đính kèm thẻ vào một thông báo hiện có, bạn có thể cập nhật thẻ một cách không đồng bộ bằng cách sử dụng xác thực ứng dụng. Điều này cho phép ứng dụng của bạn làm mới nội dung thẻ mà không cần lượt tương tác của người dùng. Chỉ ứng dụng Chat đã thêm thẻ vào tin nhắn của người dùng mới có thể thay thế thẻ đó. Nếu người dùng chỉnh sửa nội dung tin nhắn, thì các thẻ thuộc sở hữu của ứng dụng sẽ bị xoá và ứng dụng của bạn sẽ không thể cập nhật các thẻ đó nữa.

Khi thẻ được cập nhật không đồng bộ, Google Chat sẽ hiển thị chỉ báo Đã chỉnh sửa bên cạnh thông tin ghi nhận của thẻ để thông báo cho người dùng rằng nội dung thẻ đã được làm mới độc lập với tin nhắn.

Để cập nhật thẻ, hãy gọi phương thức replaceCards bằng nội dung sau:

  • Phạm vi uỷ quyền chat.bot.
  • name của thông báo cần cập nhật.
  • Danh sách cardsV2 mới. Thao tác này sẽ thay thế tất cả thẻ hiện có trong thông báo. Nếu bạn cung cấp một danh sách trống, các thẻ sẽ bị xoá. Nếu xoá tất cả thẻ, bạn không thể dùng replaceCards để thêm lại thẻ. Thay vào đó, hãy dùng UpdateMessage có xác thực người dùng để đính kèm thẻ mới.

Ví dụ sau đây cho thấy cách cập nhật thẻ của một thông báo:

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);
  }
}

Các điểm hạn chế

  • Khi tạo tin nhắn có thẻ thay cho người dùng hoặc cập nhật thẻ, ứng dụng Chat phải là thành viên của không gian. Yêu cầu này áp dụng khi:

    Yêu cầu này khác với các API khác sử dụng tính năng xác thực người dùng, thường không yêu cầu ứng dụng phải là thành viên của không gian.

  • Khi cập nhật một thông báo bằng thông tin xác thực người dùng, nếu cards_v2 được chỉ định trong updateMask, thì không thể cập nhật các trường khác (chẳng hạn như text) trong cùng một yêu cầu.

  • Phương thức replaceCards hỗ trợ thay thế và xoá thẻ, đồng thời bạn có thể thêm thẻ khác trong khi thay thế thẻ, nhưng bạn không thể thêm thẻ vào một thông báo chưa có thẻ. Để đính kèm thẻ vào một thông báo không có thẻ, hãy sử dụng UpdateMessage với tính năng xác thực người dùng.

  • Thông tin và quyền sở hữu thẻ:

    • Thẻ được đính kèm vào một tin nhắn của người dùng sẽ được phân bổ và thuộc về ứng dụng Chat đã đính kèm thẻ đó, như được chỉ ra bởi trường CardWithId.owner chỉ có thể xuất.
    • Ứng dụng Chat chỉ có thể thay thế những thẻ mà ứng dụng này đã đính kèm vào một tin nhắn, chứ không thể thay thế những thẻ mà các ứng dụng Chat khác đã đính kèm.
  • Nếu người dùng chỉnh sửa nội dung tin nhắn, thì các thẻ thuộc ứng dụng Chat sẽ bị xoá và bạn không thể cập nhật các thẻ đó nữa.