Make an outbound call with Twilio
The following flow diagram shows the sequence of operations performed once an agent starts an outbound call from the Fusion application:
- When the agent starts an outbound call from the Fusion application by clicking
on the phone number, the
onOutgoingEvent
event is fired. - The
onOutgoingEvent
event listener in your media toolbar application receives this event and starts the outbound call by calling the Twiliodevice.connect
API by passing the phone number to be dialed. - Twilio starts the outbound call and returns the
Call
object. - The
newCommEvent
action is called from your media toolbar application. - The Fusion application shows the dialing panel once the
newCommEvent
action is received
To make an outbound call using Twilio , we need to call the connect method of the Twilio
Device
object. The code looks like this:
const device = new Device(token);
let call = await device.connect({
params: {
To: '+15551234567'
}
});
This example shows an try to create a new connection with the Twilio application that you
associated with the Access Token used when instantiating the Device
instance. This method returns a Promise
with the Call
object. You can track this Call
object to monitor or change the active
call. You can listen to user actions by listening to the to the accept
,
disconnect
and cancel
events on the Call
object.
You can update the makeOutboundCall
method in
VendorHandler
class for this as shown in the following example:
public async makeOutboundCall(phoneNumber: string, eventId: string): Promise<void> {
const params = {
To: phoneNumber,
};
if (this.device) {
this.call = await this.device.connect({ params });
const callId = this.call.parameters.CallSid
this.call.on("accept", () => { this.integrationEventsHandler.outboundCallAcceptedHandler(callId) });
this.call.on("disconnect", () => { this.integrationEventsHandler.callHangupHandler(callId) });
this.call.on("cancel", () => { this.integrationEventsHandler.callRejectedHandler(callId) });
}
}
Complete code
Here's the complete code of the vendorHandler.ts
file for starting
an outbound call:
import { Call, Device } from '@twilio/voice-sdk';
import { ICtiVendorHandler } from './ICtiVendorHandler';
import { IntegrationEventsHandler } from '../integrationEventsHandler';
export class VendorHandler implements ICtiVendorHandler {
private twilio: any;
private device: Device | null;
private integrationEventsHandler: IntegrationEventsHandler;
private call: Call | null;
public idAndToken: any;
constructor(integrationEventsHandler: IntegrationEventsHandler) {
this.twilio = (window as any).Twilio;
this.device = null;
this.idAndToken = null;
this.integrationEventsHandler = integrationEventsHandler;
this.call = null;
}
public async makeAgentAvailable(): Promise<void> {
this.idAndToken = await this.getIdAndToken();
this.device = new this.twilio.Device(this.idAndToken.token, {
logLevel: 1,
codecPreferences: ["opus", "pcmu"],
enableRingingState: true
});
let resolve: Function;
let reject: Function;
if (this.device) {
this.device.on("registered", () => {
console.log("Registration completed ...")
resolve();
});
this.device.on("error", (deviceError) => {
console.error("Registration Failed ...", deviceError);
reject();
});
this.device.on("incoming", this.incomingCallCallback);
this.device.register();
}
return new Promise((res: Function, rej: Function) => {
resolve = res;
reject = rej;
});
}
public incomingCallCallback = (call: Call) => {
this.integrationEventsHandler.incomingCallHandler(call.parameters.From, call.parameters.CallSid);
this.call = call;
}
public async makeAgentUnavailable(): Promise<void> {
let resolve: Function;
let reject: Function;
if (this.device) {
this.device.on("unregister", () => {
console.log("Successfully UnRegistered ...")
resolve();
});
this.device.on("error", (deviceError) => {
console.error("Failed to unregister ...", deviceError);
reject();
});
this.device.unregister();
}
return new Promise((res: Function, rej: Function) => {
resolve = res;
reject = rej;
});
}
public async makeOutboundCall(phoneNumber: string, eventId: string): Promise<void> {
const params = {
To: phoneNumber,
};
if (this.device) {
this.call = await this.device.connect({ params });
const callId = this.call.parameters.CallSid
this.call.on("accept", () => { this.integrationEventsHandler.outboundCallAcceptedHandler(callId) });
this.call.on("disconnect", () => { this.integrationEventsHandler.callHangupHandler(callId) });
this.call.on("cancel", () => { this.integrationEventsHandler.callRejectedHandler(callId) });
}
}
public async acceptCall(): Promise<void> {
if (this.call) {
this.call.accept();
}
}
public async rejectCall(): Promise<void> {
if (this.call) {
this.call.reject();
}
}
public async hangupCall(): Promise<void> {
if (this.call) {
this.call.disconnect();
}
}
private async getIdAndToken(): Promise<any> {
const headers: Headers = (new Headers()) as Headers;
headers.set('Accept', 'application/json');
const request: Request = new Request('https://twilio-voice-stream.com/token', {
method: 'GET',
headers: headers
}) as Request;
const idAndToken: Response = await fetch(request);
this.idAndToken = await idAndToken.json();
return this.idAndToken;
}
}
Verify your progress
After finishing these steps, use OJET server to start you application and sign in to your Fusion application. Open the media toolbar and make your agent available for calls by clicking on the Agent Availability button. To start an outbound call, open the contact from your Fusion application and click the phone number, which starts the outbound call.