You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

Google联系人更新失败:People.People.getContact方法报错排查

问题:Google Apps Script中People.People.getContact()调用失败

背景

我开发了一个Google Apps Script脚本,可从表格读取联系人信息并在Google Contacts中创建新联系人,创建逻辑运行正常。脚本会将外部联系人ID、Resource name和etag保存至名为"Mapping Google Contacts"的第二个表格,用于后续查找那些初始无邮箱/电话但至少有姓名和物理地址的联系人。

表格示例数据:

ID Personne Appsheet    Ressource name  etag
CF32F4F6    people/c184383266205945415  %EigBAgMEBQYHCAkKCwwNDg8QERITFBUWFxkfISIjJCUmJy40NTc9Pj9AGgQBAgUHIgxMNlNjOFJMcG55TT0=

问题详情

执行updateContact函数时失败,经排查定位到const contact = People.People.getContact(resourceName);这行代码报错。相关函数代码片段如下:

function updateContact(personData) {
  const spreadsheetId = "1NNkW8joHAWXgatSXyAu0O4fjPgkgYeZVjx4s9KZkAZw"; // Replace with your spreadsheet ID
  const ss = SpreadsheetApp.openById(spreadsheetId);

  const lookupSheet = ss.getSheetByName("Mapping Google Contacts");
  let resourceName = findContactByAppsheetId(personData.appsheetId, lookupSheet);
  Logger.log("resourceName : " + resourceName)


  Logger.log("resourceName (before prefix): " + resourceName);

  if (resourceName) {
    try {
      Logger.log("getcontact");
      const contact = People.People.getContact(resourceName);
      Logger.log("getcontact after " + contact);

      if (contact) {
        Logger.log("Contact found");
        const updatedContact = { // Create a *new* contact object
          names: [{
            givenName: personData.firstName || (contact.names && contact.names.length > 0 ? contact.names[0].givenName : ""),
            familyName: personData.lastName || (contact.names && contact.names.length > 0 ? contact.names[0].familyName : "")
          }],
          phoneNumbers: [], // Initialize phoneNumbers as an empty array
          emailAddresses: [], // Initialize emailAddresses as an empty array
          organizations: [], // Initialize organizations as an empty array
          addresses: [], // Initialize addresses as an empty array
          birthdays: contact.birthdays ? [...contact.birthdays] : [],
          user_defined: contact.user_defined ? {...contact.user_defined} : {}
        };
        Logger.log("updatedContact created");

// 后续代码省略

排查与解决方案

1. 校验Resource Name格式

Google People API的getContact方法要求resourceName必须是people/[ID]的完整格式,从表格示例看格式正确,但需确认findContactByAppsheetId返回值是否存在多余空格或拼写错误。可以添加日志查看原始返回值:

Logger.log("Raw resourceName: '" + resourceName + "'"); // 用单引号包裹,便于识别前后空格

若存在空格,用resourceName = resourceName.trim()处理。

2. 确认API权限与启用状态

  • 确保脚本已启用People API:在脚本编辑器中依次点击「扩展程序」→「Apps Script API」,确认已启用;同时在左侧「服务」面板添加People API(点击「添加服务」,找到People API并添加)。
  • 检查授权状态:运行脚本时是否已授权访问Google Contacts的权限,若授权过期或被撤销,重新授权即可。

3. 验证联系人是否存在

保存的resourceName对应的联系人可能已被手动删除,此时调用getContact会返回404错误。可以添加异常捕获验证:

try {
  const contact = People.People.getContact(resourceName);
} catch (e) {
  Logger.log("Error fetching contact: " + e.message);
  if (e.message.includes("404")) {
    // 联系人不存在,可移除映射表格中的对应记录或重新创建
    Logger.log("Contact not found, removing from mapping sheet");
    // 此处可添加删除对应行的逻辑
  }
}

4. 指定API调用的字段参数

People.People.getContact方法可通过personFields参数指定需要获取的字段,显式指定字段可避免默认返回字段不足的问题,同时符合API规范:

const contact = People.People.getContact(resourceName, {
  personFields: "names,phoneNumbers,emailAddresses,addresses,birthdays,userDefined"
});

注意字段名使用驼峰式(如userDefined而非user_defined),多个字段用逗号分隔。

5. 同步etag(可选)

若之前保存的etag已过期,虽不会直接导致getContact报错,但后续更新可能失败。可在获取联系人后对比etag,不一致则更新映射表格中的值:

// 从映射表格中获取对应行的savedEtag
const savedEtag = lookupSheet.getRange(row, 3).getValue();
if (contact.etag !== savedEtag) {
  lookupSheet.getRange(row, 3).setValue(contact.etag);
}

内容的提问来源于stack exchange,提问作者Martin Leblanc

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.06.14 14:47:12