I want to know the current callers(client) Phone Number and then be able to verify it from my HubSpot CRM to see which language my client speaks. Then Enqueue the call to the agent that speaks the language or give the Caller an option to choose the preferred language.
Anyhoo
Right now my goal is to just get the number of the caller(client).
exports.handler = function(context, event, callback) {
console.log(event);
//const request = require('request');
//const client = require('twilio');
const res = new Twilio.Response();
res.appendHeader('Access-Control-Allow-Origin', '*');
res.appendHeader('Access-Control-Allow-Methods', 'OPTIONS POST');
res.appendHeader('Content-Type', 'application/json');
res.appendHeader('Access-Control-Allow-Headers', 'Content-Type');
const fetch = require("node-fetch");
var phoneNumber = event.From; //|| [ "+63XXXXXXXXXX" ];
const apiUrl = "https://myapiurl.com/contact-details.php?number="+phoneNumber;
fetch(apiUrl,{
method: 'GET',
headers: { 'Content-Type': 'application/x-www-form-urlencoded'}
})
.then( response =>{
return response.json();
})
.then(json=>{
console.log(json);
res.setBody(json);
callback(null,res);
})
.catch(error=>{
console.log(error);
callback();
});
};
Also let me know if there is a better way to do it.
Twilio developer evangelist here.
Your code shows you getting event.From. This is the number of the person calling, so you have already done it!
Related
I'm following the docs in zapier regarding the callbackUrl https://platform.zapier.com/cli_docs/docs#zgeneratecallbackurl however cannot seem to get the performResume step to be run. The zap I'm creating based on this integration also does not seem to wait for the callbackUrl to be hit.
const createScreenshot = (z, bundle) => {
const callbackUrl = z.generateCallbackUrl();
const promise = z.request({
url: 'https://myapi.com/v1/render',
method: 'POST',
params: {},
headers: {
'Content-Type': 'application/json',
Accept: 'application/json',
},
body: {
...bundle.inputData,
webhook_url: callbackUrl
},
removeMissingValuesFrom: {},
});
z.console.log("Returning from perform / createScreenshot");
return promise.then((response) => ({ ...response.data, waiting_for: "performResume" }));
const onScreenshotFinished = (z, bundle) => {
z.console.log("In performResume / onScreenshotFinished", bundle.cleanedRequest);
const responseBody = bundle.cleanedRequest;
let screenshotUrl;
if (responseBody.event === "render.succeeded") {
z.console.log("render was processed successfully", responseBody);
screenshotUrl = responseBody.result.renderUrl;
return { screenshotUrl, ...responseBody };
}
z.console.log("render was not processed", responseBody);
throw z.errors.Error("Screenshot was not successful");
}
module.exports = {
operation: {
perform: createScreenshot,
performResume: onScreenshotFinished,
...
}
}
We talked through this question (and its solution) on GitHub (zapier/zapier-platform#398), but to summarize for SO readers:
When setting up a resumable Zap, the editor uses the sample to populate the data in the callback. No actual waiting happens during the setup process. Once the zap is live, it works like normal.
So, to implement:
perform should return sample data that matches the data the "resume" webhook sends
performSubscribe can read that data and operate normally
See the GH issue for more info.
Is it possible to programmatically register multiple webhook URLs for a single Twilio number? (When we receive an inbound SMS we would like multiple webhooks to be called with that data)
The docs for "update an incomingPhoneNumber resource" suggest that you can optionally set the smsUrl, but it's not clear how you would set multiple webhook URLs for a single number.
Not through the Twilio console options. You can write a Twilio Function that can fork out multiple outbound webhooks such as below, and then you just point the Twilio console to this Twilio Function.
const axios = require('axios');
const qs = require('querystring');
exports.handler = function(context, event, callback) {
let twiml = new Twilio.twiml.MessagingResponse();
let {
ApiVersion,
SmsSid,
SmsStatus,
SmsMessageSid,
NumSegments,
ToState,
From,
MessageSid,
AccountSid,
ToCity,
FromCountry,
ToZip,
FromCity,
To,
FromZip,
ToCountry,
Body,
NumMedia,
FromState
} = event;
let requestBody = {
ApiVersion,
SmsSid,
SmsStatus,
SmsMessageSid,
NumSegments,
ToState,
From,
MessageSid,
AccountSid,
ToCity,
FromCountry,
ToZip,
FromCity,
To,
FromZip,
ToCountry,
Body,
NumMedia,
FromState
};
let url1 = "https://example.com/1";
let url2 = "https://example.com/2";
const config = {
headers: {
'Content-Type': 'application/x-www-form-urlencoded'
}
};
Promise.all([
axios.post(url1, qs.stringify(requestBody), config),
axios.post(url2, qs.stringify(requestBody), config)
]).then(result => {
callback(null, twiml);
}).catch(err => {
console.log(err);
callback(err);
});
};
I am trying to develop a simple application with Twilio and I have some issues. I have the code made with Python to make the call.
def makeCall(self, phoneNumber, from_num, message):
call = self.client.calls.create(
method='POST',
machine_detection='Enable',
to= phoneNumber,
from_= from_num,
url= self.url + urlencode({'Message' : message}),
status_callback= self.url_callback,
status_callback_method = 'POST'
)
return call.sid
And I also have a Node.js application with the Twiml response.
const express = require('express');
const VoiceResponse = require('twilio').twiml.VoiceResponse;
const urlencoded = require('body-parser').urlencoded;
const app = express();
app.post('/start', (request, response) => {
const twiml = new VoiceResponse();
const gather = twiml.gather({
numDigits: 1,
action: '/confirmation'
});
gather.say({
language:'en-EN'
}, 'Hello, are you ok?' );
gather.pause({
length: 1
});
gather.say({
language:'en-EN'
}, 'If no press one, if yes press two');
response.type('text/xml');
response.send(twiml.toString());
});
app.post('/confirmation', (request, response) => {
const twiml = new VoiceResponse();
if (request.body.Digits) {
switch (request.body.Digits) {
case '2':
twiml.say({
language:'en-EN'
}, 'I am sorry to hear that');
case '1':
twiml.say({
language:'en-EN'
}, 'Perfect!');
default:
twiml.say({
language:'en-EN'
}, 'Sorry, I don't understand you.');
twiml.pause({
length: 1
});
twiml.say({
language: 'en-EN'
}, 'Repeat please');
}
}
response.type('text/xml');
response.send(twiml.toString());
});
app.post('/callback', (request, response) => {
console.log(request.body.CallStatus);
console.log('--------------------');
console.log(request.body.AnsweredBy);
console.log('--------------------');
response.type('text/xml')
response.send(request.AnsweredBy)
});
app.listen(3000);
The problem is that when I execute the python function. If the user reject the call or doesn't answer, it sends a voicemessage to the answering machine and I would like to avoid it. I would also like to detect in the python code, if the call is rejected or not answered.
Thanks in advance
Twilio developer evangelist here.
You can't detect whether the call was answered in your python code that creates the call. That will queue up the call to be dispatched by Twilio, so all further events will happen asynchronously to that API call.
For your Node.js application that is receiving the webhook you can check what the current status of the call is by inspecting the CallStatus parameter that is sent as part of the body of the request. The CallStatus can be one of: "queued", "ringing", "in-progress", "completed", "busy", "failed" or "no-answer" and you can see more about the CallStatus parameter in the documentation.
To read the CallStatus parameter, you'll need to ensure you are using the body-parser middleware properly, urlencoded is a function and you need to set the express app to use it.
const urlencoded = require('body-parser').urlencoded;
const app = express();
app.use(urlencoded({ extended: false });
You can then get the call status in your response function.
app.post('/start', (request, response) => {
console.log(request.body.CallStatus);
// and so on
Then you can handle it from there.
I'm trying to implement a Twilio function to (1) forward calls to my personal phone, (2) send a "heads up" SMS just before, and (3) say a whisper prior to connecting. I've been able to set up Twilio to do any 2 of the previous 3 things but never the 3 at the same time!
exports.handler = function(context, event, callback) {
// Get an initialized Twilio API client
const client = context.getTwilioClient();
twilioClient.messages.create({
to: 'PERSONAL_PHONE',
from: 'TWILIO_PHONE',
body: 'Incoming!!!'
}).then(function() {
const twiml = new Twilio.twiml.VoiceResponse();
twiml.dial.number({ url: WHISPER_URL }, 'PERSONAL_PHONE');
callback(null, twiml);
});
};
When implementing this, it sends the SMS but the call never connects (and the calling party hears an error message).
Would really appreciate a lesson here :)
Thank you!
Btw, I found a solution:
exports.handler = function(context, event, callback) {
// Get an initialized Twilio API client
const client = context.getTwilioClient();
twilioClient.messages.create({
to: 'NUMBER',
from: 'TWILIO_PHONE',
body: 'Incoming!!!'
}).then(function() {
const twiml = new Twilio.twiml.VoiceResponse();
const dialobj = twiml.dial();
dialobj.number({url:'WHISPER_URL'},'NUMBER');
callback(null, twiml);
});
};
I'm trying to set up messages delivery status check with twilio. For some reasons twilio statusCallback doesn't fire. Could you please help me to find an error?
Here is a file where I do initialization and send messages:
const Twilio = require('twilio');
const {
TWILIO_ACCOUNT_SID,
TWILIO_AUTH_TOKEN,
TWILIO_PHONE_NUMBER
} = require('config');
const client = new Twilio(TWILIO_ACCOUNT_SID, TWILIO_AUTH_TOKEN);
module.exports = {
send: (body, phoneNumber) => client.messages.create({
body,
to: phoneNumber,
from: TWILIO_PHONE_NUMBER,
statusCallback: 'http://postb.in/b/XXXXXXXX'
})
.then((message) => {
console.log(message.sid);
return message.sid;
})
};
Here is a test where I call message sending after initialization:
const { expect } = require('chai');
const smsUtility = require('utils/sms');
describe('Sms utility', () => {
it('should send a message and return message sid', (done) => {
const body = 'Body';
const number = '+XXXXXXXXXXX';
smsUtility.send(body, number)
.then((messageSid) => {
expect(typeof messageSid).to.equal('string');
return done();
})
.catch((err) => {
console.log(err);
return done();
});
});
});
I use test credentials, but when I replace it with real twilio credentials, I successfully receive a message, so this part works fine. Also, when I try to ping postb.in url manually (with curl), it also works OK. Only statusCallback doesn't work.
Thanks.
Twilio developer evangelist here.
It looks to me like you have everything set up nicely aside from your Postbin URL.
I noticed you show your URL as http://postb.in/b/XXXXXXXX. But the /b/ version of the URL is the dashboard for your Postbin. Requests to the dashboard won't show up on the dashboard.
Instead, you should use the URL that looks like: http://postb.in/XXXXXXXX. Try that and let me know if it's working.