Getting Started with IVR
Requirements: IPWorks VoIP
Introduction
The IVR (Interactive Voice Response) component provides access to simple and intuitive operations designed to implement an automated IVR menu. This guide will cover the basics of activating the component, handling incoming calls, user input, and more.
Contents
- Registration
- Handle Incoming Calls
- Security
- Automated Responses
- Handling User Input
- Call Termination
Registration
To begin, the first step is activating, or registering, the component. The Server, Port, User, and Password properties must be set to the appropriate values to register with your SIP server/provider. After these values are set, call the Activate method. If the component has successfully activated/registered, the Activated event will fire and the Active property will be set to true. The component will now be able to make and receive phone calls. For example:
ivr1.OnActivated += (o, e) => {
Console.WriteLine("Activation Successful");
};
ivr1.User = "sip_user";
ivr1.Password = "sip_password";
ivr1.Server = "sip_server";
ivr1.Port = 5060; // Default, 5061 is typical for SSL/TLS
ivr1.Activate();
Additionally, it's important to note that the registration of a SIP client will expire if not refreshed. The expiration time is negotiated with the server when registering. By default, the component will attempt to negotiate a value of 60 seconds. This value can be changed via the RegistrationInterval config. Note this is merely a suggestion to the server, and the server can change this accordingly. If the server does change this, after registration is complete, the NegotiatedRegistrationInterval config will be updated. Afterwards, the component will attempt to refresh the registration every NegotiatedRegistrationInterval seconds.
Clients may wish to refresh the registration prior to this interval to ensure the registration does not expire. To do so, the RefreshInterval config can be set after successful registration. If set, this value should be less than or equal to NegotiatedRegistrationInterval. For example, to refresh the registration 5 seconds prior to it's expiration, you can do:
component.Config("RegistrationInterval=120");
component.Activate();
int lifetime = component.Config("NegotiatedRegistrationInterval");
// Refresh the registration 5 seconds prior to expiration
component.Config("RefreshInterval=" + (lifetime - 5));
To prevent the registration from expiring, the component will refresh the registration within the DoEvents method, when needed. To ensure this occurs, we recommend calling DoEvents frequently. In a form-based application, we recommend doing so within a timer. For example, this could look something like:
private void timer1_Tick(object sender, EventArgs e)
{
ivr1.DoEvents();
}
private System.Windows.Forms.Timer timer1;
timer1.Interval = 1000;
timer1.Tick += new System.EventHandler(this.timer1_Tick);
timer1.Enabled = true;
Note that in console applications, you must call DoEvents in a loop to provide accurate message processing, in addition to this case.
Handle Incoming Calls
After successful activation, incoming calls will be detected, and the IncomingCall event will fire for each call. Within this event, the Answer and Decline methods can be used to handle these calls. For example:
ivr.OnIncomingCall += (sender, e) => {
ivr.Answer(e.CallId);
};
Security
By default, the component operates in plaintext for both SIP signaling and RTP (audio) communication. To enable completely secure communication using the component, both SIPS (Secure SIP) and SRTP (Secure RTP) must be enabled.
Enable SIPS
To enable SIPS (Secure SIP, or SIP over SSL/TLS) the SIPTransportProtocol property must be set to 2 (TLS). The Port property will typically need to be set to 5061 (this may vary). Additionally, the SSLServerAuthentication event must be handled, allowing users to check the server identity and other security attributes related to server authentication. Once this is complete, the component can then be activated. All subsequent SIP signaling will now be secured. For example:
ivr1.OnSSLServerAuthentication += (o, e) => {
if (!e.Accept) {
if (e.CertSubject == "SIPS_SAMPLE_SUBJECT" && e.CertIssuer == "SIPS_CERT_ISSUER") {
e.Accept = true;
}
}
};
// Enable SIPS
ivr1.SIPTransportProtocol = IvrSIPTransportProtocols.tpTLS;
ivr1.User = "sip_user";
ivr1.Password = "sip_password";
ivr1.Server = "sip_server";
ivr1.Port = 5061; // 5061 is typical for SSL/TLS
ivr1.Activate();
Information related to the SSL/TLS handshake will be available within the SSLStatus event with the prefix [SIP TLS].
Enable SRTP
While the above process enables secure SIP signaling, this does not secure RTP (audio) communication. The RTPSecurityMode property can be used to specify the security mode that will be used when transmitting RTP packets. By default, this property is 0 (None), and RTP packets will remain unencrypted during communication with the remote party.
To ensure the audio data is encrypted and SRTP is enabled, the RTPSecurityMode property must be set to either of the following modes: 1 (SDES), or 2 (DTLS-SRTP). The selected mode will be used to securely derive a key used to encrypt and decrypt RTP packets, enabling secure audio communication with the remote party. The appropriate mode to use may depend on the service provider and configuration of a particular user. For example:
ivr1.OnSSLServerAuthentication += (o, e) => {
if (!e.Accept) {
if (e.CertSubject == "SIPS_SAMPLE_SUBJECT" && e.CertIssuer == "SIPS_CERT_ISSUER") {
e.Accept = true;
}
}
};
ivr1.RTPSecurityMode = IvrRTPSecurityModes.etSDES; // Enable SRTP (SDES)
ivr1.RTPSecurityMode = IvrRTPSecurityModes.etDTLS; // Enable SRTP (DTLS-SRTP)
ivr1.SIPTransportProtocol = IvrSIPTransportProtocols.tpTLS;
ivr1.User = "sip_user";
ivr1.Password = "sip_password";
ivr1.Server = "sip_server";
ivr1.Port = 5061; // 5061 is typical for SSL/TLS
ivr1.Activate();
ivr1.Dial("123456789", "", true);
Note it is highly recommended that the SIPTransportProtocol is set to 2 (TLS) when enabling SRTP. Additionally, if SRTP is enabled, the remote party must support the selected mode, otherwise no call will be established.
Automated Responses
Throughout the menu, there are various ways to prompt a caller. For example, you may want to play an initial message to an answered call. Once the call has been answered, the CallReady event will fire, where you can use either the PlayText, PlayFile, or PlayBytes methods to do so. For example:
ivr1.OnCallReady += (o, e) => {
ivr1.PlayText(e.CallId, "Please press 1 to be transferred to sales. Press 2 to be transferred to support. Press 3 to hear the options again.");
};
Only audio data with a sampling rate of 8 kHz and a bit depth of 16 bits per sample can be played (PCM 8 kHz 16-bit format). Note that these methods are non-blocking. The component can play audio to multiple calls at once.
Once the audio has finished playing to a particular call, the Played event will fire, with the call ID as a parameter. Please refer to the method and event descriptions for further details on the expected behavior when using the PlayBytes method and Played event.
Handle User Input
A main focus of an IVR menu revolves around handling user input. The component keeps track of the touch-tone inputs of a caller in the call's "UserInput" field. Additionally, the Digit event will fire whenever user input is detected. The event will contain the digit pressed, and the associated call ID. The component can detect digits 0-9, *, and # tones. Based on current and previous inputs, you can implement various menu options, from transferring calls to certain extensions, checking a user's account status, placing users on hold, etc. For example:
ivr1.OnDigit += (o, e) => {
if (e.Digit.Equals("1")) {
ivr1.Transfer(e.CallId, "Sales Number");
} else if (e.Digit.Equals("2")) {
ivr1.Transfer(e.CallId, "Support Number");
} else if (e.Digit.Equals("3")) {
ivr1.PlayText(e.CallId, "Please press 1 to be transferred to sales. Press 2 to be transferred to support. Press 3 to hear the options again.");
} else {
// Unhandled input
}
};
Call Termination
Ongoing calls are terminated by passing the CallId to the Hangup method, or by calling HangupAll, which will terminate all ongoing calls. When a call has ended (by either party), the CallTerminated event will fire.
We appreciate your feedback. If you have any questions, comments, or suggestions about this article please contact our support team at support@nsoftware.com.