Commit bd6156dd authored by Oleksandr Gotgelf's avatar Oleksandr Gotgelf
Browse files

Unit tests fix

parent 916311b3
<?php
declare(strict_types=1);
namespace Trilix\CrefoPay\Model\Mns;
use DateTime;
use Exception;
use Magento\Framework\Exception\AlreadyExistsException;
use Magento\Framework\Exception\StateException;
use Psr\Log\LoggerInterface;
use Trilix\CrefoPay\Api\Data\CrefoPayMnsInterface;
use Trilix\CrefoPay\Client\Constants;
use Trilix\CrefoPay\Client\UpgFactory;
use Trilix\CrefoPay\Logger\MnsLogger;
use Trilix\CrefoPay\Model\Mns\ProcessSupervisor\SupervisorInterface;
use Upg\Library\Callback\Exception\MacValidation;
use Magento\Framework\Api\SearchCriteriaBuilder;
class MnsService
{
/**
* @var UpgFactory
*/
private $upgFactory;
/**
* @var LoggerInterface
*/
private $logger;
/**
* @var MnsLogger
*/
private $mnsLogger;
/**
* @var MnsConsumerPool
*/
private $consumerPool;
/**
* @var MnsEventFactory
*/
private $mnsEventFactory;
/**
* @var MnsRepository
*/
private $mnsRepository;
/**
* @var SearchCriteriaBuilder
*/
private $searchCriteriaBuilder;
/**
* @var SupervisorInterface
*/
private $supervisor;
/**
* MnsService constructor.
*
* @param UpgFactory $upgFactory
* @param LoggerInterface $logger
* @param MnsLogger $mnsLogger
* @param MnsConsumerPool $consumerPool
* @param MnsEventFactory $mnsEventFactory
* @param MnsRepository $mnsRepository
* @param SearchCriteriaBuilder $searchCriteriaBuilder
* @param SupervisorInterface $supervisor
*/
public function __construct(
UpgFactory $upgFactory,
LoggerInterface $logger,
MnsLogger $mnsLogger,
MnsConsumerPool $consumerPool,
MnsEventFactory $mnsEventFactory,
MnsRepository $mnsRepository,
SearchCriteriaBuilder $searchCriteriaBuilder,
SupervisorInterface $supervisor
) {
$this->upgFactory = $upgFactory;
$this->logger = $logger;
$this->mnsLogger = $mnsLogger;
$this->consumerPool = $consumerPool;
$this->mnsEventFactory = $mnsEventFactory;
$this->mnsRepository = $mnsRepository;
$this->searchCriteriaBuilder = $searchCriteriaBuilder;
$this->supervisor = $supervisor;
}
/**
* Save the MNS event for further processing
*
* @param array $notificationDetails
*/
public function acknowledge(array $notificationDetails): void
{
$macCalculator = $this->upgFactory->createCallbackMacCalculator($notificationDetails);
try {
$macCalculator->validateResponse();
$mnsEvent = $this->mnsEventFactory->createFromPost($notificationDetails);
if (!$this->doesNotificationAlreadyExist($mnsEvent)) {
$this->mnsRepository->save($mnsEvent);
}
} catch (MacValidation $e) {
$mac = array_key_exists('mac', $notificationDetails) ? $notificationDetails['mac'] : '';
$this->mnsLogger->error(sprintf('MAC validation failed for CrefoPay MNS event: %s', $mac));
return;
} catch (Exception $e) {
$this->logger->error(sprintf('Error during acknowledging MNS event: %s', $e->getMessage()));
$this->mnsLogger->error($e->getMessage());
}
}
/**
* Process all the pending MNS events
*
* @param SupervisorInterface|null $supervisor
* @throws AlreadyExistsException
* @throws StateException
*/
public function process(SupervisorInterface $supervisor = null): void
{
if ($supervisor) {
$this->supervisor = $supervisor;
}
$isTotalCountReported = false;
$itemsProcessedCnt = 0;
$searchCriteria = $this->searchCriteriaBuilder
->addFilter(CrefoPayMnsInterface::MNS_STATUS, CrefoPayMnsInterface::STATUS_ACK)
->setPageSize(100)
->setCurrentPage(1)
->create();
while ($searchResult = $this->mnsRepository->getList($searchCriteria)) {
if (!$isTotalCountReported) {
$this->supervisor->setTotalCount($searchResult->getTotalCount());
$isTotalCountReported = true;
}
foreach ($searchResult->getItems() as $mns) {
$this->processMns($mns);
}
$searchCriteria->setCurrentPage($searchCriteria->getCurrentPage() + 1);
$itemsProcessedCnt += $searchCriteria->getPageSize();
if ($itemsProcessedCnt >= $searchResult->getTotalCount()) {
break;
}
}
}
/**
* @param MnsEvent $mnsEvent
* @return bool
*/
private function doesNotificationAlreadyExist(MnsEvent $mnsEvent): bool
{
$result = false;
if (in_array(
$mnsEvent->getTransactionStatus(),
[Constants::TX_ACK, Constants::TX_CIA, Constants::TX_MERCHANT], true
)) {
$searchCriteria = $this->searchCriteriaBuilder->addFilter(
CrefoPayMnsInterface::ORDER_INCREMENT_ID,
$mnsEvent->getIncrementOrderId()
)->addFilter(
CrefoPayMnsInterface::STORE_ID,
$mnsEvent->getStoreId()
)->addFilter(
CrefoPayMnsInterface::TRANSACTION_STATUS,
$mnsEvent->getTransactionStatus()
)->create();
if ($this->mnsRepository->getList($searchCriteria)->getTotalCount()) {
$result = true;
}
}
return $result;
}
/**
* @param MnsEvent $mns
* @throws AlreadyExistsException
* @throws StateException
*/
private function processMns(MnsEvent $mns): void
{
$numberOfAttemptsToProcessNotification = $mns->getNumberOfAttemptsToProcessNotification() + 1;
try {
$applicableConsumers = $this->consumerPool->getConsumersByEvent($mns);
foreach ($applicableConsumers as $consumer) {
$consumer->process($mns);
}
//throw new Exception("test");
} catch (Exception $e) {
$mns->setProcessedAt(new DateTime());
$mns->setErrorDetails(sprintf('%s (%s): %s', get_class($e), $e->getCode(), $e->getMessage()));
if ($numberOfAttemptsToProcessNotification >= 3) {
$mns->setMnsStatus(CrefoPayMnsInterface::STATUS_FAILED);
}
$mns->setNumberOfAttemptsToProcessNotification($numberOfAttemptsToProcessNotification);
$this->mnsRepository->save($mns);
$this->supervisor->fail($mns);
return;
}
$mns->setProcessedAt(new DateTime());
$mns->setMnsStatus(CrefoPayMnsInterface::STATUS_CONSUMED);
$mns->setNumberOfAttemptsToProcessNotification($numberOfAttemptsToProcessNotification);
$this->mnsRepository->save($mns);
$this->supervisor->ok($mns);
}
}
<?php
declare(strict_types=1);
namespace Trilix\CrefoPay\Model\Mns;
use DateTime;
use Exception;
use Magento\Framework\Exception\AlreadyExistsException;
use Magento\Framework\Exception\StateException;
use Psr\Log\LoggerInterface;
use Magento\Framework\Api\SearchCriteriaBuilder;
use Upg\Library\Callback\Exception\MacValidation;
use Trilix\CrefoPay\Api\Data\CrefoPayMnsInterface;
use Trilix\CrefoPay\Client\Constants;
use Trilix\CrefoPay\Client\UpgFactory;
use Trilix\CrefoPay\Logger\MnsLogger;
use Trilix\CrefoPay\Model\Mns\ProcessSupervisor\SupervisorInterface;
class MnsService
{
/**
* @var UpgFactory
*/
private $upgFactory;
/**
* @var LoggerInterface
*/
private $logger;
/**
* @var MnsLogger
*/
private $mnsLogger;
/**
* @var MnsConsumerPool
*/
private $consumerPool;
/**
* @var MnsEventFactory
*/
private $mnsEventFactory;
/**
* @var MnsRepository
*/
private $mnsRepository;
/**
* @var SearchCriteriaBuilder
*/
private $searchCriteriaBuilder;
/**
* @var SupervisorInterface
*/
private $supervisor;
/**
* MnsService constructor.
*
* @param UpgFactory $upgFactory
* @param LoggerInterface $logger
* @param MnsLogger $mnsLogger
* @param MnsConsumerPool $consumerPool
* @param MnsEventFactory $mnsEventFactory
* @param MnsRepository $mnsRepository
* @param SearchCriteriaBuilder $searchCriteriaBuilder
* @param SupervisorInterface $supervisor
*/
public function __construct(
UpgFactory $upgFactory,
LoggerInterface $logger,
MnsLogger $mnsLogger,
MnsConsumerPool $consumerPool,
MnsEventFactory $mnsEventFactory,
MnsRepository $mnsRepository,
SearchCriteriaBuilder $searchCriteriaBuilder,
SupervisorInterface $supervisor
) {
$this->upgFactory = $upgFactory;
$this->logger = $logger;
$this->mnsLogger = $mnsLogger;
$this->consumerPool = $consumerPool;
$this->mnsEventFactory = $mnsEventFactory;
$this->mnsRepository = $mnsRepository;
$this->searchCriteriaBuilder = $searchCriteriaBuilder;
$this->supervisor = $supervisor;
}
/**
* Save the MNS event for further processing
*
* @param array $notificationDetails
*/
public function acknowledge(array $notificationDetails): void
{
$macCalculator = $this->upgFactory->createCallbackMacCalculator($notificationDetails);
try {
$macCalculator->validateResponse();
$mnsEvent = $this->mnsEventFactory->createFromPost($notificationDetails);
if (!$this->doesNotificationAlreadyExist($mnsEvent)) {
$this->mnsRepository->save($mnsEvent);
}
} catch (MacValidation $e) {
$mac = array_key_exists('mac', $notificationDetails) ? $notificationDetails['mac'] : '';
$this->mnsLogger->error(sprintf('MAC validation failed for CrefoPay MNS event: %s', $mac));
return;
} catch (Exception $e) {
$this->logger->error(sprintf('Error during acknowledging MNS event: %s', $e->getMessage()));
$this->mnsLogger->error($e->getMessage());
}
}
/**
* Process all the pending MNS events
*
* @param SupervisorInterface|null $supervisor
* @throws AlreadyExistsException
* @throws StateException
*/
public function process(SupervisorInterface $supervisor = null): void
{
if ($supervisor) {
$this->supervisor = $supervisor;
}
$isTotalCountReported = false;
$itemsProcessedCnt = 0;
$searchCriteria = $this->searchCriteriaBuilder
->addFilter(CrefoPayMnsInterface::MNS_STATUS, CrefoPayMnsInterface::STATUS_ACK)
->setPageSize(100)
->setCurrentPage(1)
->create();
while ($searchResult = $this->mnsRepository->getList($searchCriteria)) {
if (!$isTotalCountReported) {
$this->supervisor->setTotalCount($searchResult->getTotalCount());
$isTotalCountReported = true;
}
foreach ($searchResult->getItems() as $mns) {
$this->processMns($mns);
}
$searchCriteria->setCurrentPage($searchCriteria->getCurrentPage() + 1);
$itemsProcessedCnt += $searchCriteria->getPageSize();
if ($itemsProcessedCnt >= $searchResult->getTotalCount()) {
break;
}
}
}
/**
* @param MnsEvent $mnsEvent
* @return bool
*/
private function doesNotificationAlreadyExist(MnsEvent $mnsEvent): bool
{
$result = false;
if (in_array(
$mnsEvent->getTransactionStatus(),
[Constants::TX_ACK, Constants::TX_CIA, Constants::TX_MERCHANT], true
)) {
$searchCriteria = $this->searchCriteriaBuilder->addFilter(
CrefoPayMnsInterface::ORDER_INCREMENT_ID,
$mnsEvent->getIncrementOrderId()
)->addFilter(
CrefoPayMnsInterface::STORE_ID,
$mnsEvent->getStoreId()
)->addFilter(
CrefoPayMnsInterface::TRANSACTION_STATUS,
$mnsEvent->getTransactionStatus()
)->create();
if ($this->mnsRepository->getList($searchCriteria)->getTotalCount()) {
$result = true;
}
}
return $result;
}
/**
* @param MnsEvent $mns
* @throws AlreadyExistsException
* @throws StateException
*/
private function processMns(MnsEvent $mns): void
{
$numberOfAttemptsToProcessNotification = $mns->getNumberOfAttemptsToProcessNotification() + 1;
try {
$applicableConsumers = $this->consumerPool->getConsumersByEvent($mns);
foreach ($applicableConsumers as $consumer) {
$consumer->process($mns);
}
} catch (Exception $e) {
$mns->setProcessedAt(new DateTime());
$mns->setErrorDetails(sprintf('%s (%s): %s', get_class($e), $e->getCode(), $e->getMessage()));
if ($numberOfAttemptsToProcessNotification >= 3) {
$mns->setMnsStatus(CrefoPayMnsInterface::STATUS_FAILED);
}
$mns->setNumberOfAttemptsToProcessNotification($numberOfAttemptsToProcessNotification);
$this->mnsRepository->save($mns);
$this->supervisor->fail($mns);
return;
}
$mns->setProcessedAt(new DateTime());
$mns->setMnsStatus(CrefoPayMnsInterface::STATUS_CONSUMED);
$mns->setNumberOfAttemptsToProcessNotification($numberOfAttemptsToProcessNotification);
$this->mnsRepository->save($mns);
$this->supervisor->ok($mns);
}
}
<?php
declare(strict_types=1);
namespace Trilix\CrefoPay\Test\Unit\Model\Mns;
use PHPUnit\Framework\MockObject\MockObject;
use PHPUnit\Framework\TestCase;
use Psr\Log\LoggerInterface;
use Magento\Framework\Api\SearchCriteriaBuilder;
use Trilix\CrefoPay\Model\Mns\MnsEvent;
use Upg\Library\Callback\MacCalculator;
use Trilix\CrefoPay\Client\UpgFactory;
use Trilix\CrefoPay\Logger\MnsLogger;
use Trilix\CrefoPay\Model\Mns\MnsConsumerPool;
use Trilix\CrefoPay\Model\Mns\MnsEventFactory;
use Trilix\CrefoPay\Model\Mns\MnsRepository;
use Trilix\CrefoPay\Model\Mns\MnsService;
use Trilix\CrefoPay\Model\Mns\ProcessSupervisor\SupervisorInterface;
class MnsServiceTest extends TestCase
{
/** @var MnsService */
private $mnsService;
/** @var UpgFactory|MockObject */
private $upgFactoryMock;
/** @var LoggerInterface|MockObject */
private $loggerMock;
/** @var MnsLogger|MockObject */
private $mnsLoggerMock;
/** @var MnsConsumerPool|MockObject */
private $mnsConsumerPoolMock;
/** @var MnsEventFactory|MockObject */
private $mnsEventFactoryMock;
/** @var MnsRepository|MockObject */
private $mnsRepositoryMock;
/** @var SearchCriteriaBuilder|MockObject */
private $searchCriteriaBuilderMock;
/** @var SupervisorInterface|MockObject */
private $supervisorMock;
/** @var MacCalculator|MockObject */
private $macCalculatorMock;
public function setUp(): void
{
$this->upgFactoryMock = $this->createMock(UpgFactory::class);
$this->loggerMock = $this->createMock(LoggerInterface::class);
$this->mnsLoggerMock = $this->createMock(MnsLogger::class);
$this->mnsConsumerPoolMock = $this->createMock(MnsConsumerPool::class);
$this->mnsEventFactoryMock = $this->createMock(MnsEventFactory::class);
$this->mnsRepositoryMock = $this->createMock(MnsRepository::class);
$this->searchCriteriaBuilderMock = $this->createMock(SearchCriteriaBuilder::class);
$this->supervisorMock = $this->createMock(SupervisorInterface::class);
$this->macCalculatorMock = $this->createMock(MacCalculator::class);
$this->mnsService = new MnsService(
$this->upgFactoryMock,
$this->loggerMock,
$this->mnsLoggerMock,
$this->mnsConsumerPoolMock,
$this->mnsEventFactoryMock,
$this->mnsRepositoryMock,
$this->searchCriteriaBuilderMock,
$this->supervisorMock
);
}
public function testAcknowledge()
{
$notificationDetails = $this->generateNotification();
$this->upgFactoryMock->expects(self::once())
->method('createCallbackMacCalculator')
->willReturn($this->macCalculatorMock);
$this->macCalculatorMock->expects(self::once())
->method('validateResponse')
->willReturn(true);
$this->mnsEventFactoryMock->expects(self::once())
->method('createFromPost')
->with($notificationDetails)
->willReturn(new MnsEvent());
$this->mnsRepositoryMock->expects(self::once())
->method('save');
$this->mnsService->acknowledge($notificationDetails);
}
private function generateNotification(): array
{
return [
'merchant_id' => 4,
'store_id' => 3,
'order_increment_id' => 1213,
'capture_id' => 32,
'merchant_reference' => '323',
'payment_reference' => '222',
'user_id' => 4,
'INPROGRESS'
];
}
}
<?php
declare(strict_types=1);
namespace Trilix\CrefoPay\Test\Unit\Model\Mns;
use PHPUnit\Framework\MockObject\MockObject;
use PHPUnit\Framework\TestCase;
use Psr\Log\LoggerInterface;
use Magento\Framework\Api\SearchCriteriaBuilder;
use Magento\Framework\Api\SearchCriteriaInterface;
use Upg\Library\Callback\MacCalculator;
use Upg\Library\Callback\Exception\MacValidation;
use Trilix\CrefoPay\Api\Data\CrefoPayMnsInterface;
use Trilix\CrefoPay\Api\Data\CrefoPayMnsSearchResultInterface;
use Trilix\CrefoPay\Client\Constants;
use Trilix\CrefoPay\Model\Mns\MnsEvent;
use Trilix\CrefoPay\Client\UpgFactory;
use Trilix\CrefoPay\Logger\MnsLogger;
use Trilix\CrefoPay\Model\Mns\MnsConsumerPool;
use Trilix\CrefoPay\Model\Mns\MnsEventFactory;
use Trilix\CrefoPay\Model\Mns\MnsRepository;
use Trilix\CrefoPay\Model\Mns\MnsService;
use Trilix\CrefoPay\Model\Mns\ProcessSupervisor\SupervisorInterface;
class MnsServiceTest extends TestCase
{
/** @var MnsService */
private $mnsService;
/** @var UpgFactory|MockObject */
private $upgFactoryMock;
/** @var LoggerInterface|MockObject */
private $loggerMock;
/** @var MnsLogger|MockObject */
private $mnsLoggerMock;
/** @var MnsConsumerPool|MockObject */
private $mnsConsumerPoolMock;
/** @var MnsEventFactory|MockObject */
private $mnsEventFactoryMock;
/** @var MnsRepository|MockObject */
private $mnsRepositoryMock;
/** @var SearchCriteriaBuilder|MockObject */
private $searchCriteriaBuilderMock;
/** @var SupervisorInterface|MockObject */
private $supervisorMock;
/** @var MacCalculator|MockObject */
private $macCalculatorMock;
/** @var MnsEvent|MockObject */