Twilio StatusCallBack Incorrect - twilio

I'm developing a vb net application using twilio api.
This is my code:
Twilio.TwilioClient.Init(AccountSid, AuthToken)
Dim call_to As PhoneNumber = New PhoneNumber("...")
Dim call_from As PhoneNumber = New PhoneNumber("...")
Dim call_option As CreateCallOptions = New CreateCallOptions(call_to, call_from)
call_option.Method = "Get"
call_option.Timeout = 25
call_option.Url = New Uri(ws_url & "/GET_CALL_XML" & ws_parameter)
call_option.StatusCallback = New Uri(ws_url & "/GET_CALL_FEEDBACK" & ws_parameter)
call_option.FallbackUrl = New Uri(ws_url & "/GET_CALL_ERROR" & ws_parameter)
call_option.StatusCallbackEvent.Add("answered")
call_option.StatusCallbackEvent.Add("completed")
Dim call_ As CallResource = CallResource.Create(call_option)
The call is successfully performed.
Now the problem is:
if the user answer the call, i receive the StatusCallBack with "callstatus"="in-progress"
if the user refuse the call, i receive the StatusCallBack with "callstatus"="in-progress" equally
How can i know if the user really answer the call?
Thank you

Twilio developer evangelist here.
If the user actually answers the call, then you will get a webhook to the Url that you set, in your example, the one with the path /GET_CALL_XML.
If the user refuses the call then you will not receive a webhook to that URL.

Related

Using Twilio I want to add a third party into a call using an iOS Device

I'm using Twilio in an iOS app using the TwilioClient library in Swift. The app I've built can connect from user A's device to user B's device or to an outside phone number. This is working fine. What I need to do now is to bring a third party into the call, either a third iOS device (user C) or an additional outside line.
I understand that I will need to use the Conference capability to do this, but I'm not finding examples of how to do this with the TwilioClient library for iOS. Currently my TwiML server is the Python quick start server (which has been fine for two-party calls).
What I'm unclear on is:
Using the TwilioClient device.connect(...) call how do I connect User A & User B into a conference room in the first place?
Once I have A & B in the conference call, how, using TwilioClient, do I bring in party C? I've connected with device.connect(...) which hides all of the REST API code from me.
Since I don't know at the beginning of the call if I'll need the third party is there a way to start off with a direct connect then add all parties to a conference call once we decide we need to add User C?
Thanks,
KeithB
Below is an answer on how to solve question 1 in my OP.
When you use the iOS call device.connect(...) it calls the TwiML server /call URL (in my case a Python server), which returns "TwiML" (Twilio Markup Language). The basic pattern is to call a destination directly. To do this the TwiML server uses the passed parameters To: and From: and constructs a TwiML "Dial" string that is returned. This causes Twilio to dial the To: number using the From: number as a callerid.
In order to have both parties put into a conference it is a two step process. First you modify your TwiML code to tell Twilio to put the Caller into the conference room. Second, you use the REST API at the TwiML server to have Twilio call out to the To: caller and put them in the conference room.
This requires several changes. First you must pass in the conference room name from the device.connect(...) call in your iOS app.
connection = device?.connect(["To": "+1234567890", "Conference": "MyConference"], delegate: delegate)
Then you have to modify the /call route in the Python server to return TwiML for a conference room AND make the outbound REST call.
from twilio.rest import TwilioRestClient
#app.route('/call', methods=['GET', 'POST'])
def call():
account_sid = os.environ.get("ACCOUNT_SID", ACCOUNT_SID)
auth_token = os.environ.get("AUTH_TOKEN", AUTH_TOKEN)
from_value = request.values.get('From')
to = request.values.get('To')
conf_room = request.values.get('Conference')
callsid_value = request.values.get('CallSid')
# This section creates the TwiML code that will be returned
# This causes the caller to be placed in a conference room
# Note: endConferenceOnExit=true ends conference when call originator exits
conf_response = twilio.twiml.Response()
conf_response.dial(callerId=from_value).conference(conf_room, endConferenceOnExit="true")
# This section makes the REST call out to the To: number
client = TwilioRestClient(account_sid, auth_token)
call = client.calls.create(url="www.YourPythonServer" + "/getconf?Conference=" + conf_room,
to=to,
from_=from_value,
method="POST",
status_callback="www.YourPythonServer" + "/callback?init_callsid=" + callsid_value,
status_callback_method="POST",
status_events=["completed"])
return str(conf_response)
When we call client.calls.create(...) it causes Twilio to then call the URL "www.yourpythonserver/getconf..." to get the TwiML it uses to know how to execute the outgoing call.
#app.route('/getconf', methods=['GET', 'POST'])
def getconf():
resp = twilio.twiml.Response()
conf_room = request.values.get('Conference')
resp.dial().conference(conf_room)
return str(resp)
You'll notice up above we also have a parameter "status_callback". This is used to let us know the To: caller's status. In this case we request 'complete' but we may also get "no-answer", "busy" & "failed". If we don't do this and the call is unsuccessful then the caller will just sit in an empty conference room w/o knowing the outgoing call was unsuccessful. This requires yet another route in our Python server.
#app.route('/callback', methods=['GET', 'POST'])
def callback():
account_sid = os.environ.get("ACCOUNT_SID", ACCOUNT_SID)
auth_token = os.environ.get("AUTH_TOKEN", AUTH_TOKEN)
init_callsid = request.values.get('init_callsid')
callback_status = request.values.get('CallStatus')
# Check to see what status was passed in. Note that "completed" is
# passed after a successful call and the To: party hangs up or drops.
# You can implement any behavior you want here, but this code
# simply hangs up the originating caller. This might not be appropriate
# if there are still other parties in the call.
if callback_status == 'completed' or callback_status == "no-answer" or callback_status == 'busy' or callback_status == 'failed':
client = TwilioRestClient(account_sid, auth_token)
call = client.calls.hangup(init_callsid)
return str("")
The following is an answer to question #2 in my OP.
After step #1 we have a conference room named 'MyConference' with parties 1 & 2 (From & To). Now we would like to add a third party to the conference and trigger that action from our iPhone.
What we need to do is create a new Route in our python server and call that route directly from our iOS code.
The code in the python server will look something like this:
#app.route('/add_to_conference', methods=['GET', 'POST'])
def add_to_conference():
account_sid = os.environ.get("ACCOUNT_SID", ACCOUNT_SID)
auth_token = os.environ.get("AUTH_TOKEN", AUTH_TOKEN)
from_value = request.values.get('From')
to = request.values.get('To')
conf_room = request.values.get('Conference')
client = TwilioRestClient(account_sid, auth_token)
call = client.calls.create(url="www.YourPythonServer" + "/getconf?Conference=" + conf_room,
to=to,
from_=from_value,
method="POST",
status_callback="www.YourPythonServer" + "/callback?Conference=" + conf_room,
status_callback_method="POST",
if_machine = "Hangup",
status_events=["completed"]
)
return str("True")
The code above will make a REST call that will cause Twilio to make an outgoing call to the "To" phone number and place the party in the conference room. You will notice that like the code in step #1 we employ the '/getconf' route. The Twilio server will call this URL to get the TwiML that defines how it should process the call.
#app.route('/getconf', methods=['GET', 'POST'])
def getconf():
resp = twilio.twiml.Response()
conf_room = request.values.get('Conference')
resp.dial().conference(conf_room)
return str(resp)
We also defined a '/callback' route that is called upon call completion (hangup) or failure of caller #2 or #3. Since answering Step 1 I have enhanced the way this callback works. My goal is that when all 'To' parties hang up, leaving only the original caller in the conference room, the call should hangup for the original caller. Otherwise, the From caller will just be left in the conference room listening to music. This is not what is expected.
Therefore I implemented the following callback code:
#app.route('/callback', methods=['GET', 'POST'])
def callback():
account_sid = os.environ.get("ACCOUNT_SID", ACCOUNT_SID)
auth_token = os.environ.get("AUTH_TOKEN", AUTH_TOKEN)
callback_status = request.values.get('CallStatus')
conf_room = request.values.get('Conference')
client = TwilioRestClient(account_sid, auth_token)
conferences = client.conferences.list(friendly_name=conf_room, status = "in-progress")
if (len(conferences) > 0):
conference = conferences[0]
participants = client.participants(conference.sid).list()
if len(participants) == 1:
participant = participants[0]
call = client.calls.hangup(participant.call_sid)
return str("200")
When called, this code grabs the conference room by name, then grabs the list of participants in the conference room. If there is only one participant remaining then it hangs up on the last participant.
The final step is making the call from your iOS code. This is quite simple, you do not need to use the Twilio client libraries for this call, you simply make an http GET request passing in From, To and the Conference room name as parameters. Like this:
http:/yourpythonserver.com/add_to_conference?To=1234567890&From=0987654321&Conference=MyConference
This will activate the entire process and party #3 will be placed in the conference room!

Twilio Lookup API is not returning value in java

As part of our project we need to call Twilio to get E164 format of the Phone Number. In order to do that I followed the below steps to achieve. If the phone number is valid then the below step is working but if the phone number is not valid and we are passing the same to Twillo then it is not returning anything back and halt the process.
I know that the below mention number is not valid but that doesn't mean when I am trying to lookup with invalid number it should not return any response. It should return at least an error but actually it is not which is making me more confused. I am trying with IBM websphere server.
Can some one please help me to fix this issue or is there any way where I can set request time out for twilio lookup so that it will allow other process to continue if any failures in twilio lookup. Also, correct me if I did any mistake in my coding for twilio lookup.
Sample URL "https://lookups.twilio.com/v1/PhoneNumbers/phoneNumber"
Steps Followed:
LookupsClient client = new LookupsClient(ACCOUNT_SID, AUTH_TOKEN);
client.setHttpClient(getProxyClient());
// Twilio Lookup with country code
String twilioURL = createURL(phoneNumber, countryCd);
String twilioE164Number = getTwilioNumber(client, twilioURL);
//Twilio Lookup without country code
StringBuilder appender = new StringBuilder();
appender.append(TWILIO_URL);
appender.append(PLUS);
appender.append(phoneNumber);
String twilioE164Number = getTwilioNumber(client, appender.toString());
//Create lookup URL
private String createURL(String phoneNumber, String countryCode){
StringBuilder appender = new StringBuilder();
appender.append(phoneNumber);
appender.append(QUERY_PARAM);
appender.append(countryCode);
return TWILIO_URL+appender.toString();
}
//Get Twilio E164 Number
private String getTwilioNumber(LookupsClient client,String url){
TwilioRestResponse response;
String twilioResult = "";
try {
response = client.get(url);
String str = response.getResponseText();
//Code for parsing the JSON response and set the twilioResult.
} catch (TwilioRestException e) {
logger.error("TwilioRestException while calling twilio "+e);
}catch(Exception ex){
logger.error("Error in twilio Calling "+ex);
}
return twilioResult;
}
//Get proxy client to set.
private HttpClient getProxyClient() {
HttpHost proxy = new HttpHost(PROXY_HOST, PROXY_PORT);
//new DefaultHttpClient().getParams().setParameter(arg0, arg1)
DefaultProxyRoutePlanner routePlanner = new DefaultProxyRoutePlanner(proxy);
CredentialsProvider credentialsProvider = new BasicCredentialsProvider();
credentialsProvider.setCredentials(new AuthScope(AuthScope.ANY_HOST, AuthScope.ANY_PORT),new UsernamePasswordCredentials(ACCOUNT_SID, AUTH_TOKEN));
CloseableHttpClient httpClient = HttpClients.custom()
.setRoutePlanner(routePlanner)
.setDefaultCredentialsProvider(credentialsProvider)
.build();
return httpClient;
}
v6.3.0 of twilio-java has a LookupsClient has a .getPhoneNumber() method that allows you to pass a phone number instead of requiring that you construct the URL from scratch. The whole point of using LookupsClient instead of a vanilla TwilioClient is that the class does the bulk of the work for you.
Have you tried client.getPhoneNumber(phoneNumber) in this case? This page also demonstrates the structure of the response that you should receive when using that particular endpoint. The E164-formatted phone number should be the phone_number property in the response, although I use twilio-python and I don't know how the Java library exposes response objects for your consumption.
If you aren't getting a response at all, you might want to try making the same request without your proxy configuration to make sure the proxy isn't causing the problem. As for your timeout question, twilio-java's requests are processed synchronously, one way to get around that would be to wrap the request in an asynchronous method call.
Hope some of this helps you diagnose your issue!

twilio javascript client set from number , also how I can get the call sid after connect?

twilio javascript client set from number , Also how I can get the call sid after connect?
I tried to set the from Number in the call options like the next lines before connect and still the same issue in the javascript
$(document).ready(function () {
Twilio.Device.setup(token);
var connection = null;
$("#call").click(function () {
var params = { "Phone": $('#Phone').val(), "from":$('#Phone').val() };
connection = Twilio.Device.connect(params);
return false;
});
});
-- and inside the server side code vbnet when I am generating the token I added the next code but this doesn't solve the from number issue
Dim options As New CallOptions()
options.Record = True
options.From = model.FromNumber
Dim cap = New TwilioCapability(_settings.AccountSID, _settings.AuthToken)
cap.AllowClientOutgoing(_settings.ClientCallApplicationSID, options)
dim token = cap.GenerateToken()
Twilio evangelist here.
The params collection that you pass into the connect function is just a dictionary of key/value pairs. Those key/values simply get passed as parameters to the Voice URL that Twilio requests when Client makes its connection to Twilio, and you can use those parameters to dynamically generate some TwiML markup. Twilio does not do anything with them.
For example, if this is a PHP application, in the Voice URL you could do something like:
<Response>
<Dial>$_REQUEST['From']</Dial>
</Response>
One note of caution, Twilio already adds a parameter called from (which in the case of Client will be the client identifier set when you made your capability token) to the parameters sent to the Voice URL, so you might want to choose a different key name for your dictionary entry. I normally use a name like target for the key that holds the number that I want to dial.
Hope that helps.
To get the call sid, you can get it in connect event.
Please note that I am using Twilio JS v1.9.7
device.on('connect', function (conn) {
log('Successfully established call!');
//Get the CallSid for this call
callUUID = conn.outboundConnectionId;
console.log('CallSid: ' + callUUID);
});

Monitoring a mailbox for new email message using EWS Managed API

I'm working on a task which I never worked in earlier.
Task: Monitor a specific mailbox inbox on exchange server 2007. Iterate through all email messages(Just email messages), do some processing and move to a specific folder under same mailbox.
Work I did
// Create the binding
ExchangeService service = new ExchangeService(ExchangeVersion.Exchange2007_SP1);
//service.Credentials = new WebCredentials("mailbox", "password", "mailbox#something.com");
service.Credentials = new NetworkCredential(ConfigurationManager.AppSettings["ExchangeUsername"].ToString(), ConfigurationManager.AppSettings["ExchangePassword"].ToString(), "something/domain");
// Set the url.
//service.AutodiscoverUrl("mailbox#something.com");
service.Url = new Uri(ServiceUrl);
ItemView view = new ItemView(10);
view.Traversal = ItemTraversal.Shallow;
view.PropertySet = new PropertySet(BasePropertySet.IdOnly);
List<SearchFilter> searchFilterCollection = new List<SearchFilter>();
//searchFilterCollection.Add(new SearchFilter.ContainsSubstring(ItemSchema.ItemClass, "MessageType"));
searchFilterCollection.Add(new SearchFilter.ContainsSubstring(ItemSchema.Subject, "test to be deleted"));
SearchFilter searchFilter = new SearchFilter.SearchFilterCollection(LogicalOperator.Or, searchFilterCollection.ToArray());
FindItemsResults<Item> results = service.FindItems(WellKnownFolderName.Inbox, view);
For some reason i always get results.items.count = 9, but there is only one EmailMessage in Mailbox#something.com. Am i doing any thing wrong in searching. If inbox had 5 emails, then i should get count as 5 and loop through the 5 emails. Is there a way to query just the email messages? Any help is appreciated. Thank you.
I answered my own questiona a while ago, but forgot to update here. So when i said count was not matching, it was monitoring mailbox of impersonating account. Coincidentally, the impersonating account has a mailbox.

find signature is required or not using shipment API (USPS, UPS, DHL, FeDex)

I am integrating the Carrier (USPS, UPS, DHL, FeDex) API with my application.
For that i need to find different statuses for that shipment like is it delivered or not, which is getting me properly.
Similarly, i need to check whether the shipment required the signature or not?
How do i came to know this using the different API?
Regards,
Salil Gaikwad
Not all APIs support the same functionality. All will tell you the current status and some will provide the shipper/recipient information but I don't believe any will tell you if it was sent signature required.
E.g. for FedEx if you want to know about parcel's tracking events (delivered or not, any problems, delivery time and many other info) use this service endpoint - https://ws.fedex.com:443/web-services/track. The request to FedEx will be look like this (C# sample):
TrackRequest request = new TrackRequest();
request.WebAuthenticationDetail = new WebAuthenticationDetail();
request.WebAuthenticationDetail.UserCredential = new WebAuthenticationCredential()
{
Key = "ApiKey",
Password = "PasswordKey"
};
request.ClientDetail = new ClientDetail
{
AccountNumber = "...",
MeterNumber = "..."
};
request.TransactionDetail = new TransactionDetail();
request.PackageIdentifier = new TrackPackageIdentifier();
request.PackageIdentifier.Value = "parcel tracking number";
request.PackageIdentifier.Type = TrackIdentifierType.TRACKING_NUMBER_OR_DOORTAG;
request.IncludeDetailedScans = true;
request.IncludeDetailedScansSpecified = true;
request.Version = new VersionId();
When you receive from FedEx - TrackReply, you should check TrackDetails array. There will be tracking info. As for other carriers, the common idea is the same. Almost every carrier use tracking number.

Resources