Zoom Web SDK加入会议超时失败问题(Flask后端)
问题描述
尝试用Flask作为后端实现Zoom Web SDK客户端视图,初始化环节执行正常,但点击加入会议时出现如下提示:
Joining Meeting Timeout.
Fail to join the meeting
已关闭会议等候室功能,控制台显示会议号、密码、签名等各项数据均准确,请求排查并解决加入会议失败的问题。
前端代码
<html> <body> </body> <script src="https://source.zoom.us/2.9.7/lib/vendor/react.min.js"></script> <script src="https://source.zoom.us/2.9.7/lib/vendor/react-dom.min.js"></script> <script src="https://source.zoom.us/2.9.7/lib/vendor/redux.min.js"></script> <script src="https://source.zoom.us/2.9.7/lib/vendor/redux-thunk.min.js"></script> <script src="https://source.zoom.us/2.9.7/lib/vendor/lodash.min.js"></script> <!-- CDN for client view --> <script src="https://source.zoom.us/zoom-meeting-2.9.7.min.js"></script> <head> <link type="text/css" rel="stylesheet" href="https://source.zoom.us/2.9.5/css/bootstrap.css" /> <link type="text/css" rel="stylesheet" href="https://source.zoom.us/2.9.5/css/react-select.css" /> </head> <script> ZoomMtg.setZoomJSLib('https://source.zoom.us/2.9.7/lib', '/av') // loads dependent assets ZoomMtg.preLoadWasm() ZoomMtg.prepareWebSDK() // loads language files, also passes any error messages to the ui ZoomMtg.i18n.load('en-US') ZoomMtg.i18n.reload('en-US') const sdkKey = "xxxxxxx"; const userName = sessionStorage.getItem("N"); const meetingNumber = sessionStorage.getItem("ID"); const passWord = sessionStorage.getItem("Pass"); const leaveUrl = "http://localhost:5050/videolist"; console.log(meetingNumber) console.log(passWord) //const KJUR = require('jsrsasign') // https://www.npmjs.com/package/jsrsasign const signature = "{{ signature }}" console.log(signature) ZoomMtg.init({ leaveUrl: leaveUrl, // https://example.com/thanks-for-joining success: (success) => { console.log('Success init') ZoomMtg.join({ sdkKey: sdkKey, signature: signature, // role in SDK signature needs to be 0 meetingNumber: meetingNumber, passWord: passWord, userName: userName, userEmail: "xxxxxx", //Actual Email ID was given success: (success) => { console.log('Success join') console.log(success) }, error: (error) => { console.log("A" + error + " B " + error.message) console.log(sdkKey) console.log(signature) console.log(meetingNumber) console.log(passWord) console.log(userName) } }) }, error: (error) => { console.log(error) } }) </script> <!-- <script src="{{ url_for('static', filename='script/meeting.js') }}" type="module"></script> --> </html>
后端Flask代码
@app.route('/meeting/<IDP>', methods=['GET']) def meet(IDP): ID = IDP[:IDP.index(' ')] payload = {'sdkKey': SDK_KEY, "meetingNumber": ID, "role": 0, "user": IDP[IDP.index(' ')+1:], "iat": time.strftime("%d %b %y %H:%M:%S",time.gmtime())} encoded = jwt.encode({"some": payload}, SECRET, algorithm="HS256") return render_template('meeting.html', signature = encoded)
问题排查与修复
1. 签名生成逻辑错误(核心问题)
Zoom Web SDK对签名JWT的格式有严格要求,当前后端代码存在两个致命错误:
- payload被错误嵌套在
some字段中,Zoom无法识别有效信息 iat使用了格式化的时间字符串,而非要求的Unix时间戳(整数)
这两个错误会直接导致签名验证失败,触发加入超时。
修复后的后端代码
import time import jwt @app.route('/meeting/<IDP>', methods=['GET']) def meet(IDP): ID = IDP[:IDP.index(' ')] # 按照Zoom要求构造payload,iat为Unix时间戳,添加合理过期时间 payload = { 'sdkKey': SDK_KEY, 'meetingNumber': ID, 'role': 0, 'user': IDP[IDP.index(' ')+1:], 'iat': int(time.time()), 'exp': int(time.time()) + 3600 # 签名1小时内有效 } # 直接对payload签名,无需嵌套额外字段 encoded = jwt.encode(payload, SECRET, algorithm="HS256") return render_template('meeting.html', signature=encoded)
2. 前端HTML结构错误
原代码中<head>标签放在了<body>和<script>之后,不符合HTML规范,可能导致样式加载异常或SDK初始化受影响。需调整结构,并同步CSS版本与SDK版本:
修复后的前端HTML结构开头
<html> <head> <!-- 同步CSS版本为2.9.7,与SDK版本一致 --> <link type="text/css" rel="stylesheet" href="https://source.zoom.us/2.9.7/css/bootstrap.css" /> <link type="text/css" rel="stylesheet" href="https://source.zoom.us/2.9.7/css/react-select.css" /> </head> <body> <!-- 所有脚本和页面内容放在body内 --> <script src="https://source.zoom.us/2.9.7/lib/vendor/react.min.js"></script> <script src="https://source.zoom.us/2.9.7/lib/vendor/react-dom.min.js"></script> <script src="https://source.zoom.us/2.9.7/lib/vendor/redux.min.js"></script> <script src="https://source.zoom.us/2.9.7/lib/vendor/redux-thunk.min.js"></script> <script src="https://source.zoom.us/2.9.7/lib/vendor/lodash.min.js"></script> <!-- CDN for client view --> <script src="https://source.zoom.us/zoom-meeting-2.9.7.min.js"></script> <!-- 后续脚本代码 --> </body> </html>
3. 额外验证点
- 确认
SECRET是Zoom开发者平台中对应SDK Key的Secret Key,切勿混淆其他密钥 - 前端
sdkKey必须与后端使用的SDK_KEY完全一致 - 确保目标会议处于已启动状态(仅创建未启动的会议无法加入)
- 检查浏览器控制台是否有CORS错误,若有需在Zoom开发者后台配置允许的域名
内容的提问来源于stack exchange,提问作者George
相关产品推荐
相关产品推荐

