闪联
← 返回闪联官网
SHANLIAN · WEBRTC VOICE PLATFORM

闪联 WebRTC 语音平台对接文档

号码池 · SIP/WebRTC 坐席 · 事件推送 全接口集成指南
项目内容
文档版本V1.0
发布日期2026 年 9 月 2 日
目标读者后端 / 前端开发者
前置知识HTTP API 、 WebSocket 、 SIP 与 WebRTC 基本概念

一、概述

第三方系统通过「号码池 API + SIP/WebRTC 坐席 +事件 Webhook」三个接口,即可将闪联的网页通话能力集成进自己的业务系统。

闪联提供基于 WebRTC 的网页软电话能力:坐席无需安装任何客户端,在浏览器(含微信内置浏览器)里即可注册上线、拨打和接听 PSTN 电话,全程支持通话录音、事件推送与话单回传。

对接总流程

二、一句话集成(网页组件)

「一句话集成」是闪联推荐的接入方式:客户在自己的网页里加一行 <script>,即可获得完整的网页通话能力(通话按钮、弹窗、录音、埋点),无需自建服务端、也无需接触任何 API Key。

2.1 集成代码

<script src="https://shanlian.bj-yzqt.com/widget/sl.js" data-site="SL-xxxxx" async></script>

data-site 为闪联分配的站点标识,全局唯一,由闪联在开通时提供。

2.2 组件配置项

属性必填默认值说明
data-site站点标识,闪联分配(全局唯一)
data-apihttps://api.bj-yzqt.com通话 API 地址
data-positionbottom-right按钮位置:bottom-right / bottom-left / inline
data-theme#6c63ff按钮主色
data-text免费通话inline 模式按钮文案
data-tiptrue是否显示「不会获取手机号」气泡

2.3 事件回调

组件挂载全局对象 ShanLian,可用 ShanLian.on 订阅通话事件:

<script>
ShanLian.on('call:connected', function (e) { /* 已接通 */ });
ShanLian.on('call:ended', function (e) { console.log('通话时长', e.duration, '秒'); });
</script>
事件触发时机字段
ready组件就绪site, title
call:start开始呼叫
call:connected接通
call:ended挂断duration(秒)
call:failed失败cause
error组件错误code, msg

2.4 安全机制

2.5 通话体验

三、对接准备

本章列出正式联调前需要向闪联申请的账号凭证、平台侧配置项,以及坐席侧的网络放行要求。

3.1 账号与凭证

对接前由闪联分配:

项目说明示例
accountNo9 位账号,号码池按此前缀分配坐席号860100000
API Key调用号码池 API 的 Bearer 令牌sk-9d8c7b6a5g4c3a2b1a0f9e8d7c6b5b4e(仅示例,真实需向闪联申请)
事件推送 URL贵方接收呼叫事件 / 话单的 HTTPS 接口https://your-domain.com/api/callevent
推送 Authorization (可选)平台推送事件时携带的鉴权头,无需鉴权可留空Bearer your-token

3.2 网络端口要求

端口协议方向用途
8059TCP/HTTP业务系统 → 平台号码池与凭证 API
8089TCP/WSS浏览器 → 平台SIP over WebSocket (注册与呼叫信令)
13478UDP浏览器 → 平台STUN/TURN (媒体中继)
15060UDPSIP 终端 → 平台SIP (非 WebRTC 终端接入用)
18098TCP/HTTP业务系统 → 外呼平台外呼 API

四、接口一:号码池与凭证 API

Base URL:http://shanlian:8059(仅示例)

4.1 认证

所有接口必须携带 Bearer 令牌,令牌即账号的 API Key:

Authorization: Bearer sk-8c7b6a5f4e3d2c1b0a9f8e7d6c5d4c3a(仅示例,真实需向闪联申请)
HTTP 状态body含义
401{"code":-4,"ret":"Missing Authorization Header"}缺少 Authorization 头
400{"code":-5,"ret":"Invalid Authorization Scheme, expected Bearer"}不是 Bearer 格式
403{"code":-1,"ret":"Forbidden"}令牌与账号不匹配

4.2 取号(分配坐席号码)

GET /np/account/{accountNo}?action=fetch

从该账号的号码池中取一个空闲且在线的 SIP 号码并标记为占用。成功响应:

{
  "code": 0,
  "peers": "86010000001",
  "stun_server": "stun:shanlian.com:13478",
  "turn_server": "turn:shanlian.com:13478",
  "ws_server": "wss://shanlian.com:8089/ws",
  "peer_server": "shanlian.com:15060"
}
字段说明
peers分到的坐席号码( SIP 用户名 = 密码 = 此号码)。池空时为空串,需重试
stun_server / turn_serverICE 服务器地址,直接填入 WebRTC iceServers
ws_serverSIP over WSS 接入地址
peer_serverSIP 域(构造 SIP URI 用)

注意事项:

4.3 放号(释放坐席号码)

GET /np/peers/{peer}?action=release
{peer} 为 fetch 分到的完整号码。响应:
{"code": 0, "ret": "success"}

4.4 获取 TURN 临时凭证

GET /np/account/{accountNo}?action=get_turn_credentials
{"username": "1788310476", "password": "aBcDeF...="}

五、接口二:SIP/WebRTC 坐席接入

坐席侧通过 jssip 在浏览器内完成 SIP 注册与呼叫,本章给出接入参数与可直接复用的代码示例。

5.1 接入参数

参数取值来源
WSS 地址wss://shanlian.com:8089/wsfetch 响应 ws_server
SIP URIsip:{peers}@{peer_server}拼接
用户名 / 密码均为 fetch 分到的 peers 号码fetch 响应
ICE 服务器turn:{turn_server} + 临时凭证fetch + get_turn_credentials

5.2 注册上线(jssip 3.x 示例)

const socket = new JsSIP.WebSocketInterface(ws_server);
const ua = new JsSIP.UA({
  uri: `sip:${peers}@${peer_server}`,
  authorization_user: peers,
  password: peers,              // 密码与用户名相同
  sockets: [socket],
  session_timers: false,
  register: true
});
ua.on('registered',   () => console.log('已注册上线'));
ua.on('registrationFailed', e => console.log('注册失败', e.cause));
ua.start();

5.3 主叫(坐席拨出)

注册成功后向目标号码发 INVITE。平台接入号规则为 90 + 被叫号码(固话省略区号前导 0,具体路由以平台 dialplan 为准,对接时请与闪联确认号段):

const pcConfig = {
  iceTransportPolicy: 'relay',  // 只用 TURN 中继,起呼快、行为确定
  iceServers: [{ urls: turn_server, username: cred.username, credential: cred.password }]
};
const session = ua.call('01012345678', {
  mediaConstraints: { audio: true, video: false },
  pcConfig,
  eventHandlers: {              
    icecandidate: (e) => {
      if (e.candidate && e.candidate.type === 'relay') e.ready(); 
    }
  }
});

5.4 被叫(接听平台回呼)

平台外呼或 PSTN 呼入时,SipServer 会向坐席号码发 INVITE。该版本 jssip 的 answer() 不处理 eventHandlers 选项,被叫侧必须在 newRTCSession 回调里提前挂 icecandidate:

ua.on('newRTCSession', (e) => {
  if (e.originator !== 'remote') return;
  const s = e.session;
  s.on('icecandidate', (ev) => {
    if (ev.candidate && ev.candidate.type === 'relay') ev.ready();
  });
  // 弹出接听界面;用户点击接听时:
  // s.answer({ mediaConstraints: {audio:true, video:false}, pcConfig });
});

5.5 播放远端声音与移动端兼容

session.connection.addEventListener('track', (e) => {
  remoteAudio.srcObject = e.streams[0];
  remoteAudio.play().catch(() => {}); // iOS 微信需用户交互后才能出声
});

iOS 微信浏览器有自动播放限制,需在首次点击事件中做一次 play()+pause() 预热(参考实现 call.js 已内置)。

5.6 参考实现

平台提供两个参考文件,可直接作为对接起点:

安全提示:生产环境请将 fetch / release / get_turn_credentials / 外呼调用放在贵方服务端,不要把 API Key 下发到浏览器。

六、接口三:事件推送 Webhook

通话生命周期中的关键事件(建立、振铃、接听、话单)由平台主动推送到贵方配置的 URL,本章定义推送方式与报文字段。

6.1 推送方式

平台向账号配置的推送 URL 发起 HTTP POST:

6.2 公共字段

字段说明
caller主叫号码
callee被叫号码
event_name事件名,见 5.3
event_time事件时间,毫秒时间戳
call_id呼叫 UUID ,同一通电话所有事件一致
request_id外呼 API 传入的 requestid (坐席主叫时为空)
task_id任务 ID (预留,通常为空)
pay_load事件负载,仅 cdr 事件携带
account_no归属账号

6.3 事件清单

事件触发时机
callIn坐席侧呼叫建立( WebRTC 腿接通)
secondRinging第二腿( PSTN 侧)开始振铃
secondAnswer第二腿接听,双方正式通话
cdr通话结束,推送完整话单

6.4 cdr 事件负载

pay_load 为 CDR 对象数组,一通电话包含两腿(坐席腿 + PSTN 腿):

字段说明
caller / callee该腿主被叫
start_time / answer_time / end_time毫秒时间戳;未应答时 answer_time 为 0
hangup_side挂机方: caller / callee
call_type11 = 坐席呼入腿, 12 = 平台呼出腿
is_record1 = 有录音
record_file录音文件名( mp3 ),命名规则见第七节
out_call_type呼叫方向标记(如 callin )
call_id / request_id与公共字段一致

6.5 cdr 推送示例

{
  "caller": "86010000001",
  "callee": "01012345678",
  "event_name": "cdr",
  "event_time": 1788310400000,
  "call_id": "f47ac10b58cc",
  "request_id": "1234567890",
  "task_id": "",
  "account_no": "860100000",
  "pay_load": [
    {"caller":"86010000001","callee":"01012345678","call_type":"11","answer_time":1788310398000,"end_time":1788310400000,"is_record":1,"record_file":"860100000-20260902-f47ac10b58cc-86010000001.mp3"}
  ]
}

七、录音

八、附录

错误码速查表,供开发与运维随时翻阅。

错误码速查

codeHTTP含义
0200成功
-1403Bearer 令牌与账号不匹配
-4401缺少 Authorization 头
-5400Authorization 不是 Bearer 格式
-10404站点(siteId)不存在
-11403域名未授权(不在白名单)
-12401wt 缺失或签名错误
-13401wt 已过期
-14403siteId 与 wt 不匹配
-20200号码池空 / 并发打满
© 2026 北京易中全天科技有限公司 文档版本 v1.0 · 最后更新 2026-09-04