1
0
mirror of https://github.com/invoiceninja/invoiceninja.git synced 2024-11-15 07:33:04 +01:00
invoiceninja/app/Services/Quickbooks/SdkWrapper.php

215 lines
5.9 KiB
PHP
Raw Normal View History

2024-07-29 22:17:29 +02:00
<?php
2024-08-23 14:55:31 +02:00
/**
* Invoice Ninja (https://invoiceninja.com).
*
* @link https://github.com/invoiceninja/invoiceninja source repository
*
* @copyright Copyright (c) 2024. Invoice Ninja LLC (https://invoiceninja.com)
*
* @license https://www.elastic.co/licensing/elastic-license
*/
2024-07-29 22:17:29 +02:00
2024-08-26 12:17:51 +02:00
namespace App\Services\Quickbooks;
2024-07-29 22:17:29 +02:00
2024-08-26 01:49:22 +02:00
use App\DataMapper\QuickbooksSettings;
2024-08-23 06:17:37 +02:00
use Carbon\Carbon;
use App\Models\Company;
use QuickBooksOnline\API\DataService\DataService;
use QuickBooksOnline\API\Core\OAuth\OAuth2\OAuth2AccessToken;
2024-07-29 22:17:29 +02:00
2024-08-23 06:17:37 +02:00
class SdkWrapper
2024-07-29 22:17:29 +02:00
{
2024-08-22 08:45:06 +02:00
public const MAXRESULTS = 10000;
2024-07-29 22:17:29 +02:00
2024-09-21 08:30:13 +02:00
private $entities = ['Customer','Invoice','Item','SalesReceipt', 'Vendor', 'Purchase'];
2024-07-29 22:17:29 +02:00
2024-08-23 06:17:37 +02:00
private OAuth2AccessToken $token;
public function __construct(public DataService $sdk, private Company $company)
2024-07-29 22:17:29 +02:00
{
2024-08-23 06:17:37 +02:00
$this->init();
2024-07-29 22:17:29 +02:00
}
2024-08-23 06:17:37 +02:00
private function init(): self
2024-07-29 22:17:29 +02:00
{
2024-08-23 06:17:37 +02:00
isset($this->company->quickbooks->accessTokenKey) ? $this->setNinjaAccessToken($this->company->quickbooks) : null;
return $this;
2024-08-02 04:34:13 +02:00
}
2024-07-29 22:17:29 +02:00
2024-08-23 06:17:37 +02:00
public function getAuthorizationUrl(): string
2024-08-02 04:34:13 +02:00
{
2024-08-23 06:17:37 +02:00
return $this->sdk->getOAuth2LoginHelper()->getAuthorizationCodeURL();
2024-07-29 22:17:29 +02:00
}
2024-08-23 06:17:37 +02:00
public function getState(): string
2024-07-29 22:17:29 +02:00
{
2024-08-23 06:17:37 +02:00
return $this->sdk->getOAuth2LoginHelper()->getState();
2024-07-29 22:17:29 +02:00
}
2024-08-23 06:17:37 +02:00
public function getRefreshToken(): string
2024-08-22 08:45:06 +02:00
{
2024-08-23 06:17:37 +02:00
return $this->accessToken()->getRefreshToken();
2024-07-29 22:17:29 +02:00
}
2024-08-23 06:17:37 +02:00
public function company()
2024-07-29 22:17:29 +02:00
{
2024-08-23 06:17:37 +02:00
return $this->sdk->getCompanyInfo();
2024-07-29 22:17:29 +02:00
}
2024-08-23 06:17:37 +02:00
/*
accessTokenKey
tokenType
refresh_token
accessTokenExpiresAt
refreshTokenExpiresAt
accessTokenValidationPeriod
refreshTokenValidationPeriod
clientID
clientSecret
realmID
baseURL
*/
public function accessTokenFromCode(string $code, string $realm): OAuth2AccessToken
2024-08-21 07:07:52 +02:00
{
2024-08-23 06:17:37 +02:00
$token = $this->sdk->getOAuth2LoginHelper()->exchangeAuthorizationCodeForToken($code, $realm);
2024-08-22 08:45:06 +02:00
2024-08-23 06:17:37 +02:00
$this->setAccessToken($token);
return $this->accessToken();
}
/**
* Set Stored NinjaAccessToken
*
2024-08-26 01:49:22 +02:00
* @param QuickbooksSettings $token_object
2024-08-23 06:17:37 +02:00
* @return self
*/
2024-08-26 01:49:22 +02:00
public function setNinjaAccessToken(QuickbooksSettings $token_object): self
2024-08-23 06:17:37 +02:00
{
$token = new OAuth2AccessToken(
config('services.quickbooks.client_id'),
config('services.quickbooks.client_secret'),
$token_object->accessTokenKey,
$token_object->refresh_token,
3600,
8726400
);
2024-08-27 06:47:18 +02:00
$token->setAccessTokenExpiresAt($token_object->accessTokenExpiresAt); //@phpstan-ignore-line
$token->setRefreshTokenExpiresAt($token_object->refreshTokenExpiresAt); //@phpstan-ignore-line
2024-08-23 06:17:37 +02:00
$token->setAccessTokenValidationPeriodInSeconds(3600);
$token->setRefreshTokenValidationPeriodInSeconds(8726400);
$this->setAccessToken($token);
if($token_object->accessTokenExpiresAt < time()){
2024-09-23 04:44:34 +02:00
$this->refreshToken($token_object->refresh_token);
2024-08-23 06:17:37 +02:00
}
return $this;
}
2024-09-23 04:43:43 +02:00
public function refreshToken(string $refresh_token): self
{
$new_token = $this->sdk->getOAuth2LoginHelper()->refreshAccessTokenWithRefreshToken($refresh_token);
$this->setAccessToken($new_token);
$this->saveOAuthToken($this->accessToken());
return $this;
}
2024-08-23 06:17:37 +02:00
/**
* SetsAccessToken
*
* @param OAuth2AccessToken $token
* @return self
*/
public function setAccessToken(OAuth2AccessToken $token): self
{
$this->token = $token;
2024-07-29 22:17:29 +02:00
2024-08-23 06:17:37 +02:00
return $this;
2024-07-29 22:17:29 +02:00
}
2024-08-23 06:17:37 +02:00
public function accessToken(): OAuth2AccessToken
2024-07-29 22:17:29 +02:00
{
2024-08-23 06:17:37 +02:00
return $this->token;
2024-07-29 22:17:29 +02:00
}
2024-08-23 06:17:37 +02:00
public function saveOAuthToken(OAuth2AccessToken $token): void
2024-08-22 08:45:06 +02:00
{
2024-08-26 01:49:22 +02:00
$obj = $this->company->quickbooks ?? new QuickbooksSettings();
2024-08-23 06:17:37 +02:00
$obj->accessTokenKey = $token->getAccessToken();
$obj->refresh_token = $token->getRefreshToken();
$obj->accessTokenExpiresAt = Carbon::createFromFormat('Y/m/d H:i:s', $token->getAccessTokenExpiresAt())->timestamp; //@phpstan-ignore-line - QB phpdoc wrong types!!
$obj->refreshTokenExpiresAt = Carbon::createFromFormat('Y/m/d H:i:s', $token->getRefreshTokenExpiresAt())->timestamp; //@phpstan-ignore-line - QB phpdoc wrong types!!
$obj->realmID = $token->getRealmID();
$obj->baseURL = $token->getBaseURL();
2024-07-29 22:17:29 +02:00
2024-08-23 06:17:37 +02:00
$this->company->quickbooks = $obj;
$this->company->save();
2024-07-29 22:17:29 +02:00
}
2024-08-23 14:55:31 +02:00
/// Data Access ///
public function totalRecords(string $entity): int
2024-08-22 08:45:06 +02:00
{
2024-08-23 14:55:31 +02:00
return (int)$this->sdk->Query("select count(*) from $entity");
2024-07-29 22:17:29 +02:00
}
2024-08-26 00:24:51 +02:00
private function queryData(string $query, int $start = 1, $limit = 1000): array
2024-07-29 22:17:29 +02:00
{
return (array) $this->sdk->Query($query, $start, $limit);
}
2024-08-26 00:24:51 +02:00
public function fetchById(string $entity, $id)
{
return $this->sdk->FindById($entity, $id);
}
public function fetchRecords(string $entity, int $max = 100000): array
2024-08-23 14:55:31 +02:00
{
if(!in_array($entity, $this->entities)) {
return [];
}
$records = [];
$start = 0;
2024-08-26 00:24:51 +02:00
$limit = 1000;
2024-08-23 14:55:31 +02:00
try {
2024-09-19 12:12:56 +02:00
2024-08-23 14:55:31 +02:00
$total = $this->totalRecords($entity);
$total = min($max, $total);
// Step 3 & 4: Get chunks of records until the total required records are retrieved
do {
$limit = min(self::MAXRESULTS, $total - $start);
2024-09-19 12:12:56 +02:00
2024-08-23 14:55:31 +02:00
$recordsChunk = $this->queryData("select * from $entity", $start, $limit);
if(empty($recordsChunk)) {
break;
}
$records = array_merge($records, $recordsChunk);
$start += $limit;
2024-09-19 12:12:56 +02:00
2024-08-23 14:55:31 +02:00
} while ($start < $total);
if(empty($records)) {
throw new \Exception("No records retrieved!");
}
} catch (\Throwable $th) {
nlog("Fetch Quickbooks API Error: {$th->getMessage()}");
}
return $records;
}
2024-07-29 22:17:29 +02:00
}