Skip to content

Commit

Permalink
private methods for reconnect and dataservice error checking done. pu…
Browse files Browse the repository at this point in the history
…blic methods for reading and creating invoices done
  • Loading branch information
zura2 committed Nov 21, 2017
1 parent 71bf9e5 commit f75b616
Showing 1 changed file with 70 additions and 91 deletions.
161 changes: 70 additions & 91 deletions Quickbooks.php
Original file line number Diff line number Diff line change
@@ -1,10 +1,4 @@
<?php
/**
* Created by PhpStorm.
* User: beqa
* Date: 11/13/17
* Time: 12:25 PM
*/

namespace omcrn\quickbooks;

Expand All @@ -18,101 +12,75 @@

class Quickbooks extends Component
{
private $authMode = 'oauth2';
private $clientID;
private $clientSecret;
private $accessTokenKey;
private $refreshTokenKey;
private $realmID;
private $baseUrl;
public $authMode;
public $realmId;
public $baseUrl;
public $discoveryDocumentUrl;
public $clientId;
public $clientSecret;
public $accessToken;
public $refreshToken;
/**
* @var DataService
*/
private $dataService;
public $dataServiceConfig = null;
private $discoveryDocument;

public function __construct($data, $config = []){
if (!$data || !is_array($data) || !$data['clientID'] || !$data['clientSecret'] || !$data['accessTokenKey'] || !$data['refreshTokenKey'] || !$data['realmID'] || !$data['baseUrl']){
throw new InvalidConfigException('Invalid Config');
}
$this->authMode = $data['authMode'];
parent::__construct($config);
}

public function init()
{
parent::init();
//discovery document. try catch maybe? if not accessible (0% chance) to fall back to default baseUrl. Will do later after consulting with Zura
$this->discoveryDocument = json_decode(file_get_contents(Yii::$app->keyStorage->get('discovery_document')), true);
if ($this->dataServiceConfig === null){
$this->dataServiceConfig = [
'auth_mode' => $this->authMode,
'ClientID' => $this->clientID,
'ClientSecret' => $this->clientSecret,
'accessTokenKey' => $this->accessTokenKey,
'refreshTokenKey' => $this->refreshTokenKey,
'QBORealmID' => $this->realmID,
'baseUrl' => $this->baseUrl,
];
}
$this->dataService = DataService::Configure($this->dataServiceConfig);
$ks = Yii::$app->keyStorage;
$this->accessToken = $ks->get('quickbooks.access-token');
$this->refreshToken = $ks->get('quickbooks.refresh-token');
$this->dataServiceInit();
}

static function getDataServiceConfig(){
$ks = Yii::$app->keyStorage;
private function getDataServiceConfig(){
return [
'auth_mode' => 'oauth2',
'ClientID' => $ks->get('quickbooks.client-id'),
'ClientSecret' => $ks->get('quickbooks.client-secret'),
'accessTokenKey' => $ks->get('quickbooks.access-token'),
'refreshTokenKey' => $ks->get('quickbooks.refresh-token'),
// პროდაქშენისთვის სხვა URL-ა
'baseUrl' => $ks->get('quickbooks.base-url' . (getenv('YII_ENV') == 'dev' ? '-dev' : '')),
'QBORealmID' => $ks->get('quickbooks.realm-id')
'auth_mode' => $this->authMode,
'ClientID' => $this->clientId,
'ClientSecret' => $this->clientSecret,
'baseUrl' => $this->baseUrl,
'QBORealmID' => $this->realmId,
'accessTokenKey' => $this->accessToken,
'refreshTokenKey' => $this->refreshToken
];
}

static function dataServiceInit(){
// ეს ერორს არ აგდებს ტოკენს ვადაც რომ ქონდეს გასული, API CALL-ის დროს უნდა შევამოწმო ერორზე
$dataService = DataService::Configure(self::getDataServiceConfig());
public function dataServiceInit(){
$dataService = DataService::Configure($this->getDataServiceConfig());
if (!$dataService)
exit("Problem while initializing DataService.\n");
return $dataService;
throw new InvalidConfigException("Problem while initializing DataService.\n");
$this->dataService = $dataService;
}

// ერთ საათში ვადა გასდის access token-ს და გვჭირდება refresh token-ის გამოყენებით განახლება
// თვითონ refresh token 101 დღიანია, ამის მერე ყველა ვარიანტში CONNECT QUICKBOOKS ღილაკზეა დაჭერა საჭირო
// თუ refresh token-ს ვადა აქვს გასული, ან საერთოდ არაა დაკონეკტებული, ამ მეთოდმა უნდა ამოაგდოს შეტყობინება, რომ საჭიროა ღილაკზე დაჭერა
// წარმატებული რეკონეკტის მერე ბარემ DataService-ის ინსტანსსაც შევქმნი და დავაბრუნებ
static function reconnect(){
// access token expires in an hour, reconnect function revokes it using refresh token
// refresh token lasts 101 days, after that it is necessary to click he QUICKBOOKS CONNECT button and reauthorize
// tokens are saved in db and in instance and new DataService is instantiated after a successful reconnect
public function reconnect(){
$ks = Yii::$app->keyStorage;

// discovery document. try catch maybe? if not accessible (0% chance) to fall back to default baseUrl. Will do later after consulting with Zura
$discoveryDocument = json_decode(file_get_contents($ks->get('quickbooks.discovery_document' . (getenv('YII_ENV') == 'dev' ? '_dev' : ''))), true);

// refresh_token თუ არ მაქვს, ესე იგი ჯერ პირველადი კონექტიც არ გამიკეტებია და რეკონექტი არ გამოვა
$refreshToken = $ks->get('quickbooks.refresh-token');
if (!$refreshToken){
// if refresh_token is not set, it means the app never connected to quickbooks
if (!$this->refreshToken){
throw new Exception('Refresh token not set. You need to click CONNECT QUICKBOOKS button');
}

//გავიმზადოთ პარამეტრები. უბრალოდ წაკითხვადობისთვის, თორე მე ერთ ხაზზე მერჩია დამეწერა
$clientId = $ks->get('quickbooks.client-id');
$clientSecret = $ks->get('quickbooks.client-secret');
// discovery document
$discoveryDocument = json_decode(file_get_contents($this->discoveryDocumentUrl), true);

//სადაც იგზავნება POST, მომაქვს discovery document-დან
// ready the params, just for readability

// the URL for reconnect POST, from discovery document
$tokenEndPointUrl = $discoveryDocument['token_endpoint'];

//დოკუმენტაციის მიხედვით ტოკენის განახლების დროს აქ უნდა იყოს refresh_token
// according to the dcos, this param is always refresh_token for reconnect
$grantType = 'refresh_token';

//ყველაფერი მაქვს intuit-ის დოკუმენტაციის მიხედვით
//ვაგზავნი POST-ს და ვიღებ JSON რესპონსს
// POST and wait for JSON response
$curl = curl_init();
$header = [
'Accept: application/json',
'Authorization: Basic ' . base64_encode($clientId . ':' . $clientSecret),
'Authorization: Basic ' . base64_encode($this->clientId . ':' . $this->clientSecret),
'Content-Type: application/x-www-form-urlencoded',
'Cache-Control: no-cache'
];
Expand All @@ -122,44 +90,47 @@ static function reconnect(){
CURLOPT_URL => $tokenEndPointUrl,
CURLOPT_POSTFIELDS => http_build_query([
'grant_type' => $grantType,
'refresh_token' => $refreshToken
'refresh_token' => $this->refreshToken
]),
CURLOPT_HTTPHEADER => $header
]);
$result = curl_exec($curl);
//ყოველი შემთხვევისთვის შეცდომაზეც შევამოწმოთ
// check for errors, just in case
if ($curl_error = curl_error($curl)) {
throw new Exception($curl_error);
} else {
$result = json_decode($result, true);
}
curl_close($curl);
// if reponse JSON contains "error" key, it means token is either expired or never set
if (isset($result['error'])){
throw new Exception($result['error'] . '. Need to click CONNECT QUICKBOOKS button');
}

// მიღებული ტოკენების შენახვა ბაზაში, key_storage_item ცხრილში
$ks->set('quickbooks.access-token', $result['access_token']);
// save the received tokens in key_storage_item and in the instance
$this->accessToken = $result['access_token'];
$ks->set('quickbooks.access-token', $this->accessToken);
$ks->set('quickbooks.access-token-expires-in', $result['expires_in']);
$ks->set('quickbooks.refresh-token', $result['refresh_token']);
$this->refreshToken = $result['refresh_token'];
$ks->set('quickbooks.refresh-token', $this->refreshToken);
$ks->set('quickbooks.refresh-token-expires-in', $result['x_refresh_token_expires_in']);

return self::dataServiceInit();
$this->dataServiceInit();
}

static function dataServiceCheckRetry(DataService $dataService, $object){
$resultObject = $dataService->add($object);
$error = $dataService->getLastError();
private function dataServiceCheckRetry($object){
$resultObject = $this->dataService->add($object);
$error = $this->dataService->getLastError();
if ($error !== null){
$statusCode = $error->getHttpStatusCode();
echo "The Status code is: " . $statusCode . "\n";
echo "The Helper message is: " . $error->getOAuthHelperError() . "\n";
echo "The Response message is: " . $error->getResponseBody() . "\n";
if (401 == $statusCode){
// 401 == ვადაგასულ ტოკენს, ამიტომ რეკონეკტი
$dataService = self::reconnect();
// !!! რეკურსია
return self::dataServiceCheckRetry($dataService, $object);
// 401 == token expired, need to reconnect
$this->reconnect();
// !!! recursive call
return $this->dataServiceCheckRetry($object);
}
else{
throw new Exception($statusCode . ' ' . $error->getOAuthHelperError());
Expand All @@ -168,15 +139,23 @@ static function dataServiceCheckRetry(DataService $dataService, $object){
return $resultObject;
}

public static function createCustomer($data){
$dataService = self::dataServiceInit();
$customer = Customer::create($data);
return self::dataServiceCheckRetry($dataService, $customer);
public function createCustomer($data){
return $this->dataServiceCheckRetry(Customer::create($data));
}

public function createInvoice($data){
return $this->dataServiceCheckRetry(Invoice::create($data));
}

public static function createInvoice($data){
$dataService = self::dataServiceInit();
$invoice = Invoice::create($data);
return self::dataServiceCheckRetry($dataService, $invoice);
public function viewInvoices($pageNumber, $pageSize){
$allInvoices = $this->dataService->FindAll('Invoice', $pageNumber, $pageSize);
$error = $this->dataService->getLastError();
if ($error != null) {
echo "The Status code is: " . $error->getHttpStatusCode() . "\n";
echo "The Helper message is: " . $error->getOAuthHelperError() . "\n";
echo "The Response message is: " . $error->getResponseBody() . "\n";
exit();
}
return $allInvoices;
}
}

0 comments on commit f75b616

Please sign in to comment.