From 402c20d184e405e64fb2fee5c34ebeac44c2c41b Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=D0=9F=D0=B0=D0=B2=D0=B5=D0=BB?= Date: Tue, 6 Oct 2020 12:47:38 +0300 Subject: [PATCH] refactor client workflow which resulted in correct behaviour for signatures --- src/Builder/ContainerBuilder.php | 17 +--- src/Builder/TopClientBuilder.php | 3 - src/Component/Exception/TopApiException.php | 31 ++----- .../Storage/ProductSchemaStorage.php | 3 +- src/Factory/TopRequestFactory.php | 91 ++++++++++++++++--- src/Interfaces/RequestSignerInterface.php | 12 ++- src/Interfaces/TopRequestFactoryInterface.php | 7 ++ .../TopRequestProcessorInterface.php | 45 --------- .../Request/AliExpress/SolutionOrderGet.php | 1 - src/Model/Response/ErrorResponseBody.php | 16 ++++ src/Service/RequestSigner.php | 47 +++------- src/Service/TopRequestProcessor.php | 81 ----------------- src/TopClient/TopClient.php | 40 ++++---- .../Builder/AuthorizationUriBuilderTest.php | 39 ++++++++ .../Tests/Service/RequestSignerTest.php | 28 +++--- .../RetailCrm/Tests/TopClient/ClientTest.php | 7 +- 16 files changed, 211 insertions(+), 257 deletions(-) delete mode 100644 src/Interfaces/TopRequestProcessorInterface.php delete mode 100644 src/Service/TopRequestProcessor.php create mode 100644 tests/RetailCrm/Tests/Builder/AuthorizationUriBuilderTest.php diff --git a/src/Builder/ContainerBuilder.php b/src/Builder/ContainerBuilder.php index 406191e..267a515 100644 --- a/src/Builder/ContainerBuilder.php +++ b/src/Builder/ContainerBuilder.php @@ -36,11 +36,9 @@ use RetailCrm\Interfaces\FileItemFactoryInterface; use RetailCrm\Interfaces\RequestSignerInterface; use RetailCrm\Interfaces\RequestTimestampProviderInterface; use RetailCrm\Interfaces\TopRequestFactoryInterface; -use RetailCrm\Interfaces\TopRequestProcessorInterface; use RetailCrm\Service\RequestDataFilter; use RetailCrm\Service\RequestSigner; use RetailCrm\Service\RequestTimestampProvider; -use RetailCrm\Service\TopRequestProcessor; use RuntimeException; use Symfony\Component\Validator\Validation; use Symfony\Component\Validator\Validator\TraceableValidator; @@ -230,16 +228,7 @@ class ContainerBuilder implements BuilderInterface }); $container->set(RequestDataFilter::class, new RequestDataFilter()); $container->set(RequestSignerInterface::class, function (ContainerInterface $container) { - return new RequestSigner( - $container->get(Constants::SERIALIZER), - $container->get(RequestDataFilter::class) - ); - }); - $container->set(TopRequestProcessorInterface::class, function (ContainerInterface $container) { - return (new TopRequestProcessor()) - ->setSigner($container->get(RequestSignerInterface::class)) - ->setValidator($container->get(Constants::VALIDATOR)) - ->setTimestampProvider($container->get(RequestTimestampProviderInterface::class)); + return new RequestSigner($container->get(RequestDataFilter::class)); }); $container->set(TopRequestFactoryInterface::class, function (ContainerInterface $container) { return (new TopRequestFactory()) @@ -247,7 +236,9 @@ class ContainerBuilder implements BuilderInterface ->setSerializer($container->get(Constants::SERIALIZER)) ->setStreamFactory($container->get(StreamFactoryInterface::class)) ->setRequestFactory($container->get(RequestFactoryInterface::class)) - ->setUriFactory($container->get(UriFactoryInterface::class)); + ->setUriFactory($container->get(UriFactoryInterface::class)) + ->setSigner($container->get(RequestSignerInterface::class)) + ->setTimestampProvider($container->get(RequestTimestampProviderInterface::class)); }); $container->set(ServiceLocator::class, function (ContainerInterface $container) { $locator = new ServiceLocator(); diff --git a/src/Builder/TopClientBuilder.php b/src/Builder/TopClientBuilder.php index 323e465..8a5b5b8 100644 --- a/src/Builder/TopClientBuilder.php +++ b/src/Builder/TopClientBuilder.php @@ -15,14 +15,12 @@ namespace RetailCrm\Builder; use RetailCrm\Component\Constants; use RetailCrm\Component\Environment; use RetailCrm\Component\ServiceLocator; -use RetailCrm\Component\Storage\ProductSchemaStorage; use RetailCrm\Factory\ProductSchemaStorageFactory; use RetailCrm\Interfaces\AppDataInterface; use RetailCrm\Interfaces\AuthenticatorInterface; use RetailCrm\Interfaces\BuilderInterface; use RetailCrm\Interfaces\ContainerAwareInterface; use RetailCrm\Interfaces\TopRequestFactoryInterface; -use RetailCrm\Interfaces\TopRequestProcessorInterface; use RetailCrm\TopClient\TopClient; use RetailCrm\Traits\ContainerAwareTrait; @@ -90,7 +88,6 @@ class TopClientBuilder implements ContainerAwareInterface, BuilderInterface $client->setLogger($this->container->get(Constants::LOGGER)); $client->setRequestFactory($this->container->get(TopRequestFactoryInterface::class)); $client->setServiceLocator($this->container->get(ServiceLocator::class)); - $client->setProcessor($this->container->get(TopRequestProcessorInterface::class)); $client->setProductSchemaStorageFactory($this->container->get(ProductSchemaStorageFactory::class)); if (null !== $this->authenticator) { diff --git a/src/Component/Exception/TopApiException.php b/src/Component/Exception/TopApiException.php index 63a2d9b..a937fbe 100644 --- a/src/Component/Exception/TopApiException.php +++ b/src/Component/Exception/TopApiException.php @@ -29,43 +29,28 @@ use Throwable; class TopApiException extends Exception { /** - * @var string $subCode + * @var ErrorResponseBody $error */ - private $subCode; - - /** - * @var string $requestId - */ - private $requestId; + private $error; /** * TopApiException constructor. * * @param \RetailCrm\Model\Response\ErrorResponseBody $responseBody - * @param string|null $requestId - * @param \Throwable|null $previous + * @param \Throwable|null $previous */ - public function __construct(ErrorResponseBody $responseBody, ?string $requestId, Throwable $previous = null) + public function __construct(ErrorResponseBody $responseBody, Throwable $previous = null) { parent::__construct($responseBody->msg, $responseBody->code, $previous); - $this->subCode = $responseBody->subCode; - $this->requestId = $requestId; + $this->error = $responseBody; } /** - * @return string + * @return \RetailCrm\Model\Response\ErrorResponseBody */ - public function getSubCode(): ?string + public function getError(): ErrorResponseBody { - return $this->subCode; - } - - /** - * @return string - */ - public function getRequestId(): ?string - { - return $this->requestId; + return $this->error; } } diff --git a/src/Component/Storage/ProductSchemaStorage.php b/src/Component/Storage/ProductSchemaStorage.php index c1853ae..a65caa8 100644 --- a/src/Component/Storage/ProductSchemaStorage.php +++ b/src/Component/Storage/ProductSchemaStorage.php @@ -98,8 +98,9 @@ class ProductSchemaStorage $error = new ErrorResponseBody(); $error->msg = $response->responseData->result->errorMessage; $error->code = (int) $response->responseData->result->errorCode; + $error->requestId = $response->requestId; - throw new TopApiException($error, $response->requestId); + throw new TopApiException($error); } /** diff --git a/src/Factory/TopRequestFactory.php b/src/Factory/TopRequestFactory.php index 3911423..85f4bdc 100644 --- a/src/Factory/TopRequestFactory.php +++ b/src/Factory/TopRequestFactory.php @@ -19,11 +19,15 @@ use Psr\Http\Message\RequestInterface; use Psr\Http\Message\StreamFactoryInterface; use Psr\Http\Message\UriFactoryInterface; use RetailCrm\Component\Exception\FactoryException; +use RetailCrm\Component\Exception\NotImplementedException; use RetailCrm\Interfaces\AppDataInterface; use RetailCrm\Interfaces\FileItemInterface; +use RetailCrm\Interfaces\RequestSignerInterface; +use RetailCrm\Interfaces\RequestTimestampProviderInterface; use RetailCrm\Interfaces\TopRequestFactoryInterface; use RetailCrm\Model\Request\BaseRequest; use RetailCrm\Service\RequestDataFilter; +use RetailCrm\Service\TopRequestProcessor; use UnexpectedValueException; /** @@ -64,6 +68,38 @@ class TopRequestFactory implements TopRequestFactoryInterface */ private $uriFactory; + /** + * @var \RetailCrm\Interfaces\RequestSignerInterface $signer + */ + private $signer; + + /** + * @var RequestTimestampProviderInterface $timestampProvider + */ + private $timestampProvider; + + /** + * @param \RetailCrm\Interfaces\RequestSignerInterface $signer + * + * @return \RetailCrm\Factory\TopRequestFactory + */ + public function setSigner(RequestSignerInterface $signer): TopRequestFactory + { + $this->signer = $signer; + return $this; + } + + /** + * @param \RetailCrm\Interfaces\RequestTimestampProviderInterface $timestampProvider + * + * @return \RetailCrm\Factory\TopRequestFactory + */ + public function setTimestampProvider(RequestTimestampProviderInterface $timestampProvider): TopRequestFactory + { + $this->timestampProvider = $timestampProvider; + return $this; + } + /** * @param \RetailCrm\Service\RequestDataFilter $filter * @@ -119,6 +155,33 @@ class TopRequestFactory implements TopRequestFactoryInterface return $this; } + /** + * @param \RetailCrm\Model\Request\BaseRequest $request + * + * @return array + * @throws \RetailCrm\Component\Exception\FactoryException + */ + public function getRequestArray(BaseRequest $request): array + { + $requestData = $this->serializer->toArray($request); + + foreach ($requestData as $key => $value) { + if ($value instanceof FileItemInterface) { + continue; + } + + $requestData[$key] = $this->castValue($value); + } + + if (empty($requestData)) { + throw new FactoryException('Empty request data'); + } + + ksort($requestData); + + return $requestData; + } + /** * @param \RetailCrm\Model\Request\BaseRequest $request * @param \RetailCrm\Interfaces\AppDataInterface $appData @@ -130,22 +193,20 @@ class TopRequestFactory implements TopRequestFactoryInterface BaseRequest $request, AppDataInterface $appData ): RequestInterface { - $requestData = $this->serializer->toArray($request); - $requestHasBinaryData = $this->filter->hasBinaryFromRequestData($requestData); + $request->appKey = $appData->getAppKey(); + $this->timestampProvider->provide($request); + $requestData = $this->getRequestArray($request); - ksort($requestData); - - if (empty($requestData)) { - throw new FactoryException('Empty request data'); + try { + $requestData['sign'] = $this->signer->generateSign($requestData, $appData, $request->signMethod); + } catch (NotImplementedException $exception) { + throw new FactoryException(sprintf('Cannot sign request: %s', $exception->getMessage())); } - if ($requestHasBinaryData) { + if ($this->filter->hasBinaryFromRequestData($requestData)) { return $this->makeMultipartRequest($appData->getServiceUrl(), $requestData); } - //TODO - // And how this call should process arrays? It will process them, yes. - // But in which format AliExpress TOP expects that? Should definitely check that. $queryData = http_build_query($requestData); try { @@ -177,11 +238,7 @@ class TopRequestFactory implements TopRequestFactoryInterface if ($value instanceof FileItemInterface) { $builder->addResource($param, $value->getStream(), ['filename' => $value->getFileName()]); } else { - $casted = $this->castValue($value); - - if (null !== $casted) { - $builder->addResource($param, $casted); - } + $builder->addResource($param, $value); } } @@ -203,6 +260,7 @@ class TopRequestFactory implements TopRequestFactoryInterface * @param mixed $value * * @return string|resource|null + * @todo Arrays will be encoded to JSON. Is this correct? Press X to doubt. */ private function castValue($value) { @@ -217,6 +275,9 @@ class TopRequestFactory implements TopRequestFactoryInterface case 'double': case 'string': return (string) $value; + case 'array': + case 'object': + return (string) $this->serializer->serialize($value, 'json'); default: throw new UnexpectedValueException(sprintf('Got value with unsupported type: %s', $type)); } diff --git a/src/Interfaces/RequestSignerInterface.php b/src/Interfaces/RequestSignerInterface.php index 39dac4a..43d3056 100644 --- a/src/Interfaces/RequestSignerInterface.php +++ b/src/Interfaces/RequestSignerInterface.php @@ -13,8 +13,6 @@ namespace RetailCrm\Interfaces; -use RetailCrm\Model\Request\BaseRequest; - /** * Interface RequestSignerInterface * @@ -28,10 +26,14 @@ use RetailCrm\Model\Request\BaseRequest; interface RequestSignerInterface { /** - * Signs provided request. + * Generate sign for provided request data. * - * @param \RetailCrm\Model\Request\BaseRequest $request + * @param array $request * @param \RetailCrm\Interfaces\AppDataInterface $appData + * @param string $signMethod + * + * @return string + * @throws \RetailCrm\Component\Exception\NotImplementedException */ - public function sign(BaseRequest $request, AppDataInterface $appData): void; + public function generateSign(array $request, AppDataInterface $appData, string $signMethod): string; } diff --git a/src/Interfaces/TopRequestFactoryInterface.php b/src/Interfaces/TopRequestFactoryInterface.php index 14b9991..446c768 100644 --- a/src/Interfaces/TopRequestFactoryInterface.php +++ b/src/Interfaces/TopRequestFactoryInterface.php @@ -40,4 +40,11 @@ interface TopRequestFactoryInterface BaseRequest $request, AppDataInterface $appData ): RequestInterface; + + /** + * @param \RetailCrm\Model\Request\BaseRequest $request + * + * @return array + */ + public function getRequestArray(BaseRequest $request): array; } diff --git a/src/Interfaces/TopRequestProcessorInterface.php b/src/Interfaces/TopRequestProcessorInterface.php deleted file mode 100644 index a45039c..0000000 --- a/src/Interfaces/TopRequestProcessorInterface.php +++ /dev/null @@ -1,45 +0,0 @@ - - * @license MIT https://mit-license.org - * @link http://retailcrm.ru - * @see http://help.retailcrm.ru - */ - -namespace RetailCrm\Interfaces; - -use Psr\Http\Message\RequestInterface; -use RetailCrm\Model\Request\BaseRequest; - -/** - * Interface TopRequestProcessorInterface - * - * @category TopRequestProcessorInterface - * @package RetailCrm\Interfaces - * @author RetailDriver LLC - * @license MIT https://mit-license.org - * @link http://retailcrm.ru - * @see https://help.retailcrm.ru - */ -interface TopRequestProcessorInterface -{ - /** - * Modifies request in order to prepare it for TOP API (timestamp, signature, etc). - * - * @param \RetailCrm\Model\Request\BaseRequest $request - * @param \RetailCrm\Interfaces\AppDataInterface $appData - * - * @return void - * @throws \RetailCrm\Component\Exception\FactoryException - * @throws \RetailCrm\Component\Exception\ValidationException - */ - public function process( - BaseRequest $request, - AppDataInterface $appData - ): void; -} diff --git a/src/Model/Request/AliExpress/SolutionOrderGet.php b/src/Model/Request/AliExpress/SolutionOrderGet.php index f67a298..bd4b087 100644 --- a/src/Model/Request/AliExpress/SolutionOrderGet.php +++ b/src/Model/Request/AliExpress/SolutionOrderGet.php @@ -36,7 +36,6 @@ class SolutionOrderGet extends BaseRequest * * @JMS\Type("RetailCrm\Model\Request\AliExpress\Data\OrderQuery") * @JMS\SerializedName("param0") - * @todo Should be marshaled to JSON before building request? Check that. */ public $param0; diff --git a/src/Model/Response/ErrorResponseBody.php b/src/Model/Response/ErrorResponseBody.php index 8959c0a..36cf671 100644 --- a/src/Model/Response/ErrorResponseBody.php +++ b/src/Model/Response/ErrorResponseBody.php @@ -49,4 +49,20 @@ class ErrorResponseBody * @JMS\SerializedName("sub_code") */ public $subCode; + + /** + * @var string $subMsg + * + * @JMS\Type("string") + * @JMS\SerializedName("sub_msg") + */ + public $subMsg; + + /** + * @var string $requestId + * + * @JMS\Type("string") + * @JMS\SerializedName("request_id") + */ + public $requestId; } diff --git a/src/Service/RequestSigner.php b/src/Service/RequestSigner.php index 68c476e..f4d1c81 100644 --- a/src/Service/RequestSigner.php +++ b/src/Service/RequestSigner.php @@ -12,12 +12,10 @@ */ namespace RetailCrm\Service; -use JMS\Serializer\SerializerInterface; use RetailCrm\Component\Exception\NotImplementedException; use RetailCrm\Interfaces\AppDataInterface; use RetailCrm\Interfaces\RequestSignerInterface; use RetailCrm\Model\Enum\AvailableSignMethods; -use RetailCrm\Model\Request\BaseRequest; /** * Class RequestSigner @@ -28,22 +26,9 @@ use RetailCrm\Model\Request\BaseRequest; * @license MIT https://mit-license.org * @link http://retailcrm.ru * @see https://help.retailcrm.ru - * - *TODO - * AliExpress TOP API won't accept signature generated by this component (it returns 'Invalid signature' error message). - * But I used incorrect session token (it can be found in the .env.dist file) - maybe, that's the problem. - * I cannot obtain session token via authorization URL (it says I don't have redirect URL, but it's present in the URL). - * This NEEDS to be checked, and if the problem remains even with the correct session token, it must be fixed. - * Request signing is a vital part of this library. If it doesn't work properly, then this library suddenly - * turns into pile of garbage. */ class RequestSigner implements RequestSignerInterface { - /** - * @var SerializerInterface|\JMS\Serializer\Serializer $serializer - */ - private $serializer; - /** * @var RequestDataFilter $filter */ @@ -52,22 +37,22 @@ class RequestSigner implements RequestSignerInterface /** * RequestSigner constructor. * - * @param \JMS\Serializer\SerializerInterface $serializer * @param \RetailCrm\Service\RequestDataFilter $filter */ - public function __construct(SerializerInterface $serializer, RequestDataFilter $filter) + public function __construct(RequestDataFilter $filter) { $this->filter = $filter; - $this->serializer = $serializer; } /** - * @param BaseRequest $request + * @param array $request * @param \RetailCrm\Interfaces\AppDataInterface $appData + * @param string $signMethod * + * @return string * @throws \RetailCrm\Component\Exception\NotImplementedException */ - public function sign(BaseRequest $request, AppDataInterface $appData): void + public function generateSign(array $request, AppDataInterface $appData, string $signMethod): string { $stringToBeSigned = ''; $params = $this->getDataForSigning($request); @@ -76,33 +61,27 @@ class RequestSigner implements RequestSignerInterface $stringToBeSigned .= $param . $value; } - switch ($request->signMethod) { + switch ($signMethod) { case AvailableSignMethods::MD5: $stringToBeSigned = $appData->getAppSecret() . $stringToBeSigned . $appData->getAppSecret(); - $request->sign = strtoupper(md5($stringToBeSigned)); - break; + return strtoupper(md5($stringToBeSigned)); case AvailableSignMethods::HMAC_MD5: - $request->sign = strtoupper(hash_hmac('md5', $stringToBeSigned, $appData->getAppSecret())); - break; + return strtoupper(hash_hmac('md5', $stringToBeSigned, $appData->getAppSecret())); default: - throw new NotImplementedException(sprintf('Invalid signing method: %s', $request->signMethod)); - break; + throw new NotImplementedException(sprintf('Invalid signing method: %s', $signMethod)); } } /** - * @param \RetailCrm\Model\Request\BaseRequest $request + * @param array $request * * @return array */ - private function getDataForSigning(BaseRequest $request): array + private function getDataForSigning(array $request): array { - $params = $this->filter->filterBinaryFromRequestData($this->serializer->toArray($request)); - $params = array_filter(array_filter($params, static function ($val) { - return !is_array($val); - })); + $params = $this->filter->filterBinaryFromRequestData($request); - unset($params['sign'], $params['session']); + unset($params['sign']); ksort($params); return $params; diff --git a/src/Service/TopRequestProcessor.php b/src/Service/TopRequestProcessor.php deleted file mode 100644 index b0d00ed..0000000 --- a/src/Service/TopRequestProcessor.php +++ /dev/null @@ -1,81 +0,0 @@ - - * @license MIT - * @link http://retailcrm.ru - * @see http://help.retailcrm.ru - */ -namespace RetailCrm\Service; - -use RetailCrm\Interfaces\AppDataInterface; -use RetailCrm\Interfaces\RequestSignerInterface; -use RetailCrm\Interfaces\RequestTimestampProviderInterface; -use RetailCrm\Interfaces\TopRequestProcessorInterface; -use RetailCrm\Model\Request\BaseRequest; -use RetailCrm\Traits\ValidatorAwareTrait; - -/** - * Class TopRequestProcessor - * - * @category TopRequestProcessor - * @package RetailCrm\Service - * @author RetailDriver LLC - * @license MIT - * @link http://retailcrm.ru - * @see https://help.retailcrm.ru - */ -class TopRequestProcessor implements TopRequestProcessorInterface -{ - use ValidatorAwareTrait; - - /** - * @var \RetailCrm\Interfaces\RequestSignerInterface $signer - */ - private $signer; - - /** - * @var RequestTimestampProviderInterface $timestampProvider - */ - private $timestampProvider; - - /** - * @param \RetailCrm\Interfaces\RequestSignerInterface $signer - * - * @return TopRequestProcessor - */ - public function setSigner(RequestSignerInterface $signer): TopRequestProcessor - { - $this->signer = $signer; - return $this; - } - - /** - * @param \RetailCrm\Interfaces\RequestTimestampProviderInterface $timestampProvider - * - * @return TopRequestProcessor - */ - public function setTimestampProvider(RequestTimestampProviderInterface $timestampProvider): TopRequestProcessor - { - $this->timestampProvider = $timestampProvider; - return $this; - } - - /** - * @inheritDoc - */ - public function process( - BaseRequest $request, - AppDataInterface $appData - ): void { - $request->appKey = $appData->getAppKey(); - - $this->timestampProvider->provide($request); - $this->signer->sign($request, $appData); - $this->validate($request); - } -} diff --git a/src/TopClient/TopClient.php b/src/TopClient/TopClient.php index 239f30f..421eac1 100644 --- a/src/TopClient/TopClient.php +++ b/src/TopClient/TopClient.php @@ -30,7 +30,6 @@ use RetailCrm\Interfaces\AuthenticatorInterface; use RetailCrm\Interfaces\BuilderInterface; use RetailCrm\Interfaces\TopClientInterface; use RetailCrm\Interfaces\TopRequestFactoryInterface; -use RetailCrm\Interfaces\TopRequestProcessorInterface; use RetailCrm\Model\Request\BaseRequest; use RetailCrm\Model\Response\BaseResponse; use RetailCrm\Model\Response\TopResponseInterface; @@ -80,11 +79,6 @@ class TopClient implements TopClientInterface */ protected $serviceLocator; - /** - * @var TopRequestProcessorInterface $processor - */ - protected $processor; - /** * @var \RetailCrm\Interfaces\AuthenticatorInterface $authenticator */ @@ -155,17 +149,6 @@ class TopClient implements TopClientInterface $this->serviceLocator = $serviceLocator; } - /** - * @param \RetailCrm\Interfaces\TopRequestProcessorInterface $processor - * - * @return TopClient - */ - public function setProcessor(TopRequestProcessorInterface $processor): TopClient - { - $this->processor = $processor; - return $this; - } - /** * @param \RetailCrm\Interfaces\AuthenticatorInterface $authenticator * @@ -269,8 +252,6 @@ class TopClient implements TopClientInterface throw new TopClientException(sprintf('TopClient only supports JSON mode, got `%s` mode', $request->format)); } - $this->processor->process($request, $this->appData); - $httpRequest = $this->requestFactory->fromModel($request, $this->appData); try { @@ -292,10 +273,19 @@ class TopClient implements TopClientInterface } if (null !== $response->errorResponse) { - throw new TopApiException($response->errorResponse, $response->requestId); + if ($this->debugLogging()) { + $this->logger->debug(sprintf( + ' Request %s (%s): got error response %s', + $request->getMethod(), + $httpRequest->getUri()->__toString(), + $bodyData + )); + } + + throw new TopApiException($response->errorResponse); } - if (null !== $this->logger && !($this->logger instanceof NullLogger) && $this->env->isDebug()) { + if ($this->debugLogging()) { $this->logger->debug(sprintf( ' Request %s (%s): got response %s', $request->getMethod(), @@ -329,6 +319,14 @@ class TopClient implements TopClientInterface return $this->sendRequest($request); } + /** + * @return bool + */ + protected function debugLogging(): bool + { + return null !== $this->logger && !($this->logger instanceof NullLogger) && $this->env->isDebug(); + } + /** * Returns body stream data (it should work like that in order to keep compatibility with some implementations). * diff --git a/tests/RetailCrm/Tests/Builder/AuthorizationUriBuilderTest.php b/tests/RetailCrm/Tests/Builder/AuthorizationUriBuilderTest.php new file mode 100644 index 0000000..db57a80 --- /dev/null +++ b/tests/RetailCrm/Tests/Builder/AuthorizationUriBuilderTest.php @@ -0,0 +1,39 @@ + + * @license http://retailcrm.ru Proprietary + * @link http://retailcrm.ru + * @see http://help.retailcrm.ru + */ + +namespace RetailCrm\Tests\Builder; + +use RetailCrm\Builder\AuthorizationUriBuilder; +use RetailCrm\Test\TestCase; + +/** + * Class AuthorizationUriBuilderTest + * + * @category AuthorizationUriBuilderTest + * @package RetailCrm\Tests\Builder + * @author RetailDriver LLC + * @license https://retailcrm.ru Proprietary + * @link http://retailcrm.ru + * @see https://help.retailcrm.ru + */ +class AuthorizationUriBuilderTest extends TestCase +{ + public function testBuild() + { + $appData = $this->getEnvAppData(); + $builder = new AuthorizationUriBuilder($appData->getAppKey(), $appData->getRedirectUri()); + $result = $builder->build(); + + self::assertNotFalse(strpos($result, $appData->getAppKey())); + self::assertNotFalse(strpos($result, urlencode($appData->getRedirectUri()))); + } +} diff --git a/tests/RetailCrm/Tests/Service/RequestSignerTest.php b/tests/RetailCrm/Tests/Service/RequestSignerTest.php index a10f2e0..789eef9 100644 --- a/tests/RetailCrm/Tests/Service/RequestSignerTest.php +++ b/tests/RetailCrm/Tests/Service/RequestSignerTest.php @@ -16,6 +16,7 @@ use RetailCrm\Component\AppData; use RetailCrm\Component\Constants; use RetailCrm\Interfaces\AppDataInterface; use RetailCrm\Interfaces\RequestSignerInterface; +use RetailCrm\Interfaces\TopRequestFactoryInterface; use RetailCrm\Model\Enum\AvailableSignMethods; use RetailCrm\Test\TestCase; use RetailCrm\Test\TestSignerRequest; @@ -35,43 +36,46 @@ class RequestSignerTest extends TestCase /** * @dataProvider signDataProvider * - * @param \RetailCrm\Test\TestSignerRequest $request + * @param array $request * @param \RetailCrm\Interfaces\AppDataInterface $appData * @param string $expectedHash + * + * @throws \RetailCrm\Component\Exception\NotImplementedException */ - public function testSign(TestSignerRequest $request, AppDataInterface $appData, string $expectedHash): void + public function testSign(array $request, AppDataInterface $appData, string $expectedHash): void { /** @var RequestSignerInterface $signer */ $signer = $this->getContainer()->get(RequestSignerInterface::class); - $signer->sign($request, $appData); - self::assertEquals($expectedHash, $request->sign); + self::assertEquals($expectedHash, $signer->generateSign($request, $appData, $request['sign_method'])); } public function signDataProvider(): array { + /** @var TopRequestFactoryInterface $factory */ + $factory = $this->getContainer()->get(TopRequestFactoryInterface::class); $appData = $this->getAppData(); return [ [ - $this->getTestRequest(AvailableSignMethods::MD5), + $factory->getRequestArray($this->getTestRequest(AvailableSignMethods::MD5)), $appData, - '468BF7C95925C187D0DFD7D042072EB4' + '4BC79C5FAA1B5E254E95A97E65BACEAB' ], [ - $this->getTestRequest(AvailableSignMethods::HMAC_MD5), + $factory->getRequestArray($this->getTestRequest(AvailableSignMethods::HMAC_MD5)), $appData, - '5EF5C76D5C158BFFA9F35BAAA712A879' + '497FA7FCAD98F4F335EFAE2451F8291D' ], [ - $this->getTestRequest(AvailableSignMethods::MD5, true), + $factory->getRequestArray($this->getTestRequest(AvailableSignMethods::MD5, true)), $appData, - '468BF7C95925C187D0DFD7D042072EB4' + '4BC79C5FAA1B5E254E95A97E65BACEAB' ], [ - $this->getTestRequest(AvailableSignMethods::HMAC_MD5, true), + $factory->getRequestArray($this->getTestRequest(AvailableSignMethods::HMAC_MD5, true)), $appData, - '5EF5C76D5C158BFFA9F35BAAA712A879' + '497FA7FCAD98F4F335EFAE2451F8291D' ] ]; } diff --git a/tests/RetailCrm/Tests/TopClient/ClientTest.php b/tests/RetailCrm/Tests/TopClient/ClientTest.php index efd3b6c..fbc27e9 100644 --- a/tests/RetailCrm/Tests/TopClient/ClientTest.php +++ b/tests/RetailCrm/Tests/TopClient/ClientTest.php @@ -12,11 +12,10 @@ */ namespace RetailCrm\Tests\TopClient; +use DateTime; use Http\Message\RequestMatcher\CallbackRequestMatcher; use Psr\Http\Message\RequestInterface; use RetailCrm\Builder\TopClientBuilder; -use RetailCrm\Component\ConstraintViolationListTransformer; -use RetailCrm\Component\Exception\ValidationException; use RetailCrm\Model\Entity\CategoryInfo; use RetailCrm\Model\Enum\FeedOperationTypes; use RetailCrm\Model\Enum\FeedStatuses; @@ -41,7 +40,6 @@ use RetailCrm\Model\Response\AliExpress\Data\SolutionSellerCategoryTreeQueryResp use RetailCrm\Model\Response\AliExpress\Data\SolutionSellerCategoryTreeQueryResponseDataChildrenCategoryList; use RetailCrm\Model\Response\AliExpress\PostproductRedefiningCategoryForecastResponse; use RetailCrm\Model\Response\AliExpress\SolutionFeedListGetResponse; -use RetailCrm\Model\Response\AliExpress\SolutionProductSchemaGetResponse; use RetailCrm\Model\Response\AliExpress\SolutionSellerCategoryTreeQueryResponse; use RetailCrm\Model\Response\ErrorResponseBody; use RetailCrm\Model\Response\Taobao\HttpDnsGetResponse; @@ -602,6 +600,9 @@ EOF; ->setAuthenticator($this->getEnvTokenAuthenticator()) ->build(); $query = new OrderQuery(); + $query->pageSize = 20; + $query->currentPage = 1; + $query->createDateStart = new DateTime(); $query->orderStatus = OrderStatuses::PLACE_ORDER_SUCCESS; $request = new SolutionOrderGet(); $request->param0 = $query;