refactor client workflow which resulted in correct behaviour for signatures
This commit is contained in:
parent
405621bfdf
commit
402c20d184
@ -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();
|
||||
|
@ -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) {
|
||||
|
@ -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;
|
||||
}
|
||||
}
|
||||
|
@ -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);
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -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));
|
||||
}
|
||||
|
@ -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;
|
||||
}
|
||||
|
@ -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;
|
||||
}
|
||||
|
@ -1,45 +0,0 @@
|
||||
<?php
|
||||
|
||||
/**
|
||||
* PHP version 7.3
|
||||
*
|
||||
* @category TopRequestProcessorInterface
|
||||
* @package RetailCrm\Interfaces
|
||||
* @author RetailCRM <integration@retailcrm.ru>
|
||||
* @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 <integration@retailcrm.ru>
|
||||
* @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;
|
||||
}
|
@ -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;
|
||||
|
||||
|
@ -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;
|
||||
}
|
||||
|
@ -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;
|
||||
|
@ -1,81 +0,0 @@
|
||||
<?php
|
||||
|
||||
/**
|
||||
* PHP version 7.3
|
||||
*
|
||||
* @category TopRequestProcessor
|
||||
* @package RetailCrm\Service
|
||||
* @author RetailCRM <integration@retailcrm.ru>
|
||||
* @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 <integration@retailcrm.ru>
|
||||
* @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);
|
||||
}
|
||||
}
|
@ -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(
|
||||
'<AliExpress TOP Client> 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(
|
||||
'<AliExpress TOP Client> 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).
|
||||
*
|
||||
|
@ -0,0 +1,39 @@
|
||||
<?php
|
||||
/**
|
||||
* PHP version 7.3
|
||||
*
|
||||
* @category AuthorizationUriBuilderTest
|
||||
* @package RetailCrm\Tests\Builder
|
||||
* @author RetailCRM <integration@retailcrm.ru>
|
||||
* @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 <integration@retailcrm.ru>
|
||||
* @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())));
|
||||
}
|
||||
}
|
@ -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'
|
||||
]
|
||||
];
|
||||
}
|
||||
|
@ -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;
|
||||
|
Loading…
Reference in New Issue
Block a user