Skip to content

Commit 088787f

Browse files
committed
Fix #111 and make static refresh token API call and revoke API call
1 parent e03b742 commit 088787f

File tree

4 files changed

+117
-17
lines changed

4 files changed

+117
-17
lines changed

src/Core/OAuth/OAuth2/OAuth2AccessToken.php

+11-3
Original file line numberDiff line numberDiff line change
@@ -17,6 +17,7 @@
1717
namespace QuickBooksOnline\API\Core\OAuth\OAuth2;
1818

1919
use QuickBooksOnline\API\Exception\SdkException;
20+
use QuickbooksOnline\API\Core\CoreConstants;
2021

2122
/**
2223
* Class OAuth2AccessToken
@@ -146,7 +147,14 @@ public function setRealmID($realmID){
146147
* @param Long $realmID The realmID for the access token
147148
*/
148149
public function setBaseURL($baseURL){
149-
$this->baseURL = $baseURL;
150+
if(strcasecmp($baseURL, CoreConstants::DEVELOPMENT_SANDBOX) == 0){
151+
$this->baseURL = CoreConstants::SANDBOX_DEVELOPMENT;
152+
}else if(strcasecmp($baseURL, CoreConstants::PRODUCTION_QBO) == 0){
153+
$this->baseURL = CoreConstants::QBO_BASEURL;
154+
}else{
155+
$this->baseURL = $baseURL;
156+
}
157+
150158
}
151159

152160
/**
@@ -313,7 +321,7 @@ public function getRealmID(){
313321
if(isset($this->realmID) && !empty($this->realmID)){
314322
return $this->realmID;
315323
}else{
316-
throw new SdkException("Can't get OAuth 2 realmID from Access Token Object. It is not set.");
324+
return "";
317325
}
318326
}
319327

@@ -325,7 +333,7 @@ public function getBaseURL(){
325333
if(isset($this->baseURL) && !empty($this->baseURL)){
326334
return $this->baseURL;
327335
}else{
328-
throw new SdkException("Can't get OAuth 2 baseURL from Access Token Object. It is not set.");
336+
return "";
329337
}
330338
}
331339

src/Core/OAuth/OAuth2/OAuth2LoginHelper.php

+36
Original file line numberDiff line numberDiff line change
@@ -22,6 +22,7 @@
2222
use QuickBooksOnline\API\Exception\ServiceException;
2323
use QuickBooksOnline\API\Core\HttpClients\CurlHttpClient;
2424
use QuickBooksOnline\API\Core\CoreConstants;
25+
use QuickBooksOnline\API\Core\OAuth\OAuth1\OAuth1;
2526

2627
/**
2728
* Class OAuth2LoginHelper
@@ -304,6 +305,41 @@ public function revokeToken($accessTokenOrRefreshToken){
304305
}
305306
}
306307

308+
/**
309+
* Provide OAuth 1 token generation for OAuth 2 token. This function currently is not available on QUickBooks Online yet.
310+
* @param String $consumerKey The consumer key of OAuth 1
311+
* @param String $consumerSecre The consumer Secre of OAuth 1
312+
* @param String $accessToken The access token key of OAuth 1
313+
* @param String $accessTokenSecret The access Token Secret key of OAuth 1
314+
* @param String $scope The scope of the key
315+
* @return OAuth2AccessToken
316+
*/
317+
public function OAuth1ToOAuth2Migration($consumerKey, $consumerSecret, $accessToken, $accessTokenSecret, $scope){
318+
$oauth1Encrypter = new OAuth1($consumerKey, $consumerSecret, $accessToken, $accessTokenSecret);
319+
$parameters = array(
320+
'scope' => $scope,
321+
'redirect_uri' => "https://developer.intuit.com/v2/OAuth2Playground/RedirectUrl",
322+
'client_id' => $this->getClientID(),
323+
'client_secret' => $this->getClientSecret()
324+
);
325+
$baseURL = "https://developer.api.intuit.com/v2/oauth2/tokens/migrate";
326+
$authorizationHeaderInfo = $oauth1Encrypter->getOAuthHeader($baseURL, array(), "POST");
327+
$http_header = array(
328+
'Accept' => 'application/json',
329+
'Authorization' => $authorizationHeaderInfo,
330+
'Content-Type' => 'application/json'
331+
);
332+
$intuitResponse = $this->curlHttpClient->makeAPICall($baseURL, CoreConstants::HTTP_POST, $http_header, json_encode($parameters), null, false);
333+
$this->faultHandler = $intuitResponse->getFaultHandler();
334+
if($this->faultHandler) {
335+
throw new ServiceException("Migrate OAuth 1 token to OAuth 2 token failed. Body: [" . $this->faultHandler->getResponseBody() . "].", $this->faultHandler->getHttpStatusCode());
336+
}else{
337+
$this->faultHandler = false;
338+
$this->oauth2AccessToken = $this->parseNewAccessTokenFromResponse($intuitResponse->getBody());
339+
return $this->getAccessToken();
340+
}
341+
}
342+
307343
/**
308344
* Get the error from last request
309345
*

src/Core/ServiceContext.php

+4
Original file line numberDiff line numberDiff line change
@@ -354,6 +354,10 @@ private function getIppConfig()
354354
}
355355
}
356356

357+
/**
358+
* Update OAuth 2 Access Token with the new Token Value
359+
* @param OAuth2AccessToken The OAuth 2 token that contains access token, refresh token
360+
*/
357361
public function updateOAuth2Token($OAuth2AccessToken){
358362
if($OAuth2AccessToken instanceof OAuth2AccessToken && $this->requestValidator instanceof OAuth2AccessToken){
359363
$this->IppConfiguration->Security = $OAuth2AccessToken;

src/DataService/DataService.php

+66-14
Original file line numberDiff line numberDiff line change
@@ -29,6 +29,7 @@
2929
use QuickBooksOnline\API\Data\IPPAttachable;
3030
use QuickBooksOnline\API\Data\IPPIntuitEntity;
3131
use QuickBooksOnline\API\Data\IPPTaxService;
32+
use QuickBooksOnline\API\Data\IPPid;
3233
use QuickBooksOnline\API\Exception\IdsException;
3334
use QuickBooksOnline\API\Exception\ServiceException;
3435
use QuickBooksOnline\API\Exception\IdsExceptionManager;
@@ -685,7 +686,7 @@ public function FindById($entity, $Id = null)
685686
throw new IdsException('Argument Null Exception when calling FindById for Endpoint:' . get_class($entity));
686687
}
687688
$this->verifyOperationAccess($entity, __FUNCTION__);
688-
$entityId = $entity->Id;
689+
$entityId = $this->getIDString($entity->Id);
689690
// Normal case
690691
$uri = implode(CoreConstants::SLASH_CHAR, array('company', $this->serviceContext->realmId, $urlResource, $entityId));
691692
// Send request
@@ -840,19 +841,22 @@ public function Upload($imgBits, $fileName, $mimeType, $objAttachable)
840841
/**
841842
* Returns PDF for entities which can be downloaded as PDF
842843
* @param IPPIntuitEntity $entity
844+
* @param Directory a writable directory for the PDF to be saved.
843845
* @return boolean
844846
* @throws IdsException, SdkException
845847
*
846848
*/
847-
public function DownloadPDF($entity)
849+
public function DownloadPDF($entity, $dir=null)
848850
{
849851
$this->validateEntityId($entity);
850852
$this->verifyOperationAccess($entity, __FUNCTION__);
851853

854+
//Find the ID
855+
$entityID = $this->getIDString($entity->Id);
852856
$uri = implode(CoreConstants::SLASH_CHAR, array('company',
853857
$this->serviceContext->realmId,
854858
self::getEntityResourceName($entity),
855-
$entity->Id,
859+
$entityID,
856860
CoreConstants::getType(CoreConstants::CONTENTTYPE_APPLICATIONPDF)));
857861
$requestParameters = $this->getGetRequestParameters($uri, CoreConstants::CONTENTTYPE_APPLICATIONPDF);
858862
$restRequestHandler = $this->getRestHandler();
@@ -866,7 +870,7 @@ public function DownloadPDF($entity)
866870
return null;
867871
} else {
868872
$this->lastError = false;
869-
return $this->processDownloadedContent(new ContentWriter($responseBody), $responseCode, $this->getExportFileNameForPDF($entity, "pdf"));
873+
return $this->processDownloadedContent(new ContentWriter($responseBody), $responseCode, $this->getExportFileNameForPDF($entity, "pdf"), $dir);
870874
}
871875
}
872876

@@ -884,16 +888,17 @@ public function SendEmail($entity, $email = null)
884888
$this->validateEntityId($entity);
885889
$this->verifyOperationAccess($entity, __FUNCTION__);
886890

891+
$entityId=$this->getIDString($entity->Id);
887892
$uri = implode(CoreConstants::SLASH_CHAR, array('company',
888893
$this->serviceContext->realmId,
889894
self::getEntityResourceName($entity),
890-
$entity->Id,
895+
$entityId,
891896
'send'));
892897

893898
if (is_null($email)) {
894-
$this->logInfo("Entity " . get_class($entity) . " with id=" . $entity->Id . " is using default email");
899+
$this->logInfo("Entity " . get_class($entity) . " with id=" . $entityId . " is using default email");
895900
} else {
896-
$this->logInfo("Entity " . get_class($entity) . " with id=" . $entity->Id . " is using $email");
901+
$this->logInfo("Entity " . get_class($entity) . " with id=" . $entityId . " is using $email");
897902
if (!$this->verifyEmailAddress($email)) {
898903
$this->logError("Valid email is expected, but received $email");
899904
throw new SdkException("Valid email is expected, but received $email");
@@ -907,11 +912,11 @@ public function SendEmail($entity, $email = null)
907912
* Retrieves specified entities based passed page number and page size and query
908913
*
909914
* @param string $query Query to issue
910-
* @param int $pageNumber Starting page number
911-
* @param int $pageSize Page size
915+
* @param int $startPosition Starting page number
916+
* @param int $maxResults Page size
912917
* @return array Returns an array of entities fulfilling the query. If the response is Empty, it will return NULL
913918
*/
914-
public function Query($query, $pageNumber = 0, $pageSize = 500)
919+
public function Query($query, $startPosition = null, $maxResults = null)
915920
{
916921
$this->serviceContext->IppConfiguration->Logger->RequestLog->Log(TraceLevel::Info, "Called Method Query.");
917922

@@ -922,7 +927,7 @@ public function Query($query, $pageNumber = 0, $pageSize = 500)
922927
}
923928

924929
$httpsUri = implode(CoreConstants::SLASH_CHAR, array('company', $this->serviceContext->realmId, 'query'));
925-
$httpsPostBody = $query;
930+
$httpsPostBody = $this->appendPaginationInfo($query, $startPosition, $maxResults);
926931

927932
$requestParameters = $this->getPostRequestParameters($httpsUri, $httpsContentType);
928933
$restRequestHandler = $this->getRestHandler();
@@ -951,6 +956,38 @@ public function Query($query, $pageNumber = 0, $pageSize = 500)
951956
}
952957
}
953958

959+
/**
960+
* Append the Pagination Data to the Query string if it is not appended
961+
* @param Integer StartPostion
962+
* @param Integer MaxResults
963+
* @return String The query string
964+
*/
965+
private function appendPaginationInfo($query, $startPosition, $maxResults){
966+
$query = trim($query);
967+
if(isset($startPosition) && !empty($startPosition)){
968+
if(stripos($query, "STARTPOSITION") === false){
969+
if(stripos($query, "MAXRESULTS") !== false){
970+
//In MaxResult is defined,we don't set startPosition
971+
}else{
972+
$query = $query . " " . "STARTPOSITION " . $startPosition;
973+
}
974+
}else{
975+
//Ignore the startPosition if it is already used on the query
976+
}
977+
}
978+
979+
if(isset($maxResults) && !empty($maxResults)){
980+
if(stripos($query, "MAXRESULTS") === false){
981+
$query = $query . " " . "MAXRESULTS " . $maxResults;
982+
}else{
983+
//Ignore the maxResults if it is already used on the query
984+
}
985+
}
986+
987+
return $query;
988+
989+
}
990+
954991
/**
955992
* Retrieves all entities by name
956993
*
@@ -1292,7 +1329,7 @@ public function getExportFileNameForPDF($entity, $ext, $usetimestamp = true)
12921329
//TODO: add timestamp or GUID
12931330
$this->validateEntityId($entity);
12941331

1295-
return self::getEntityResourceName($entity) . "_" . $entity->Id . ($usetimestamp ? "_" . time() : "") . ".$ext";
1332+
return self::getEntityResourceName($entity) . "_" . $this->getIDString($entity->Id) . ($usetimestamp ? "_" . time() : "") . ".$ext";
12961333
}
12971334

12981335
/**
@@ -1315,11 +1352,13 @@ protected function getRestHandler()
13151352
* @param string $fileName
13161353
* @return mixed full path with filename or open handler
13171354
*/
1318-
protected function processDownloadedContent(ContentWriter $writer, $responseCode, $fileName = null)
1355+
protected function processDownloadedContent(ContentWriter $writer, $responseCode, $fileName = null, $dir)
13191356
{
13201357
$writer->setPrefix($this->getPrefixFromSettings());
13211358
try {
1322-
if ($this->isTempFile()) {
1359+
if(isset($dir) && !empty($dir)){
1360+
$writer->saveFile($dir, $fileName);
1361+
}else if ($this->isTempFile()) {
13231362
$writer->saveTemp();
13241363
} elseif ($this->isFileExport()) {
13251364
$writer->saveFile($this->getFileExportDir(), $fileName);
@@ -1577,4 +1616,17 @@ public function getCompanyPreferences()
15771616
return $parsedResponseBody;
15781617
}
15791618
}
1619+
1620+
/**
1621+
* Get the actual ID string value of either an IPPid object, or an Id string
1622+
* @param Object $id
1623+
* @return String Id
1624+
*/
1625+
private function getIDString($id){
1626+
if($id instanceof IPPid || $id instanceof QuickBooksOnline\API\Data\IPPid){
1627+
return (String)$id->value;
1628+
}else{
1629+
return (String)$id;
1630+
}
1631+
}
15801632
}

0 commit comments

Comments
 (0)