ColdFusion Post To Twitter Authentication Error - post

First off, my project requires me to make my own module so I can't use the various packages and products out there. Having said that, using the correct token, consumer_key, consumer_secret and token_secret variables, creating the correct Base Signature String and thus OAuth Signature from that string, I have had NO problem grabbing Twitter data via my ColdFusion module. If either of them were off, I wouldn't be able to even get Twitter data.
So knowing that my variables are correct, I am still unable to POST a simple status tweet to my Twitter account via ColdFusion. Each time I try I get the same error: "Code:32, Message:'Could not authenticate you'". Since I know it can't be the variables, it has got to be how I'm sending the POST via ColdFusion, but I am unsure of what I am doing wrong. The following is the code I use to submit the POST:
<cfhttp url="https://api.twitter.com/1.1/statuses/update.json" method="POST" throwonerror="yes" >
<cfhttpparam type="header" name="Authorization" value='OAuth oauth_consumer_key="#oauthStruct.oauth_consumer_key#", oauth_nonce="#oauthStruct.oauth_nonce#", oauth_signature="#oauthStruct.oauth_signature#", oauth_signature_method="#oauthStruct.oauth_signature_method#", oauth_timestamp="#oauthStruct.oauth_timestamp#", oauth_token="#oauthStruct.oauth_token#", oauth_version="#oauthStruct.oauth_version#"'>
<cfhttpparam type="header" name="Content-Type" value="application/x-www-form-urlencoded">
<cfhttpparam type="formfield" name="status" value="#oauthStruct.status#">
</cfhttp>
Can somebody please look over the above code and help me figure out if I'm missing something or submitting incorrectly this call?
Update: I changed the above code to this:
<cfhttp url="https://api.twitter.com/1.1/statuses/update.json" method="POST" throwonerror="yes" >
<cfhttpparam type="header" name="Authorization" value='OAuth oauth_consumer_key="#oauthStruct.oauth_consumer_key#", oauth_nonce="#oauthStruct.oauth_nonce#", oauth_signature="#oauthStruct.oauth_signature#", oauth_signature_method="#oauthStruct.oauth_signature_method#", oauth_timestamp="#oauthStruct.oauth_timestamp#", oauth_token="#oauthStruct.oauth_token#", oauth_version="#oauthStruct.oauth_version#"'>
<cfhttpparam type="header" name="Content-Type" value="application/x-www-form-urlencoded">
<cfhttpparam type="header" name="oauth_consumer_key" value="#oauthStruct.oauth_consumer_key#">
<cfhttpparam type="header" name="oauth_nonce" value="#oauthStruct.oauth_nonce#">
<cfhttpparam type="header" name="oauth_signature" value="#oauthStruct.oauth_signature#">
<cfhttpparam type="header" name="oauth_signature_method" value="#oauthStruct.oauth_signature_method#">
<cfhttpparam type="header" name="oauth_timestamp" value="#oauthStruct.oauth_timestamp#">
<cfhttpparam type="header" name="oauth_token" value="#oauthStruct.oauth_token#">
<cfhttpparam type="header" name="oauth_version" value="#oauthStruct.oauth_version#">
<cfhttpparam type="body" value="#signature_string#">
</cfhttp>
It still does not work, same authenticate error. Any other ideas?

I figured it out. So that others can understand how this process goes, with the new API (1.1), this is how you post a status update to your Twitter account:
<cfhttp url="https://api.twitter.com/1.1/statuses/update.json" method="POST" throwonerror="yes" >
<cfhttpparam type="header" name="Authorization" value='OAuth oauth_consumer_key="#oauthStruct.oauth_consumer_key#", oauth_nonce="#oauthStruct.oauth_nonce#", oauth_signature="#oauthStruct.oauth_signature#", oauth_signature_method="#oauthStruct.oauth_signature_method#", oauth_timestamp="#oauthStruct.oauth_timestamp#", oauth_token="#oauthStruct.oauth_token#", oauth_version="#oauthStruct.oauth_version#"'>
<cfhttpparam type="header" name="Content-Type" value="application/x-www-form-urlencoded">
<cfhttpparam type="body" value="status=#oauthStruct.status#">
</cfhttp>
If I did not have the Authorization header parameter, I ended up with a 400 Bad Request error. You put all the necessary OAuth parameters, including your digital signature, in a comma delimited list as shown above, indicate your content-type, and most importantly, you provide as a URL Query String the remaining variables in the body parameter of your cfhttp call.

Related

CFHTTP and the differences in OAuth2.0 POST login methods

I'm constantly doing login POSTs to various APIs using Coldfusion 2016. No matter how specific the API documentation seems to be (with CURL and HTTPie examples) it always seems to be a trial and error process to work out how to pass the required variable using CFHTTP.
Are there any shortcuts I can use to know which CFHTTP method to use first time? OS, age of API, HEAD requests, etc.
Eg. A login designated as OAuth2.0 can require either...
<!--- "form" variables posted as a URL encoded string in the body --->
<cfhttp method="POST" url="https://some.important.api/oauth/oauth20/token">
<cfhttpparam type="header" name="Content-Type" value="application/x-www-form-urlencoded" />
<cfhttpparam type="body" value="grant_type=client_credentials&client_id=#ID#&client_secret=#secret#" />
</cfhttp>
<!--- "form" variables posted as JSON in the body --->
<cfhttp method="POST" url="https://some.important.api/oauth/oauth20/token">
<cfhttpparam type="header" name="Content-Type" value="application/json" />
<cfhttpparam type="body"
value="{ grant_type : 'client_credentials', client_id : '#ID#', client_secret : '#secret#' }" />
</cfhttp>
<!--- Actual form variables posted as such. This is what makes sense from CURL examples but is only correct about 1/3 of the time --->
<cfhttp method="POST" url="https://some.important.api/oauth/oauth20/token">
<cfhttpparam type="formfield" name="grant_type" value="client_credentials" />
<cfhttpparam type="formfield" name="client_id" value="#ID#" />
<cfhttpparam type="formfield" name="client_secret" value="#secret#" />
</cfhttp>
Another example is passing a file using CFHTTP
<!--- Post a file using CFHTTP. Works 1/2 the time --->
<cfhttp method="POST" url="https://some.important.api/postOrder">
<cfhttpparam type="file" name="order_file" file="#pathToCSVfile#" />
<cfhttpparam type="formfield" name="apikey" value="#apiKey#" />
</cfhttp>
<!--- Requires completely manual method the other 1/2 of the time --->
<cfhttp method="POST" url="https://some.important.api/postOrder">
<cfhttpparam type="header" name="content-type" value="multipart/form-data; boundary=----WebKitFormBoundary7MA4YWxkTrZu0gW" />
<cfhttpparam type="body" value='------WebKitFormBoundary7MA4YWxkTrZu0gW
Content-Disposition: form-data; name="order_file"; filename="myCSVFile"
Content-Type: text/csv
#actualCSVText#
------WebKitFormBoundary7MA4YWxkTrZu0gW
Content-Disposition: form-data; name="apikey"
#apiKey#
------WebKitFormBoundary7MA4YWxkTrZu0gW--' />
</cfhttp>

Posting Multiple Images to Twitter with Coldfusion using MonkehTweet

I am using MonkehTweet Coldfusion wrapper for Twitter Authentication. I have everything up working, but i cannot get my head around posting multiple images using the PostUpdateWithMedia function. I am relatively new to coldfusion, and learning it along the way. A simple call to PostUpdateWithMedia(status="", media="") would post to Twitter with an image, but how can i use this to post multiple images. The PostUpdateWithMedia function from MonkehTweet is,
<cffunction name="postUpdateWithMedia" access="public" output="false" hint="Updates the authenticating user's status. Request must be a POST. A status update with text identical to the authenticating user's current status will be ignored to prevent duplicates.">
<cfargument name="status" required="true" type="String" hint="The text of your status update. URL encode as necessary. Statuses over 140 characters will be forceably truncated." />
<cfargument name="media" required="true" type="string" hint="Up to max_media_per_upload files may be specified in the request, each named media[]. Supported image formats are PNG, JPG and GIF. Animated GIFs are not supported." />
<cfargument name="possibly_sensitive" required="false" type="boolean" default="false" hint="Set to true for content which may not be suitable for every audience." />
<cfargument name="in_reply_to_status_id" required="false" type="String" hint="The ID of an existing status that the update is in reply to." />
<cfargument name="lat" required="false" type="String" hint="The location's latitude that this tweet refers to." />
<cfargument name="long" required="false" type="String" hint="The location's longitude that this tweet refers to." />
<cfargument name="place_id" required="false" type="String" hint="A place in the world. These IDs can be retrieved from geo/reverse_geocode." />
<cfargument name="display_coordinates" required="false" type="String" hint="Whether or not to put a pin on the exact coordinates a tweet has been sent from." />
<cfargument name="checkHeader" required="false" type="boolean" default="false" hint="If set to true, I will abort the request and return the response headers for debugging." />
<cfargument name="timeout" required="false" type="string" default="#variables.instance.timeout#" hint="An optional timeout value, in seconds, that is the maximum time the cfhttp requests can take. If the time-out passes without a response, ColdFusion considers the request to have failed." />
<cfset var strTwitterMethod = '' />
<cfset arguments["media[]"] = arguments.media />
<cfset structDelete(arguments,'media') />
<cfset strTwitterMethod = getCorrectEndpoint('api') & 'statuses/update_with_media.json' />
<cfreturn genericAuthenticationMethod(timeout=getTimeout(), httpURL=strTwitterMethod,httpMethod='POST', parameters=arguments, checkHeader=arguments.checkHeader) />
</cffunction>
I have tried passing in multiple files as,
PostUpdateWithMedia(status="", media="", media=""); but it didnot work. But, I am passing in the multiple media arguments wrong. Can someone help me with how to pass in multiple media arguments.
Unfortunately, MonkehTweet does not include support for the Twitter API media/upload endpoint, which is required for multi-image Tweets - it only supports the deprecated statuses/update_with_media, which still works, but only supports a single image. I also noticed that the code still refers to 140 character Tweets, so it probably has not been updated for some time. I'm not aware of an alternative ColdFusion wrapper for the API, either, so this is something you would need to build for yourself.

PayPal `rm` hidden value not returning POST data

<form action=" https://www.sandbox.paypal.com/cgi-bin/webscr" method="post" id="paypalform" name="paypalform">
<input type="hidden" name="cmd" value="_cart">
<input type="hidden" name="business" value="abc#abc.com">
<input type="hidden" name="no_shipping" value="1">
<input type="hidden" name="upload" value="1">
<input type="hidden" name="currency_code" value="<?php echo $currency ?>">
<input type="hidden" name="rm" value="2">
<input type="hidden" name="country" value="US">
<input type="hidden" name="return" value="http://abc-return.com">
<input type="hidden" name="cancel_return" value="http://abc-cancel.com">
<input type="hidden" name="item_name_1" value="Recharge">
<input type="hidden" name="item_number_1" value="<?php echo $user_id ?>">
<input type="hidden" name="amount_1" value="<?php echo $price ?>">
</form>
<script type="text/javascript">document.paypalform.submit();</script>
I'm using PayPal Payments Standard, via the HTML hidden name-value pair.
Payment was working great and smooth as butter until the 9th of this month, when things started getting worse. The return method rm = 2 was returning the post data to my return page before this date, but when I checked on 9th, the post data is not returning to my page.
I've spent more than a week and still can't figure out how could the same code works one day, and not the day afterwards.
I've implemented this method in my many other projects which could get me into trouble if the data is not posting back on my return page. Everything is just fine with my HTML forms, and I'm also receiving the payment on my PayPal Sandbox
The only issue is I'm not getting the post data on my return page.
Please help me resolve this.
Yes, I also confirm this issue. I am not certain if this is a Paypal change or a Paypal error - for it is difficult to find authoritative answers from them.
I also have a form that used to return POST data to the return url - however it recently stopped working and I was able to get it working again using GET method instead by following this helpful article.
However, this will require some changes to your IPN and success pages.
Curious to know how you solved your issue. Please update us.
Thanks for your update, however, I think there's some confusion here. The IPN url is called the notify_URL and that should receive the POSTed data back to verify the transaction. The Thank you page (or success page) is called the return url - which is where your AutoReturn takes you. I have always been receiving the POST data to my IPN page no problem AND the the POST data to my return URL. However, just in the last few weeks, the POST data stopped coming to my success (return) URL but there's no explanation as to why it would suddenly stop. Now, I can only receive GET data at my success/return page by turning on PDT. But it's OK - I re-wrote my thank you page script to use the GET variables instead. PayPal must have change this without there being any notification - very annoyed with them.

ETRADE - Get Request Token using ColdFusion

I'm attempting to get a Token from ETrade to start the authentication process, but I can't seem to get the signature to match what eTrade thinks it should be.
The Link to the ETrade API:
https://developer.etrade.com/ctnt/dev-portal/getDetail?contentUri=V0_Documentation-AuthorizationAPI-GetRequestToken
The Link to the OAuth Spec:
https://oauth.net/core/1.0a/#sig_base_example
I've had to scrample the consumer key and secret for obvious reasons so this code can't be tested directly... but the issue seems to be that the parameters that I send over don't match the hash that I'm sending.
The response I receive back from Etrade is: oauth_problem=signature_invalid. I've seen a number of libraries, I'm open to attempting one of those but none seem to match up with Etrade's approach. All thoughts welcome! Thanks in advance.
<!--- Generate epoctime --->
<cfset TheDate = now()>
<cfset TheDate = DateAdd("h",5,TheDate)>
<cfset EpocTime = DateDiff("s", "January 1 1970 00:00", DateConvert("local2utc", TheDate))>
<!--- Set Keys / URL --->
<cfset consumer_key = "aaaaaaaaa">
<cfset consumer_secret = "1111111">
<cfset GetTokenURL = "https://etws.etrade.com/oauth/request_token">
<!--- generate message for oauth signature --->
<cfset message = "GET">
<cfset message = message & "&" & "https%3A%2F%2Fetws.etrade.com%2Foauth%2Frequest_token">
<cfset message = message & "&" & "oauth_callback%3Doob">
<cfset message = message & "%26oauth_consumer_key%3D#consumer_key#">
<cfset message = message & "%26oauth_nonce%3DLTg2ODUzOTQ5MTEzMTY3MzQwMzE%3D">
<cfset message = message & "%26oauth_signature_method%3DHMAC-SHA1">
<cfset message = message & "%26oauth_timestamp%3D#epoctime#">
<!--- debug message --->
<cfoutput>#message#</cfoutput><BR><BR>
<!--- Apply HMAC function to generate signature (absent of token) --->
<cfset oauth_signature = hmac(message, consumer_secret & "&", "HMACSHA1")>
<cfoutput>#oauth_signature#</cfoutput><BR><BR>
<!--- Encode and debug output --->
<cfset oauth_signature = urlencodedformat(toBase64(Binarydecode(oauth_signature , "hex")))>
<cfoutput>#oauth_signature#</cfoutput><BR><BR>
<!--- Make the CFHTTP Request --->
<cfhttp result="result" method="GET" charset="utf-8" url="https://etws.etrade.com/oauth/request_token">
<cfhttpparam name="Authorization" type="header" value="OAuth" />
<cfhttpparam name="realm" type="url" value="">
<cfhttpparam name="oauth_callback" type="url" value="oob">
<cfhttpparam name="oauth_consumer_key" type="url" value=#consumer_key#>
<cfhttpparam name="oauth_nonce" type="url" value="LTg2ODUzOTQ5MTEzMTY3MzQwMzE%3D">
<cfhttpparam name="oauth_signature" type="url" value=#oauth_signature#>
<cfhttpparam name="oauth_signature_method" type="url" value="HMAC-SHA1">
<cfhttpparam name="oauth_timestamp" type="url" value="#epoctime#">
</cfhttp>
<!--- Output the results --->
<cfoutput>#result.FileContent#</cfoutput>
<BR><BR>
<cfdump var="#result#">

Internal Server Error when specifying maxResults parameter greater than 7 - Google YouTube Data API v3

I am getting a "500 - Internal Server Error" with no detail message in response when I make a request to the playlists section of the YouTube data api and I specify a maxResults parameter greater than 7.
A maxResults value 7 or below seems to work but not values greater than 7. The documentation states the maxResults parameter can be a value 0-50.
"The maxResults parameter specifies the maximum number of items that should be returned in the result set. Acceptable values are 0 to 50, inclusive. The default value is 5."
Below is the call I am making to the API:
<cfhttp method="get" url="https://www.googleapis.com/youtube/v3/playlists">
<cfhttpparam type="Formfield" name="key" value="MYKEY" />
<cfhttpparam type="Formfield" name="part" value="id,snippet" />
<cfhttpparam type="Formfield" name="channelId" value="CHANNELID" />
<cfhttpparam type="Formfield" name="maxResults" value="50" />
</cfhttp>
I also get the error even when using their built in API Explorer tool on the page below.
https://developers.google.com/youtube/v3/docs/playlists/list
Any help is greatly appreciated.
I also started seeing this issue approximately 37 hours ago. Through some experimentation right now, I tracked down the issue to an empty playlist that the API seems to choke on. Technically, it used to have videos but they've all been deleted. When I deleted that empty playlist the API worked again. Is the 8th playlist in your user's account an empty playlist?
I can confirm that this error was not being thrown 7 days ago, even though I still had such an empty playlist on my account. Something must have been pushed out from youtube's side that has broken this special case.

Resources