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

Flutter集成Google Calendar API时遇请求无效的访问拦截问题

Google日历事件创建URL跳转报错:请求无效问题排查与修复

访问被拦截:project-Client_ID请求无效,您无法登录,因为project-Client_ID发送了无效请求。您可以稍后重试,或联系开发者解决此问题。

我们已尝试创建Event对象并添加至Google日历,使用的依赖库:

  • googleapis: ^11.3.0
  • googleapis_auth: ^1.4.1
  • url_launcher: ^6.1.12

当前实现代码:

class CalendarClient {
  static const _scopes = [CalendarApi.calendarScope];

 insert(title, startTime, endTime) {
 var _clientID = new ClientId(
    "Client_ID",
    "");
  clientViaUserConsent(_clientID, _scopes, prompt).then((AuthClient 
  client) {
  var calendar = CalendarApi(client);
  calendar.calendarList.list().then((value) => 
  print("VAL________$value"));

  String calendarId = "primary";
  Event event = Event(); // Create object of event

  event.summary = title;

  EventDateTime start = new EventDateTime();
  start.dateTime = startTime;
  start.timeZone = "GMT+05:00";
  event.start = start;

  EventDateTime end = new EventDateTime();
  end.timeZone = "GMT+05:00";
  end.dateTime = endTime;
  event.end = end;
  try {
    calendar.events.insert(event, calendarId).then((value) {
      print("ADDEDDD_________________${value.status}");
      if (value.status == "confirmed") {
        log('Event added in google calendar');
      } else {
        log("Unable to add event in google calendar");
      }
    });
  } catch (e) {
    log('Error creating event $e');
  }
});
}
void prompt(String url) async {
print("Please go to the following URL and grant access:");
print("  => $url,, Start Time  >> ");
print("");

if (await canLaunchUrl(Uri.parse(url))) {
  await launchUrl(Uri.parse(url));
} else {
  throw 'Could not launch $url';
}
}
}

常见原因及修复方案

1. Client ID配置错误

  • 确认ClientId传入的是Google Cloud Console生成的OAuth 2.0客户端ID,而非项目ID。
  • 匹配客户端ID类型:移动端应用需创建对应平台(Android/iOS)的客户端ID,不能用Web应用类型ID。
  • 配置正确的重定向URI:在Google Cloud Console的OAuth客户端设置中,添加对应平台的重定向URI(如Android的com.your.app:/oauth2redirect,iOS的com.your.app://oauth2callback)。

2. OAuth同意屏幕与权限配置

  • 在Google Cloud Console的OAuth同意屏幕中,添加calendar.events相关权限;测试阶段需添加测试用户,否则未发布应用无法授权。
  • 可使用更窄的权限范围:如果仅需创建事件,替换_scopes为[CalendarApi.calendarEventsScope],减少权限申请范围。

3. 代码逻辑优化

改用async/await替代嵌套then,提升可读性与错误处理能力,并优化授权跳转模式:

class CalendarClient {
  static const _scopes = [CalendarApi.calendarScope];

  Future<void> insert(String title, DateTime startTime, DateTime endTime) async {
    final _clientID = ClientId("YOUR_VALID_CLIENT_ID", "");
    try {
      final AuthClient client = await clientViaUserConsent(_clientID, _scopes, prompt);
      final calendar = CalendarApi(client);
      
      // 验证客户端连接状态
      final calendarList = await calendar.calendarList.list();
      print("CALENDAR LIST: $calendarList");

      final String calendarId = "primary";
      final Event event = Event()
        ..summary = title
        ..start = EventDateTime()
          ..dateTime = startTime
          ..timeZone = "GMT+05:00"
        ..end = EventDateTime()
          ..dateTime = endTime
          ..timeZone = "GMT+05:00";

      final insertedEvent = await calendar.events.insert(event, calendarId);
      print("EVENT STATUS: ${insertedEvent.status}");
      if (insertedEvent.status == "confirmed") {
        print('事件已添加至Google日历');
      } else {
        print('无法添加事件至Google日历');
      }
    } catch (e) {
      print('创建事件出错: $e');
    }
  }

  Future<void> prompt(String url) async {
    print("请访问以下URL并授权:");
    print("  => $url");
    if (await canLaunchUrl(Uri.parse(url))) {
      // 使用外部浏览器打开授权页面,避免WebView兼容性问题
      await launchUrl(Uri.parse(url), mode: LaunchMode.externalApplication);
    } else {
      throw '无法打开URL: $url';
    }
  }
}

4. 其他排查点

  • 确保设备时间与网络时间同步,时间偏差会导致OAuth请求失效。
  • 清除应用缓存,并在Google账号设置的「第三方应用访问」中移除该应用的授权记录,重新授权测试。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.16 12:53:27