OpenXE/classes/Modules/AmazonVendorDF/ServiceFactory.php
2021-05-21 08:49:41 +02:00

173 lines
5.4 KiB
PHP

<?php
namespace Xentral\Modules\AmazonVendorDF;
use Aws\Credentials\Credentials;
use Aws\Signature\SignatureV4;
use GuzzleHttp\Client;
use GuzzleHttp\ClientInterface;
use GuzzleHttp\HandlerStack;
use Psr\Http\Message\RequestInterface;
use Psr\Http\Message\ResponseInterface;
use Psr\Log\LoggerInterface;
use Psr\Log\LogLevel;
use Xentral\Modules\AmazonVendorDF\Data\Token;
use Xentral\Modules\AmazonVendorDF\Service\InventoryService;
use Xentral\Modules\AmazonVendorDF\Service\InvoiceService;
use Xentral\Modules\AmazonVendorDF\Service\PurchaseOrderService;
use Xentral\Modules\AmazonVendorDF\Service\ShippingService;
use Xentral\Modules\AmazonVendorDF\Service\TokenService;
use Xentral\Modules\AmazonVendorDF\Service\TransactionService;
class ServiceFactory
{
const API_BASE_URL = 'https://sellingpartnerapi-eu.amazon.com';
/** @var TokenService */
private $tokenService;
/** @var Token */
private $token;
/** @var string */
private $refreshToken;
/** @var string */
private $clientId;
/** @var string */
private $clientSecret;
/** @var SignatureV4 */
private $signature;
/** @var Credentials */
private $credentials;
/** @var ClientInterface */
private $authenticatedClient;
/** @var LoggerInterface */
private $logger;
public function __construct(
string $refreshToken,
string $clientId,
string $clientSecret,
string $awsIamKey,
string $awsIamSecret,
LoggerInterface $logger
) {
$this->tokenService = new TokenService(new Client());
$this->refreshToken = $refreshToken;
$this->clientId = $clientId;
$this->clientSecret = $clientSecret;
$this->signature = new SignatureV4('execute-api', 'eu-west-1');
$this->credentials = new Credentials($awsIamKey, $awsIamSecret);
$this->logger = $logger;
}
public function getShippingService(): ShippingService
{
return new ShippingService($this->getAuthenticatedClient());
}
public function getInvoiceService(): InvoiceService
{
return new InvoiceService($this->getAuthenticatedClient());
}
public function getInventoryService(): InventoryService
{
return new InventoryService($this->getAuthenticatedClient());
}
public function getPurchaseOrderService(): PurchaseOrderService
{
return new PurchaseOrderService($this->getAuthenticatedClient());
}
public function getTransactionService(): TransactionService
{
return new TransactionService($this->getAuthenticatedClient());
}
private function getAuthenticatedClient(): ClientInterface
{
if (!$this->authenticatedClient || $this->getToken()->isExpired()) {
$stack = HandlerStack::create();
$stack->push($this->getSignatureMiddleware());
$stack->push($this->getLoggingMiddleWare());
$this->authenticatedClient = new Client(
[
'handler' => $stack,
'base_uri' => self::API_BASE_URL,
'headers' => [
'x-amz-access-token' => $this->getToken()->getAccessToken(),
],
]
);
}
return $this->authenticatedClient;
}
private function getSignatureMiddleware()
{
return function (callable $handler) {
return function (RequestInterface $request, array $options) use ($handler) {
return $handler($this->signature->signRequest($request, $this->credentials), $options);
};
};
}
private function getLoggingMiddleWare()
{
return function (callable $handler) {
return function (RequestInterface $request, array $options) use ($handler) {
$promise = $handler($request, $options);
return $promise->then(
function (ResponseInterface $response) use ($request) {
$this->logRequestAndResponse($request, $response, LogLevel::DEBUG);
return $response;
},
function (ResponseInterface $response) use ($request) {
$this->logRequestAndResponse($request, $response, LogLevel::ERROR);
return $response;
}
);
};
};
}
private function logRequestAndResponse(RequestInterface $request, ResponseInterface $response, string $level)
{
$request->getBody()->rewind();
$this->logger->log(
$level,
'Amazon Vendor DF API request',
[
'request' => [
'uri' => (string)$request->getUri(),
'method' => $request->getMethod(),
'body' => json_decode($request->getBody()->getContents(), true),
],
'response' => [
'status_code' => $response->getStatusCode(),
'headers' => $response->getHeaders(),
'body' => json_decode($response->getBody()->getContents(), true),
],
]
);
$response->getBody()->rewind();
}
private function getToken()
{
if (!$this->token) {
$this->token = $this->tokenService->requestToken($this->refreshToken, $this->clientId, $this->clientSecret);
}
return $this->token;
}
}