Twilio Two Way SMS Example

Wanted to share a proof of concept that I had put together:

In other examples such as: Send SMS through Service Task (http-connector) and Twilio (Script Based), we send SMS messages with twilio, but there was never the ability to receive a response back from the recipient of the SMS. Until now! :smile:

So consider the following scenario: You need to ask a question to a recipient and have them provide you some response. A more concrete example could be that you are looking to find out the number of free beds at a shelter, someone counts the number of beds and responds to the SMS with the number of free beds.

So we end up with the following:

So the overall flow is:

  1. Start the “Get Feedback” process and include the phoneNumber process variable.
  2. Twilio SMS is sent, and we wait for a message to come back to engine.
  3. In Twilio we have it setup so that every SMS that is sent to our Twilio phone number, calls a Twilio “Function”; that function runs a web service call to the /message Rest End-point of Camunda.
  4. The “SMS Capture” process captures the SMS message from Twilio, and runs a script that correlates the received SMS back to the “Get Feedback” process to the “Receive Response” receive task.
    1. If the Response is not received within 1 minute, we send a reminder message, every minute for 5 minutes.
  5. Once response is received, we send a confirmation SMS which is essentially a echo back to the recipient to confirm we received their message / count of the number of available beds.

Here is a more complex example:


So how does it all work:

For the twilio SMS, we use the Jsoup code we outline in: https://forum.camunda.io/t/send-sms-through-service-task-http-connector-and-twilio-script-based.

In Twilio we setup the the following:

Setup a twilio phone number that supports SMS and having people send SMS’ to that number.
In Twilio setup a function: Twilio | Login
In the function configure the following script:

exports.handler = function(context, event, callback) {

  var got = require('got');
  var requestPayload = {
    "messageName" : "sms",
    "processVariables" : {
      "smsData" : {"value" : JSON.stringify(event), "type": "Json"}
    },
    "resultEnabled" : true
  };

  got.post('http://CAMUNDA_URL_GOES_HERE/engine-rest/message', 
    { body: JSON.stringify(requestPayload), 
      headers: { 
        'accept': 'application/json',
        'content-type': 'application/json'
    }, 
    json: true
  }).then(function(response) {
    console.log(response.body)
    callback(null, response.body);

  }).catch(function(error) {
    callback(error)
  });
};

This script creates a simple POST request to the camunda engine to the /message endpoint, and takes the event variable in twilio and passes it into camunda.

We use the From property as Message Number that we correlate against.

The event variable in twilio looks something like this:

{
    "ToCountry": "CA",
    "ToState": "QC",
    "SmsMessageSid": "SMa2f94d80c31edb524746e25462b9ef90",
    "NumMedia": "0",
    "ToCity": "LACHINE",
    "FromZip": "",
    "SmsSid": "SMa2f94d80c31edb524746e25462b9ef90",
    "FromState": "ON",
    "SmsStatus": "received",
    "FromCity": "OTTAWA",
    "Body": "This is my Test Message",
    "FromCountry": "CA",
    "To": "+15555555555",
    "ToZip": "",
    "NumSegments": "1",
    "MessageSid": "SMa2f94d80c31edb524746e25462b9ef90",
    "AccountSid": "ACfc89cbc4febdd9958087bfb8c389968e",
    "From": "+14444444444",
    "ApiVersion": "2010-04-01"
}

Next in the Twilio Console in the Phone Number config (Twilio | Login), you set the number to call the Function when a SMS is received to your Twilio phone number:

Then we Start the “Get Feedback” process.

The Process is setup with:

the following:

The “Correlate SMS with Waiting Feedback” uses the following Javascript:

var smsData = execution.getVariable('smsData')
var phoneNumberRaw = smsData.prop('From').value()

var smsBodyResponse = smsData.prop('Body').value()

var correlation = execution.getProcessEngineServices()
                          .getRuntimeService()
                          .createMessageCorrelation(phoneNumber)
                          .setVariable('smsBodyResponse', smsBodyResponse)
                          .correlateWithResult();

And the Receive Response task has a Message name of ${phoneNumber}.


We used the phone number as the correlation key because it was the unique id for the “conversation”.
Another way to have multiple conversations with a single recipient would be have add a “key” to the SMS responses.

Example:

  1. “What is the current bed count?”
  2. “23”

vs

  1. “convo123: What is the current bed count?”
  2. “convo456: What is the current number of people in line?”
  3. “convo123: 15”
  4. “convo456: 40”

Would be interested in use cases that come to mind by other forum members!

2 Likes

Hi Stephen,

A common use case I see is when a consumer has an appointment, 48 hours before the appointment, an reminder/confirmation SMS is sent. Hence customer replies Y or N to confirm or cancel the appointment.

I should also mention that I tend to treat Email, SMS etc as a channel and thus the response can be channel agnostic. Hence I tend to have a utility process per channel which is used to read from the channel (email/SMS) and call the correlation API of the core business process which is ideally channel agnostic…

regards

Rob

@Webcyberrob Reminders is a good use case to model. Will put together a example of this.

For Email, I think there needs to be another proxy in place that forces the Email link to go through a validation layer.

Here is a example of a Survey scenario that went through the validation layer:

A Request URL is generated when the user task is generated. (In this scenario a user task is used for both anonymous and authentication survey response), The email link will only work if the URL has the validation param. Once the survey is completed (the user task is completed), the URL is revoked. This prevents the BPM from being abused with erroneous Messages to /message

@Webcyberrob a question draft:

Would also be interesting to push this to multi-language support + Interactive Voice Response so you can Dial the users number and provide them with a generated voice response and let them “press 1 for X and 2 for Y”

1 Like