CF-Slayer
CF-Slayer

Reputation: 169

ColdFusion With QuickBooks - App Tokens and Keys

We currently have an application with old QuickBooks SDK integration.

We've been told that May 15th will be the last day for our implementation to work. Official announcements regarding this are viewable here:

https://developer.intuit.com/blog/2013/12/19/2014-roadmap-and-migration-dates-for-existing-developers

https://developer.intuit.com/blog/2013/12/20/migration-details-quickbooks-online-sdk-to-quickbooks-online-rest-api-v3

We are currently trying to use oauth(http://oauth.riaforge.org)...

Any example or starting point would be nice.

We tried converting Twitter oauth example, but it did not pan out....

QuickBooks documentation are good, but not in-depth for ColdFusion.

Example code:

<!--- set up the parameters --->
<cfset sConsumerKey = "xxxx"> <!--- the consumer key you got from google when registering you app  --->
<cfset sConsumerSecret = "xxxx"> <!--- the consumer secret you got from google --->
<cfset sTokenEndpoint = "https://oauth.intuit.com/oauth/v1/get_request_token"> <!--- Access Token URL --->
<cfset sAuthorizationEndpoint = "https://appcenter.intuit.com/Connect/Begin"> <!--- Authorize URL --->
<cfset sCallbackURL = "www.myurl.com"> <!--- where google will redirect to after the user enters their details --->
<cfset sClientToken = ""> <!--- returned after an access token call --->
<cfset sClientTokenSecret = ""> <!--- returned after an access token call --->


<!--- set up the required objects including signature method--->
<cfset oReqSigMethodSHA = CreateObject("component", "oauth.oauthsignaturemethod_hmac_sha1")>
<cfset oToken = CreateObject("component", "oauth.oauthtoken").createEmptyToken()>
<cfset oConsumer = CreateObject("component", "oauth.oauthconsumer").init(sKey = sConsumerKey, sSecret = sConsumerSecret)>


<cfset oReq = CreateObject("component", "oauth.oauthrequest").fromConsumerAndToken(
    oConsumer = oConsumer,
    oToken = oToken,
    sHttpMethod = "GET",
    sHttpURL = sTokenEndpoint)>
<cfset oReq.signRequest(
    oSignatureMethod = oReqSigMethodSHA,
    oConsumer = oConsumer,
    oToken = oToken)>

<cfhttp url="#oREQ.getString()#&oauth_callback=#sCallbackURL#" method="get" result="tokenResponse"/>

<!--- grab the token and secret from the response if its there--->
<cfif findNoCase("oauth_token",tokenresponse.filecontent)>
    <cfset sClientToken = listlast(listfirst(tokenResponse.filecontent,"&"),"=")>
    <cfset sClientTokenSecret = listlast(listlast(tokenResponse.filecontent,"&"),"=")>

    <!--- you can add some additional parameters to the callback --->
    <cfset sCallbackURL = sCallbackURL & "?" &
        "key=" & sConsumerKey &
        "&" & "secret=" & sConsumerSecret &
        "&" & "token=" & sClientToken &
        "&" & "token_secret=" & sClientTokenSecret &
        "&" & "endpoint=" & URLEncodedFormat(sAuthorizationEndpoint)>

    <cfoutput>#tokenResponse.filecontent#</cfoutput>
<cfelse>
    <cfoutput>#tokenResponse.filecontent#</cfoutput>
</cfif>

Here is the error we are getting:

oauth_problem=parameter_absent&oauth_parameters_absent=oauth_callback

UPDATED NEW ERROR - Fixed the above.

oauth_problem=signature_invalid

Upvotes: 2

Views: 908

Answers (2)

beloitdavisja
beloitdavisja

Reputation: 1509

The problem is you have to add the oauth_callback paramter to the request object before you sign it. Try this:

<!--- set up the parameters --->
<cfset sConsumerKey = "xxxx"> <!--- the consumer key you got from google when registering you app  --->
<cfset sConsumerSecret = "xxxx"> <!--- the consumer secret you got from google --->
<cfset sTokenEndpoint = "https://oauth.intuit.com/oauth/v1/get_request_token"> <!--- Access Token URL --->
<cfset sAuthorizationEndpoint = "https://appcenter.intuit.com/Connect/Begin"> <!--- Authorize URL --->
<cfset sCallbackURL = "www.myurl.com"> <!--- where google will redirect to after the user enters their details --->
<cfset sClientToken = ""> <!--- returned after an access token call --->
<cfset sClientTokenSecret = ""> <!--- returned after an access token call --->


<!--- set up the required objects including signature method--->
<cfset oReqSigMethodSHA = CreateObject("component", "oauth.oauthsignaturemethod_hmac_sha1")>
<cfset oToken = CreateObject("component", "oauth.oauthtoken").createEmptyToken()>
<cfset oConsumer = CreateObject("component", "oauth.oauthconsumer").init(sKey = sConsumerKey, sSecret = sConsumerSecret)>


<cfset oReq = CreateObject("component", "oauth.oauthrequest").fromConsumerAndToken(
    oConsumer = oConsumer,
    oToken = oToken,
    sHttpMethod = "GET",
    sHttpURL = sTokenEndpoint)>
<!--- Add the parameter before you sign the request --->
<cfset oReq.setParameter('oauth_callback', sCallbackURL)>
<cfset oReq.signRequest(
    oSignatureMethod = oReqSigMethodSHA,
    oConsumer = oConsumer,
    oToken = oToken)>

<!--- Now just send the request using oREQ.getString() --->
<cfhttp url="#oREQ.getString()#" method="get" result="tokenResponse"/>

<!--- grab the token and secret from the response if its there--->
<cfif findNoCase("oauth_token",tokenresponse.filecontent)>
    <cfset sClientToken = listlast(listfirst(tokenResponse.filecontent,"&"),"=")>
    <cfset sClientTokenSecret = listlast(listlast(tokenResponse.filecontent,"&"),"=")>

    <!--- you can add some additional parameters to the callback --->
    <cfset sCallbackURL = sCallbackURL & "?" &
        "key=" & sConsumerKey &
        "&" & "secret=" & sConsumerSecret &
        "&" & "token=" & sClientToken &
        "&" & "token_secret=" & sClientTokenSecret &
        "&" & "endpoint=" & URLEncodedFormat(sAuthorizationEndpoint)>

    <cfoutput>#tokenResponse.filecontent#</cfoutput>
<cfelse>
    <cfoutput>#tokenResponse.filecontent#</cfoutput>
</cfif>

Upvotes: 1

user3548176
user3548176

Reputation: 1

I haven't tried it myself but CF11 has apparently done a lot of work on oauth, release date is pre May 15th if I remember Ray correctly. Worth a look?

https://wikidocs.adobe.com/wiki/display/coldfusionen/cfoauth

Upvotes: 0

Related Questions