Copy link to clipboard
Copied
Kind of a newbie question.... We started using Twilio for SMS. Inbound texts are sent via an HTTP post using webhooks. I'm a bit lost on how to convert the string I get to a structure I can work with. When I use: <cfset requestBody = toString( getHttpRequestData().content ) /> and dump requestbody to a text file I get:
ToCountry=US&ToState=MA&SmsMessageSid=SMcaba8a187004c59cf83f1b97d3ff091c&NumMedia=0&ToCity=ROXBURY&FromZip=01760 ...etc
Looks like & is the delimiter.
Thanks in advance for any suggestions.
Gary
So since I was going to be working with twilio soon anyways I decided to set up a quick webhook and try it. I set up a webhook that emails me dumps of the CGI, URL, and Form scopes whenever the webhook gets a request and the values from Twilio are all in the Form Scope. The following is a list of the struct keys that were in the form scope ( I removed the values because they contain my personal phone number and stuff)
FORM - struct |
---|
ACCOUNTSID |
APIVERSION |
BODY |
FIELDNAMES |
FROM |
FROMCITY |
FROMCOUNTRY |
FROMSTATE |
Copy link to clipboard
Copied
if it's in a query string format you could use
Copy link to clipboard
Copied
If the message has been converted to use ASCII characters in place of special characters, Scott's suggestion will work. However, if it is not converted AND if the user who sent the message places an ampersand (&) in the message, using & as the delimiter will fail.
So, before implementing Scott's suggestion, make sure that the message the user sends is converted.
V/r,
^ _ ^
Copy link to clipboard
Copied
Yes... The little bit of the string you showed appears to be URL encoded which is why I suggested that function. If it isn't for some reason, then you will need to write a function to parse it properly based on whatever format they are using. Looking at the Twilio documentation, it seems like it should be in the url or form scope of the request, but i have not tried setting up a webhook yet... coincidentally I will be working on a Twilio integration soon though so this would be good to know...TwiML™ for Programmable SMS - Twilio
Copy link to clipboard
Copied
Out of curiosity... have you tried just dumping out the form scope? <cfdump var="#form#>
Based on the documentation, and what you are seeing in the request body, you may just need to access the data like #Form.ToCountry# #form.SmsMessageSid#, etc
Copy link to clipboard
Copied
So since I was going to be working with twilio soon anyways I decided to set up a quick webhook and try it. I set up a webhook that emails me dumps of the CGI, URL, and Form scopes whenever the webhook gets a request and the values from Twilio are all in the Form Scope. The following is a list of the struct keys that were in the form scope ( I removed the values because they contain my personal phone number and stuff)
FORM - struct |
---|
ACCOUNTSID |
APIVERSION |
BODY |
FIELDNAMES |
FROM |
FROMCITY |
FROMCOUNTRY |
FROMSTATE |
FROMZIP |
MESSAGESID |
MESSAGINGSERVICESID |
NUMMEDIA |
NUMSEGMENTS |
SMSMESSAGESID |
SMSSID |
SMSSTATUS |
TO |
TOCITY |
TOCOUNTRY |
TOSTATE |
TOZIP |
Copy link to clipboard
Copied
Thanks, Scott. I've only used webhooks with JSON. Never thought it would be a simple as form scope.
Copy link to clipboard
Copied
no problem.... twilio is a remarkably easy to use API!
In less than an hour I sent a message to my phone from CF and recieved a reply from my phone via a webhook to a cfm file.
I have integrated CF code with MANY APIs over the years, and this one of the least painful.
Copy link to clipboard
Copied
Twilio actually had a tutorial for sending with CF....
Component:
<cffunction access="public" name="sendToTwilio" returntype="string" output="false">
<cfargument name="to" type="string" required="true" />
<cfargument name="body" type="string" required="true" />
<cflock timeout="1" scope="Application" type="readonly" throwontimeout="true">
<cfset twilioaccountSID = APPLICATION.twilio.accountSID>
<cfset twilioauthToken = APPLICATION.twilio.authToken>
<cfset twiliophone = APPLICATION.twilio.phone>
</cflock>
<cfhttp method = "post" result="result" url = "https://api.twilio.com/2010-04-01/Accounts/#twilioaccountSID#/Messages" username = "#twilioaccountSID#" password = "#twilioauthToken#">
<cfhttpparam type = "formfield" name = "From" value = "#twiliophone#">
<cfhttpparam type = "formfield" name = "To" value = "+1#arguments.to#">
<cfhttpparam type = "formfield" name = "Body" value = "#arguments.body#">
</cfhttp>
<cfif len(result.filecontent) GT 400 >
<cfreturn "0">
<cfelse>
<cfreturn Left(result.filecontent,5)>
</cfif>
</cffunction>
In application:
<cfset APPLICATION.twilio.accountSID = "SID HERE">
<cfset APPLICATION.twilio.authToken = "Token Here">
<cfset APPLICATION.twilio.phone = "Phone Here">
Page:
<cfif isdefined("Form.Send")>
<cfinvoke component="utility" method="sendToTwilio" to="#form.phone#" body="#form.message#" returnvariable="error">
<cfoutput>Errors: #error#</cfoutput>
</cfif>
<form method="post">
<p>
<label for="textfield">Cell:</label>
<input type="text" name="phone" id="phone">
</p>
<p>
<label for="textarea">Message:</label>
<textarea name="message" rows="3" maxlength="160" id="message"></textarea>
</p>
<p>
<input type="submit" name="Send" id="Send">
</p>
<p> </p>
</form>
Copy link to clipboard
Copied
didn't see that... but I wrote basically the same function in my cfc in about 25 minutes by just reading the api docs, and then I wrote a simple webhook handler that just sends me the form, url, and cgi scopes when twilio sends the webhook posts. (I replaced the sensitive parts with placeholders like myvalueishere but you'll get the point).
The hardest part was figuring out how to set up the test phone number and where to enter my webhook url for testing.... that took me almost 30 minutes
/com/integrations/twilio.cfc
<cfcomponent>
<cfscript>
this.ssid = 'MYSSIDISHERE';
this.authtoken = 'MYTOKENISHERE';
</cfscript>
<cffunction name="sendSMS" access="public" hint="retreives tracking information">
<cfargument name="message" type="string" required="true">
<cfargument name="from" type="string" required="true">
<cfargument name="to" type="string" required="true">
<cfhttp url="https://api.twilio.com/2010-04-01/Accounts/#this.ssid#/Messages.json" method="post" username="#this.ssid#" password="#this.authtoken#">
<cfhttpparam type="formfield" name="Body" value="#arguments.message#" >
<cfhttpparam type="formfield" name="From" value="#arguments.from#" >
<cfhttpparam type="formfield" name="To" value="#arguments.to#" >
</cfhttp>
<cfreturn deserializejson(cfhttp.FileContent) />
</cffunction>
</cfcomponent>
/testtwilio.cfm
<cfinvoke component="com.integrations.twilio" method="sendSMS" returnvariable="results">
<cfinvokeargument name="message" value="this is a test from ColdFusion Code" >
<cfinvokeargument name="from" value="+mytestphonenumberhere" >
<cfinvokeargument name="to" value="+myactualphonenumberhere">
</cfinvoke>
<cfdump var="#results#">
/webhooks/twilio/sms.cfm
<cfmail to="myemailaddressishere" subject="SMS Webhook" from="myfromaddressishere" type="html">
<cfdump var="#url#" label="URL" expand="no">
<cfdump var="#form#" label="FORM" expand="no">
<cfdump var="#CGI#" label="CGI" expand="no">
</cfmail>
Copy link to clipboard
Copied
I'm curious how you're responding to Twilio when an SMS is received. I can manipulate the form data from the webhook to do what I need it to do but every inbound text generates an error in Twilio's dashboard. It's looking for some type of XML reply.
The provided XML does not conform to the Twilio Markup XML schema. Please refer to the specific error and correct the problem.