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

Google Calendar API全域委派下events.watch推送通知400错误排查

问题排查与解决方案

一、推送返回400错误的核心排查点

1. 路由路径不匹配(最可能的直接原因)

看你的Flask日志:POST /calendar_push HTTP/1.1,但你的路由是@app.route("/calendar-push", methods=["GET", "POST"])——这里路径里的横杠和下划线不匹配!Google是按照你创建watch时提供的address参数发送请求的,如果你watch里填的是https://xxxx.eu.ngrok.io/calendar_push,但代码里的路由是/calendar-push,就会导致请求找不到正确的处理端点,直接返回400。

先确认:

  • 创建watch时的address参数是否和Flask路由完全一致(包括大小写、横杠/下划线)
  • 修正路由路径,保持和watch的address一致。

2. 请求解析失败(Flask无法读取request.json)

Google Calendar的推送通知不是JSON格式,而是application/x-www-form-urlencoded的表单格式,所以你用request.json会返回None,导致Flask在返回request.json时抛出400(因为返回了空值或者不符合JSON要求的内容)。

修改你的Flask端点代码:

@app.route("/calendar-push", methods=["GET", "POST"])
def add_message():
    app.logger.info("HIT THE /calendar-push ROUTE")
    # 改用form获取推送内容
    content = request.form.to_dict()
    app.logger.info(content)
    return content, 200

这样就能正确读取Google推送的内容了,比如channel_id、resource_id这些关键信息。

3. 检查watch请求的参数完整性

创建watch时必须指定以下参数,否则可能导致推送异常:

req = my_service.events().watch(
    calendarId=USER_EMAIL,
    body={
        "id": UUID,  # 唯一的通道ID,比如UUID生成的字符串
        "type": "web_hook",
        "address": f"{BASE_URL}/calendar-push",  # 必须和Flask路由完全一致
        "token": "可选的自定义令牌,用于验证请求来源"
    }
).execute()

注意:

  • id必须是全局唯一的,不能重复使用
  • type必须是web_hook,不能省略
  • address必须是公网可访问的URL(你的ngrok URL是可以的,但要确保ngrok处于运行状态)

二、关于resourceUri的403错误

这个是正常现象,resourceUri是Google内部用来追踪日历资源的地址,不需要你直接访问。Google会用自己的授权凭证去访问这个URI,你直接打开肯定会因为缺少API密钥或OAuth授权而返回403,不用理会这个问题。

三、是否需要添加Bearer Token?

不需要。Google Calendar的推送通知不需要你在watch()方法中添加Bearer Token,Google会在推送请求中带上X-Goog-Signature等头信息,用于验证请求确实来自Google(可选验证,不是强制要求)。你不需要在watch请求中添加额外的Token参数。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.11 18:45:34