I want to share with you an application that is built with .NET that allows for checking your account balance via the telephone. This application uses telephony along with .NET to provide the necessary technologies to create an account balance inquiry system.
An Open Source telephony framework called Asterisk is used to provide this telephony or IP PBX functionality. Later I will go through an interactive demo so hold on as it’s going to get exciting. For those that have played with telephony you know how exciting it is to build a phone system and ring your first phone via software.
This application is not the typical Web Application or Report Application we are used to seeing at ToolBox, but I thought I would share something that pushes me out of my typical comfort level.
Before I dive into Asterisk here is a definition for PBX. PBX is short for private branch exchange. A PBX is a business phone system such as the one used at ToolBox and found in many companies. A PBX acts as the central switching system for phone calls within a business.
Key PBX Features
- VOIP
- Voicemail
- Mobility - Find Me aka call forwarding and Follow Me
- Conferencing
- Interactive Voice Response (IVR)
- Voicemail
- Mobility - Find Me aka call forwarding and Follow Me
- Conferencing
- Interactive Voice Response (IVR)
What is Asterisk?
Asterisk is an open source framework for building communications applications. Asterisk turns an ordinary computer into a communications server. Asterisk powers IP PBX systems, VoIP gateways, conference servers and other custom solutions. It is used by small businesses, large businesses, call centers, carriers and government agencies, worldwide. Asterisk is free and open source. To learn more go here. http://www.asterisk.org/get-started
What Is An IVR System?
IVR stands for Interactive Voice Response, a technology that automates routine customer service interactions by allowing callers to interact using touch tone digits or their voice. A basic example of an IVR application is an automated attendant or voice menu: callers are presented with a recorded menu and respond by selecting a digit or, in some cases, by entering an extension number. The automated attendant eliminates the need for a live operator to handle the call.
More complex applications include prescription refill for pharmacies, password reset, voice surveys, account balance inquiries, flight status checks, package tracking, pre-sales qualification questionnaires, etc. The key idea is to automate a routine, repetitive task that would otherwise require the time and effort of an employee. The savings potential gives IVR solutions a very rapid return on investment (ROI), as on server can potentially eliminate multiple live agents.
Asterisk comes with many PBX features out of the box such as the ability to configure VOIP, Voicemail, Mobility (Find Me, Follow Me), Conferencing and IVR. You can build basic Interactive Voice Response systems that would allow you to say call into a number and then have voice prompts that would to Press 1 for Sales, Press 2 for Sales, etc. For more complex functionality that will take an account id (i.e credit card number, telco account Id, etc.) and to then query a database for the account balance Asterisk provides the Asterisk Gateway Interface that allows you to build external applications in any language to create Interactive Voice Response functionality.
Account Balance IVR Application - An account balance inquiry application that uses .NET and Asterisk
In this sample a caller retrieves their account balance for their utility bill by:
1. Dialing a number
2. Hears a voice prompt to enter their account id followed by the hash key
3. Caller enters their account id followed by the hash key
4. Hears a voice prompt to enter their pin code for their account, followed by the hash key
5. Caller enters their pin code followed by the hash key
6. Hears a voice stating the balance is 45.23.
7. Hangup
2. Hears a voice prompt to enter their account id followed by the hash key
3. Caller enters their account id followed by the hash key
4. Hears a voice prompt to enter their pin code for their account, followed by the hash key
5. Caller enters their pin code followed by the hash key
6. Hears a voice stating the balance is 45.23.
7. Hangup
To see this application in action call:. Demo is down for now.
Example flow..this is not a real number assigned to my PBX so this sample will now work:
1. Dial 204-666-7932
2. Enter the account id 4531 followed by the hash key
3. Enter the pin code 1111 followed by the hash key
2. Enter the account id 4531 followed by the hash key
3. Enter the pin code 1111 followed by the hash key
If you enter an invalid entry you will hear 404, which I have used in place of voice prompts to save time.
4. You should hear your account balance and then a hangup.
This application is hosted was hosted on MS Azure with a CentOS based virtual machine that is running Asterisk with FreePBX. The AGI is hosted on a Windows Server that runs the .NET 4.5.1 Console Application below.
Asterisk Extension
To configure the phone number above (204...) I am using a VOIP provider called les.net with the Asterisk VOIP protocol called IAX2 which is similar to SIP only better.
Les.net provide a free DID's (phone number) with all accounts. The details to configure Asterisk Trunk setup and AGI configuration would be quite lengthily to write in this post (more on that later). If you are familiar with Asterisk or do venture to learn Asterisk you will find below the Asterisk AGI extension that is located in the asterisk folder in etc. /etc/asterisk/extentions_custom.conf.
[myaccount]
exten => 100,1,Agi(agi://vsweb.cloudapp.net/acccheck)
exten => 100,1,Agi(agi://vsweb.cloudapp.net/acccheck)
See below for the different the ways to get started with Asterisk.
.NET AGI Application
The AGI application is the main application to provide the Account Balance IVR Application functionality. Asterisk connects to the remote Console Application AGI (located on the Windows Server host) via FastAGI.
This application is using Entity Framework Code first and a Sql Azure database to store the account balances.
The data model for account balance:
CREATE TABLE [dbo].[CustomerAccount]
(
[CustomerAccountId] INT NOT NULL PRIMARY KEY IDENTITY,
[FirstName] NVARCHAR(64) NULL,
[LastName] NVARCHAR(64) NULL,
[PhoneNumber] NVARCHAR(16) NOT NULL,
[Password] NVARCHAR(64) NOT NULL,
[Balance] DECIMAL(18, 2) NOT NULL,
[IsActive] BIT NOT NULL DEFAULT 1,
[AccountIdentifier] NVARCHAR(24) NOT NULL
)
(
[CustomerAccountId] INT NOT NULL PRIMARY KEY IDENTITY,
[FirstName] NVARCHAR(64) NULL,
[LastName] NVARCHAR(64) NULL,
[PhoneNumber] NVARCHAR(16) NOT NULL,
[Password] NVARCHAR(64) NOT NULL,
[Balance] DECIMAL(18, 2) NOT NULL,
[IsActive] BIT NOT NULL DEFAULT 1,
[AccountIdentifier] NVARCHAR(24) NOT NULL
)
Console Application:
class Program
{
static void Main(string[] args)
{
//var port = agiServer.BindPort;
var mapStrategy = new GeneralMappingStrategy(
new List<ScriptMapping>()
{
new ScriptMapping() {
ScriptName = "acccheck",
ScriptClass = "MyAccount.Agi.AccCheckAGI"
}
});
{
static void Main(string[] args)
{
//var port = agiServer.BindPort;
var mapStrategy = new GeneralMappingStrategy(
new List<ScriptMapping>()
{
new ScriptMapping() {
ScriptName = "acccheck",
ScriptClass = "MyAccount.Agi.AccCheckAGI"
}
});
AsteriskFastAGI agiServer = new AsteriskFastAGI(mapStrategy);
agiServer.PoolSize = 200;
Console.WriteLine("Press ctrl-c to exit.");
agiServer.Start();
}
}
AccCheckAGI
class AccCheckAGI : AGIScript
{
public override void Service(AGIRequest param1, AGIChannel param2)
{
// Answer the call, this is important as otherwise
// we wont be able to perform certain action on the
// call flow.
Answer();
{
public override void Service(AGIRequest param1, AGIChannel param2)
{
// Answer the call, this is important as otherwise
// we wont be able to perform certain action on the
// call flow.
Answer();
// Get a numeric sequence from the caller, we prompt them
// to enter the number by playing an audio file asking
// them to do so.
// We're going to:
// # Play the file called "acccheck-enter_your_acc_number"
// # wait a fixed period of 20 seconds (20000ms) for them to
// enter the digits.
var accountId = GetData("custom/acccheck-enter_your_acc_number", 20000);
// to enter the number by playing an audio file asking
// them to do so.
// We're going to:
// # Play the file called "acccheck-enter_your_acc_number"
// # wait a fixed period of 20 seconds (20000ms) for them to
// enter the digits.
var accountId = GetData("custom/acccheck-enter_your_acc_number", 20000);
if (string.IsNullOrEmpty(accountId) )
{
SayNumber("404");
// TODO put in a loop asking for account id again
Hangup();
}
{
SayNumber("404");
// TODO put in a loop asking for account id again
Hangup();
}
// Get account id and verify by checking if not null
var accountByAccountId = GetAccountByAccountId(accountId);
var accountByAccountId = GetAccountByAccountId(accountId);
if (accountByAccountId != null)
{
var passcode = GetData("custom/acccheck-enter_your_pincode", 20000);
{
var passcode = GetData("custom/acccheck-enter_your_pincode", 20000);
// Verify pincode/password
if (!string.IsNullOrEmpty(passcode) && accountByAccountId.Password == passcode)
{
var balance = accountByAccountId.Balance.ToString();
var dollars = balance.Split(new char[] { '.' })[0];
var cents = balance.Split(new char[] { '.' })[1];
if (!string.IsNullOrEmpty(passcode) && accountByAccountId.Password == passcode)
{
var balance = accountByAccountId.Balance.ToString();
var dollars = balance.Split(new char[] { '.' })[0];
var cents = balance.Split(new char[] { '.' })[1];
StreamFile("custom/acccheck-your_balance_is");
SayNumber(dollars);
StreamFile("custom/acccheck-dollars");
StreamFile("custom/acccheck-and");
StreamFile("custom/acccheck-dollars");
StreamFile("custom/acccheck-and");
SayNumber(cents);
StreamFile("custom/acccheck-cents");
}
else // TODO stream file pass code does not match
{
SayNumber("404");
Hangup();
}
}
else // TODO stream file pass code does not match
{
SayNumber("404");
Hangup();
}
StreamFile("custom/acccheck-cents");
}
else // TODO stream file pass code does not match
{
SayNumber("404");
Hangup();
}
}
else // TODO stream file pass code does not match
{
SayNumber("404");
Hangup();
}
Hangup();
}
}
public static CustomerAccount GetAccountByAccountId(string accountId)
{
ICustomerAccountRepository repo = new CustomerAccountRepository();
{
ICustomerAccountRepository repo = new CustomerAccountRepository();
var accountByAccountId = repo.GetCustomerAccounts().FirstOrDefault(ca => ca.AccountIdentifier == accountId);
return accountByAccountId ?? null;
}
}
return accountByAccountId ?? null;
}
}
Getting started with Asterisk
The quickest way to get up and running with Asterisk is to download an ISO from FreePBX fromhttp://www.freepbx.org/freepbx-distro and then install this in a VM using VirtualBox or on some commodity hardware. Alternatively you can use PBX in a flash to install Asterisk with FreePBX on an existing Centos install by going through this article: http://nerdvittles.com/?p=10079
IVR application is that we use for to reply the user about the product......
ReplyDeletetwilio plugin
Empowers an editable portrayal for a post sort to show at the highest point of the post sort file page.
ReplyDeletepost plugins
Hi,
ReplyDeleteThanks a lot for sharing the great piece of information with us. For more information about to the IVR application try www.Telcob.com now.
Thanks again! Keep it works and share it.
Hi,
ReplyDeleteThanks for sharing excellent info on DA and PA account. Please keep sharing with us.
Techvns