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

调用Google Calendar API插入事件时提示‘缺少结束时间’问题求助

问题描述

使用服务账号域级代权代表域内用户插入Google Calendar事件时,返回「缺少结束时间」错误,但能正常获取该用户的日历数据。已尝试添加/移除calendarId、resource参数,以及调整start/end的时区配置,均无法解决问题。

原代码如下:

function testRequest(){

  var service = getDWDS('Calendar: ', 'https://www.googleapis.com/auth/calendar', 'user@example.com');

  var requestBody = 
    {
      calendarId: "user@example.com",
      resource: {
        start: {
          dateTime: '2022-12-09T09:00:00Z',
        },
        end: {
          dateTime: '2022-12-09T11:30:00Z',
        },

        summary: "Test Request",
        conferenceData: {
          createRequest: {
            requestId: 'random'
          }
        },
      }
    };
    requestBody.headers            = {'Authorization': 'Bearer ' + service.getAccessToken()};
    requestBody.contentType        = "application/json";
    requestBody.method             = "POST";
    requestBody.muteHttpExceptions = false;  

  var url = 'https://www.googleapis.com/calendar/v3/calendars/primary/events?conferenceDataVersion=1&sendUpdates=none';

  Logger.log(requestBody)
  Logger.log(JSON.parse(UrlFetchApp.fetch(url, requestBody)))

  return JSON.parse(UrlFetchApp.fetch(url, requestBody));
}


const OAUTH2_SERVICE_ACCOUNT_PRIVATE_KEY = "KEY GOES HERE"
const OAUTH2_SERVICE_ACCOUNT_CLIENT_EMAIL = 'SERVICE ACCOUNT EMAIL HERE';

function getDWDS(serviceName, scope, email) {

  // Logger.log('starting getDomainWideDelegationService for email: ' + email);

  return OAuth2.createService(serviceName + email)
    // Set the endpoint URL.
    .setTokenUrl('https://accounts.google.com/o/oauth2/token')

    // Set the private key and issuer.
    .setPrivateKey(OAUTH2_SERVICE_ACCOUNT_PRIVATE_KEY)
    .setIssuer(OAUTH2_SERVICE_ACCOUNT_CLIENT_EMAIL)

    // Set the name of the user to impersonate. This will only work for
    // Google Apps for Work/EDU accounts whose admin has setup domain-wide
    // delegation:
    // https://developers.google.com/identity/protocols/OAuth2ServiceAccount#delegatingauthority
    .setSubject(email)

    // Set the property store where authorized tokens should be persisted.
    .setPropertyStore(PropertiesService.getScriptProperties())

    // Set the scope. This must match one of the scopes configured during the
    // setup of domain-wide delegation.
    .setScope(scope);

}

问题分析与修复

核心错误点

  1. 请求体结构不符合API要求:
    Google Calendar创建事件的POST接口,要求事件数据作为请求体的原始JSON内容传递,而非嵌套在resource字段中;同时calendarId需要放在URL路径里,不能放在请求体中。
  2. UrlFetchApp请求配置错误:
    发送JSON类型POST请求时,需要将事件数据序列化为JSON字符串,通过payload字段传递,原代码未做这一步,导致API无法解析到正确的事件时间参数。

修正后的代码

function testRequest(){
  const userEmail = "user@example.com";
  const service = getDWDS('Calendar: ', 'https://www.googleapis.com/auth/calendar', userEmail);

  // 定义事件的核心数据
  const eventData = {
    start: {
      dateTime: '2022-12-09T09:00:00Z',
    },
    end: {
      dateTime: '2022-12-09T11:30:00Z',
    },
    summary: "Test Request",
    conferenceData: {
      createRequest: {
        requestId: 'random'
      }
    },
  };

  // 配置UrlFetchApp请求参数
  const requestConfig = {
    headers: {'Authorization': 'Bearer ' + service.getAccessToken()},
    contentType: "application/json",
    method: "POST",
    muteHttpExceptions: false,
    payload: JSON.stringify(eventData) // 关键:将事件数据序列化为JSON字符串
  };

  // 把用户邮箱作为calendarId放入URL,或保留primary(代权后primary对应用户主日历)
  const url = `https://www.googleapis.com/calendar/v3/calendars/${encodeURIComponent(userEmail)}/events?conferenceDataVersion=1&sendUpdates=none`;

  try {
    const response = UrlFetchApp.fetch(url, requestConfig);
    const result = JSON.parse(response.getContentText());
    Logger.log("事件创建成功:", result);
    return result;
  } catch(e) {
    Logger.log("请求错误:", e.toString());
    throw e;
  }
}

const OAUTH2_SERVICE_ACCOUNT_PRIVATE_KEY = "KEY GOES HERE";
const OAUTH2_SERVICE_ACCOUNT_CLIENT_EMAIL = 'SERVICE ACCOUNT EMAIL HERE';

function getDWDS(serviceName, scope, email) {
  return OAuth2.createService(serviceName + email)
    .setTokenUrl('https://accounts.google.com/o/oauth2/token')
    .setPrivateKey(OAUTH2_SERVICE_ACCOUNT_PRIVATE_KEY)
    .setIssuer(OAUTH2_SERVICE_ACCOUNT_CLIENT_EMAIL)
    .setSubject(email)
    .setPropertyStore(PropertiesService.getScriptProperties())
    .setScope(scope);
}

关键修正说明

  • 将事件数据与请求配置拆分,把事件数据通过JSON.stringify转为字符串后放在payload字段,这是UrlFetchApp发送JSON POST请求的标准方式
  • 将calendarId移至URL路径中,符合Google Calendar API的参数传递规则
  • 添加encodeURIComponent处理用户邮箱,避免特殊字符导致URL解析失败
  • 增加try-catch块,方便排查请求过程中的异常

内容的提问来源于stack exchange,提问作者JS Henney

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.09 11:45:26