Twilio inbound SMS using webhooks and Coldfusion - coldfusion

I have setup SMS on Twilio and can receive an SMS via webhooks. I can manipulate the form data to do what I want however every inbound SMS message throws an error on Twilio's dashboard. It's looking for some response. Right now I'm just dumping the form to a text file while testing.
<!doctype html>
<?xml version="1.0" encoding="UTF-8"?>
<html>
<head>
<Response>
</Response>
<cfdump
var="#form#"
label="HTTP Body" output="C:/webhook-sms.txt"
/>
</head>
</html>
The error is: MESSAGE
The markup in the document preceding the root element must be well-formed.
Warning - 12200
Schema validation warning
The provided XML does not conform to the Twilio Markup XML schema. Please refer to the specific error and correct the problem.
What do I need to respond to Twilio with?
Thanks in advance for any help!
Gary

Twilio expects a content type of text/xml and also expects the first line of the response to be <?xml version="1.0" encoding="UTF-8"?>.
If your response has one or more empty lines before <?xml version="1.0" encoding="UTF-8"?> you're still going to get an error.
What I ended up doing, was with an Application.cfm something like this:
<cfsetting enablecfoutputonly="true" showdebugoutput="false" requesttimeout="30" />
<cfheader name="content-type" value="text/xml" />
<!--- // more code --->
and endpoint files which start with the first line like this:
<cfoutput><?xml version="1.0" encoding="UTF-8"?></cfoutput>
<!--- // more code --->
And make sure you send back valid TwiML (Twilio's XML) (no HTML).

Thanks everybody. My final test code looked like this:
<cfsetting enablecfoutputonly="true" showdebugoutput="false" requesttimeout="30" />
<cfheader name="content-type" value="text/xml" />
<cfoutput><?xml version="1.0" encoding="UTF-8"?>
<Response>
<Message>Thanks for getting in touch, I'll call you later</Message>
</Response></cfoutput>

Related

Web service proxy server in Karaf with Camel and cxf adds 1000 to MTOM messages

I am creating new proxy for web services in Karaf 4.4.1 with Camel 3.18.1 and cxf 3.5.3.(I've tried it on older versions too 4.4.0, 3.18.0, 3.5.2). And it works fine, but I have a problem with MTOM attachments. For some reason it adds several times number 1000 into the message. And it is not every 1000 bytes. The spaces between them are different (from 377 to 4157 bytes). Here is picture of comparison of my incoming messages. The bad one goes through proxy and the good one don't:
comparsion 1
comparsion 2
Does anyone knows where is the mistake?
Here is my blueprint:
...
<camelcxf:cxfEndpoint id="SrvEndpoint">
<camelcxf:properties>
<entry key="dataFormat" value="CXF_MESSAGE" />
<entry key="ws-security.ut.no-callbacks" value="true"/>
<entry key="ws-security.validate.token" value="false"/>
<entry key="schema-validation-enabled" value="true" />
<entry key="lazyStartProducer" value="true" />
<entry key="mtom-enabled" value="true" />
</camelcxf:properties>
<camelcxf:inInterceptors>
<ref component-id="SrvWsSecInterceptor" />
<ref component-id="SrvAuthenticationInterceptor"/>
<ref component-id="SrvLoggingInInterceptor"/>
</camelcxf:inInterceptors>
<camelcxf:outInterceptors>
<ref component-id="SrvLoggingOutInterceptor"/>
</camelcxf:outInterceptors>
</camelcxf:cxfEndpoint>
<!-- this is the Camel route which proxies the real web service and forwards SOAP requests to it -->
<camelContext id="SrvRoute" trace="false" xmlns="http://camel.apache.org/schema/blueprint">
<route>
<!-- CXF consumer using CXF_MESSAGE format -->
<from uri="cxf:bean:SrvEndpoint"/>
<!-- Need to remove the http headers which could confuse the http endpoint -->
<removeHeaders pattern="CamelHttp*"/>
<!-- Don't know why but if not set returns empty response header and body -->
<setProperty name="CamelCXFDataFormat"><constant>PAYLOAD</constant></setProperty>
<!-- send proxied request to real web service -->
<to uri="{{SrvProxy.target.url}}?throwExceptionOnFailure=false"/>
</route>
</camelContext>
I've tried to change dataFormat to PAYLOAD and clean it from authentication and validation but nothing helped.

cfhttp returning a connection failure for a network url that a browser can reach via both http and https

I am using cfhttp to try to pull some json from one of our organizations APIs. I have the code working when trying to pull example json from one of our own servers, but when I point it to the API itself I receive a connection failure. This is the code:
<cfhttp method="get" url="http://[url]/api/menu">
<cfhttpparam type="URL" name="id" value="[guid]">
</cfhttp>
<cfset FileWrite("#application.tempDirPath#/temp.json", CFHTTP.FileContent)>
I have replaced the real values with [url] and [guid].
I have tried accessing this url in a browser at https://[url]/api/menu?id=[guid] and it works perfectly fine, indicating that my machine has no problem reaching that url. The url is a server in our network that I can access as long as I'm on the company VPN.
Things that I have tried:
The live code should point to https. I've tried both http and https.
I've tried hitting the home page at that same url and it also results in a connection failure, but works in a browser.
I've tried this same code with http://www.google.com, and that downloads the Google html without issue.
I've tried restarting ColdFusion and my machine.
I've tried disabling compression via headers:
<cfhttp method="get" url="http://[url]/api/menu">
<cfhttpparam type="header" name="Accept-Encoding" value="deflate;q=0" />
<cfhttpparam type="header" name="TE" value="deflate;q=0" />
<cfhttpparam type="URL" name="id" value="[guid]">
</cfhttp>
I do not have access to the target server. I can ask those who do have access for help, but their conclusion at this point is "this is a ColdFusion problem.", so I'm not sure how much help I can get. This makes it impossible for me to check for Firewall rules or user-agent restrictions; suggestions on ways to test for those things locally would be welcome.
Edit
Per comments on this question I determined that http is just redirecting to https at that address. So I followed the instructions provided at ColdFusion https connection failure to import the certificate. After doing so I followed the instructions to verify that the cert was imported successfully. I then restarted CF Server.
After that I ran my code again and dumped the cfhttp struct as a whole into the temp file. This was the result:
<?xml version="1.0" encoding="UTF-8"?>
<STRUCT ID="1">
<ENTRY NAME="Errordetail" TYPE="STRING">I/O Exception: sun.security.validator.ValidatorException: PKIX path building failed: sun.security.provider.certpath.SunCertPathBuilderException: unable to find valid certification path to requested target</ENTRY>
<ENTRY NAME="Mimetype" TYPE="STRING">Unable to determine MIME type of file.</ENTRY>
<ENTRY NAME="Statuscode" TYPE="STRING">Connection Failure. Status code unavailable.</ENTRY>
<ENTRY NAME="Filecontent" TYPE="STRING">Connection Failure</ENTRY>
<ENTRY NAME="Responseheader" TYPE="STRUCT">
<STRUCT ID="2" />
</ENTRY>
<ENTRY NAME="Text" TYPE="BOOLEAN">true</ENTRY>
<ENTRY NAME="Charset" TYPE="STRING" />
<ENTRY NAME="Header" TYPE="STRING" />
</STRUCT>

Calling a SOAP Web Service Function

I am trying to use a web service to save data. The web service URL is something like:
http://example.com/webservice1/order.asmx
When I want to save an order, I will send a SOAP Envelope and have to call the function saveorder. How can I specify in ColdFusion that I want to call this function?
You'll have to use cfhttp and build up your SOAP Envelope and pass it through with your cfhttp request.
This is something I wrote some time ago:
<cfscript>
savecontent variable="local.sSoap" {
WriteOutput("
<?xml version='1.0' encoding='utf-8'?>
<soap:Envelope xmlns:xsi='http://www.w3.org/2001/XMLSchema-instance' xmlns:xsd='http://www.w3.org/2001/XMLSchema' xmlns:soap='http://schemas.xmlsoap.org/soap/envelope/'>
<soap:Body>
#arguments.sData#
</soap:Body>
</soap:Envelope>
");
}
</cfscript>
<cfhttp url="https://apiconnector.com/API.asmx" method="post" result="httpResponse">
<cfhttpparam type="header" name="SOAPAction" value="http://apiconnector.com/#arguments.sMethod#"/>
<cfhttpparam type="header" name="accept-encoding" value="no-compression"/>
<cfhttpparam type="xml" value="#trim( local.sSOAP )#"/>
</cfhttp>
You'll obviously have to make changes to suit your own needs, but the gist is there.

Cancel order on Amazon by using Amazon Marketplace Web Service

I am using this code to ship my order on Amazon. This xml request is sent to the Amazon Marketplace Web Service, and my order gets shipped. Now I want to cancel the order using the same Web Service. But I am not sure what changes I have to make to the xml to perform the order cancel process. Can anyone help?
<cfsavecontent variable="Final_FulFillMent_XML">
<?xml version="1.0" encoding="UTF-8"?>
<AmazonEnvelope xsi:noNamespaceSchemaLocation="amzn-envelope.xsd"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance">
<Header>
<DocumentVersion>1.01</DocumentVersion>
<MerchantIdentifier>xxxxxxxxxxxx</MerchantIdentifier>
</Header>
<MessageType>OrderFulfillment</MessageType>
<Message>
<MessageID>1</MessageID>
<OrderFulfillment>
<AmazonOrderID>#AmazonOrderID#</AmazonOrderID>
<MerchantFulfillmentID>#MerchantFulfillmentID#</MerchantFulfillmentID>
<FulfillmentDate>#FulfillmentDate#</FulfillmentDate>
<FulfillmentData><CarrierCode>#CarrierCode#</CarrierCode>
<ShippingMethod>#ShippingMethod#</ShippingMethod>
<ShipperTrackingNumber>#ShippingTrackingNumber#</ShipperTrackingNumber>
</FulfillmentData></OrderFulfillment>
</Message>
</AmazonEnvelope>
</cfsavecontent>
<cfhttp method="post" url="#FinalQueryString#">
<cfhttpparam name="Content-Type" type="header" value="text/xml; charset=iso-8859-1">
<cfhttpparam name="FeedContent" type="body" value="#Final_FulFillMent_XML#">
<cfhttpparam type="header" name="Content-MD5" value="#ToBase64(BinaryDecode(Hash(Final_FulFillMent_XML), 'hex'))#">
</cfhttp>
To cancel entire orders, you need to modify the an "Order Acknowledge Feed" that you're probably sending already and specify a StatusCode of Failure and a CancelReason, e.g. BuyerCanceled.
To cancel partial orders, you need to send an "Order Adjustment Feed" which lets you specify how many items you were unable to ship and why.
Both XML feeds are described in Selling on Amazon: Guide to XML

ColdFusion soap client

The following is a sample SOAP 1.2 request and response. The placeholders shown need to be replaced with actual values.
POST /CommunicationOfficeService1_0/CompanyAccountXmlService.asmx HTTP/1.1
Host: webservices.nbs.rs
Content-Type: application/soap+xml; charset=utf-8
Content-Length: length
<?xml version="1.0" encoding="utf-8"?>
<soap12:Envelope xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:xsd="http://www.w3.org/2001/XMLSchema" xmlns:soap12="http://www.w3.org/2003/05/soap-envelope">
<soap12:Header>
<AuthenticationHeader xmlns="http://communicationoffice.nbs.rs">
<UserName>string</UserName>
<Password>string</Password>
<LicenceID>guid</LicenceID>
</AuthenticationHeader>
</soap12:Header>
<soap12:Body>
<GetCompanyAccountByNationalIdentificationNumber xmlns="http://communicationoffice.nbs.rs">
<nationalIdentificationNumber>long</nationalIdentificationNumber>
</GetCompanyAccountByNationalIdentificationNumber>
</soap12:Body>
</soap12:Envelope>
HTTP/1.1 200 OK
Content-Type: application/soap+xml; charset=utf-8
Content-Length: length
<?xml version="1.0" encoding="utf-8"?>
<soap12:Envelope xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:xsd="http://www.w3.org/2001/XMLSchema" xmlns:soap12="http://www.w3.org/2003/05/soap-envelope">
<soap12:Body>
<GetCompanyAccountByNationalIdentificationNumberResponse xmlns="http://communicationoffice.nbs.rs">
<GetCompanyAccountByNationalIdentificationNumberResult>string</GetCompanyAccountByNationalIdentificationNumberResult>
</GetCompanyAccountByNationalIdentificationNumberResponse>
</soap12:Body>
</soap12:Envelope>
I have generated the ColdFusion code that looks like this
<cfsavecontent variable="soapBody">
<cfoutput>
POST /CommunicationOfficeService1_0/CompanyAccountXmlService.asmx HTTP/1.1
Host: webservices.nbs.rs
Content-Type: application/soap+xml; charset=utf-8
Content-Length: length
<?xml version="1.0" encoding="utf-8"?>
<soap12:Envelope xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:xsd="http://www.w3.org/2001/XMLSchema" xmlns:soap12="http://www.w3.org/2003/05/soap-envelope">
<soap12:Header>
<AuthenticationHeader xmlns="http://communicationoffice.nbs.rs">
<UserName>my_username</UserName>
<Password>my_password</Password>
<LicenceID>My_licence_id</LicenceID>
</AuthenticationHeader>
</soap12:Header>
<soap12:Body>
<GetCompanyAccountByNationalIdentificationNumber xmlns="http://communicationoffice.nbs.rs">
<nationalIdentificationNumber>20774550</nationalIdentificationNumber>
</GetCompanyAccountByNationalIdentificationNumber>
</soap12:Body>
</soap12:Envelope>
</cfoutput>
</cfsavecontent>
<!---
Now that we have our SOAP body defined, we need to post it as
a SOAP request to the Campaign Monitor website. Notice that
when I POST the SOAP request, I am NOT required to append the
"WSDL" flag to the target URL (this is only required when you
actually want to get the web service definition).
--->
<cfhttp
url="https://webservices.nbs.rs/CommunicationOfficeService1_0/CompanyAccountXmlService.asmx"
method="post"
result="httpResponse">
<!---
Most SOAP action require some sort of SOAP Action header
to be used.
--->
<cfhttpparam
type="header"
name="SOAPAction"
value="http://communicationoffice.nbs.rs/GetCompanyAccountByNationalIdentificationNumber"
/>
<!---
I typically use this header because CHTTP cannot handle
GZIP encoding. This "no-compression" directive tells the
server not to pass back GZIPed content.
--->
<cfhttpparam
type="header"
name="accept-encoding"
value="no-compression"
/>
<!---
When posting the SOAP body, I use the CFHTTPParam type of
XML. This does two things: it posts the XML as a the BODY
and sets the mime-type to be XML.
NOTE: Be sure to Trim() your XML since XML data cannot be
parsed with leading whitespace.
--->
<cfhttpparam
type="xml"
value="#trim( soapBody )#"
/>
</cfhttp>
<!---
When the HTTP response comes back, our SOAP response will be
in the FileContent atribute. SOAP always returns valid XML,
even if there was an error (assuming the error was NOT in the
communication, but rather in the data).
--->
<cfif find( "200", httpResponse.statusCode )>
<!--- Parse the XML SOAP response. --->
<cfset soapResponse = xmlParse( httpResponse.fileContent ) />
<!---
Query for the response nodes using XPath. Because the
SOAP XML document has name spaces, querying the document
becomes a little funky. Rather than accessing the node
name directly, we have to use its local-name().
--->
<cfset responseNodes = xmlSearch(
soapResponse,
"//*[ local-name() = 'Subscriber.AddAndResubscribeResult' ]"
) />
<!---
Once we have the response node, we can use our typical
ColdFusion struct-style XML node access.
--->
<cfoutput>
Code: #responseNodes[ 1 ].Code.xmlText#
<br />
Success: #responseNodes[ 1 ].Message.xmlText#
</cfoutput>
</cfif>
I have none results . The web service uses this is the web site
This is the wsdl file
Serbian National Bank Web Service
How to make this web service run
I've modified a function I've used in the past to pass data form ColdFusion to Dynamics GP via soap.
<cffunction name="callWebService" access="public" output="false">
<cfargument name="soap" type="xml" required="true">
<cfhttp url="https://webservices.nbs.rs/CommunicationOfficeService1_0/CompanyAccountXmlService.asmx" method="post">
<cfhttpparam type="header" name="content-type" value="application/soap+xml">
<cfhttpparam type="header" name="SOAPAction" value="http://communicationoffice.nbs.rs/GetCompanyAccountByNationalIdentificationNumber">
<cfhttpparam type="header" name="accept-encoding" value="no-compression">
<cfhttpparam type="header" name="content-length" value="#len(Arguments.soap)#">
<cfhttpparam type="header" name="charset" value="utf-8">
<cfhttpparam type="xml" name="message" value="#trim(Arguments.soap)#">
</cfhttp>
<cfreturn Trim(cfhttp.FileContent)>
</cffunction>
I believe I've updated the <cfhttpparam />s necessary for the web service you've linked. I would recommend using a software called SOAP UI to test your connection to the service and SOAP XML body outside of ColdFusion. In my above function, the argument soap would be your saved content "soapBody".
One thing needs to be fixed in your soapBody. The text prior to the start of XML is information regarding data that needs to be in the HTTP header, and I've only seen these values imputed as <cfhttpparam />.
The reason I think you may not be getting the desired 200 response with your above code is that the XML body is incorrectly formatted with the WSDL HTTP header example text. I also did not see the length of the body being declared as well.
While trying to set up your connection try just dumping httpResponse out until you start seeing valid soap responses from the server.