-
Notifications
You must be signed in to change notification settings - Fork 248
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Update the Core function from PECL OAuth extension to native
- Loading branch information
Showing
16 changed files
with
811 additions
and
122 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,93 @@ | ||
<?php | ||
namespace QuickBooksOnline\API\Core\HttpClients; | ||
|
||
use QuickBooksOnline\API\Exception\SdkException; | ||
|
||
class BaseCurl{ | ||
|
||
private $curl; | ||
|
||
public function __construct(){ | ||
$this->init(); | ||
} | ||
|
||
public function init(){ | ||
if (!extension_loaded('curl')) { | ||
throw new \Exception('The PHP exention curl must be installed to use this PDK.'); | ||
} | ||
$this->curl = curl_init(); | ||
} | ||
|
||
public function isCurlSet(){ | ||
if(!isset($this->curl)) return false; | ||
return true; | ||
} | ||
|
||
public function setupOption($k, $v){ | ||
if($this->isCurlSet()){ | ||
curl_setopt($this->curl, $k, $v); | ||
} else { | ||
throw new SdkException("cURL instance is not set when calling setup Option."); | ||
} | ||
} | ||
|
||
public function setupCurlOptArray(array $ary){ | ||
if($this->isCurlSet()){ | ||
curl_setopt_array($this->curl, $ary); | ||
} else { | ||
throw new SdkException("cURL instance is not set when calling setup curl Option from array."); | ||
} | ||
} | ||
|
||
public function execute(){ | ||
if($this->isCurlSet()){ | ||
return curl_exec($this->curl); | ||
} else { | ||
throw new SdkException("cURL instance is not set when trying to execute it."); | ||
} | ||
} | ||
|
||
public function errno(){ | ||
if($this->isCurlSet()){ | ||
return curl_errno($this->curl); | ||
} else { | ||
throw new SdkException("cURL instance is not set when trying to get errno code from the execution."); | ||
} | ||
} | ||
|
||
public function error(){ | ||
if($this->isCurlSet()){ | ||
return curl_error($this->curl); | ||
} else { | ||
throw new SdkException("cURL instance is not set when trying to get error from the execution."); | ||
} | ||
} | ||
|
||
public function version(){ | ||
return curl_version(); | ||
} | ||
|
||
/** | ||
* Get info from a curl reference from the type | ||
* Mainly used after execute() | ||
* use $type=CURLINFO_HEADER_OUT for header, and $type=CURLINFO_HTTP_CODE for http_code | ||
*/ | ||
public function getInfo($type) | ||
{ | ||
if($this->isCurlSet()){ | ||
return curl_getinfo($this->curl, $type); | ||
}else { | ||
throw new SdkException("cURL instance is not set when trying to get info from the type:" . $type); | ||
} | ||
} | ||
|
||
/** | ||
* Close the resource connection to curl | ||
*/ | ||
public function close() | ||
{ | ||
curl_close($this->curl); | ||
} | ||
} | ||
|
||
?> |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,129 @@ | ||
<?php | ||
namespace QuickBooksOnline\API\Core\HttpClients; | ||
|
||
use QuickBooksOnline\API\Exception\SdkException; | ||
|
||
class CurlHttpClient{ | ||
|
||
//The basecURL will be re-used once it is created. | ||
private $basecURL; | ||
private $rawResponse; | ||
private $faultHandler; | ||
|
||
public function __construct($curl = null) | ||
{ | ||
if(isset($curl)){ | ||
$this->basecURL = $curl; | ||
}else{ | ||
$this->basecURL = new BaseCurl(); | ||
} | ||
} | ||
|
||
public function makeAPICall($url, $method, array $headers, $body, $timeOut, $verifySSL){ | ||
$this->clearAllPreviousData(); | ||
$this->prepareRequest($url, $method, $headers, $body, $timeOut, $verifySSL); | ||
$this->executeRequest(); | ||
$this->handleErrors(); | ||
return $this->getIntuitResponse(); | ||
} | ||
|
||
private function clearAllPreviousData(){ | ||
$this->response = null; | ||
$this->faultHandler = null; | ||
} | ||
/** | ||
* Set the cURL with all required parameters. | ||
* For Query Parameters, for get, please append it to the URI. For POST, please use the $body | ||
*/ | ||
private function prepareRequest($url, $method, array $headerArray, $body, $timeOut, $verifySSL){ | ||
//Set basic Curl Info | ||
$curl_opt = [ | ||
CURLOPT_URL => $url, | ||
CURLOPT_CUSTOMREQUEST => trim($method), | ||
CURLOPT_RETURNTRANSFER => true, | ||
CURLOPT_HTTPHEADER => $this->getHeaders($headerArray), | ||
//10 seconds is allowed to make the connection to the server | ||
CURLOPT_CONNECTTIMEOUT => 10, | ||
CURLOPT_TIMEOUT => isset($timeOut) ? $timeOut : 100, | ||
CURLOPT_RETURNTRANSFER => true, | ||
//When CURLOPT_HEADER is set to 0 the only effect is that header info from the response is excluded from the output. | ||
//So if you don't need it that's a few less KBs that curl will return to you. | ||
//In our case, header is required | ||
CURLOPT_HEADER => true | ||
]; | ||
|
||
if ($method !== "GET" && isset($body)) { | ||
$curl_opt[CURLOPT_POSTFIELDS] = $body; | ||
} | ||
|
||
//Set SSL. Only Enabled for OAuth 2 | ||
$this->setSSL($curl_opt, $verifySSL); | ||
|
||
$this->intializeCurl(); | ||
$this->basecURL->setupCurlOptArray($curl_opt); | ||
} | ||
|
||
private function executeRequest(){ | ||
$this->rawResponse = $this->basecURL->execute(); | ||
} | ||
|
||
private function handleErrors(){ | ||
if($this->basecURL->errno()){ | ||
$errorMsg = $this->basecURL->error(); | ||
$errorNumber = $this->basecURL->errno(); | ||
throw new SdkException("cURL error during making API call. cURL Error Number:[" . $errorNumber . "] with error:[" . $errorMsg . "]"); | ||
} | ||
} | ||
|
||
private function getIntuitResponse(){ | ||
$headerSize = $this->basecURL->getInfo(CURLINFO_HEADER_SIZE); | ||
$rawHeaders = mb_substr($this->rawResponse, 0, $headerSize); | ||
$rawBody = mb_substr($this->rawResponse, $headerSize); | ||
$httpStatusCode = $this->basecURL->getInfo(CURLINFO_HTTP_CODE); | ||
$IntuitResponse = new IntuitResponse($rawHeaders, $rawBody, $httpStatusCode); | ||
return $IntuitResponse; | ||
} | ||
|
||
private function intializeCurl(){ | ||
|
||
if($this->basecURL->isCurlSet()){ return; } | ||
else {$this->basecURL->init();} | ||
} | ||
|
||
private function getHeaders($headers){ | ||
if(!isset($headers) || empty($headers)){ | ||
throw new SdkException("Error. The headers set for cURL are either NULL or Empty"); | ||
}else{ | ||
$convertedHeaders = $this->convertHeaderArrayToHeaders($headers); | ||
return $convertedHeaders; | ||
} | ||
} | ||
|
||
private function setSSL($curl_opt, $verifySSL){ | ||
if($verifySSL){ | ||
$curl_opt[CURLOPT_SSL_VERIFYPEER] = true; | ||
$curl_opt[CURLOPT_SSL_VERIFYHOST] = 2; | ||
$curl_opt[URLOPT_CAINFO] = "";//"Some File Location." | ||
} | ||
} | ||
|
||
/** | ||
* Convert an Array to Curl Headers | ||
* @param array $headerArray The request headers | ||
* @return Curl Array Headers | ||
*/ | ||
public function convertHeaderArrayToHeaders(array $headerArray){ | ||
$headers = array(); | ||
foreach($headerArray as $k => $v){ | ||
$headers[] = $k . ":" . $v; | ||
} | ||
return $headers; | ||
} | ||
|
||
public function closeConnection(){ | ||
$this->basecURL->close(); | ||
} | ||
|
||
} | ||
|
||
?> |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,73 @@ | ||
<?php | ||
namespace QuickBooksOnline\API\Core\HttpClients; | ||
|
||
use QuickBooksOnline\API\Exception\SdkException; | ||
|
||
class IntuitResponse{ | ||
|
||
private $headers; | ||
|
||
private $body; | ||
|
||
private $httpResponseCode; | ||
|
||
private $faultHandler; | ||
|
||
public function __construct($passedHeaders, $passedBody, $passedHttpResponseCode){ | ||
if(isset($passedHeaders)){ | ||
$this->setHeaders($passedHeaders); | ||
}else{ | ||
throw new SdkException("Headers are null."); | ||
} | ||
|
||
if(isset($passedBody)){ | ||
$this->body = $passedBody; | ||
}else{ | ||
throw new SdkException("Response Body are null."); | ||
} | ||
|
||
if(isset($passedHttpResponseCode)){ | ||
$this->httpResponseCode = (int)$passedHttpResponseCode; | ||
if($this->httpResponseCode < 200 || $this->httpResponseCode >= 300){ | ||
$this->faultHandler = new FaultHandler(); | ||
$this->faultHandler->setHttpStatusCode($this->httpResponseCode); | ||
$this->faultHandler->setResponseBody($this->body); | ||
//Manually set the error message | ||
$this->faultHandler->setOAuthHelperError("Invalid auth/bad request (got a 401, expected HTTP/1.1 20X or a redirect)"); | ||
} | ||
}else{ | ||
throw new SdkException("Passed Http status code is null."); | ||
} | ||
} | ||
|
||
public function setHeaders($rawHeaders){ | ||
$rawHeaders = str_replace("\r\n", "\n", $rawHeaders); | ||
$response_headers_rows = explode("\n", trim($rawHeaders)); | ||
foreach ($response_headers_rows as $line) { | ||
if(strpos($line, ': ') == false){ | ||
continue; | ||
}else { | ||
list($key, $value) = explode(': ', $line); | ||
$this->headers[$key] = $value; | ||
} | ||
} | ||
|
||
} | ||
|
||
public function getHeaders(){ | ||
return $this->headers; | ||
} | ||
|
||
public function getBody(){ | ||
return $this->body; | ||
} | ||
|
||
public function getStatusCode(){ | ||
return $this->httpResponseCode; | ||
} | ||
|
||
public function getFaultHandler(){ | ||
return $this->faultHandler; | ||
} | ||
|
||
} |
Oops, something went wrong.