创建一个简便的自动外呼提示活动。

使用3CX Call Control API来自动化外呼活动。将电话号码列表连接到IVR系统,播放自动消息,并根据IVR菜单选择将通话转接到不同目的地。与传统外呼相比,这种方法在消息传递、呼叫路由和CRM或数据库集成方面提供了更大的灵活性。继续阅读了解更多详情和入门指南。

何时使用外呼提示活动脚本

航班取消是一个很好的例子。航空公司可以通过录制的消息通知乘客,并提供菜单选项以便连接到支持人员。

这只是一个基本用例,但可以进行扩展。您可以使用DTMF输入处理和音频流控制为外呼活动构建自定义IVR。

查看3CX官方GitHub仓库获取更多示例 呼叫处理设置和API集成

创建3CX IVR,将其添加到Call Control API访问中,并从分机列表中选择它。 呼叫初始化

客户端UI使用一个简单的文本区域来输入以逗号分隔的号码列表。

 const destinations = source  
.split(',')  
.map((num) => num.trim())  
.filter(Boolean);  

队列结构逐个处理呼叫。未应答或忙线的呼叫可以排队重拨。

 destinations.forEach((destNumber) => this.callQueue.enqueue(destNumber));  

呼叫逻辑

下面的函数从队列中检索第一个号码并开始处理。

 public async makeCallsToDst() {  
if (this.callQueue.isEmpty()) return;
 const destNumber = this.callQueue.dequeue();  
// …

在拨号之前,系统会检查PBX连接并确保源分机未被使用

 if (!this.sourceDn || !this.externalApiSvc.connected) {  
if (destNumber)  
this.failedCalls.push({  
callerId: destNumber,  
reason: NO_SOURCE_OR_DISCONNECTED,  
});  
return;  
}
 const participants = this.getParticipantsOfDn(this.sourceDn);  

if (participants && participants.size > 0) { if (destNumber) this.failedCalls.push({ callerId: destNumber, reason: CAMPAIGN_SOURCE_BUSY, }); return; }

 //…

发起呼叫

呼叫使用第一个可用设备发起。

您可以在 呼叫控制状态 中找到特定DN的可用设备列表。

  
try {  
const source = this.fullInfo?.callcontrol.get(this.sourceDn);  
const device: DNDevice | undefined = source?.devices?.values().next().value;  
if (!device?.device_id) {  
throw new BadRequest('Devices not found');  
}  
const response = await this.externalApiSvc.makeCallFromDevice(  
this.sourceDn,  
encodeURIComponent(device.device_id),  
destNumber,  
);  
//…  

makeCallFromDevice方法使用此端点:

  
public makeCallFromDevice(source: string, deviceId: string, dest: string) {
  
const url = '/callcontrol' + `/${source}` + '/devices' + `/${deviceId}` + '/makecall';  

return this.fetch!.post( url, { destination: dest, }, { headers: { ‘Content-Type’: ‘application/json; charset=utf-8’, }, }, ); }

错误处理
-------

如果**PBX接受请求**,则**存储呼叫ID**。否则,记录错误。

if (response.data.result?.id) { this.incomingCallsParticipants.set(response.data.result.id, response.data.result); } else { this.failedCalls.push({ callerId: destNumber!, reason: response?.data?.reasontext || UNKNOWN_CALL_ERROR, }); } //…

**应用程序和PBX**之间的错误在这里处理:

//… } catch (error: unknown) { if (axios.isAxiosError(error)) { this.failedCalls.push({ callerId: destNumber!, reason: error.response?.data.reasontext || UNKNOWN_CALL_ERROR, }); } else { this.failedCalls.push({ callerId: destNumber!, reason: UNKNOWN_CALL_ERROR, }); } }

参与者事件处理
------------

**(<https://www.3cx.com/docs/call-control-api-endpoints/#h.dh9ktn455jkz>)**用于跟踪IVR状态、启动新呼叫和管理参与者。

您可以在此[指南](<https://www.3cx.com/docs/call-control-api/>)中找到有关**WebSocket事件结构**和其他相关方面的更多详细信息。

private wsEventHandler = (json: string) => { try { const wsEvent: WSEvent = JSON.parse(json); if (!this.externalApiSvc.connected || !wsEvent?.event?.entity) { return; } const { dn, type } = determineOperation(wsEvent.event.entity); //…

当发生更新时,应用程序**获取并存储**新数据。

case EventType.Upset: { this.externalApiSvc .requestUpdatedEntityFromWebhookEvent(wsEvent) .then((res) => { const data = res.data; set(this.fullInfo, wsEvent.event.entity, data); // 更新本地状态 if (dn === this.sourceDn) { if (type === PARTICIPANT_TYPE_UPDATE) { /**

  • 在此处理参与者更新 */ if (removed?.id) { //… if (!participants || participants?.size < 1) { // 处理程序空闲 this.makeCallsToDst(); // 继续活动 } } } } }
我们可以在WebSocket事件监听器中使用这个**事件处理程序**。

ws.on(‘message’, (buffer) => { const message = decoder.decode(buffer as Buffer); wsEventHandler(message);});



更多的呼叫流程脚本

我们的网站上有一系列呼叫流程脚本。查看它们并了解如何自动化 3CX 以满足您的需求。