ColdFusion API help Converting curl to cfhttp - coldfusion

I am trying to mimic this curl request with ColdFusion cfhttp from this sample here:
https://docs.fatzebra.com.au/purchases
In a linux terminall the curl request works perfectly
<cfset origTemp = '
\{ \
\"card_holder\": \"Jim Smith\", \
\"card_number\": \"5123456789012346\", \
\"card_expiry\": \"05/2014\", \
\"cvv\": \"987\", \
\"amount\": 1000, \
\"reference\": \"zzzzsORD98976\", \
\"customer_ip\": \"111.222.111.123\" \
}'/>
<cfset tmp = {} />
<cfset tmp['card_holder'] = "Jim Smith" />
<cfset tmp['card_number'] = '512345678901234a6' />
<cfset tmp['card_expiry'] = '05/2013' />
<cfset tmp['cvv'] = '987z' />
<cfset tmp['amount'] = 'a1000' />
<cfset tmp['reference'] = 'ORD98976' />
<cfset tmp['customer_ip'] = '111.222.111.123' />
<cfhttp url='https://gateway.sandbox.fatzebra.com.au/v1.0/purchases' useragent="#cgi.http_user_agent#" username="Test" password="Test" result="r" method="post" >
<cfhttpparam type="header" name="content-type" value="application/json" />
<!---<cfhttpparam type="body" value="#origTemp#" />--->
<cfhttpparam type="body" value="#serializeJson(tmp)#" />
</cfhttp>
<cfdump var="#r#" />
Without any luck.

The cUrl call is using login: TEST, password: TEST. Your code is using login: Test, password: Test. Those are two different sets of credentials, and the error you're getting suggests that's the issue.
(disclosure: CFJones & I worked through this offline, and this was the answer we arrived at)

Related

cfschedule: Fire onError function if url cannot be found

We have ColdFusion tasks defined like this:
<cfschedule
action="update"
task="Test"
operation="HTTPRequest"
url="#path.getFileFolder()#tasks/test.cfm"
startDate="#now()#"
startTime="00:00"
interval="daily"
resolveURL="no"
publish="yes"
file="test.txt"
path="#path.getLogFolder#"
eventHandler="tasks.eventHandler"
onException="invokeHandler">
The onError function in the eventHandler looks like this:
<cffunction name="onError" returntype="void">
<cfargument name="context" type="struct" required="false" />
<cfscript>
var slackHookURL = 'urlToOurSlackErrorChannel';
var slackMessage = 'ourSlackMessage';
</cfscript>
<cftry>
<cfhttp url="#slackHookURL#" method="post" result="httpResp" timeout="60">
<cfhttpparam type="header" name="Content-Type" value="application/json" />
<cfhttpparam type="body" value="#slackMessage#" />
</cfhttp>
<cfcatch></cfcatch>
</cftry>
</cffunction>
We had the problem that after a server switch our config file missed a / in the file folder path. So the url referenced in all of our tasks pointed to something like https://ourPagetasks/test.cfm instead of https://ourPage/tasks/test.cfm. The onError function hasn't been fired. We just "accidentally" stumbled upon all our tasks not having been executed ever since.
In the test.txt log file however we found the message "Connection timeout". Shouldn't the onError function warn us if that happens? Or is there any workaround so I can check the text that's about to be written to the log file? The onTaskEnd function of the eventHandler is only allowed to have the parameter context which tells me nothing about what's going to be logged.
I hope I explained my problem somehow understandable. Thanks in advance!
I managed to implement a workaround. In our scheduledTasks.cfm I added the following lines at the end to check if any of the urls are invalid:
<!--- Check if the tasks are defined correctly --->
<cfschedule action="list" mode="server" result="tasks" />
<cfloop query="tasks">
<cfhttp method="head" url="#tasks.URL#" />
<cfif len(cfhttp.errorDetail)>
<cfscript>
slackHookURL = 'urlToOurSlackErrorChannel';
slackMessage = 'ourSlackMessage';
</cfscript>
<cftry>
<cfhttp url="#slackHookURL#" method="post" result="httpResp" timeout="60">
<cfhttpparam type="header" name="Content-Type" value="application/json" />
<cfhttpparam type="body" value="#slackMessage#" />
</cfhttp>
<cfcatch></cfcatch>
</cftry>
</cfif>
</cfloop>

How to Send this API Call to Twilio Flow via CFHTTP

So I'm trying to setup the API call to Twilio Flow using CFHTTP but am having no luck. Keeps returning CFHTTP doesn't exist when I try to view the response.
I've already tried adjusting from formfields to body, setting the charset to utf-8, etc. I was successfully able to send an SMS using the Programmable SMS portion but am having no luck hitting the Flow.
<cfset twilioUsername = "XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX" />
<cfset twilioFlowSid = "XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX" />
<cfset twilioPassword = "XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX" />
<cfset twilioFrom = "+1XXXXXXXXXX" />
<cfset twilioTo = "+1XXXXXXXXXX" />
<cfset bodyFields = {
"name" : "Tester",
"cases" : "This Case this Time"
} />
<cfset twilioFlowResource = (
"https://studio.twilio.com/v1/Flows/#twilioFlowSid#/Executions.json"
) />
<cfhttp result="POST" method="POST" charset="utf-8" url="#twilioFlowResource#" username="#twilioUsername#" password="#twilioPassword#">
<cfhttpparam type="formfield" name="From" value="twilioFrom" />
<cfhttpparam type="formfield" name="To" value="twilioTo" />
<cfhttpparam type="formfield" name="Parameters" value="#serializeJSON(bodyFields)#" />
</cfhttp>
All I keep receiving is variable CFHTTP doesn't exist when I try to view the contents of cfhttp.filecontent.
It is because you used cfhttp's "result" attribute which ".. lets you specify an alternate variable in which to receive a result". Meaning CF won't populate the default variable named cfhttp. So in your example, you should be dumping the variable named #POST#. (Though to avoid further confusion, I'd recommend using something else, like "response".)
<cfhttp result="response"
method="POST"
charset="utf-8"
url="#twilioFlowResource#"
username="#twilioUsername#"
password="#twilioPassword#">
... parameters ...
</cfhttp>
<cfdump var="#response#">
Also, perhaps it's just a typo, but ... if that's the actual code you're using, it's missing pound signs around the variables in the <cfhttpparam> declarations. So the code is actually sending the literal string "twilioFrom" instead of the variable value: +1XXXXXXXXXX. These lines:
<cfhttpparam type="formfield" name="From" value="twilioFrom" />
<cfhttpparam type="formfield" name="To" value="twilioTo" />
... should be changed to this:
<cfhttpparam type="formfield" name="From" value="#twilioFrom#" />
<cfhttpparam type="formfield" name="To" value="#twilioTo#" />

CF web service array vs. .Net web service array

MethodCRM api has this example in .Net
Dim arrUpdateFieldsArray(1) As String
Dim arrUpdateValueArray(1) As String
arrUpdateFieldsArray(0) = Me.txtUpdateField1.Text
arrUpdateValueArray(0) = Me.txtUpdateValue1.Text
arrUpdateFieldsArray(1) = Me.txtUpdateField12Text
arrUpdateValueArray(1) = Me.txtUpdateValue2.Text
'Call the MethodAPI to update the record
sResult = wbsMethodAPI.MethodAPIUpdateV2(sCompanyAccount, sUserName, sPassword, "", _sUpdateTable, arrUpdateFrieldsArray, arrUpdateValueArray, intRecordID)
wbsMethodAPI = Nothing
I have tried to build this equivalent but not with success, this is what I have tried
<CFSCRIPT>
s = "salesRep,CustomerType";
array1 = s.split(",");
s = "#Signature_RepName#,#Payment_CompanyType#";
array2 = s.split(",");
string = CreateObject("java", "java.lang.String");
array = CreateObject("java", "java.lang.reflect.Array");
cookies = array.newInstance(string.getClass(), 3);
array.set(cookies, 0, "salesRep");
array.set(cookies, 1, "CustomerType");
string2 = CreateObject("java", "java.lang.String");
array2 = CreateObject("java", "java.lang.reflect.Array");
cookies2 = array2.newInstance(string.getClass(), 3);
array2.set(cookies2, 0, "#Signature_RepName#");
array2.set(cookies2, 1, "#Payment_CompanyType#");
</CFSCRIPT>
<cfhttp url="https://www.methodintegration.com/MethodAPI/service.asmx/MethodAPIUpdateV2" method="GET">
<cfhttpparam type="URL" name="strCompanyAccount" value="xxxx"/>
<cfhttpparam type="URL" name="strLogin" value="xxxx"/>
<cfhttpparam type="URL" name="strPassword" value="xxxx"/>
<cfhttpparam type="URL" name="strSessionID" value=""/>
<cfhttpparam type="URL" name="strTable" value="Customer"/>
<cfhttpparam type="URL" name="arrUpdateFieldsArray" value=#cookies#/>
<cfhttpparam type="URL" name="arrUpdateValueArray" value=#cookies2#/>
<cfhttpparam type="URL" name="intRecordID" value="#customerid#"/>
</cfhttp>
Please let me know what I am doing wrong. TIA
I believe those are SOAP web services according to http://www.methodintegration.com/Method-API-for-QuickBooks-CRM.aspx. Proof: https://www.methodintegration.com/MethodAPI/service.asmx?wsdl
Therefore, use cfinvoke to consume them.
<cfinvoke
webservice="https://www.methodintegration.com/MethodAPI/service.asmx?wsdl"
method="MethodAPIUpdateV2"
returnVariable="ws" >
<cfinvokeargument name="strCompanyAccount" value="" />
<cfinvokeargument name="strLogin" value="" />
<cfinvokeargument name="strPassword" value="" />
<cfinvokeargument name="strSessionID" value="" />
<cfinvokeargument name="strTable" value="" />
<cfinvokeargument name="arrUpdateFieldsArray" value="" />
<cfinvokeargument name="arrUpdateValueArray" value="" />
<cfinvokeargument name="intRecordID" value="" />
</cfinvoke>
or
<cfset wbsMethodAPI
= createObject("webservice",
"https://www.methodintegration.com/MethodAPI/service.asmx?wsdl")>
<cfset ws = wbsMethodAPI.MethodAPIUpdateV2(
strLogin="", strCompanyAccount="", strTable="", arrUpdateValueArray="",
arrUpdateFieldsArray="", intRecordID="", strPassword="", strSessionID="")>
See: http://help.adobe.com/en_US/ColdFusion/9.0/Developing/WSc3ff6d0ea77859461172e0811cbec22c24-78b4.html
The 2 array's are of type tns:ArrayOfString, see: http://forums.adobe.com/message/4337438

Create Wufoo webhook with PUT request in ColdFusion

I'm having troubles with building correct PUT request to the Wufoo.
In all my attempts I see the same error:
404 A WebHook must contain a url parameter.
Here is the version with JSON data type:
<cfset local.action = "forms/#local.formHash#/webhooks.json" />
<cfset local.request = {"url" : local.webHookURL, "handshakeKey" : local.webHookKey} />
<cfset local.request["handshakeKey"] = local.webHookKey />
<cfhttp url="#local.baseURL##local.action#" method="put" username="#local.apiKey#" password="#local.apiPass#">
<cfhttpparam type="header" name="Content-Type" value="application/json; charset=UTF-8" />
<cfhttpparam type="body" value="#SerializeJSON(local.request)#" />
</cfhttp>
Same failure when using file:
<cfset local.action = "forms/#local.formHash#/webhooks.json" />
<cfset local.request = {"url" : local.webHookURL, "handshakeKey" : local.webHookKey} />
<cffile action="write" file="#GetTempDirectory()#webhook.json" output="#SerializeJSON(local.request)#">
<cfhttp url="#local.baseURL##local.action#" method="put" username="#local.apiKey#" password="#local.apiPass#">
<cfhttpparam type="header" name="Content-Type" value="application/json; charset=UTF-8" />
<cfhttpparam type="file" mimetype="application/json" name="json" file="#GetTempDirectory()#webhook.json" />
</cfhttp>
UPDATE:
To make the code working in ACF (my code works in Railo only) use this syntax for request:
<cfset local.request = {} />
<cfset local.request["url"] = local.webHookURL />
<cfset local.request["handshakeKey"] = local.webHookKey />
Both methods should produce same JSON with case-sensitive keys.
Also I've tried the XML data type:
<cfset local.action = "forms/#local.formHash#/webhooks.xml" />
<cfsavecontent variable="putXML">
<cfoutput>
<?xml version="1.0" encoding="UTF-8"?>
<WebHookPutRequest>
<url>#XMLFormat(local.webHookURL)#</url>
<handshakeKey>#XMLFormat(local.webHookKey)#</handshakeKey>
</WebHookPutRequest>
</cfoutput>
</cfsavecontent>
<cffile action="write" file="#GetTempDirectory()#webhook.xml" output="#Trim(putXML)#">
<cfhttp url="#local.baseURL##local.action#" method="put" username="#local.apiKey#" password="#local.apiPass#">
<cfhttpparam type="header" name="Content-Type" value="application/xml; charset=UTF-8" />
<cfhttpparam type="body" value="#putXML#" />
</cfhttp>
Here I'm not sure if my XML is correct, though for JSON everything should be fine.
Any ideas what's wrong with my code?
Thanks in advance.
Wufoo asks for the parameters to be "be passed as post parameters to the Web Hook API". Try using the application/x-www-form-urlencoded encoding for the body of the request. In ColdFusion, you can do this with <cfhttpparam type="FormField" />.
<cfhttpparam type="FormField" name="url" value="#local.webHookURL#" />
<cfhttpparam type="FormField" name="handshakeKey" value="#local.webHookKey#" />
However, ColdFusion rejects this technique with PUT methods. You can encode the body yourself using:
<cfhttpparam type="header" name="Content-Type" value="application/x-www-form-urlencoded; charset=UTF-8" />
<cfhttpparam type="body" value="url=#UrlEncode(local.webHookURL)#&handshakeKey=#UrlEncode(local.webHookKey)#" />
In ColdFusion, generally, variable names are case-insensitive and uppercase.
<cfset local.request = {
url = local.webHookURL,
handshakeKey = local.webHookKey
} />
This gives you a struct with keys URL and HANDSHAKEKEY.
On the Web, presumably including with the Wufoo REST API, keys are case-sensitive. In this case, Wufoo accepts keys url, handshakeKey, and metadata - in that casing.
In ColdFusion, associative-array notation with struct puts (assignments) lets you keep the precise casing you want.
<cfset local.request = { } />
<cfset local.request["url"] = local.webHookURL />
<cfset local.request["handshakeKey"] = local.webHookKey />
This gives you a struct with keys url and handshakeKey.
Not familiar with this api but should the url, handshakekey, etc be form post params?
The following parameters must be
passed as post parameters to the Web
Hook API
url - this required parameter
represents the URL on your server that
the Web Hook will call when a new
entry is submitted. We do validate the
URL and reject malformed URLs.
handshakeKey - this optional parameter
is described in the Web Hook
integration getting started
documentation.
metadata=true - this optional value
parameter the Web Hook to send along
form/field
The way I read that, it looks like they are asking
for each of the params.
The error is suggesting it can't find the URL param, maybe that is it.

Twitter, oauth and coldfusion

I am trying to post to twitter. I have the app already authenticated and now want to post an update.
This is what my http post is at:
<cfhttp url="http://api.twitter.com/1/statuses/update.json" method="post">
<cfhttpparam type="header" name="status" value="#urlEncodedFormat('my test post')#" />
<cfhttpparam type="header" name="oauth_consumer_key" value="xxx" />
<cfhttpparam type="header" name="oauth_nonce" value="xxx" />
<cfhttpparam type="header" name="oauth_signature_method" value="#urlEncodedFormat('HMAC-SHA1')#" />
<cfhttpparam type="header" name="oauth_token" value="xxx" />
<cfhttpparam type="header" name="oauth_timestamp" value="#GetTickCount()#" />
<cfhttpparam type="header" name="oauth_version" value="1.0" />
</cfhttp>
Has anyone done this? Am I going down the right route?
have you read this?
http://dev.twitter.com/pages/auth#auth-request
you need to construct the "signature base string" and post as body (warning: untested code, for CF8+)
<cffunction name="makeSignatureBaseString" returntype="string" output="false">
<cfargument name="httpMethod" type="string" required="true">
<cfargument name="baseUri" type="string" required="true">
<cfargument name="values" type="struct" required="true">
<cfset var signatureBaseString = "#httpMethod#&#URLEncodedFormat(baseUri)#&">
<cfset var keys = StructKeyArray(values)>
<cfset var key = "">
<cfset ArraySort(keys, "textNoCase")>
<cfloop array="#keys#" index="key">
<cfset signatureBaseString &= URLEncodedFormat("&#key#=#values[key]#")>
</cfloop>
<cfreturn signatureBaseString>
</cffunction>
-
<!--- using values from http://dev.twitter.com/pages/auth#auth-request --->
<cfset params = {
oauth_consumer_key = "GDdmIQH6jhtmLUypg82gる",
oauth_nonce = "oElnnMTQIZvqvlfXM56aBLAf5noGD0AQR3Fmi7Q6Y",
oauth_signature_method = "HMAC-SHA1",
oauth_token = "819797-Jxq8aYUDRmykzVKrgoLhXSq67TEa5ruc4GJC2rWimw",
oauth_timestamp = "1272325550",
oauth_version = "1.0"
}>
<cfhttp url="http://api.twitter.com/1/statuses/update.json" method="POST">
<cfloop collection="#params#" item="key">
<cfheader type="header" name="#key#" value="#params[key]#">
</cfloop>
<!--- add status to the params for makeSignatureBaseString() --->
<cfset params.status = "setting up my twitter 私のさえずりを設定する">
<cfhttpparam type="body"
value="#makeSignatureBaseString('POST', 'http://api.twitter.com/1/statuses/update.json', params)#">
</cfhttp>