如何为基于ZegoCloud/Agora的视频通话Web应用添加按分钟计费功能
ZegoCloud视频通话按分钟计费实现方案
核心原则
计费逻辑必须后端主导,所有余额校验、扣费、断连指令均由后端处理,前端仅负责状态展示、用户交互及ZegoCloud通话的启停,避免前端篡改数据导致资金损失。
一、后端核心实现
数据存储设计
- 在数据库中维护用户钱包表,字段至少包含:
user_id(用户唯一标识)、balance(当前余额)、call_status(通话状态:空闲/活跃)、call_start_time(通话开始时间戳)、total_deducted(累计扣费金额)。
- 在数据库中维护用户钱包表,字段至少包含:
通话发起校验
- 用户发起通话前,前端必须调用后端
initiate_call接口,后端执行以下操作:- 校验用户
balance是否大于等于单分钟费率(如1$); - 若校验通过,将
call_status设为「活跃」,记录call_start_time,返回通话授权凭证给前端; - 若余额不足,直接返回错误提示,前端禁止启动通话。
- 校验用户
- 用户发起通话前,前端必须调用后端
定时扣费与余额监控
- 后端启动每分钟执行一次的定时任务(可使用Redis定时任务、Spring Scheduler等),遍历所有
call_status为「活跃」的用户:- 计算当前时间与
call_start_time的差值,取整得到实际通话分钟数(不足1分钟按1分钟计算,或按需调整精度); - 计算累计应扣费用:
实际分钟数 × 单分钟费率,与total_deducted对比,扣除未结算的费用; - 更新用户
balance和total_deducted; - 若更新后
balance < 单分钟费率,触发断连流程:- 调用ZegoCloud服务端API(如
kickUserFromRoom),强制将用户移出通话房间; - 将用户
call_status设为「空闲」,记录通话结束时间及总时长。
- 调用ZegoCloud服务端API(如
- 计算当前时间与
- 后端启动每分钟执行一次的定时任务(可使用Redis定时任务、Spring Scheduler等),遍历所有
主动结束通话结算
- 用户主动挂断通话时,前端调用后端
end_call接口:- 后端根据
call_start_time和当前时间计算实际通话时长,完成最终扣费; - 更新
balance、call_status,清除call_start_time。
- 后端根据
- 用户主动挂断通话时,前端调用后端
二、前端配合逻辑
通话前校验
- 发起通话前必须先请求后端
initiate_call接口,仅在拿到授权凭证后,再调用ZegoCloud的joinRoom接口启动通话。
- 发起通话前必须先请求后端
实时状态展示
- 每隔30秒调用后端接口获取当前
balance及剩余可通话时长,实时展示给用户。
- 每隔30秒调用后端接口获取当前
断连事件处理
- 监听ZegoCloud的
onDisconnect或onRoomUserLeave事件,若检测到是后端触发的强制断连(可通过后端返回的断连标识判断),弹出提示:「余额不足,通话已自动结束」,并更新本地钱包展示。
- 监听ZegoCloud的
本地时长统计(仅参考)
- 前端可本地统计通话时长,但最终扣费以后端记录的
call_start_time和结束时间为准,避免网络延迟导致的时长偏差。
- 前端可本地统计通话时长,但最终扣费以后端记录的
三、ZegoCloud集成要点
- 服务端鉴权:提前在ZegoCloud控制台获取
AppID和ServerSecret,用于调用服务端API时生成签名,确保接口调用的合法性。 - 强制断连API:使用ZegoCloud服务端的
kickUserFromRoom接口,传入房间ID和用户ID,即可强制用户退出通话。 - 事件监听:前端需监听ZegoCloud的通话状态变更事件,及时同步后端的断连指令。
四、异常处理
- 网络波动:若用户通话过程中网络断开,后端定时任务仍会继续统计时长,待用户重新连接时,前端需调用后端接口同步最新余额及通话状态,补做状态提示。
- 并发安全:更新余额和通话状态时,使用数据库事务或乐观锁,避免同一用户同时触发多次扣费或状态变更。
- 精度调整:若需按秒计费,可将时长计算单位改为秒,费率折算为
1$/60秒,累计扣费后四舍五入或按实际秒数结算。
内容的提问来源于stack exchange,提问作者Harshvardhan Kumar
相关产品推荐
相关产品推荐

