CF accepts JSON string in cf2016 but not in cf9 - json

I am calling an API and need to send it a JSON string with credentials. We are currently transitioning from CF9 to CF2016. In DEVL I have both versions. In Test and Prod I currently have CF9 only. Originally I wrote the code and tested on CF2016 and it worked fine. When I pushed it up to Test, it did not work. I retried in DEVL, on CF9, and it also errors. The code is:
<cfset logininfo = {"username": "eistech", "password": "#sat_pw#"}>
<cfset fromdate=dateformat(DateAdd('d', -1, dat), "yyyy-MM-dd") & 'T00:00:00-0500'>
<!--- Get token info--->
<cfhttp url="https://scoresdownload.collegeboard.org/pascoredwnld/files/list?fromDate=#fromdate#" method="post" result="finfo">
<cfhttpparam name="Content-Type" type="HEADER" value="application/json">
<cfhttpparam name="Accept" type="HEADER" value="application/json">
<cfhttpparam type="body" value="#serializeJSON(logininfo)#">
</cfhttp>
When running it in CF9, I get:
Invalid CFML construct found on line 5 at column 20. ColdFusion was
looking at the following text:
{ (Line 20 is <cfset logininfo =
{"username": "eistech", "password": "#sat_pw#"}>
I tried enclosing it in single quotes, but this fails in both instances. How can I get this to work in both CF2016 and CF9?

CF9 does not understand : as used in the JSON string in the question.
Use =!
<cfset logininfo = {"username"= "eistech", "password"= "#sat_pw#"}>

Related

ColdFusion and SmartSheet API

I'm attempting to call the smartsheet.com api and read the JSON data from a list sheet request. Im new to API's so I'm certain I'm missing much with my code.
Here is what I have so far:
<cfscript>
apiURL = "https://api.smartsheet.com/2.0/sheets";
apiToken = "xxxxxxxxxxxxxxxxxxxxxxxxx";
</cfscript>
<cfhttp url="#apiURL#" method="GET" result="httpResp" timeout="120" charset="utf-8">
<cfhttpparam type="header" name="Authorization" value="Bearer #apiToken#" />
</cfhttp>
However I do not receive the desired response:
I was attempting to use the sample provided to retrieve the data:
SmartSheet API 2.0
Example Request:
curl https://api.smartsheet.com/2.0/sheets -H "Authorization: Bearer ACCESS_TOKEN"
Example Response:
{
"pageNumber":1,
"pageSize":100,
"totalPages":1,
"totalCount":2,
"data":[
{
"accessLevel":"OWNER",
"id":4583173393803140,
"name":"sheet 1",
"createdAt":"2015-06-05T20:05:29Z",
"modifiedAt":"2015-06-05T20:05:43Z"
},
{
"accessLevel":"OWNER",
"id":2331373580117892,
"name":"sheet 2",
"createdAt":"2015-06-05T20:05:29Z",
"modifiedAt":"2015-06-05T20:05:43Z"
}
]
}
What version of CF? Looks similar to this issue: ColdFusion 9.0.1 - 3574332 CHTTP returns filecontent as java.io.ByteArrayOutputStream when mimetype is application/json. The workaround is to either:
Set the CFHTTP attribute getasbinary="never" OR
Convert the returned fileContent object into a string using:
<cfset rawJSONString = httpResp.fileContent.toString()>

Coldfusion CFHTTP access API Openpay.mx Unexpected character ('m' (code 109)): expected a valid value

I'm having some problems using the API OpenPay.mx (payments Mexican Banks & other payments services). This API returns JSON. I'm try to access the API with CFHTTP, but it is returning an HTTP 400 Incorrect request error.
Complete error:
https://sandbox-api.openpay.mx/v1/maidzkihk7utcvzhucwk/charges
{"category":"request","description":"Unexpected character ('m' (code
109)): expected a valid value (number, String, array, object, 'true',
'false' or
'null')","http_code":400,"error_code":1001,"request_id":"79a19194-61a2-49e5-8cbc-c83f5c93ce69"}
In the error list from the API help about errors 1001-400, this is the explanation:
The request format is JSON, the fields do not have the correct format,
or the request does not have fields that are required.
ColdFusion Code:
<cfset request_id = "sk_722a9645ea0040899ccd1f0a53dfcf53">
<cfset method="store">
<cfset amount=100>
<cfset description="Cargo con tienda">
<cfset customer="Gabriel Villafuerte">
<cfhttp url="https://sandbox-api.openpay.mx/v1/maidzkihk7utcvzhucwk/charges"
method="post" charset="utf-8" username="#request_id#" password=""
throwonerror="no">
<cfhttpparam type="header" name="Content-Type" value="application/json"/>
<cfhttpparam name="method" type="formfield" value="#method#">
<cfhttpparam name="amount" type="FormField" value="#amount#">
<cfhttpparam name="description" type="FormField" value="#description#">
<cfhttpparam name="customer" type="FormField" value="#customer#">
</cfhttp>
<CFDUMP var="#cfhttp#">
<!---display results--->
<cfoutput>
HTTP Response = #cfhttp.statusCode# <br>
<textarea cols=80 rows=10>
https://sandbox-api.openpay.mx/v1/maidzkihk7utcvzhucwk/charges
#cfhttp.fileContent#
</textarea>
</cfoutput>
These are the rules for the access OpenPay.mx API:
Does anyone have a clue about how I can give the correct format of the fields?
I am not familiar with the API, but looking over the documentation and examples, I suspect the error message means exactly what it says (emphasis mine).
The format of the request is not JSON, the fields do not have the
correct format, OR the request does not have fields that are required.
The request values must be submitted as JSON, not separate fields, and obviously must contain all of the required values. Instead of using "formfield", put the values in a structure. Convert it into a JSON using serializeJSON(). Then pass the JSON to the API using parameter type "body".
You will need to review the API examples, for whichever method you are invoking, to figure out which parameters are required. However, the Charges via Store Example worked with some slight modifications:
The "due_date" cannot be a past date
The "order_id" must be a value not already processed. (I just increased the sample number by an arbitrary amount until I hit a valid id.)
Charges via Store Example
<!--- sample request from API --->
<!--- note: increased "order_id" value by arbitrary amount --->
<cfset timeNow = now()>
<cfset requestData = {
"method" : "store",
"amount" : 100,
"description" : "Cargo con tienda",
"order_id" : "oid-00100",
"due_date" : dateFormat(timeNow, "yyyy-mm-dd")&"T"&timeFormat(timeNow, "HH:nn:ss")
}>
<cfhttp url="https://sandbox-api.openpay.mx/v1/mzdtln0bmtms6o3kck8f/customers/ag4nktpdzebjiye1tlze/charges"
method="post"
charset="utf-8"
username="sk_e568c42a6c384b7ab02cd47d2e407cab:"
password=""
throwonerror="no">
<cfhttpparam type="header" name="Content-Type" value="application/json"/>
<cfhttpparam type="body" value="#serializeJSON(requestData)#">
</cfhttp>
<cfdump var="#cfhttp#">
Result:

How to send header info in cfhttpparam

I have been given the following directions to pull a JSON list of data from a webservice.
GET /criminal_api/1.0/service/requests
HTTP Header: Authorization: Bearer 6EDC52118E164AE659EA2C772F3B9804
The following values in the header Bearer 6EDC52118E164AE659EA2C772F3B9804 are dynamic and will be set using the following content variable
<cfset content = deserializeJSON( {
"access_token": "84F224956C6AB5287038C0209EBAC5AB",
"token_type": "bearer",
"refresh_token": "E48BB9C164FE2125D3BE2CD602E4A692",
"expires_in": 7199,
"scope": "read write"
})>
So I am tried the following:
<cfhttp method="get" url="https://test.mywebsite.com/criminal_api//1.0/service/requests" result="orderList">
<cfhttpparam type="HEADER" name="Authorization" value="#content.token_type# #content.access_token#">
</cfhttp>
But when I check the filecontent instead of getting a JSON list I get: Connection Failure
I have a feeling it is how I am setting the header value I am just not sure what I am doing wrong.
EDIT:
When I added a ":" in between the token type and access token I got a new error:
struct
error -1
error_description Invalid access token: : 82D773278FB69CFBCFB4CB8CEF8AC03D
Obviously it thinks the ":" is part of the access token so it is connecting I am just not sure how to have both values in the value= field so it is read correctly.
Have you tried:
<cfhttp method="get" url="https://test.mywebsite.com/criminal_api//1.0/service/requests" result="orderList" username="#content.token_type#" password="#content.access_token#">
This will produce an authorization header of "Basic Bearer:6EDC52118E164AE659EA2C772F3B9804"
Manually, that would be:
<cfhttp method="get" url="https://test.mywebsite.com/criminal_api//1.0/service/requests" result="orderList">
<cfhttpparam type="HEADER" name="Authorization" value="Basic #content.token_type#:#content.access_token#">
There's also the question of what that hex value contains. Take a look at Getting Basic Authentication to work with ColdFusion - maybe this more closely reflects your situation.

why I can't call functions in a Coldfusion CFC on live server when it works on production?

I'm at a loss.
I'm posting to a Coldfusion8 cfc via Ajax and while it works fine on my local machine, on the live server I cannot call any function in this CFC or it's extended CFC.
I want to do this:
<cfset LOCAL.response = THIS.commit() />
If I dump:
<cfdump output="e:\path\to\dump.txt" label="catch" var="committing">
<cfdump output="e:\path\to\dump.txt" label="catch" var="#THIS#">
<cfset dickhead = THIS.Commit() >
<cfdump output="e:\path\to\dump.txt" label="catch" var="out">
I'm getting:
committing
****************************************************************
catch - component services.form_service_user
extends controllers.form_switch
Methods:
DEFAULTS
[function]
Arguments: none
ReturnType: struct
Roles:
Access: public
Output: false
DisplayName:
Description:
PROCESS
[function]
Arguments: none
ReturnType: struct
Roles:
Access: remote
Output: true
DisplayName:
Description:
COMMIT
[function]
Arguments: none
ReturnType: struct
Roles:
Access: public
Output: false
Description:
...
So the methods/functions are there. But I'm not getting to out. Also I have cleared out the commit function except for a lone return value and a dump. I'm neither getting the dump nor the return value.
QUESTION:
If I'm inside PROCESS, why can I not call COMMIT on the live server when it works fine on production? Is this some kind of caching or whatever setting? Also, I don't have access to the CFadmin, so I'm more or less guessing blind?
Thanks for any infos!
EDIT:
The commit call is inside a try/catch:
<cftry>
<cfdump output="e:\dump.txt" label="catch" var="a">
<cfdump output="e:\dump.txt" label="catch" var="#THIS#">
<cfset LOCAL.Response = THIS.Commit() >
<cfdump output="e:\dump.txt" label="catch" var="b">
<!--- COMMIT ERRORS --->
<cfcatch>
<cfdump output="e:\dump.txt" label="catch" var="ERROR">
<cfset LOCAL.Response.Success = false />
<cfset LOCAL.Response.Errors = [["server_error","commit error"]] />
</cfcatch>
</cftry>
I'm getting the "commit error" returned by AJAX
Check the access attribute on your methods.
If you are calling a method in a component (or inherited from a parent component) from another method in the same component, then access must be private, public or package. It cannot be remote.
Make sure your ColdFusion mappings are correct for the live server.
Make sure you have deployed all of the application files to the live server in the right location.

how to remote debug Coldfusion AJAX application without CFadmin access?

I have to debug an Ajax Coldfusion8 application from a remote access point and am struggling to get anything to work.
The system works fine on my localhost but on the production server, I'm getting nowhere with nowhere being the page loads fine but all Ajax requests go into oblivion (commit error) without triggering a Coldfusion error.
My AJAX setup is as follows:
1). Setup
$(document).on( "click", '.su, .cu' , function() {
var form = $(this).closest('form'),
switcher = form.find('input[name="form_sub"]').val(),
service = "../serve/form_user.cfc",
method = "process",
returnformat = "JSON",
targetUrl = "",
formdata = form.serialize()+"&method="+method+"&returnformat="+returnformat,
successHandler = function() {
alert("hello")
};
ajaxFormSubmit( form, service, formdata, targetUrl, successHandler, "no" );
return false;
});
make AJAX call
var ajaxFormSubmit =
function ( form, service, formdata, targetUrl, successHandler, dataHandler ){
$.ajax({ async: false, type: "post",
url: service, data: formdata, dataType: "json",
success: function( objResponse ){
if (objResponse.SUCCESS){
alert("success!");
successHandler( objResponse )
}
})
}
Server Side
On the server side I have a "master-slave" cfc-setup. There are type-cfcs (user, whatever), which are extensions of a main form_switch like so:
Both files are mapped from application.cfc like so:
THIS.mappings["/controllers"] = GetDirectoryFromPath( GetCurrentTemplatePath() ) & "controllers";
THIS.mappings["/serve"] = GetDirectoryFromPath( GetCurrentTemplatePath() ) & "services";
The type cfc extends to the form_switch
// user cfc
<cfcomponent extends="controllers.form_switch" output="false">
...
</cfcomponent>
The form_switch itself does all the basic stuff like validation and calling database commit in the type.cfc. Looks like this:
<cfcomponent output="false" hint="switchboard for form handling">
...
// function called by AJAX
<cffunction name="Process" access="remote" returntype="struct" output="false">
<cfset var LOCAL = {} />
<cfset LOCAL.Response = { Success = true, Errors = [], Data = "" } />
// set form data
<cfif IsStruct( ARGUMENTS[ 1 ] )>
<cfset THIS.SetFormData( ARGUMENTS[ 1 ] ) />
<cfelse>
<cfset THIS.SetFormData( ARGUMENTS ) />
</cfif>
// validate
<cfset LOCAL.Response.Errors = THIS.Validate() />
// commit
<cfif ArrayLen( LOCAL.Response.Errors )>
<cfset LOCAL.Response.Success = false />
<cfset LOCAL.Response.Errors = serializeJSON(LOCAL.Response.Errors)>
<cfelse>
<cftry>
<cfset LOCAL.Response = THIS.Commit() />
<cfcatch>
<cfset LOCAL.Response.Success = false />
<cfset LOCAL.Response.Errors = [["server_error","commit error"]] />
</cfcatch>
</cftry>
</cfif>
<cfreturn LOCAL.Response />
</cffunction>
</cfcomponent>
I'm clueless why it does not work and even worse I'm guessing blind why?
The ajax returns "commit error", so I'm reaching *form_switch* alright.
Question: How can I debug this?
I tried:
Dumping to screen > does not work as I'm using AJAX.
Dumping to file (I have the full path of the server and I can access the server, so I set up a dump.txt and tried
<cfdump output="F:\full\path\to_root\dump.txt" label="catch" var="hello">
but this gives me a 505 error email with
Diagnose: An error occurred when performing a file operation write on file F:\full\path\to_root\dump.txt
I can't use the CF admin AJAX debugging because I don't have access to the CFAdmin from remote.
What else can I do? Also, if someone knows what the problem might be... answers are also welcome... Must be something basic, like messed up mappings or not having some sort of user privilige on the server ...I assume?
THANKS!
And it's Coldfusion8 and MySql 5.0.88 .... with production being MySQL 5.5, but this is another issue I think.
EDIT:
Ok. I have to use e:\ and E:\ to write to dump.txt from application.cfc. But it still does not work from form_switch.
Have you tried calling your cfc method directly in the browser using url parameters instead of the post you would do from AJAX?
Stick a cfdump in the catch with a cfabort.
Call your cfc like this:
http://yourdomain.com/serve/forms users.cfc?method=process&arg1=qwe&arg2=963
This should either give you a result from your method or a dump of the error
Basic problem indeed....
E:\ != e:\