PHP ActiveX
PHP ActiveX
Quickbooks OAuth1 Authorization (3-legged)
See more QuickBooks Examples
Demonstrates 3-legged OAuth1 authorization for Quickbooks.Chilkat PHP ActiveX Downloads
<?php
$success = 0;
$consumerKey = 'QUICKBOOKS_CONSUMER_KEY';
$consumerSecret = 'QUICKBOOKS_CONSUMER_SECRET';
$requestTokenUrl = 'https://oauth.intuit.com/oauth/v1/get_request_token';
$authorizeUrl = 'https://appcenter.intuit.com/Connect/Begin';
$accessTokenUrl = 'https://oauth.intuit.com/oauth/v1/get_access_token';
// The port number is picked at random. It's some unused port that won't likely conflict with anything else..
$callbackUrl = 'http://localhost:3017/';
$callbackLocalPort = 3017;
// The 1st step in 3-legged OAuth1.0a is to send a POST to the request token URL to obtain an OAuth Request Token
$http = new COM("Chilkat.Http");
$http->OAuth1 = 1;
$http->OAuthConsumerKey = $consumerKey;
$http->OAuthConsumerSecret = $consumerSecret;
$http->OAuthCallback = $callbackUrl;
$req = new COM("Chilkat.HttpRequest");
$req->HttpVerb = 'POST';
$req->ContentType = 'application/x-www-form-urlencoded';
$resp = new COM("Chilkat.HttpResponse");
$success = $http->HttpReq($requestTokenUrl,$req,$resp);
if ($success == 0) {
print $http->LastErrorText . "\n";
exit;
}
if ($resp->StatusCode >= 400) {
print 'Error response status code = ' . $resp->StatusCode . "\n";
print $resp->BodyStr . "\n";
exit;
}
// If successful, the resp.BodyStr contains this:
// oauth_token=-Wa_KwAAAAAAxfEPAAABV8Qar4Q&oauth_token_secret=OfHY4tZBX2HK4f7yIw76WYdvnl99MVGB&oauth_callback_confirmed=true
print $resp->BodyStr . "\n";
$hashTab1 = new COM("Chilkat.Hashtable");
$hashTab1->AddQueryParams($resp->BodyStr);
$requestToken = $hashTab1->lookupStr('oauth_token');
$requestTokenSecret = $hashTab1->lookupStr('oauth_token_secret');
$http->OAuthTokenSecret = $requestTokenSecret;
print 'oauth_token = ' . $requestToken . "\n";
print 'oauth_token_secret = ' . $requestTokenSecret . "\n";
// ---------------------------------------------------------------------------
// The next step is to form a URL to send to the AuthorizeUrl
// This is an HTTP GET that we load into a popup browser.
$sbUrlForBrowser = new COM("Chilkat.StringBuilder");
$sbUrlForBrowser->Append($authorizeUrl);
$sbUrlForBrowser->Append('?oauth_token=');
$sbUrlForBrowser->Append($requestToken);
$url = $sbUrlForBrowser->getAsString();
// When the urlForBrowser is loaded into a browser, the response from Quickbooks will redirect back to localhost:3017
// We'll need to start a socket that is listening on port 3017 for the callback from the browser.
$listenSock = new COM("Chilkat.Socket");
$backLog = 5;
$success = $listenSock->BindAndListen($callbackLocalPort,$backLog);
if ($success == 0) {
print $listenSock->LastErrorText . "\n";
exit;
}
// Wait for the browser's connection in a background thread.
// (We'll send load the URL into the browser following this..)
// Wait a max of 60 seconds before giving up.
$sock = new COM("Chilkat.Socket");
$maxWaitMs = 60000;
// task is a Chilkat.Task
$task = $listenSock->AcceptNextAsync($maxWaitMs,$sock);
$task->Run();
// Launch the system's default browser navigated to the URL.
$oauth2 = new COM("Chilkat.OAuth2");
$success = $oauth2->LaunchBrowser($url);
if ($success == 0) {
print $oauth2->LastErrorText . "\n";
exit;
}
// Wait for the listenSock's task to complete.
$success = $task->Wait($maxWaitMs);
if (!$success or ($task->StatusInt != 7) or ($task->TaskSuccess != 1)) {
if (!$success) {
// The task.LastErrorText applies to the Wait method call.
print $task->LastErrorText . "\n";
}
else {
// The ResultErrorText applies to the underlying task method call (i.e. the AcceptNextConnection)
print $task->Status . "\n";
print $task->ResultErrorText . "\n";
}
exit;
}
// If we get to this point, the connection from the browser arrived and was accepted.
// We no longer need the listen socket...
// Close it so that it's no longer listening on port 3017.
$listenSock->Close(10);
// Read the start line of the request..
$startLine = $sock->receiveUntilMatch('\r\n');
if ($sock->LastMethodSuccess == 0) {
print $sock->LastErrorText . "\n";
exit;
}
// Read the request header.
$requestHeader = $sock->receiveUntilMatch('\r\n\r\n');
if ($sock->LastMethodSuccess == 0) {
print $sock->LastErrorText . "\n";
exit;
}
// The browser SHOULD be sending us a GET request, and therefore there is no body to the request.
// Once the request header is received, we have all of it.
// We can now send our HTTP response.
$sbResponseHtml = new COM("Chilkat.StringBuilder");
$sbResponseHtml->Append('<html><body><p>Chilkat thanks you!</b></body</html>');
$sbResponse = new COM("Chilkat.StringBuilder");
$sbResponse->Append('HTTP/1.1 200 OK\r\n');
$sbResponse->Append('Content-Length: ');
$sbResponse->AppendInt($sbResponseHtml->Length);
$sbResponse->Append('\r\n');
$sbResponse->Append('Content-Type: text/html\r\n');
$sbResponse->Append('\r\n');
$sbResponse->AppendSb($sbResponseHtml);
$sock->SendString($sbResponse->getAsString());
$sock->Close(50);
// The information we need is in the startLine.
// For example, the startLine will look like this:
// GET /?oauth_token=abcdRQAAZZAAxfBBAAABVabcd_k&oauth_verifier=9rdOq5abcdCe6cn8M3jabcdj3Eabcd HTTP/1.1
$sbStartLine = new COM("Chilkat.StringBuilder");
$sbStartLine->Append($startLine);
$numReplacements = $sbStartLine->Replace('GET /?','');
$numReplacements = $sbStartLine->Replace(' HTTP/1.1','');
$sbStartLine->Trim();
// oauth_token=qyprdP04IrTDIXtP1HRZz0geQdjXHVlGDxXPexlXZsjZNRcY&oauth_verifier=arx5pj5&realmId=193514465596199&dataSource=QBO
print 'startline: ' . $sbStartLine->getAsString() . "\n";
$hashTab1->Clear();
$hashTab1->AddQueryParams($sbStartLine->getAsString());
$requestToken = $hashTab1->lookupStr('oauth_token');
$authVerifier = $hashTab1->lookupStr('oauth_verifier');
// ------------------------------------------------------------------------------
// Finally , we must exchange the OAuth Request Token for an OAuth Access Token.
$http->OAuthToken = $requestToken;
$http->OAuthVerifier = $authVerifier;
$req->HttpVerb = 'POST';
$req->ContentType = 'application/x-www-form-urlencoded';
$success = $http->HttpReq($accessTokenUrl,$req,$resp);
if ($success == 0) {
print $http->LastErrorText . "\n";
exit;
}
// Make sure a successful response was received.
if ($resp->StatusCode != 200) {
print $resp->StatusLine . "\n";
print $resp->Header . "\n";
print $resp->BodyStr . "\n";
exit;
}
// If successful, the resp.BodyStr contains something like this:
// oauth_token=12347455-ffffrrlaBdCjbdGfyjZabcdb5APNtuTPNabcdEpp&oauth_token_secret=RxxxxJ8mTzUhwES4xxxxuJyFWDN8ZfHmrabcddh88LmWE
print $resp->BodyStr . "\n";
$hashTab2 = new COM("Chilkat.Hashtable");
$hashTab2->AddQueryParams($resp->BodyStr);
$accessToken = $hashTab2->lookupStr('oauth_token');
$accessTokenSecret = $hashTab2->lookupStr('oauth_token_secret');
// The access token + secret is what should be saved and used for
// subsequent REST API calls.
print 'Access Token = ' . $accessToken . "\n";
print 'Access Token Secret = ' . $accessTokenSecret . "\n";
// Save this access token for future calls.
$json = new COM("Chilkat.JsonObject");
$json->AppendString('oauth_token',$accessToken);
$json->AppendString('oauth_token_secret',$accessTokenSecret);
// Also save the realmId and dataSource from hashTab1.
$realmId = $hashTab1->lookupStr('realmId');
print 'realmId = ' . $realmId . "\n";
$dataSource = $hashTab1->lookupStr('dataSource');
print 'dataSource = ' . $dataSource . "\n";
$json->AppendString('realmId',$realmId);
$json->AppendString('dataSource',$dataSource);
$fac = new COM("Chilkat.FileAccess");
$fac->WriteEntireTextFile('qa_data/tokens/quickbooks.json',$json->emit(),'utf-8',0);
print 'Success.' . "\n";
?>