RWI 协议参考
RWI(实时 WebSocket 接口) 是 RustPBX 面向外部软件的控制面:通过单个 WebSocket 承载命令/事件协议,并为非交互式消费方提供 HTTP Webhook 桥。本页是协议参考;Webhook 配置见对应页面。
1. 传输与认证
| 项目 | 说明 |
|---|---|
| 协议 | WebSocket(生产环境使用 WSS) |
| 方向 | 全双工——命令发出,事件在同一有序通道返回 |
| 认证 | 控制台会话、坐席令牌,或部署配置的 API Token |
| 范围 | 一个 socket 连接代表一个已认证主体 |
一个客户端一条 socket 是推荐模式。主体范围内的事件会自动到达,无需轮询,也不需要逐通订阅。
2. 事件模型
每个呼叫范围内的事件都携带根通话标识块,子腿可归并为一通逻辑通话:
| 字段 | 含义 |
|---|---|
call_id | 事件所属的腿 |
session_id | 逻辑通话的根会话(根腿时等于 call_id) |
direction | inbound / outbound |
src_ip / client_ip | 多租户与安全过滤所需的归因信息 |
Event categories
| Category | Examples |
|---|---|
| 通话生命周期 | call_created、call_ringing、call_answered、call_hangup |
| 通话错误 | 统一 call_error,含错误目录引用 |
| 媒体 | call_early_media、录音起停、播放完成 |
| DTMF / IVR | dtmf、ivr_step_trace、流程 resume |
| 队列 / ACD | queue_joined、queue_agent_connected、overflow_joined、dequeued |
| 坐席 | 状态迁移、整理起止、小休变更 |
| 会话数据 | user_data 更新、呼叫变量变更 |
| 集群 | 会话归属变更、对端存活 |
事件示例
{
"event": "call_answered",
"call_id": "d3f0-…@10.0.0.1",
"session_id": "d3f0-…@10.0.0.1",
"direction": "inbound",
"caller": "8613800001001",
"callee": "1001",
"agent_id": "demo-agent-alice",
"queue_id": "demo-support-tier1",
"src_ip": "203.0.113.20",
"client_ip": "198.51.100.7",
"timestamp": "2026-10-04T09:12:03.482Z"
}
根腿的 session_id 等于 call_id;子腿(队列派单、转接)携带相同的 session_id,消费方据此归组。
顺序与投递
- 同一会话的事件按归属节点的观测顺序排列。
- Webhook 投递为至少一次,幂等键在重试间保持不变,消费方据此去重。
rwi_event_queue_latency_seconds直方图(可选开启)跟踪网关→处理器的排队延迟。
3. 命令模型
命令是带 command 字段的 JSON 消息,能力与平台对齐:
| 分组 | 命令 |
|---|---|
| 呼叫控制 | originate、answer、hangup、bridge、transfer(盲转/咨询)、hold、resume |
| 媒体 | play(支持 side_only)、send_dtmf(rfc4733 / SIP INFO)、app.stop |
| 会话数据 | set_userdata / get_userdata、set_var / get_var |
| 队列 | 入队 / 出队、坐席分配、优先级更新 |
| 会议 | 创建房间、加入/移除参与者、结束房间 |
REST 等价接口
交互式命令在 /api 下有对应的 REST 接口,便于脚本化:
| 操作 | 端点 |
|---|---|
| 列出活动通话 | GET /api/calls/active |
| 查看会话 | GET /api/calls/active/{session_id} |
| 发送命令 | POST /api/calls/active/{session_id}/commands |
| 读写用户数据 | GET / PUT /api/calls/active/{session_id}/userdata |
| 强制挂断 | GET /ami/v1/hangup/{id} |
命令示例
{
"command": "transfer",
"session_id": "d3f0-…@10.0.0.1",
"type": "attended",
"target": "1002",
"request_id": "req-7f31"
}
响应回显 request_id;结果也以事件形式在同一 socket 返回,客户端无需轮询即可关联「命令 → 结果」。
4. 会话用户数据
用户数据是挂在会话上的应用状态——CRM 工单号、营销活动标签、坐席上下文。规则:
- 任意时刻可写,任意节点可读
- 复制到对端节点
- 被子会话与队列派单继承
- 可从 RWI socket 与上述 REST 端点访问
- 在线路上,逐键
X-<key>SIP 头把扁平视图带给主被叫腿(聚合的X-User-Data形态已废止)
5. 集群行为
集群中,所连节点未必持有该通话。协议对此透明:
| 行为 | 说明 |
|---|---|
| 归属路由 | 命令透明转发到归属节点 |
| 信封 | /cluster/session_op(终端节点本地执行) |
| 会话操作 | set_userdata / set_var 同样按归属路由 |
| 归属查询 | GET /cluster/session_owner/{call_id} |
| 集群列举 | GET /cluster/list_calls |
| 故障 | 归属节点失效时其会话标记为 offline,而不是变成幽灵会话 |
6. Webhook 桥
对不持有 socket 的消费方,同样的事件经 HTTP 投递:
[rwi_webhook]
url = "https://your-server.example.com/api/rwi/events"
events = ["call_hangup", "call_error", "queue_agent_connected"]
retries = 3
- 独立 worker 线程:慢速接收端不会拖垮通话
- 传输错误、5xx、429 按指数退避重试
- 幂等键在重试间一致,请求体逐字节相同
- 配置支持热更新
7. 集成模式
- 连接 socket、完成认证,自动获得主体范围内的事件
- 维护以
session_id为键的本地映射 - 在应答时通过
set_userdata附加业务上下文 - 用同一 socket 下发控制命令;批处理任务走 REST
- 被动消费方走 Webhook,按幂等键去重
- 集群环境下依赖归属路由——不要假设本地节点持有通话