Aug 13, 2013

Get Recent Tweets using Twitter REST API v1.1 by ColdFusion - Part 2

Let's start where we left in Part 1. In this post our main Goal will be to create Dynamic Oath Header for authorizing  an API request. We already created Oath Header using shamApp Application and get our latest tweet but this is not our permanent solution .

To create Oath Header we need
1. Oath Settings - which we created using Twitter Application
2. Time Stamp  - when we create our oath request.
3. Oath Nonce - create using 32 byte random alphanumeric characters.
4. Oath Signature - create using HMAC-SHA1 encryption with Signing Key and Signature Based String (Secret Message).
5. Oath Creation - using above 4
6. HTTP request to User Time Line API to get latest Tweets.

Declare your Oath Settings values first:

/**************Declare your Oath Settings***********************/
<cfscript>
// User Time Line API settings - to get twitter post
request.methodType = "GET";
request.userTimelineAPIURL = "https://api.twitter.com/1.1/statuses/user_timeline.json";
request.tweetCount = 2;
request.oauthSignatureMethod = "HMAC-SHA1";
request.oauthVersion = "1.0";
//Twitter API settings, All below settings will be found on https://dev.twitter.com/apps for user twitter account
request.userId = "shamTwit";
request.oauthConsumerKey = "QpAQWEGHIkAeAUvekvs4WQ";
request.oauthConsumerSecret = "dHKfDqZrMdOUjCDzdnvmcablRyU8Z9TTarWUodEc0I";
request.oauthToken = "110582524-wu4RTO5a0hwuSvo3EXNdTmGYOck6vQIZf014ONjX";
request.oauthTokenSecret = "RndBHs08x7b2awyL4yyzo5LRagfJJzuYB1gGveVvzQ";
</cfscript>
view raw oathSettings hosted with ❤ by GitHub
Now  Create Time Stamp and Oath nonce:
Note: We can also create Timestamp using now() function too but I suggest you to first convert into GMT format time and then to epoch time.

<cfscript>
//Creating Oath TimeStamp:Creating Oath TimeStamp,Its in second : Convert the date to UTC format and then to TimeStamp
request.oauthTimeStamp = DateDiff("s",CreateDate(1970,1,1),DateAdd( "s", GetTimeZoneInfo().UTCTotalOffset,Now()));
//Generating Oath nonce 32 bytes of random data, Here we are creating it by Random Alphanumeric characters
request.alphaNumeric = "0,1,2,3,4,5,6,7,8,9,a,b,c,d,e,f,g,h,i,j,k,l,m,n,o,p,q,r,s,t,u,v,w,x,y,z";
request.alphaIndex = "1";
request.randString = "";
request.randNumber = "";
for(request.alphaIndex=1; request.alphaIndex LTE 32; request.alphaIndex=request.alphaIndex+1) {
request.randNumber=RandRange(1,36);
request.randString="#request.randString##ListGetAt(request.alphaNumeric,request.randNumber)#";
}
</cfscript>
view raw oathSettings1 hosted with ❤ by GitHub

Now lets move to create Signing Key and Signing base string(Message)  using Percent Encoding which will be used to create Oath Signature using HMAC-SHA1 Encryption.

<cfscript>
/*Appending Method Type and API url and converting it to Percent Encoding Format
(RFC 3986 follows Encode all characters except dot[.],tilde[~],hyphen[-],underscore[_])
As API needs signed Signature which used for authorizing a request and folllows "RFC 3986" */
request.encodeAPIUrl = request.methodType & "&" &
replacelist(urlEncodedFormat(request.userTimelineAPIURL),"%2D,%2E,%5F,%7E","-,.,_,~");
//Creating Parameter String to be appended to above API URl
request.parameterString = 'count'& "=" & request.tweetCount & "&" &
'oauth_consumer_key' & "=" & request.oauthConsumerKey & "&" &
'oauth_nonce' & "=" & request.randString & "&" &
'oauth_signature_method' & "=" & request.oauthSignatureMethod & "&" &
'oauth_timestamp'& "=" & request.oauthTimeStamp & "&" &
'oauth_token'& "=" & request.oauthToken & "&" &
'oauth_version'& "=" & request.oauthVersion & "&" &
'user_id'& "=" & request.userId ;
// Creating Signature Base String (Message) by appending percent encode of API url and parameter string
request.signatureString = request.encodeAPIUrl & "&" &
replacelist(urlencodedformat(request.parameterString),"%2D,%2E,%5F,%7E","-,.,_,~");
//Creating Signing Key by concatinating consumersecret and oauth token secret
request.signingKey = request.oauthConsumerSecret & "&" & request.oauthTokenSecret;
</cfscript>
view raw createSignature hosted with ❤ by GitHub
So our Signature Key and Signature base string(secret message) is ready. Lets pass these two to our function  called HmacSHA1 encryption to get Oath Signature.
"There is no MAC function Included in CF 9 but CF 10 provides HMAC function to achieve this. So Let's do it in CF 9 using  MAC and Secret Key class provided by JAVA to achieve it"

<cffunction name = "HmacSHA1Encryption" returntype = "binary" access = "public" output = "false"
hint = "This Function create MAC encryption by passing Signature Key and Signaturestring(Messsage)">
<cfargument
name = "signatureKey" type = "string" required = "true"
hint = "Accepts Signature Key"/>
<cfargument
name = "signatureString" type = "string" required="true"
hint = "Accepts Signature String/Secrete Message"/>
<cfscript>
//Converting String to Binary Representation
local.binaryMessage = charsetDecode(arguments.signatureString, "utf-8");
local.binaryKey = charsetDecode(arguments.signatureKey, "utf-8");
//Creating java objects for secret key : used to construct a SecretKey from a byte array
local.secretKey = createObject("java","javax.crypto.spec.SecretKeySpec");
/*Creating java objects for Massage Auhentication Code (MAC) :
check the integrity of information transmitted based on a secret key */
local.secretMac = createObject("java","javax.crypto.Mac");
//Initialize Secret Key with our binary Key created above using HMAC-SH1 ALGO
local.secretKey = local.secretKey.init(local.binaryKey,"HmacSHA1");
//Get an instance of our MAC generator for the given hashing algorithm.
local.secretMac = local.secretMac.getInstance(local.secretKey.getAlgorithm());
//Initialize the Mac with our secret key.
local.secretMac.init(local.secretKey);
//MAC Processing the given byte with our secret Message.
local.secretMac.update(local.binaryMessage);
//Calling this method to Finish the MAC operation
return local.secretMac.doFinal();
</cfscript>
</cffunction>
<cfscript>
//Calling HmacSHA1Encryption() to get macEncryptedKey
request.macEncryptedKey = HmacSHA1Encryption(request.signingKey,request.signatureString)
//Converting MAC key to base 64
request.base64EncryptedKey = ToString(tobase64(request.macEncryptedKey));
</cfscript>
view raw macEncryption hosted with ❤ by GitHub

So our Final step is to create Oath Header and send this Oath Header via HTTP request to User Timeline API to get our latest tweet post.

<cfscript>
//Calling HmacSHA1Encryption() and setting return value to macEncryptedKey variable
request.macEncryptedKey = HmacSHA1Encryption(request.signingKey,request.signatureString);
//Converting MAC key to base 64
request.base64EncryptedKey = ToString(tobase64(request.macEncryptedKey));
//Creating Oath Signature with MAC key and changing it to percent encode
request.oauthSignature = replacelist(urlEncodedFormat(request.base64EncryptedKey),'%2E,%7E,%2D,%5F','.,~,-,,_');
//Creating Oath Header using above results, Oath Header will be passed in HTTP request to get Tweet result
request.oathHeader = 'OAuth' & " " &
'oauth_consumer_key'& '="' & request.oauthConsumerKey & '", ' &
'oauth_nonce' & '="' & request.randString & '", ' &
'oauth_signature' & '="' & request.oauthSignature & '", ' &
'oauth_signature_method' & '="' & request.oauthSignatureMethod & '", ' &
'oauth_timestamp'& '="' & request.oauthTimeStamp & '", ' &
'oauth_token'& '="' & request.oauthToken & '", ' &
'oauth_version'& '="' & request.oauthVersion & '"';
</cfscript>
<!--- HTTP request to User Time Line API for getting latest tweet
HTTP Url: User Time Line API set in oathSettings.cfm
Count & user_ud set in oathSettings.cfm
Oath Header which we created above --->
<cfhttp url = "#request.userTimelineAPIURL#" method = "GET" throwonerror = "yes" resolveurl = "yes">
<cfhttpparam type = "formfield" name = "count" value = "#request.tweetCount#">
<cfhttpparam type = "formfield" name = "user_id" value = "#request.userId#">
<cfhttpparam type = "header" name = "Authorization" value = "#request.oathHeader#">
</cfhttp>
This HTTP request will give our recent tweeter posts along with lots of details associated with it in JSON format
To see our Twitter post we have to first deserialise this JSON response.

<!--- Deserialize JSON to get recent tweetst--->
<cfloop from = 1 to = #arraylen(DeserializeJSON(cfhttp.fileContent))# index = "i">
<cfoutput>
Twit: #DeserializeJSON(cfhttp.fileContent)[i].text#
</cfoutput> <br/>
</cfloop>
view raw showTwitPost hosted with ❤ by GitHub

So we get our final o/p of latest Tweets posted by user. So now you can display latest tweet in web pages. This is same result which we got from shamApp application in part1

Goal Achieved :)

Useful Links:
https://apigee.com/console/twitter (Major API console to debug )
http://quonos.nl/oauthTester/ (Signature Testing for Twitter)

Hope it will help you.
Happy Tweet :)

No comments:

Post a Comment