Commit ffbb5998 authored by Daniel Kazior's avatar Daniel Kazior 💰
Browse files

Version 1.0.0 Released

parent 59bfe294
<?php
declare(strict_types=1);
namespace Trilix\CrefoPay\Client\Request;
use Magento\Quote\Api\CartRepositoryInterface;
use Magento\Quote\Model\Quote\Address;
use Magento\Quote\Model\Quote;
use Magento\Customer\Model\Session;
use Magento\Framework\Locale\ResolverInterface as Locale;
use Magento\Customer\Model\Session;
use Upg\Library\Request\CreateTransaction as CreateTransactionRequest;
use Trilix\CrefoPay\Gateway\Request\CompanyBuilder;
use Trilix\CrefoPay\Gateway\Request\AddressBuilder;
......@@ -15,7 +17,6 @@ use Trilix\CrefoPay\Gateway\Request\BasketBuilder;
use Trilix\CrefoPay\Gateway\Request\PersonBuilder;
use Trilix\CrefoPay\Client\ConfigFactory;
use Trilix\CrefoPay\Client\Constants;
use Trilix\CrefoPay\Gateway\Config\Config;
use Trilix\CrefoPay\Gateway\Request\User\CrefoPayUserFactory;
class CreateTransactionRequestFactory extends AbstractRequestFactory
......@@ -26,9 +27,6 @@ class CreateTransactionRequestFactory extends AbstractRequestFactory
/** @var CrefoPayUserFactory */
private $crefoPayUserFactory;
/** @var Config */
private $config;
/** @var Locale */
private $locale;
......@@ -47,59 +45,61 @@ class CreateTransactionRequestFactory extends AbstractRequestFactory
/** @var CompanyBuilder */
private $companyBuilder;
/** @var UserRiskManager */
private $userRiskManager;
/** @var Session */
private $customerSession;
/**
* CreateTransactionRequestFactory constructor.
*
* @param CartRepositoryInterface $quoteRepository
* @param CrefoPayUserFactory $crefoPayUserFactory
* @param ConfigFactory $configFactory
* @param Config $config
* @param Locale $locale
* @param PersonBuilder $personBuilder
* @param AddressBuilder $addressBuilder
* @param BasketBuilder $basketBuilder
* @param AmountBuilder $amountBuilder
* @param CompanyBuilder $companyBuilder
* @param Session $customerSession
* @param CrefoPayUserFactory $crefoPayUserFactory
* @param ConfigFactory $configFactory
* @param Locale $locale
* @param PersonBuilder $personBuilder
* @param AddressBuilder $addressBuilder
* @param BasketBuilder $basketBuilder
* @param AmountBuilder $amountBuilder
* @param CompanyBuilder $companyBuilder
* @param UserRiskManager $userRiskManager
* @param Session $customerSession
*/
public function __construct(
CartRepositoryInterface $quoteRepository,
CrefoPayUserFactory $crefoPayUserFactory,
ConfigFactory $configFactory,
Config $config,
Locale $locale,
PersonBuilder $personBuilder,
AddressBuilder $addressBuilder,
BasketBuilder $basketBuilder,
AmountBuilder $amountBuilder,
CompanyBuilder $companyBuilder,
UserRiskManager $userRiskManager,
Session $customerSession
) {
parent::__construct($configFactory);
$this->quoteRepository = $quoteRepository;
$this->crefoPayUserFactory = $crefoPayUserFactory;
$this->config = $config;
$this->locale = $locale;
$this->personBuilder = $personBuilder;
$this->addressBuilder = $addressBuilder;
$this->basketBuilder = $basketBuilder;
$this->amountBuilder = $amountBuilder;
$this->companyBuilder = $companyBuilder;
$this->userRiskManager = $userRiskManager;
$this->customerSession = $customerSession;
}
/**
* @param string $quoteId
* @param int $quoteId
* @return CreateTransactionRequest
* @throws \Magento\Framework\Exception\LocalizedException
* @throws \Magento\Framework\Exception\NoSuchEntityException
* @throws \Upg\Library\Serializer\Exception\VisitorCouldNotBeFound
*/
public function create(string $quoteId): CreateTransactionRequest
public function create(int $quoteId): CreateTransactionRequest
{
/** @var Quote $quote */
$quote = $this->quoteRepository->getActive($quoteId);
......@@ -138,7 +138,7 @@ class CreateTransactionRequestFactory extends AbstractRequestFactory
$createTransactionRequest->setLocale($this->getLanguageCode());
$createTransactionRequest->setOrderID($quote->getReservedOrderId());
$createTransactionRequest->setUserRiskClass($this->config->getRiskClass());
$createTransactionRequest->setUserRiskClass($this->userRiskManager->getUserRiskClass());
$this->setMac($createTransactionRequest);
......
......@@ -6,7 +6,6 @@ use Magento\Payment\Gateway\Data\PaymentDataObjectInterface;
use Upg\Library\Request\Reserve as ReserveRequest;
use Trilix\CrefoPay\Client\ConfigFactory;
use Trilix\CrefoPay\Gateway\Request\AmountBuilder;
use Trilix\CrefoPay\Client\Request\Structure\AdditionalInfo as AdditionalInfoStructure;
class ReserveRequestFactory extends AbstractRequestFactory
......@@ -28,7 +27,12 @@ class ReserveRequestFactory extends AbstractRequestFactory
$this->amountBuilder = $amountBuilder;
}
/**
* @param string $paymentMethod
* @param PaymentDataObjectInterface $paymentDO
* @return ReserveRequest
* @throws \Upg\Library\Serializer\Exception\VisitorCouldNotBeFound
*/
public function create(string $paymentMethod, PaymentDataObjectInterface $paymentDO): ReserveRequest
{
$reserveRequest = new ReserveRequest($this->getConfig());
......
<?php
declare(strict_types=1);
namespace Trilix\CrefoPay\Client\Request;
use Magento\Customer\Model\Session;
use Trilix\CrefoPay\Gateway\Config\Config;
class UserRiskManager
{
/** @var Session */
private $customerSession;
/** @var Config */
private $config;
/**
* UserRiskManager constructor.
* @param Session $customerSession
* @param Config $config
*/
public function __construct(Session $customerSession, Config $config)
{
$this->customerSession = $customerSession;
$this->config = $config;
}
/**
* @return int
*/
public function getUserRiskClass(): int
{
$result = $this->config->getRiskClass();
$customerUserRiskClass = $this->customerSession->getUserRiskClass();
if ($customerUserRiskClass) {
$result = $customerUserRiskClass['value'];
}
return $result;
}
}
......@@ -70,6 +70,14 @@ class MnsEmitCommand extends Command
protected function configure()
{
/**
* All commands are always instantiated, no matter what command has been actually required. Here we
* use this feature to load the Magento 2.3 interface within Magento 2.2. Otherwise
* 'setup:di:compile' would throw an exception, as it does not include() class files, but reads them
* and processes tokens.
*/
\Trilix\CrefoPay\Polyfill\Polyfill::polyfill();
$this
->setName('crefopay:mns:emit')
->setDescription('Emit CrefoPay MNS event')
......
<?php
namespace Trilix\CrefoPay\Controller\Mns;
use Magento\Framework\App\Action\Action;
use Magento\Framework\App\Action\Context;
use Magento\Framework\Controller\ResultFactory;
use Trilix\CrefoPay\Model\Mns\MnsService;
class Sink extends Action
{
/**
* @var MnsService
*/
private $mnsService;
/**
* Consume constructor.
* @param Context $context
* @param MnsService $mnsService
*/
public function __construct(Context $context, MnsService $mnsService)
{
$this->mnsService = $mnsService;
return parent::__construct($context);
}
namespace {
Trilix\CrefoPay\Polyfill\Polyfill::polyfill();
}
namespace Trilix\CrefoPay\Controller\Mns {
use Magento\Framework\App\CsrfAwareActionInterface;
use Magento\Framework\App\Action\Action;
use Magento\Framework\App\Action\Context;
use Magento\Framework\App\Request\InvalidRequestException;
use Magento\Framework\App\RequestInterface;
use Magento\Framework\Controller\ResultFactory;
use Trilix\CrefoPay\Model\Mns\MnsService;
/**
* @return \Magento\Framework\App\ResponseInterface|\Magento\Framework\Controller\ResultInterface
*/
public function execute()
class Sink extends Action implements CsrfAwareActionInterface
{
/** @var \Magento\Framework\Controller\Result\Raw $result */
$result = $this->resultFactory->create(ResultFactory::TYPE_RAW);
/**
* @var MnsService
*/
private $mnsService;
$this->mnsService->acknowledge($_POST);
/**
* Consume constructor.
* @param Context $context
* @param MnsService $mnsService
*/
public function __construct(Context $context, MnsService $mnsService)
{
$this->mnsService = $mnsService;
return parent::__construct($context);
}
return $result;
/**
* @return \Magento\Framework\App\ResponseInterface|\Magento\Framework\Controller\ResultInterface
*/
public function execute()
{
/** @var \Magento\Framework\Controller\Result\Raw $result */
$result = $this->resultFactory->create(ResultFactory::TYPE_RAW);
$this->mnsService->acknowledge($_POST);
return $result;
}
/**
* Validation exception is not thrown in this action.
*
* @param RequestInterface $request
*
* @return InvalidRequestException|null
*/
public function createCsrfValidationException(RequestInterface $request): ?InvalidRequestException
{
return null;
}
/**
* CrefoPay server sends POST requests without Magento formkey, we allow it here.
*
* @param RequestInterface $request
*
* @return true
*/
public function validateForCsrf(RequestInterface $request): ?bool
{
return true;
}
}
}
}
\ No newline at end of file
<?php
namespace Trilix\CrefoPay\Gateway\Command;
use Magento\Customer\Model\Session;
use Magento\Payment\Gateway\Command\CommandException;
use Magento\Payment\Gateway\CommandInterface;
use Magento\Payment\Gateway\Helper\SubjectReader;
use Magento\Payment\Gateway\Response\HandlerInterface;
use Magento\Payment\Gateway\Validator\ValidatorInterface;
use Trilix\CrefoPay\Client\Request\ReserveRequestFactory;
use Trilix\CrefoPay\Client\Transport;
use Trilix\CrefoPay\Model\TransactionService;
use Trilix\CrefoPay\Gateway\SubjectReader;
use Upg\Library\Risk\RiskClass;
use Upg\Library\Api\Exception\ApiError;
class Reserve implements CommandInterface
{
const CREFOPAY_RESERVE_ERROR = 'crefopay_reserve_error';
/** @var Session */
private $customerSession;
/**
* @var Transport
*/
......@@ -26,11 +36,21 @@ class Reserve implements CommandInterface
*/
private $transactionService;
/**
* @var SubjectReader
*/
private $subjectReader;
/**
* @var HandlerInterface
*/
private $handler;
/**
* @var ValidatorInterface|null
*/
private $validator;
/**
* @var string
*/
......@@ -38,57 +58,89 @@ class Reserve implements CommandInterface
/**
* Reserve constructor.
* @param Session $customerSession
* @param Transport $transport
* @param ReserveRequestFactory $reserveRequestFactory
* @param TransactionService $transactionService
* @param SubjectReader $subjectReader
* @param string $methodCode
* @param HandlerInterface|null $handler\
* @param HandlerInterface|null $handler
* @param ValidatorInterface|null $validator
*/
public function __construct(
Session $customerSession,
Transport $transport,
ReserveRequestFactory $reserveRequestFactory,
TransactionService $transactionService,
SubjectReader $subjectReader,
string $methodCode,
HandlerInterface $handler = null
HandlerInterface $handler = null,
ValidatorInterface $validator = null
) {
$this->transport = $transport;
$this->customerSession = $customerSession;
$this->transport = $transport;
$this->reserveRequestFactory = $reserveRequestFactory;
$this->transactionService = $transactionService;
$this->methodCode = $methodCode;
$this->handler = $handler;
$this->transactionService = $transactionService;
$this->subjectReader = $subjectReader;
$this->methodCode = $methodCode;
$this->handler = $handler;
$this->validator = $validator;
}
/**
* @param array $commandSubject
*
* @return void
* @throws CommandException
*/
public function execute(array $commandSubject)
{
try {
$paymentDO = SubjectReader::readPayment($commandSubject);
$paymentDO = $this->subjectReader->readPayment($commandSubject);
$request = $this->reserveRequestFactory->create(
$this->methodCode,
$paymentDO
);
$response = $this->transport->sendRequest($request);
$this->transactionService->addTransaction($paymentDO, $request, $response);
} catch (\Exception $e) {
$this->processErrors($commandSubject, $e);
}
if ($this->handler) {
$this->handler->handle(
$commandSubject,
[]
);
}
// move to handler
$this->transactionService->addTransaction($paymentDO, $request, $response);
} catch (\Exception $e) {
throw new CommandException(
!empty($e->getMessage())
? __($e->getMessage())
: __('Transaction has been declined. Please try again later.')
if ($this->handler) {
$this->handler->handle(
$commandSubject,
[]
);
}
}
/**
* @param array $commandSubject
* @param \Exception $e
* @throws CommandException
*/
private function processErrors(array $commandSubject, \Exception $e)
{
$exception = new CommandException(
!empty($e->getMessage())
? __($e->getMessage())
: __('Transaction has been declined. Please try again later.')
);
if ($e instanceof ApiError && ($this->validator !== null)) {
$result = $this->validator->validate(
array_merge($commandSubject, ['response' => $e->getParsedResponse()])
);
if (!$result->isValid()) {
$this->customerSession->setUserRiskClass(['value' => RiskClass::RISK_CLASS_HIGH]);
$exception = new CommandException(__(self::CREFOPAY_RESERVE_ERROR));
}
}
throw $exception;
}
}
......@@ -5,6 +5,7 @@ namespace Trilix\CrefoPay\Gateway\Config;
use Magento\Catalog\Model\ResourceModel\Category\CollectionFactory as CategoryCollectionFactory;
use Magento\Framework\App\Config\ScopeConfigInterface;
use Magento\Framework\App\Config\Storage\WriterInterface as ConfigWriter;
use Magento\Framework\UrlInterface;
use Magento\Payment\Model\CcConfig;
use Trilix\CrefoPay\Model\Adminhtml\Source\Environment;
......@@ -49,26 +50,33 @@ class Config extends \Magento\Payment\Gateway\Config\Config
* @var CategoryCollectionFactory
*/
private $categoryCollectionFactory;
/**
* @var ConfigWriter
*/
private $configWriter;
/**
* @var UrlInterface
*/
private $urlBuilder;
/**
* Config constructor.
*
* @param ScopeConfigInterface $scopeConfig
* @param CcConfig $ccConfig
* @param ScopeConfigInterface $scopeConfig
* @param CcConfig $ccConfig
* @param CategoryCollectionFactory $categoryCollectionFactory
* @param ConfigWriter $configWriter
* @param null $methodCode
* @param string $pathPattern
* @param ConfigWriter $configWriter
* @param UrlInterface $urlBuilder
* @param null $methodCode
* @param string $pathPattern
*/
public function __construct(
ScopeConfigInterface $scopeConfig,
CcConfig $ccConfig,
CategoryCollectionFactory $categoryCollectionFactory,
ConfigWriter $configWriter,
UrlInterface $urlBuilder,
$methodCode = null,
$pathPattern = self::DEFAULT_PATH_PATTERN
) {
......@@ -76,6 +84,7 @@ class Config extends \Magento\Payment\Gateway\Config\Config
$this->ccConfig = $ccConfig;
$this->categoryCollectionFactory = $categoryCollectionFactory;
$this->configWriter = $configWriter;
$this->urlBuilder = $urlBuilder;
$this->methodCode = $methodCode;
$this->pathPattern = $pathPattern;
}
......@@ -175,8 +184,11 @@ class Config extends \Magento\Payment\Gateway\Config\Config
$environment = self::KEY_ENVIRONMENT;
switch ($this->getValue($environment)) {
case Environment::ENVIRONMENT_PRODUCTION: $subDomain = 'api'; break;
case Environment::ENVIRONMENT_SANDBOX: $subDomain = 'sandbox'; break;
case Environment::ENVIRONMENT_PRODUCTION:
$subDomain = 'api';
break;
case Environment::ENVIRONMENT_SANDBOX:
$subDomain = 'sandbox'; break;
default:
throw new \InvalidArgumentException(sprintf('Invalid value for CrefoPay environment: %s', $environment));
}
......@@ -214,16 +226,21 @@ class Config extends \Magento\Payment\Gateway\Config\Config
}
/**
* Return auto capture category collection.
*
* @return \Magento\Catalog\Model\ResourceModel\Category\Collection
* @param string $method
* @return string
*/
public function getAutoCaptureCategories(): \Magento\Catalog\Model\ResourceModel\Category\Collection
public function getLogoUrl(string $method): string
{
$categories = $this->categoryCollectionFactory->create();
$categories->addIdFilter($this->getAutoCaptureCategoryIds());
$logo = $this->getValue($method . '_logo');
$result = '';
if ($logo) {
$uploadDir = 'crefopay' . DIRECTORY_SEPARATOR . $method . DIRECTORY_SEPARATOR . 'logo';
$url = $uploadDir . DIRECTORY_SEPARATOR . $logo;
$result = $this->urlBuilder->getBaseUrl(['_type' => UrlInterface::URL_TYPE_MEDIA]) . $url;
}
return $categories;
return $result;
}
/**
......
<?php
namespace Trilix\CrefoPay\Gateway\Helper;
class SubjectReader extends \Magento\Payment\Gateway\Helper\SubjectReader
......@@ -12,4 +13,4 @@ class SubjectReader extends \Magento\Payment\Gateway\Helper\SubjectReader
{
return parent::readAmount($subject) * 100;
}
}
\ No newline at end of file
}
......@@ -21,25 +21,61 @@ class BasketBuilder
/** @var $quoteItem QuoteItem */
foreach ($quote->getAllItems() as $quoteItem) {
if ((bool)intval($quoteItem->getRowTotal())) {
$basketItem = $this->buildItem($quoteItem);
$basketItem = $this->createBasketItem(
$quoteItem->getName(),
$quoteItem->getQty(),
$quoteItem->getRowTotal()
);
$createTransactionRequest->addBasketItem($basketItem);
}
}
$basketShippingItem = $this->buildShippingItem($quote);
if ($basketShippingItem->getBasketItemAmount()) {
$createTransactionRequest->addBasketItem($basketShippingItem);
}
}
/**
* @param Quote $quote
*
* @return BasketItem
*/
private function buildShippingItem(Quote $quote)
{
$shippingAmount = 0;
/** @var \Magento\Quote\Model\Quote\Address $shippingAddress */
foreach ($quote->getAllShippingAddresses() as $shippingAddress) {