3CXPhone API Attended Transfer

Status
Not open for further replies.

fluent

Joined
Jun 19, 2015
Messages
4
Reaction score
1
Hi All,

I know its me doing this wrong so hoping someone can give me some pointers.

On my app i'm developing, I can successfully blind transfer a call. However what i need to do is an attended transfer and give options if answered. Looking through the API i can see 3 methods i think i should be using:

Code:
CallStatus  BeginTransfer (string callId, string destination)
void  CancelTransfer (string callId)
void  CompleteTransfer (string callId)

So i tried the following:
Code:
CallStatus AttendedTransfer = callHandler.BeginTransfer( call_id, calldestination );
if( AttendedTransfer.State == CallState.Connected )
{
//Caller Answered Give options here like ComlpeteTransfer or CancelTransfer based on response
}

All it seems to do is put the original caller on hold, call the destination and it hangs up when answered leaving people on hold. Not quite sure where I'm going wrong...
 
Hello @fluent,

Your logic in general terms is correct, but please note that callHandler.BeginTransfer runs asynchronously, so if you check the State in the next line, probably the call will not be connected yet... So you need to consider that the call will take time to establish...

Kind regards.
 
Hi edossantos,

Thank you for the reply. Prior to the above code running I do have these conditions in place:

Code:
private void callHandler_OnCallStatusChanged( object sender, MyPhonePlugins.CallStatus callinfo )
{
if( callinfo.State == MyPhonePlugins.CallState.Connected )
{

So the call should already be established before these options are shown should it not?

Code:
CallStatus AttendedTransfer = callHandler.BeginTransfer( call_id, calldestination );
if( AttendedTransfer.State == CallState.Connected )
{
//Caller Answered Give options here like ComlpeteTransfer or CancelTransfer based on response
}
 
You have 2 different calls in that case. The first call is the call to the external party. The second call is the call to the internal extension to which you want to transfer the first call. So in your event handler "callHandler_OnCallStatusChanged" you need to check for which call id is the event for...

But your code:
Code:
if( AttendedTransfer.State == CallState.Connected )

...just after invoking BeginTransfer:
Code:
CallStatus AttendedTransfer = callHandler.BeginTransfer( call_id, calldestination );

Doesn't look right to me... Probably, you will want to invoke BeginTransfer, and do nothing else until you receive the notification of the event OnCallStatusChanged for the new CallID. So you should do it like this:
1) You invoke BeginTransfer and save the new call id in some class variable:
Code:
CallStatus AttendedTransfer = callHandler.BeginTransfer( call_id, calldestination );
secondCallId = AttendedTransfer.CallID;

(secondCallId should be a class private member)

2) When you receive the OnCallStatusChanged event you need to check if it's for the second call:
Code:
private void callHandler_OnCallStatusChanged( object sender, MyPhonePlugins.CallStatus callinfo )
{
if (callinfo.CallID == secondCallId)
{

Kind regards.
 
Hi EdosSantos,

Thanks again for the pointers. I think i have it in my head right now, based on what you are saying I've come up with the code I believe will work from what you said.

It can probably be done a lot better, but I'm thinking the following should work. Can you cast your eye over it please and see if you think it will?

Code:
private void callHandler_OnCallStatusChanged( object sender, MyPhonePlugins.CallStatus callinfo )
{
    int ThreadID = 0;
ReRun:

    //If the CallID is the first call (Inbound Caller)
    if( callinfo.CallID == Call_One )
    {
        //Running thread to check for commands
        new Thread( ( ) =>
        {
            //Run Thread In The Background
            Thread.CurrentThread.IsBackground = true;

            //Get And Store The Thread ID
            ThreadID = Thread.CurrentThread.ManagedThreadId;
           
            //Continous Loop Checking For Commands From Crm
            while( true )
            {
                //Kill Thread if call ended.
                if( callinfo.State == MyPhonePlugins.CallState.Ended ) { Thread.CurrentThread.Abort( ); }

                if( command.Equals( "hold_call" ) )
                {
                    callHandler.Hold( Call_One, true );
                }
                else if( command.Equals( "resume_call" ) )
                {
                    callHandler.Hold( Call_One, false );
                }
                else if( command.Equals( "end_call" ) )
                {
                    callHandler.DropCall( Call_One );
                }
                else if( command.Equals( "transfer_call" ) )
                {
                    //Blind Transfer
                    //callHandler.BlindTransfer( Call_One, calldestination );

                    //Attended Transfer
                    CallStatus AttendedTransfer =   callHandler.BeginTransfer( Call_One, calldestination );
                    Call_Two                    =   AttendedTransfer.CallID;
                }

                Thread.Sleep( 500 );
            }
        } ).Start( );
    }

    //If the CallID is the second (Transferred) call
    else if( callinfo.CallID == Call_Two )
    {
        //If it starts ringing (First stage it will do)
        if( callinfo.State == CallState.Dialing )
        {
            //Wait until the Call is connected
            do {
                Thread.Sleep( 500 );
            }while( callinfo.State != CallState.Connected );

            //TODO:
            //Enter a new thread with a while true loop getting commands from the Crm.
            //This way it'll sit here until we either end Call_One (Complete Transfer) or End Call_Two (Cancel Transfer) and Resume Call_One
            //End_Call one to complete transfer
            //End Call two to cancel transfer and Resume Call_One
        }
    }

    //When The First Call Is Answered The First Time Round
    else if( callinfo.State == MyPhonePlugins.CallState.Connected )
    {
        //Set the Call_One var
        Call_One    =   callinfo.CallID;

        //Now do the code for Call_One
        goto ReRun;
    }
}
 
The event "callHandler_OnCallStatusChanged" will be executed every time the call connected to the 3CXPhone for Windows client changes its status. You don't need to create threads to monitor the status in a loop... Actually, that will probably cause unpredictable behaviour as you will be processing every notification multiple times...
 
Status
Not open for further replies.

Latest Posts

Forum statistics

Threads
112,323
Messages
591,896
Members
165,474
Latest member
costionofrei