I'm trying to connect my custom PHP application with QuickBooks Online. I'm using their SDK at https://github.com/intuit/QuickBooks-V3-PHP-SDK. But this code will throw an exception if I have a bad token:
try {
// Refresh the token
$OAuth2LoginHelper = $dataService->getOAuth2LoginHelper();
$refresh = $accessToken->getRefreshToken();
$accessTokenObj = $OAuth2LoginHelper->refreshAccessTokenWithRefreshToken($refresh);
$accessTokenObj->setRealmID($currentServiceContext->realmId);
$dataService->updateOAuth2Token($accessTokenObj);
$_SESSION['sessionAccessToken'] = serialize($accessTokenObj);
} catch (Exception $e) {
print_r($e);
}
Perhaps my PHP knowledge has a hole, but I thought a try{}catch(){} should stop the exception from shutting down my whole application. In this case, the try catch does nothing. The whole system halts to a white page instead and i have an exception listed in my error log.
Obviously, I need to be able to test if the token is good or bad and notify the user to reconnect quickbooks without shutting down the entire app.
What am I missing?
Relevant Error:
"class": "QuickBooksOnline\\API\\Exception\\ServiceException",
"message": "Refresh OAuth 2 Access token with Refresh Token failed. Body: [{\"error\":\"invalid_grant\"}].",
"code": 400,
"file": "/var/www/html/vendor/quickbooks/v3-php-sdk/src/Core/OAuth/OAuth2/OAuth2LoginHelper.php:309",
"trace": [
"/var/www/html/config.php:274",
"/var/www/html/index.php:2"
]
And here's the function in the QBO PHP SDK:
/**
* Get a new access token based on the refresh token. Static function to make easy refreshToken API call.
* @return OAuth2AccessToken A new OAuth2AccessToken that contains all the information(accessTokenkey, RefreshTokenKey, ClientID, and ClientSecret, Expiration Time, etc)
*/
public function refreshAccessTokenWithRefreshToken($refreshToken){
$http_header = $this->constructRefreshTokenHeader();
$requestBody = $this->constructRefreshTokenBody($refreshToken);
$this->LogAPIRequestToLog($requestBody, CoreConstants::OAUTH2_TOKEN_ENDPOINT_URL, $http_header);
$intuitResponse = $this->curlHttpClient->makeAPICall(CoreConstants::OAUTH2_TOKEN_ENDPOINT_URL, CoreConstants::HTTP_POST, $http_header, $requestBody, null, true);
$this->LogAPIResponseToLog($intuitResponse->getBody(), CoreConstants::OAUTH2_TOKEN_ENDPOINT_URL, $intuitResponse->getHeaders());
$this->faultHandler = $intuitResponse->getFaultHandler();
if($this->faultHandler) {
throw new ServiceException("Refresh OAuth 2 Access token with Refresh Token failed. Body: [" . $this->faultHandler->getResponseBody() . "].", $this->faultHandler->getHttpStatusCode());
}else{
$this->faultHandler = false;
$this->oauth2AccessToken = $this->parseNewAccessTokenFromResponse($intuitResponse->getBody());
return $this->getAccessToken();
}
}
This is line 309:
throw new ServiceException("Refresh OAuth 2 Access token with Refresh Token failed. Body: [" . $this->faultHandler->getResponseBody() . "].", $this->faultHandler->getHttpStatusCode());
Sometimes I just gotta write it all out to figure it out.
I see it now. It's not an Exception, it's a ServiceException. So I needed that in my try catch, as follows:
try {
// Refresh the token
$OAuth2LoginHelper = $dataService->getOAuth2LoginHelper();
$refresh = $accessToken->getRefreshToken();
$accessTokenObj = $OAuth2LoginHelper->refreshAccessTokenWithRefreshToken($refresh);
$accessTokenObj->setRealmID($currentServiceContext->realmId);
$dataService->updateOAuth2Token($accessTokenObj);
$_SESSION['sessionAccessToken'] = serialize($accessTokenObj);
} catch (ServiceException $e) {
echo "Error: " . $e->getMessage();
}