如何验证Twitch的callback以正常接收平台推送的事件?
Twitch EventSub 回调验证完整流程与实操方法
Twitch在收到你提交的事件订阅请求后,会立刻向你填写的回调地址发起验证请求,只有验证通过才会开始推送正式事件,整个流程无跳过路径,具体规则和操作如下:
验证请求基础规则
Twitch发起的验证请求为标准HTTP GET请求,会携带4个Query参数:
hub.mode:验证阶段固定值为subscribe,可作为判断是否为验证请求的标识hub.challenge:Twitch随机生成的校验字符串,是验证环节需要你返回的核心值hub.topic:当前订阅对应的事件主题标识,可用于校验请求是否对应你自己提交的订阅,拦截恶意请求hub.lease_seconds:本次订阅的有效时长,单位为秒,默认值为864000(即10天),到期前需要主动续期
具体操作步骤
- 先确保回调地址符合Twitch的基础要求:必须是公网可直达的HTTPS地址,证书由受信任的公共CA签发(自签证书直接被拦截),仅支持443端口,不支持内网地址、localhost,地址配置的3xx跳转不会被Twitch跟随,直接判定验证失败。
- 给回调接口加验证判断逻辑:收到GET请求时先校验
hub.mode值是否为subscribe,有需要的话可以同步校验hub.topic是否属于你提交过的订阅列表,过滤无关请求。 - 校验通过后直接返回响应:响应状态码必须为
200 OK,Content-Type设为text/plain,响应体仅保留hub.challenge的原始字符串值,不要包裹JSON结构、不要加引号、不要加多余的换行或注释,原封不动返回即可。
举个最小实现的伪代码参考(Python Flask):
from flask import Flask, request, Response app = Flask(__name__) @app.route('/your-twitch-callback', methods=['GET']) def verify_callback(): if request.args.get('hub.mode') == 'subscribe': # 直接原样返回challenge值,不做任何修改 return Response( request.args.get('hub.challenge'), status=200, mimetype='text/plain' ) # POST请求的正式事件接收逻辑写在后续分支
常见踩坑点
- 超时问题:Twitch等待响应的超时时间仅为1秒,收到验证请求后优先返回challenge值,日志记录、数据存储等逻辑可以异步处理,超时会直接判定验证失败
- 拦截问题:检查服务器防火墙、WAF规则,如果配置了IP白名单,需要提前放通Twitch EventSub的官方出口IP段,避免请求被拦截
- 格式问题:不要把
hub.challenge包在JSON结构里返回(比如返回{"challenge": "xxx"}),也不要修改字符串的大小写、做转码处理,任何格式改动都会导致验证失败 - 重试规则:第一次验证失败后Twitch会在10分钟内重试数次,如果一直未通过,订阅状态会标记为
validation_failed,需要重新提交订阅触发验证
内容的提问来源于stack exchange,提问作者Леонид Мишин
相关产品推荐
相关产品推荐

