diff --git a/Controller/Onepage/Cancel.php b/Controller/Onepage/Cancel.php index 18227bb3..8a37bf5d 100644 --- a/Controller/Onepage/Cancel.php +++ b/Controller/Onepage/Cancel.php @@ -100,21 +100,12 @@ public function execute() $orderId = $this->checkoutSession->getLastOrderId(); $order = $orderId ? $this->orderFactory->create()->load($orderId) : false; if ($order) { - $sQuoteId = $order->getQuoteId(); - $order->cancel()->save(); + $this->checkoutSession->restoreQuote(); $this->checkoutSession ->unsLastQuoteId() ->unsLastSuccessQuoteId() - ->unsLastOrderId() - ->unsLastRealOrderId(); - - // Use the old quote/basket again - $this->checkoutSession->setQuoteId($sQuoteId); - $this->checkoutSession->setLoadInactive(); - $oQuote = $this->checkoutSession->getQuote(); - $oQuote->setIsActive(1)->setReservedOrderId(null)->save(); - $this->checkoutSession->replaceQuote($oQuote); + ->unsLastOrderId(); } } catch (LocalizedException $e) { $this->messageManager->addExceptionMessage($e, $e->getMessage()); diff --git a/Controller/Onepage/PlaceOrder.php b/Controller/Onepage/PlaceOrder.php index 79a549be..6df24065 100644 --- a/Controller/Onepage/PlaceOrder.php +++ b/Controller/Onepage/PlaceOrder.php @@ -104,6 +104,14 @@ public function execute() protected function placeOrder() { $oQuote = $this->checkoutSession->getQuote(); + + if ($oQuote->getSubtotal() != $this->checkoutSession->getPayoneGenericpaymentSubtotal()) { + // The basket was changed - abort current checkout + $this->messageManager->addErrorMessage('An error occured during the Checkout.'); + $this->_redirect('checkout/cart'); + return; + } + $oQuote->getBillingAddress()->setShouldIgnoreValidation(true); if (!$oQuote->getIsVirtual()) { $oQuote->getShippingAddress()->setShouldIgnoreValidation(true); diff --git a/Controller/Onepage/Returned.php b/Controller/Onepage/Returned.php index eacf0e7d..2f7a8597 100644 --- a/Controller/Onepage/Returned.php +++ b/Controller/Onepage/Returned.php @@ -26,6 +26,8 @@ namespace Payone\Core\Controller\Onepage; +use Magento\Sales\Model\Order; + /** * Controller for handling return from payment provider */ @@ -38,18 +40,161 @@ class Returned extends \Magento\Framework\App\Action\Action */ protected $checkoutSession; + /** + * Quote management object + * + * @var \Magento\Quote\Model\QuoteManagement + */ + protected $quoteManagement; + + /** + * Order repository + * + * @var \Magento\Sales\Api\OrderRepositoryInterface + */ + protected $orderRepository; + + /** + * Order repository + * + * @var \Magento\Quote\Api\CartRepositoryInterface + */ + protected $quoteRepository; + + /** + * PAYONE database helper + * + * @var \Payone\Core\Helper\Database + */ + protected $databaseHelper; + + /** + * TransactionStatus factory + * + * @var \Payone\Core\Model\Entities\TransactionStatusFactory + */ + protected $statusFactory; + + /** + * TransactionStatus handler + * + * @var \Payone\Core\Model\Handler\TransactionStatus + */ + protected $transactionStatusHandler; + /** * Constructor * - * @param \Magento\Framework\App\Action\Context $context - * @param \Magento\Checkout\Model\Session $checkoutSession + * @param \Magento\Framework\App\Action\Context $context + * @param \Magento\Checkout\Model\Session $checkoutSession + * @param \Magento\Quote\Model\QuoteManagement $quoteManagement + * @param \Magento\Sales\Api\OrderRepositoryInterface $orderRepository + * @param \Magento\Quote\Api\CartRepositoryInterface $quoteRepository + * @param \Payone\Core\Helper\Database $databaseHelper + * @param \Payone\Core\Model\Entities\TransactionStatusFactory $statusFactory + * @param \Payone\Core\Model\Handler\TransactionStatus $transactionStatusHandler */ public function __construct( \Magento\Framework\App\Action\Context $context, - \Magento\Checkout\Model\Session $checkoutSession + \Magento\Checkout\Model\Session $checkoutSession, + \Magento\Quote\Model\QuoteManagement $quoteManagement, + \Magento\Sales\Api\OrderRepositoryInterface $orderRepository, + \Magento\Quote\Api\CartRepositoryInterface $quoteRepository, + \Payone\Core\Helper\Database $databaseHelper, + \Payone\Core\Model\Entities\TransactionStatusFactory $statusFactory, + \Payone\Core\Model\Handler\TransactionStatus $transactionStatusHandler ) { parent::__construct($context); $this->checkoutSession = $checkoutSession; + $this->quoteManagement = $quoteManagement; + $this->orderRepository = $orderRepository; + $this->databaseHelper = $databaseHelper; + $this->quoteRepository = $quoteRepository; + $this->statusFactory = $statusFactory; + $this->transactionStatusHandler = $transactionStatusHandler; + } + + /** + * Order was canceled before because of multi-tab browsing or back-button cancelling + * Create a clean order for the payment + * + * @param Order $canceledOrder + * @return void + */ + protected function createSubstituteOrder(Order $canceledOrder) + { + $this->checkoutSession->setPayoneCreatingSubstituteOrder(true); + + $oOldQuote = $this->quoteRepository->get($canceledOrder->getQuoteId()); + $oOldQuote->setIsActive(true); + $oOldQuote->setReservedOrderId(null); + $oOldQuote->save(); + + $orderId = $this->quoteManagement->placeOrder($oOldQuote->getId()); + $newOrder = $this->orderRepository->get($orderId); + + $oldData = $canceledOrder->getData(); + foreach ($oldData as $sKey => $sValue) { + if (stripos($sKey, 'payone') !== false) { + $newOrder->setData($sKey, $sValue); + } + } + + $newOrder->setPayoneCancelSubstituteIncrementId($canceledOrder->getIncrementId()); + $newOrder->save(); + + $this->checkoutSession->setLastOrderId($newOrder->getId()); + $this->checkoutSession->setLastRealOrderId($newOrder->getIncrementId()); + $this->checkoutSession->getQuote()->setIsActive(false)->save(); + + $this->databaseHelper->relabelTransaction($canceledOrder->getId(), $newOrder->getId(), $newOrder->getPayment()->getId()); + $this->databaseHelper->relabelApiProtocol($canceledOrder->getIncrementId(), $newOrder->getIncrementId()); + $this->databaseHelper->relabelOrderPayment($canceledOrder->getIncrementId(), $newOrder->getId()); + + $this->handleTransactionStatus($canceledOrder, $newOrder); + + $this->checkoutSession->unsPayoneCreatingSubstituteOrder(); + } + + /** + * Handle stored TransactionStatus + * + * @param Order $canceledOrder + * @param Order $newOrder + * @return void + */ + protected function handleTransactionStatus(Order $canceledOrder, Order $newOrder) + { + $aTransactionStatusIds = $this->databaseHelper->getNotHandledTransactionsByOrderId($canceledOrder->getIncrementId()); + foreach ($aTransactionStatusIds as $aRow) { + $oTransactionStatus = $this->statusFactory->create(); + $oTransactionStatus->load($aRow['id']); + + $this->transactionStatusHandler->handle($newOrder, $oTransactionStatus->getRawStatusArray()); + + $oTransactionStatus->setHasBeenHandled(true); + $oTransactionStatus->save(); + } + } + + /** + * Get canceled order. + * Return order if found. + * Return false if not found or not canceled + * + * @return bool|Order + */ + protected function getCanceledOrder() + { + $order = $this->checkoutSession->getLastRealOrder(); + if (!$order->getId() && !empty($this->checkoutSession->getPayoneCanceledOrder())) { + $order->loadByIncrementId($this->checkoutSession->getPayoneCanceledOrder()); + } + $this->checkoutSession->unsPayoneCanceledOrder(); + if ($order->getStatus() == Order::STATE_CANCELED) { + return $order; + } + return false; } /** @@ -62,6 +207,11 @@ public function execute() { $this->checkoutSession->unsPayoneCustomerIsRedirected(); + $canceledOrder = $this->getCanceledOrder(); + if ($canceledOrder !== false) { + $this->createSubstituteOrder($canceledOrder); + } + $this->_redirect($this->_url->getUrl('checkout/onepage/success')); } } diff --git a/Controller/Paypal/Express.php b/Controller/Paypal/Express.php index 0bd77bb4..b4f5a88f 100644 --- a/Controller/Paypal/Express.php +++ b/Controller/Paypal/Express.php @@ -158,6 +158,7 @@ public function execute() $oQuote->save(); $this->checkoutSession->setPayoneWorkorderId($aResponse['workorderid']); + $this->checkoutSession->setPayoneGenericpaymentSubtotal($oQuote->getSubtotal()); $this->_redirect($aResponse['redirecturl']); } return; diff --git a/Controller/Transactionstatus/Index.php b/Controller/Transactionstatus/Index.php index a6fef269..e6d74eba 100644 --- a/Controller/Transactionstatus/Index.php +++ b/Controller/Transactionstatus/Index.php @@ -33,13 +33,6 @@ */ class Index extends \Magento\Framework\App\Action\Action { - /** - * Contect object - * - * @var \Magento\Framework\App\Action\Context - */ - protected $context; - /** * TransactionStatus model * @@ -69,18 +62,11 @@ class Index extends \Magento\Framework\App\Action\Action protected $orderHelper; /** - * PAYONE TransactionStatus Mapping - * - * @var \Payone\Core\Model\TransactionStatus\Mapping - */ - protected $statusMapping; - - /** - * PAYONE TransactionStatus Forwarding + * TransactionStatus handler * - * @var \Payone\Core\Model\TransactionStatus\Forwarding + * @var \Payone\Core\Model\Handler\TransactionStatus */ - protected $statusForwarding; + protected $transactionStatusHandler; /** * Result factory for file-download @@ -89,13 +75,6 @@ class Index extends \Magento\Framework\App\Action\Action */ protected $resultRawFactory; - /** - * Event manager object - * - * @var \Magento\Framework\Event\ManagerInterface - */ - protected $eventManager; - /** * Constructor * @@ -104,8 +83,7 @@ class Index extends \Magento\Framework\App\Action\Action * @param \Payone\Core\Helper\Toolkit $toolkitHelper * @param \Payone\Core\Helper\Environment $environmentHelper * @param \Payone\Core\Helper\Order $orderHelper - * @param \Payone\Core\Model\TransactionStatus\Mapping $statusMapping - * @param \Payone\Core\Model\TransactionStatus\Forwarding $statusForwarding + * @param \Payone\Core\Model\Handler\TransactionStatus $transactionStatusHandler, * @param \Magento\Framework\Controller\Result\RawFactory $resultRawFactory */ public function __construct( @@ -114,20 +92,16 @@ public function __construct( \Payone\Core\Helper\Toolkit $toolkitHelper, \Payone\Core\Helper\Environment $environmentHelper, \Payone\Core\Helper\Order $orderHelper, - \Payone\Core\Model\TransactionStatus\Mapping $statusMapping, - \Payone\Core\Model\TransactionStatus\Forwarding $statusForwarding, + \Payone\Core\Model\Handler\TransactionStatus $transactionStatusHandler, \Magento\Framework\Controller\Result\RawFactory $resultRawFactory ) { parent::__construct($context); - $this->context = $context; $this->transactionStatus = $transactionStatus; $this->toolkitHelper = $toolkitHelper; $this->environmentHelper = $environmentHelper; $this->orderHelper = $orderHelper; - $this->statusMapping = $statusMapping; - $this->statusForwarding = $statusForwarding; + $this->transactionStatusHandler = $transactionStatusHandler; $this->resultRawFactory = $resultRawFactory; - $this->eventManager = $context->getEventManager(); } /** @@ -138,7 +112,7 @@ public function __construct( */ protected function getParam($sKey) { - return $this->context->getRequest()->getParam($sKey, ''); + return $this->getRequest()->getParam($sKey, ''); } /** @@ -148,31 +122,20 @@ protected function getParam($sKey) */ protected function getPostArray() { - return $this->context->getRequest()->getPost()->toArray(); + return $this->getRequest()->getPostValue(); } /** * Write the TransactionStatus to the database * * @param Order $oOrder + * @param array $aRequest + * @param bool $blWillBeHandled * @return void */ - protected function log(Order $oOrder = null) + protected function logTransactionStatus(Order $oOrder = null, $aRequest, $blWillBeHandled) { - $this->transactionStatus->addTransactionLogEntry($this->context, $oOrder); - } - - /** - * Order processing - * - * @param Order $oOrder - * @return void - */ - protected function handleOrder(Order $oOrder) - { - $sAction = $this->getParam('txaction'); - $oOrder->setPayoneTransactionStatus($sAction); - $oOrder->save(); + $this->transactionStatus->addTransactionLogEntry($aRequest, $oOrder, $blWillBeHandled); } /** @@ -184,27 +147,23 @@ protected function handleTransactionStatus() { if (!$this->environmentHelper->isRemoteIpValid()) { return 'Access denied'; + } elseif (!$this->toolkitHelper->isKeyValid($this->getParam('key'))) { + return 'Key wrong or missing!'; } - if ($this->toolkitHelper->isKeyValid($this->getParam('key'))) { - $oOrder = $this->orderHelper->getOrderByTxid($this->getParam('txid')); - $this->log($oOrder); - if ($oOrder) { - $this->handleOrder($oOrder); - $this->statusMapping->handleMapping($oOrder, $this->getParam('txaction')); - } - $this->statusForwarding->handleForwardings($this->getPostArray()); - - $aParams = [ - 'order' => $oOrder, - 'transactionstatus' => $this->getPostArray(), - ]; - - $this->eventManager->dispatch('payone_core_transactionstatus_all', $aParams); - $this->eventManager->dispatch('payone_core_transactionstatus_'.$this->getParam('txaction'), $aParams); - - return 'TSOK'; + + $blWillBeHandled = true; + $oOrder = $this->orderHelper->getOrderByTxid($this->getParam('txid')); + if ($this->getParam('txaction') == 'appointed' && $oOrder->getStatus() == 'canceled') { + $blWillBeHandled = false; // order was already canceled, status will be handled in substitute order mechanism, if order is finished } - return 'Key wrong or missing!'; + + $this->logTransactionStatus($oOrder, $this->getPostArray(), $blWillBeHandled); + + if ($blWillBeHandled === true) { + $this->transactionStatusHandler->handle($oOrder, $this->getPostArray()); + } + + return 'TSOK'; } /** @@ -215,8 +174,10 @@ protected function handleTransactionStatus() public function execute() { $sOutput = $this->handleTransactionStatus(); + $oResultRaw = $this->resultRawFactory->create(); $oResultRaw->setContents($sOutput); + return $oResultRaw; } } diff --git a/Helper/Database.php b/Helper/Database.php index 26e2a3bd..6054fedb 100644 --- a/Helper/Database.php +++ b/Helper/Database.php @@ -244,4 +244,78 @@ public function getOldAddressStatus(AddressInterface $oAddress, $blIsCreditratin } return $this->getDb()->fetchOne($oSelect, $aParams); } + + /** + * Relabel sales payment transaction to substitute order + * + * @param string $sOldOrderId + * @param string $sNewOrderId + * @param string $sNewPaymentId + * @return int + */ + public function relabelTransaction($sOldOrderId, $sNewOrderId, $sNewPaymentId) + { + $table = $this->databaseResource->getTableName('sales_payment_transaction'); + $data = [ + 'order_id' => $sNewOrderId, + 'payment_id' => $sNewPaymentId + ]; + $where = ['order_id = ?' => $sOldOrderId]; + return $this->getDb()->update($table, $data, $where); + } + + /** + * Relabel payone protocol api to substitute order + * + * @param string $sOldIncrementId + * @param string $sNewIncrementId + * @return int + */ + public function relabelApiProtocol($sOldIncrementId, $sNewIncrementId) + { + $table = $this->databaseResource->getTableName('payone_protocol_api'); + $data = ['order_id' => $sNewIncrementId]; + $where = ['order_id = ?' => $sOldIncrementId]; + return $this->getDb()->update($table, $data, $where); + } + + /** + * Relabel sales order payment to substitute order + * + * @param string $sOldIncrementId + * @param string $sNewOrderId + * @return int + */ + public function relabelOrderPayment($sOldIncrementId, $sNewOrderId) + { + $oSelect = $this->getDb() + ->select() + ->from(['a' => $this->databaseResource->getTableName('sales_order_payment')], ['last_trans_id']) + ->joinInner(['b' => $this->databaseResource->getTableName('sales_order')], 'a.parent_id = b.entity_id') + ->where("b.increment_id = :incrementId") + ->limit(1); + $sLastTransId = $this->getDb()->fetchOne($oSelect, ['incrementId' => $sOldIncrementId]); + + $table = $this->databaseResource->getTableName('sales_order_payment'); + $data = ['last_trans_id' => $sLastTransId]; + $where = ['parent_id = ?' => $sNewOrderId]; + return $this->getDb()->update($table, $data, $where); + } + + /** + * Return not handled transactions by order id + * + * @param string $sOrderId + * @return array + */ + public function getNotHandledTransactionsByOrderId($sOrderId) + { + $oSelect = $this->getDb() + ->select() + ->from($this->databaseResource->getTableName('payone_protocol_transactionstatus'), ['id']) + ->where("order_id = :orderId") + ->where("has_been_handled = 0") + ->order('id ASC'); + return $this->getDb()->fetchAll($oSelect, ['orderId' => $sOrderId]); + } } diff --git a/Observer/PredispatchCheckoutIndex.php b/Model/Handler/Cancellation.php similarity index 67% rename from Observer/PredispatchCheckoutIndex.php rename to Model/Handler/Cancellation.php index 101170e2..bfc1f364 100644 --- a/Observer/PredispatchCheckoutIndex.php +++ b/Model/Handler/Cancellation.php @@ -19,24 +19,20 @@ * @category Payone * @package Payone_Magento2_Plugin * @author FATCHIP GmbH - * @copyright 2003 - 2016 Payone GmbH + * @copyright 2003 - 2018 Payone GmbH * @license GNU Lesser General Public License * @link http://www.payone.de */ -namespace Payone\Core\Observer; +namespace Payone\Core\Model\Handler; -use Magento\Framework\Event\ObserverInterface; -use Magento\Framework\Event\Observer; use Magento\Checkout\Model\Session; +use Magento\Sales\Model\Order; use Magento\Sales\Model\OrderFactory; use Magento\Framework\Exception\LocalizedException; +use \Magento\Quote\Api\CartRepositoryInterface as QuoteRepo; -/** - * Event class to prevent the basket from getting lost with redirect payment types - * when the customer uses the browser back-button - */ -class PredispatchCheckoutIndex implements ObserverInterface +class Cancellation { /** * Checkout session @@ -52,38 +48,58 @@ class PredispatchCheckoutIndex implements ObserverInterface */ protected $orderFactory; + /** + * Order repository + * + * @var QuoteRepo + */ + protected $quoteRepository; + /** * Constructor * * @param Session $checkoutSession * @param OrderFactory $orderFactory + * @param QuoteRepo $quoteRepository */ - public function __construct(Session $checkoutSession, OrderFactory $orderFactory) + public function __construct(Session $checkoutSession, OrderFactory $orderFactory, QuoteRepo $quoteRepository) { $this->checkoutSession = $checkoutSession; $this->orderFactory = $orderFactory; + $this->quoteRepository = $quoteRepository; } /** - * @param Observer $observer - * @return $this + * @return void */ - public function execute(Observer $observer) + public function handle() { if ($this->checkoutSession->getPayoneCustomerIsRedirected()) { try { $orderId = $this->checkoutSession->getLastOrderId(); $order = $orderId ? $this->orderFactory->create()->load($orderId) : false; if ($order) { - $order->cancel()->save(); + $order->cancel(); + $order->addStatusHistoryComment(__('The Payone transaction has been canceled.'), Order::STATE_CANCELED); + $order->save(); - $this->checkoutSession->restoreQuote(); + $oCurrentQuote = $this->checkoutSession->getQuote(); + + $quoteId = $this->checkoutSession->getLastQuoteId(); + $oOldQuote = $this->quoteRepository->get($quoteId); + if ($oOldQuote && $oOldQuote->getId()) { + $oCurrentQuote->merge($oOldQuote); + $oCurrentQuote->collectTotals(); + $oCurrentQuote->save(); + } $this->checkoutSession ->unsLastQuoteId() ->unsLastSuccessQuoteId() ->unsLastOrderId() ->unsLastRealOrderId(); + + $this->checkoutSession->setPayoneCanceledOrder($order->getIncrementId()); } } catch (LocalizedException $e) { // catch and continue - do something when needed @@ -95,4 +111,4 @@ public function execute(Observer $observer) $this->checkoutSession->setIsPayoneRedirectCancellation(true); } } -} +} \ No newline at end of file diff --git a/Model/Handler/TransactionStatus.php b/Model/Handler/TransactionStatus.php new file mode 100644 index 00000000..c976ac03 --- /dev/null +++ b/Model/Handler/TransactionStatus.php @@ -0,0 +1,148 @@ +. + * + * PHP version 5 + * + * @category Payone + * @package Payone_Magento2_Plugin + * @author FATCHIP GmbH + * @copyright 2003 - 2018 Payone GmbH + * @license GNU Lesser General Public License + * @link http://www.payone.de + */ + +namespace Payone\Core\Model\Handler; + +use Magento\Checkout\Model\Session; +use Magento\Sales\Model\Order; +use Magento\Sales\Model\OrderFactory; +use Magento\Framework\Exception\LocalizedException; +use \Magento\Quote\Api\CartRepositoryInterface as QuoteRepo; + +class TransactionStatus +{ + /** + * TransactionStatus array + * + * @var array + */ + protected $status = []; + + /** + * PAYONE TransactionStatus Mapping + * + * @var \Payone\Core\Model\TransactionStatus\Mapping + */ + protected $statusMapping; + + /** + * PAYONE TransactionStatus Forwarding + * + * @var \Payone\Core\Model\TransactionStatus\Forwarding + */ + protected $statusForwarding; + + /** + * Magento event manager + * + * @var \Magento\Framework\Event\ManagerInterface + */ + protected $eventManager; + + /** + * Constructor + * + * @param \Payone\Core\Model\TransactionStatus\Mapping $statusMapping + * @param \Payone\Core\Model\TransactionStatus\Forwarding $statusForwarding + * @param \Magento\Framework\Event\ManagerInterface $eventManager + */ + public function __construct( + \Payone\Core\Model\TransactionStatus\Mapping $statusMapping, + \Payone\Core\Model\TransactionStatus\Forwarding $statusForwarding, + \Magento\Framework\Event\ManagerInterface $eventManager + ) { + $this->statusMapping = $statusMapping; + $this->statusForwarding = $statusForwarding; + $this->eventManager = $eventManager; + } + + /** + * Set status array + * + * @param array $aStatus + * @return void + */ + protected function setStatus($aStatus) + { + if (is_array($aStatus)) { + $this->status = $aStatus; + } + } + + /** + * Return status array + * + * @return array + */ + protected function getStatus() + { + return $this->status; + } + + /** + * Return certain key from status array + * + * @param string $sKey + * @return string|null + */ + protected function getParam($sKey) + { + if (isset($this->status[$sKey])) { + return $this->status[$sKey]; + } + return null; + } + + /** + * Handle TransactionStatus + * + * @param Order $oOrder + * @param array $aStatus + * @return void + */ + public function handle(Order $oOrder, $aStatus) + { + $this->setStatus($aStatus); + + $sAction = $this->getParam('txaction'); + + if ($oOrder) { + $oOrder->setPayoneTransactionStatus($sAction); + $oOrder->save(); + + $this->statusMapping->handleMapping($oOrder, $sAction); + } + $this->statusForwarding->handleForwardings($this->getStatus()); + + $aParams = [ + 'order' => $oOrder, + 'transactionstatus' => $this->getStatus(), + ]; + + $this->eventManager->dispatch('payone_core_transactionstatus_all', $aParams); + $this->eventManager->dispatch('payone_core_transactionstatus_'.$sAction, $aParams); + } +} \ No newline at end of file diff --git a/Model/Methods/BaseMethod.php b/Model/Methods/BaseMethod.php index 57fbdbe1..1a2b88e2 100644 --- a/Model/Methods/BaseMethod.php +++ b/Model/Methods/BaseMethod.php @@ -289,7 +289,9 @@ public function getConfigPaymentAction() public function authorize(InfoInterface $payment, $amount) { $oReturn = parent::authorize($payment, $amount); // execute Magento parent authorization - $this->sendPayoneAuthorization($payment, $amount); // send auth request to PAYONE + if (!$this->checkoutSession->getPayoneCreatingSubstituteOrder()) { + $this->sendPayoneAuthorization($payment, $amount); // send auth request to PAYONE + } return $oReturn; // return magento parent auth value } diff --git a/Model/PayoneConfig.php b/Model/PayoneConfig.php index 85cb090e..7f08a7af 100644 --- a/Model/PayoneConfig.php +++ b/Model/PayoneConfig.php @@ -32,7 +32,7 @@ abstract class PayoneConfig { /* Module version */ - const MODULE_VERSION = '2.4.1'; + const MODULE_VERSION = '2.4.2'; /* Authorization request types */ const REQUEST_TYPE_PREAUTHORIZATION = 'preauthorization'; diff --git a/Model/ResourceModel/TransactionStatus.php b/Model/ResourceModel/TransactionStatus.php index 030d5ded..f8ad7168 100644 --- a/Model/ResourceModel/TransactionStatus.php +++ b/Model/ResourceModel/TransactionStatus.php @@ -36,11 +36,11 @@ class TransactionStatus extends \Magento\Framework\Model\ResourceModel\Db\AbstractDb { /** - * Context object + * TransactionStatus POST request * - * @var \Magento\Framework\App\Action\Context + * @var array */ - protected $oContext = null; + protected $request = []; /** * Store manager object @@ -85,6 +85,29 @@ protected function _construct() $this->_init('payone_protocol_transactionstatus', 'id'); } + /** + * Set request property + * + * @param array $request + * @return void + */ + public function setRequest($request) + { + if (is_array($request)) { + $this->request = $request; + } + } + + /** + * Get request property + * + * @return array + */ + public function getRequest() + { + return $this->request; + } + /** * Get request-parameter value or a given default if not set * @@ -94,8 +117,8 @@ protected function _construct() */ public function getParam($sKey, $sDefault = '') { - if ($this->oContext) { - $sParam = $this->oContext->getRequest()->getParam($sKey, $sDefault); + if (isset($this->request[$sKey])) { + $sParam = $this->request[$sKey]; if (!$this->toolkitHelper->isUTF8($sParam)) { $sParam = utf8_encode($sParam); } @@ -107,15 +130,16 @@ public function getParam($sKey, $sDefault = '') /** * Write TransactionStatus entry to database * - * @param Context $oContext - * @param Order $oOrder + * @param array $aRequest + * @param Order $oOrder + * @param bool $blHasBeenHandled * @return $this */ - public function addTransactionLogEntry(Context $oContext, Order $oOrder = null) + public function addTransactionLogEntry($aRequest, Order $oOrder = null, $blHasBeenHandled = true) { - $this->oContext = $oContext; - $aRequest = $oContext->getRequest()->getPostValue(); - $sRawStatus = serialize($aRequest); + $this->setRequest($aRequest); + + $sRawStatus = serialize($this->getRequest()); if (!$this->toolkitHelper->isUTF8($sRawStatus)) { $sRawStatus = utf8_encode($sRawStatus); // needed for serializing the array } @@ -177,6 +201,7 @@ public function addTransactionLogEntry(Context $oContext, Order $oOrder = null) 'clearing_reference' => $this->getParam('clearing_reference'), 'clearing_instructionnote' => $this->getParam('clearing_instructionnote'), 'raw_status' => $sRawStatus, + 'has_been_handled' => $blHasBeenHandled ] ); return $this; diff --git a/Observer/CancelOrder.php b/Observer/CancelOrder.php new file mode 100644 index 00000000..0d7c8998 --- /dev/null +++ b/Observer/CancelOrder.php @@ -0,0 +1,64 @@ +. + * + * PHP version 5 + * + * @category Payone + * @package Payone_Magento2_Plugin + * @author FATCHIP GmbH + * @copyright 2003 - 2016 Payone GmbH + * @license GNU Lesser General Public License + * @link http://www.payone.de + */ + +namespace Payone\Core\Observer; + +use Magento\Framework\Event\ObserverInterface; +use Magento\Framework\Event\Observer; +use Payone\Core\Model\Handler\Cancellation; + +/** + * Event class to prevent the basket from getting lost with redirect payment types + * when the customer uses the browser back-button + */ +class CancelOrder implements ObserverInterface +{ + /** + * Checkout session + * + * @var Cancellation + */ + protected $cancellation; + + /** + * Constructor + * + * @param Cancellation $cancellation + */ + public function __construct(Cancellation $cancellation) + { + $this->cancellation = $cancellation; + } + + /** + * @param Observer $observer + * @return $this + */ + public function execute(Observer $observer) + { + $this->cancellation->handle(); + } +} diff --git a/Setup/UpgradeData.php b/Setup/UpgradeData.php index 73d0085d..07f0f30b 100644 --- a/Setup/UpgradeData.php +++ b/Setup/UpgradeData.php @@ -177,6 +177,14 @@ public function upgrade(ModuleDataSetupInterface $setup, ModuleContextInterface ['type' => 'varchar', 'length' => 64, 'default' => ''] ); } + if (!$setup->getConnection()->tableColumnExists($setup->getTable('sales_order'), 'payone_cancel_substitute_increment_id')) { + $salesInstaller = $this->salesSetupFactory->create(['resourceName' => 'sales_setup', 'setup' => $setup]); + $salesInstaller->addAttribute( + 'order', + 'payone_cancel_substitute_increment_id', + ['type' => 'varchar', 'length' => 64, 'default' => ''] + ); + } $serializedRows = $this->getSerializedConfigRows($setup); if (!empty($serializedRows) && version_compare($this->shopHelper->getMagentoVersion(), '2.2.0', '>=')) { diff --git a/Setup/UpgradeSchema.php b/Setup/UpgradeSchema.php index 52458841..fbab0888 100644 --- a/Setup/UpgradeSchema.php +++ b/Setup/UpgradeSchema.php @@ -41,13 +41,13 @@ class UpgradeSchema extends BaseSchema implements UpgradeSchemaInterface { /** - * Upgrade method + * Add new columns * * @param SchemaSetupInterface $setup * @param ModuleContextInterface $context * @return void */ - public function upgrade(SchemaSetupInterface $setup, ModuleContextInterface $context) + protected function addNewColumns(SchemaSetupInterface $setup, ModuleContextInterface $context) { if (version_compare($context->getVersion(), '1.3.0', '<')) {// pre update version is lower than 1.3.0 $this->addTable($setup, \Payone\Core\Setup\Tables\CheckedAddresses::getData()); @@ -75,12 +75,47 @@ public function upgrade(SchemaSetupInterface $setup, ModuleContextInterface $con ] ); } + if (!$setup->getConnection()->tableColumnExists($setup->getTable(Transactionstatus::TABLE_PROTOCOL_TRANSACTIONSTATUS), 'has_been_handled')) { + $setup->getConnection()->addColumn( + $setup->getTable(Transactionstatus::TABLE_PROTOCOL_TRANSACTIONSTATUS), + 'has_been_handled', + [ + 'type' => Table::TYPE_SMALLINT, + 'length' => null, + 'nullable' => false, + 'default' => 1, + 'comment' => 'Has the status been handled already' + ] + ); + } + } + + /** + * Add new tables + * + * @param SchemaSetupInterface $setup + * @param ModuleContextInterface $context + * @return void + */ + protected function addNewTables(SchemaSetupInterface $setup, ModuleContextInterface $context) + { if (!$setup->getConnection()->isTableExists($setup->getTable(PaymentBan::TABLE_PAYMENT_BAN))) { $this->addTable($setup, PaymentBan::getData()); } if (!$setup->getConnection()->isTableExists($setup->getTable(SavedPaymentData::TABLE_SAVED_PAYMENT_DATA))) { $this->addTable($setup, SavedPaymentData::getData()); } + } + + /** + * Modify already existing columns + * + * @param SchemaSetupInterface $setup + * @param ModuleContextInterface $context + * @return void + */ + protected function modifyColumns(SchemaSetupInterface $setup, ModuleContextInterface $context) + { if (version_compare($context->getVersion(), '2.3.0', '<=')) { $setup->getConnection()->modifyColumn( $setup->getTable('payone_protocol_api'), @@ -95,36 +130,41 @@ public function upgrade(SchemaSetupInterface $setup, ModuleContextInterface $con 'portalid', ['type' => Table::TYPE_INTEGER, 'default' => '0'] ); } + } - /* - * add index to payone_protocol_api::txid to speed up transaction status calls - */ + /** + * Add indexes to speed up certain calls + * + * @param SchemaSetupInterface $setup + * @param ModuleContextInterface $context + * @return void + */ + protected function addIndexes(SchemaSetupInterface $setup, ModuleContextInterface $context) + { if (version_compare($context->getVersion(), '2.3.1', '<=')) { - $connection = $setup->getConnection(); - $protocolApiTable = $connection->getTableName(Api::TABLE_PROTOCOL_API); - $indexField = 'txid'; - $connection->addIndex( - $protocolApiTable, - $connection->getIndexName($protocolApiTable, $indexField), - $indexField - ); + $protocolApiTable = $connection->getTableName(Api::TABLE_PROTOCOL_API); + $connection->addIndex($protocolApiTable, $connection->getIndexName($protocolApiTable, 'txid'), 'txid'); $transactionStatusTable = $connection->getTableName(Transactionstatus::TABLE_PROTOCOL_TRANSACTIONSTATUS); - $indexFieldTxid = 'txid'; - $indexFieldCustomerid = 'customerid'; - - $connection->addIndex( - $transactionStatusTable, - $connection->getIndexName($transactionStatusTable, $indexFieldTxid), - $indexFieldTxid - ); - $connection->addIndex( - $transactionStatusTable, - $connection->getIndexName($transactionStatusTable, $indexFieldCustomerid), - $indexFieldCustomerid - ); + $connection->addIndex($transactionStatusTable, $connection->getIndexName($transactionStatusTable, 'txid'), 'txid'); + $connection->addIndex($transactionStatusTable, $connection->getIndexName($transactionStatusTable, 'customerid'), 'customerid'); } } + + /** + * Upgrade method + * + * @param SchemaSetupInterface $setup + * @param ModuleContextInterface $context + * @return void + */ + public function upgrade(SchemaSetupInterface $setup, ModuleContextInterface $context) + { + $this->addNewColumns($setup, $context); + $this->addNewTables($setup, $context); + $this->modifyColumns($setup, $context); + $this->addIndexes($setup, $context); + } } diff --git a/Test/Unit/Controller/Onepage/CancelTest.php b/Test/Unit/Controller/Onepage/CancelTest.php index f0bf66a6..1e944683 100644 --- a/Test/Unit/Controller/Onepage/CancelTest.php +++ b/Test/Unit/Controller/Onepage/CancelTest.php @@ -109,6 +109,7 @@ protected function setUp() 'setPayoneIsError', 'unsPayoneWorkorderId', 'unsIsPayonePayPalExpress', + 'restoreQuote', ]) ->getMock(); $this->checkoutSession->method('getLastOrderId')->willReturn('12345'); diff --git a/Test/Unit/Controller/Onepage/PlaceOrderTest.php b/Test/Unit/Controller/Onepage/PlaceOrderTest.php index cf13918e..4a596b5c 100644 --- a/Test/Unit/Controller/Onepage/PlaceOrderTest.php +++ b/Test/Unit/Controller/Onepage/PlaceOrderTest.php @@ -103,16 +103,28 @@ protected function setUp() $address = $this->getMockBuilder(Address::class)->disableOriginalConstructor()->getMock(); - $quote = $this->getMockBuilder(Quote::class)->disableOriginalConstructor()->getMock(); + $quote = $this->getMockBuilder(Quote::class) + ->disableOriginalConstructor() + ->setMethods([ + 'getBillingAddress', + 'getShippingAddress', + 'getIsVirtual', + 'getId', + 'setIsActive', + 'getSubtotal', + 'save' + ]) + ->getMock(); $quote->method('getBillingAddress')->willReturn($address); $quote->method('getShippingAddress')->willReturn($address); $quote->method('getIsVirtual')->willReturn(false); $quote->method('getId')->willReturn('12345'); $quote->method('setIsActive')->willReturn($quote); + $quote->method('getSubtotal')->willReturn(100); $this->checkoutSession = $this->getMockBuilder(Session::class) ->disableOriginalConstructor() - ->setMethods(['getQuote', 'setLastQuoteId', 'setLastSuccessQuoteId', 'unsPayoneWorkorderId', 'unsIsPayonePayPalExpress']) + ->setMethods(['getQuote', 'setLastQuoteId', 'setLastSuccessQuoteId', 'unsPayoneWorkorderId', 'unsIsPayonePayPalExpress', 'getPayoneGenericpaymentSubtotal']) ->getMock(); $this->checkoutSession->method('getQuote')->willReturn($quote); $this->checkoutSession->method('setLastQuoteId')->willReturn($this->checkoutSession); @@ -134,6 +146,7 @@ protected function setUp() public function testExecute() { + $this->checkoutSession->method('getPayoneGenericpaymentSubtotal')->willReturn(100); $this->request->method('getBeforeForwardInfo')->willReturn(false); $result = $this->classToTest->execute(); $this->assertNull($result); @@ -148,6 +161,8 @@ public function testExecuteValidation() public function testExecuteException() { + $this->checkoutSession->method('getPayoneGenericpaymentSubtotal')->willReturn(100); + $exception = new \Exception(); $this->cartManagement->method('placeOrder')->willThrowException($exception); @@ -155,4 +170,12 @@ public function testExecuteException() $result = $this->classToTest->execute(); $this->assertNull($result); } + + public function testExecuteSubtotalMismatch() + { + $this->checkoutSession->method('getPayoneGenericpaymentSubtotal')->willReturn(110); + $this->request->method('getBeforeForwardInfo')->willReturn(false); + $result = $this->classToTest->execute(); + $this->assertNull($result); + } } diff --git a/Test/Unit/Controller/Onepage/ReturnedTest.php b/Test/Unit/Controller/Onepage/ReturnedTest.php index 3b48b871..882c9305 100644 --- a/Test/Unit/Controller/Onepage/ReturnedTest.php +++ b/Test/Unit/Controller/Onepage/ReturnedTest.php @@ -26,19 +26,24 @@ namespace Payone\Core\Test\Unit\Controller\Onepage; +use Magento\Quote\Model\Quote; use Payone\Core\Controller\Onepage\Returned as ClassToTest; use Magento\Framework\TestFramework\Unit\Helper\ObjectManager; use Magento\Sales\Model\Order as OrderCore; use Magento\Checkout\Model\Session; use Magento\Framework\App\Action\Context; -use Magento\Customer\Model\Session as CustomerSession; use Magento\Store\App\Response\Redirect as RedirectResponse; use Magento\Framework\App\Console\Response; use Magento\Framework\App\ResponseInterface; use Magento\Framework\UrlInterface; use Payone\Core\Test\Unit\BaseTestCase; use Payone\Core\Test\Unit\PayoneObjectManager; - +use Magento\Quote\Model\QuoteRepository; +use Magento\Sales\Model\OrderRepository; +use Magento\Sales\Model\Order\Payment; +use Payone\Core\Helper\Database; +use Payone\Core\Model\Entities\TransactionStatusFactory; +use Payone\Core\Model\Entities\TransactionStatus; class ReturnedTest extends BaseTestCase { @@ -52,6 +57,11 @@ class ReturnedTest extends BaseTestCase */ private $objectManager; + /** + * @var Session|\PHPUnit_Framework_MockObject_MockObject + */ + private $checkoutSession; + protected function setUp() { $this->objectManager = $this->getObjectManager(); @@ -70,16 +80,84 @@ protected function setUp() $context->method('getResponse')->willReturn($response); $context->method('getUrl')->willReturn($url); - $checkoutSession = $this->getMockBuilder(Session::class)->disableOriginalConstructor()->getMock(); + $this->checkoutSession = $this->getMockBuilder(Session::class) + ->disableOriginalConstructor() + ->setMethods([ + 'getLastRealOrder', + 'setLastRealOrderId', + 'getPayoneCanceledOrder', + 'unsPayoneCanceledOrder', + 'unsPayoneCustomerIsRedirected', + 'setPayoneCreatingSubstituteOrder', + 'unsPayoneCreatingSubstituteOrder', + 'setLastOrderId', + 'getQuote' + ]) + ->getMock(); + + $quote = $this->getMockBuilder(Quote::class)->disableOriginalConstructor()->getMock(); + + $quoteRepository = $this->getMockBuilder(QuoteRepository::class)->disableOriginalConstructor()->getMock(); + $quoteRepository->method('get')->willReturn($quote); + + $payment = $this->getMockBuilder(Payment::class)->disableOriginalConstructor()->getMock(); + $payment->method('getId')->willReturn(123); + + $order = $this->getMockBuilder(OrderCore::class)->disableOriginalConstructor()->getMock(); + $order->method('getPayment')->willReturn($payment); + + $orderRepository = $this->getMockBuilder(OrderRepository::class)->disableOriginalConstructor()->getMock(); + $orderRepository->method('get')->willReturn($order); + + $databaseHelper = $this->getMockBuilder(Database::class)->disableOriginalConstructor()->getMock(); + $databaseHelper->method('getNotHandledTransactionsByOrderId')->willReturn([['id' => 5]]); + + $status = $this->getMockBuilder(TransactionStatus::class)->disableOriginalConstructor()->getMock(); + + $statusFactory = $this->getMockBuilder(TransactionStatusFactory::class) + ->disableOriginalConstructor() + ->setMethods(['create']) + ->getMock(); + $statusFactory->method('create')->willReturn($status); $this->classToTest = $this->objectManager->getObject(ClassToTest::class, [ 'context' => $context, - 'checkoutSession' => $checkoutSession + 'checkoutSession' => $this->checkoutSession, + 'quoteRepository' => $quoteRepository, + 'orderRepository' => $orderRepository, + 'databaseHelper' => $databaseHelper, + 'statusFactory' => $statusFactory ]); } public function testExecute() { + $order = $this->getMockBuilder(OrderCore::class)->disableOriginalConstructor()->getMock(); + $order->method('getId')->willReturn(null); + $order->method('getStatus')->willReturn(OrderCore::STATE_COMPLETE); + + $this->checkoutSession->method('getLastRealOrder')->willReturn($order); + $this->checkoutSession->method('getPayoneCanceledOrder')->willReturn(null); + + $result = $this->classToTest->execute(); + $this->assertNull($result); + } + + public function testExecuteSubstitute() + { + $order = $this->getMockBuilder(OrderCore::class)->disableOriginalConstructor()->getMock(); + $order->method('getId')->willReturn(null); + $order->method('getStatus')->willReturn(OrderCore::STATE_CANCELED); + $order->method('getQuoteId')->willReturn('123'); + $order->method('getData')->willReturn(['payone_txid' => '12345']); + + $quote = $this->getMockBuilder(Quote::class)->disableOriginalConstructor()->getMock(); + $quote->method('setIsActive')->willReturn($quote); + + $this->checkoutSession->method('getLastRealOrder')->willReturn($order); + $this->checkoutSession->method('getPayoneCanceledOrder')->willReturn(123); + $this->checkoutSession->method('getQuote')->willReturn($quote); + $result = $this->classToTest->execute(); $this->assertNull($result); } diff --git a/Test/Unit/Controller/Transactionstatus/IndexTest.php b/Test/Unit/Controller/Transactionstatus/IndexTest.php index 53b0d158..535a69c5 100644 --- a/Test/Unit/Controller/Transactionstatus/IndexTest.php +++ b/Test/Unit/Controller/Transactionstatus/IndexTest.php @@ -62,6 +62,16 @@ class IndexTest extends BaseTestCase */ private $environmentHelper; + /** + * @var OrderCore|\PHPUnit_Framework_MockObject_MockObject + */ + private $order; + + /** + * @var Http + */ + private $request; + protected function setUp() { $this->objectManager = $this->getObjectManager(); @@ -69,25 +79,24 @@ protected function setUp() $post = $this->getMockBuilder(self::class)->disableOriginalConstructor()->setMethods(['toArray'])->getMock(); $post->method('toArray')->willReturn(['test' => 'array']); - $request = $this->getMockBuilder(Http::class) + $this->request = $this->getMockBuilder(Http::class) ->disableOriginalConstructor() ->setMethods(['getParam', 'getPost']) ->getMock(); - $request->method('getParam')->willReturn('Value'); - $request->method('getPost')->willReturn($post); + $this->request->method('getPost')->willReturn($post); $eventManater = $this->getMockBuilder(ManagerInterface::class)->disableOriginalConstructor()->getMock(); $context = $this->getMockBuilder(Context::class)->disableOriginalConstructor()->getMock(); - $context->method('getRequest')->willReturn($request); + $context->method('getRequest')->willReturn($this->request); $context->method('getEventManager')->willReturn($eventManater); $this->toolkitHelper = $this->getMockBuilder(Toolkit::class)->disableOriginalConstructor()->getMock(); $this->environmentHelper = $this->getMockBuilder(Environment::class)->disableOriginalConstructor()->getMock(); - $order = $this->getMockBuilder(OrderCore::class)->disableOriginalConstructor()->getMock(); + $this->order = $this->getMockBuilder(OrderCore::class)->disableOriginalConstructor()->getMock(); $orderHelper = $this->getMockBuilder(Order::class)->disableOriginalConstructor()->getMock(); - $orderHelper->method('getOrderByTxid')->willReturn($order); + $orderHelper->method('getOrderByTxid')->willReturn($this->order); $rawResponse = $this->getMockBuilder(Raw::class)->disableOriginalConstructor()->getMock(); $resultRawFactory = $this->getMockBuilder(RawFactory::class) @@ -107,6 +116,7 @@ protected function setUp() public function testExecuteIpInvalid() { + $this->request->method('getParam')->willReturn('Value'); $this->environmentHelper->method('isRemoteIpValid')->willReturn(false); $result = $this->classToTest->execute(); @@ -115,6 +125,7 @@ public function testExecuteIpInvalid() public function testExecuteKeyInvalid() { + $this->request->method('getParam')->willReturn('Value'); $this->environmentHelper->method('isRemoteIpValid')->willReturn(true); $this->toolkitHelper->method('isKeyValid')->willReturn(false); @@ -122,8 +133,20 @@ public function testExecuteKeyInvalid() $this->assertInstanceOf(Raw::class, $result); } + public function testExecuteCanceled() + { + $this->request->method('getParam')->willReturn('appointed'); + $this->order->method('getStatus')->willReturn('canceled'); + $this->environmentHelper->method('isRemoteIpValid')->willReturn(true); + $this->toolkitHelper->method('isKeyValid')->willReturn(true); + + $result = $this->classToTest->execute(); + $this->assertInstanceOf(Raw::class, $result); + } + public function testExecute() { + $this->request->method('getParam')->willReturn('Value'); $this->environmentHelper->method('isRemoteIpValid')->willReturn(true); $this->toolkitHelper->method('isKeyValid')->willReturn(true); diff --git a/Test/Unit/Helper/DatabaseTest.php b/Test/Unit/Helper/DatabaseTest.php index b09b98d8..1f3b94d1 100644 --- a/Test/Unit/Helper/DatabaseTest.php +++ b/Test/Unit/Helper/DatabaseTest.php @@ -80,13 +80,14 @@ protected function setUp() $this->connection = $this->getMockBuilder(Select::class) ->disableOriginalConstructor() - ->setMethods(['fetchOne', 'fetchAll', 'select', 'from', 'where', 'limit', 'order']) + ->setMethods(['fetchOne', 'fetchAll', 'select', 'from', 'where', 'limit', 'order', 'update', 'joinInner']) ->getMock(); $this->connection->method('select')->willReturn($this->connection); $this->connection->method('from')->willReturn($this->connection); $this->connection->method('where')->willReturn($this->connection); $this->connection->method('limit')->willReturn($this->connection); $this->connection->method('order')->willReturn($this->connection); + $this->connection->method('joinInner')->willReturn($this->connection); $this->databaseResource = $this->getMockBuilder(ResourceConnection::class)->disableOriginalConstructor()->getMock(); $this->databaseResource->method('getConnection')->willReturn($this->connection); @@ -217,4 +218,50 @@ public function testGetOldAddressStatus() $result = $this->database->getOldAddressStatus($address, false); $this->assertEquals($expected, $result); } + + public function testRelabelTransaction() + { + $expected = '1'; + + $this->databaseResource->method('getTableName')->willReturn('sales_payment_transaction'); + $this->connection->method('update')->willReturn($expected); + + $result = $this->database->relabelTransaction('1', '2', '3'); + $this->assertEquals($expected, $result); + } + + public function testRelabelApiProtocol() + { + $expected = '1'; + + $this->databaseResource->method('getTableName')->willReturn('payone_protocol_api'); + $this->connection->method('update')->willReturn($expected); + + $result = $this->database->relabelApiProtocol('1', '2'); + $this->assertEquals($expected, $result); + } + + public function testRelabelOrderPayment() + { + $expected = '1'; + + $this->databaseResource->method('getTableName')->willReturn('sales_order_payment'); + $this->connection->method('update')->willReturn($expected); + + $result = $this->database->relabelOrderPayment('1', '2'); + $this->assertEquals($expected, $result); + } + + public function testGetNotHandledTransactionsByOrderId() + { + $expected = [ + ['id' => '5'], + ]; + + $this->databaseResource->method('getTableName')->willReturn('payone_protocol_transactionstatus'); + $this->connection->method('fetchAll')->willReturn($expected); + + $result = $this->database->getNotHandledTransactionsByOrderId(5); + $this->assertEquals($expected, $result); + } } diff --git a/Test/Unit/Observer/PredispatchCheckoutIndexTest.php b/Test/Unit/Model/Handler/CancellationTest.php similarity index 52% rename from Test/Unit/Observer/PredispatchCheckoutIndexTest.php rename to Test/Unit/Model/Handler/CancellationTest.php index eeeb0291..2d46aa88 100644 --- a/Test/Unit/Observer/PredispatchCheckoutIndexTest.php +++ b/Test/Unit/Model/Handler/CancellationTest.php @@ -24,19 +24,20 @@ * @link http://www.payone.de */ -namespace Payone\Core\Test\Unit\Observer; +namespace Payone\Core\Test\Unit\Model\Handler; -use Payone\Core\Observer\PredispatchCheckoutIndex as ClassToTest; -use Magento\Framework\TestFramework\Unit\Helper\ObjectManager; -use Magento\Framework\Event\Observer; -use Magento\Checkout\Model\Session; -use Magento\Sales\Model\OrderFactory; +use Magento\Quote\Model\Quote; use Magento\Sales\Model\Order; -use Magento\Framework\Exception\NoSuchEntityException; +use Payone\Core\Model\Handler\Cancellation as ClassToTest; +use Magento\Framework\TestFramework\Unit\Helper\ObjectManager; use Payone\Core\Test\Unit\BaseTestCase; use Payone\Core\Test\Unit\PayoneObjectManager; +use Magento\Checkout\Model\Session; +use Magento\Sales\Model\OrderFactory; +use Magento\Quote\Model\QuoteRepository; +use Magento\Framework\Exception\LocalizedException; -class PredispatchCheckoutIndexTest extends BaseTestCase +class CancellationTest extends BaseTestCase { /** * @var ClassToTest @@ -49,77 +50,83 @@ class PredispatchCheckoutIndexTest extends BaseTestCase private $objectManager; /** - * @var Session|\PHPUnit_Framework_MockObject_MockObject + * @var Order|\PHPUnit_Framework_MockObject_MockObject */ - private $checkoutSession; + private $order; protected function setUp() { $this->objectManager = $this->getObjectManager(); - $this->checkoutSession = $this->getMockBuilder(Session::class) + $quote = $this->getMockBuilder(Quote::class)->disableOriginalConstructor()->getMock(); + $quote->method('getId')->willReturn(123); + + $checkoutSession = $this->getMockBuilder(Session::class) ->disableOriginalConstructor() ->setMethods([ 'getPayoneCustomerIsRedirected', + 'unsPayoneCustomerIsRedirected', + 'getQuote', 'getLastOrderId', - 'restoreQuote', + 'unsLastOrderId', + 'getLastQuoteId', 'unsLastQuoteId', 'unsLastSuccessQuoteId', - 'unsLastOrderId', 'unsLastRealOrderId', - 'unsPayoneCustomerIsRedirected', - 'setIsPayoneRedirectCancellation' + 'setPayoneCanceledOrder', + 'setIsPayoneRedirectCancellation', ]) ->getMock(); - $this->checkoutSession->method('getPayoneCustomerIsRedirected')->willReturn(true); - $this->checkoutSession->method('getLastOrderId')->willReturn('123'); - $this->checkoutSession->method('unsLastQuoteId')->willReturn($this->checkoutSession); - $this->checkoutSession->method('unsLastSuccessQuoteId')->willReturn($this->checkoutSession); - $this->checkoutSession->method('unsLastOrderId')->willReturn($this->checkoutSession); - - $order = $this->getMockBuilder(Order::class)->disableOriginalConstructor()->getMock(); - $order->method('load')->willReturn($order); - $order->method('cancel')->willReturn($order); + $checkoutSession->method('getPayoneCustomerIsRedirected')->willReturn(true); + $checkoutSession->method('getLastOrderId')->willReturn(123); + $checkoutSession->method('getQuote')->willReturn($quote); + $checkoutSession->method('getLastQuoteId')->willReturn(123); + $checkoutSession->method('unsLastQuoteId')->willReturn($checkoutSession); + $checkoutSession->method('unsLastSuccessQuoteId')->willReturn($checkoutSession); + $checkoutSession->method('unsLastOrderId')->willReturn($checkoutSession); + $checkoutSession->method('unsLastRealOrderId')->willReturn($checkoutSession); + + $this->order = $this->getMockBuilder(Order::class)->disableOriginalConstructor()->getMock(); + $this->order->method('load')->willReturn($this->order); + $this->order->method('getIncrementId')->willReturn(123); $orderFactory = $this->getMockBuilder(OrderFactory::class) ->disableOriginalConstructor() ->setMethods(['create']) ->getMock(); - $orderFactory->method('create')->willReturn($order); + $orderFactory->method('create')->willReturn($this->order); + + $quoteRepository = $this->getMockBuilder(QuoteRepository::class)->disableOriginalConstructor()->getMock(); + $quoteRepository->method('get')->willReturn($quote); $this->classToTest = $this->objectManager->getObject(ClassToTest::class, [ - 'checkoutSession' => $this->checkoutSession, + 'checkoutSession' => $checkoutSession, 'orderFactory' => $orderFactory, + 'quoteRepository' => $quoteRepository ]); } - public function testExecute() + public function testHandle() { - $observer = $this->getMockBuilder(Observer::class)->disableOriginalConstructor()->getMock(); - - $result = $this->classToTest->execute($observer); + $result = $this->classToTest->handle(); $this->assertNull($result); } - public function testExecuteLocalizedException() + public function testExecuteException() { - $exception = $this->objectManager->getObject(NoSuchEntityException::class); - $this->checkoutSession->expects($this->once())->method('restoreQuote')->willThrowException($exception); - - $observer = $this->getMockBuilder(Observer::class)->disableOriginalConstructor()->getMock(); + $exception = new \Exception(); + $this->order->method('cancel')->willThrowException($exception); - $result = $this->classToTest->execute($observer); + $result = $this->classToTest->handle(); $this->assertNull($result); } - public function testExecuteException() + public function testExecuteLocalizedException() { - $exception = $this->objectManager->getObject(\Exception::class); - $this->checkoutSession->expects($this->once())->method('restoreQuote')->willThrowException($exception); - - $observer = $this->getMockBuilder(Observer::class)->disableOriginalConstructor()->getMock(); + $exception = new LocalizedException(__('An error occured')); + $this->order->method('cancel')->willThrowException($exception); - $result = $this->classToTest->execute($observer); + $result = $this->classToTest->handle(); $this->assertNull($result); } } diff --git a/Test/Unit/Model/Handler/TransactionStatusTest.php b/Test/Unit/Model/Handler/TransactionStatusTest.php new file mode 100644 index 00000000..d0a4a1bf --- /dev/null +++ b/Test/Unit/Model/Handler/TransactionStatusTest.php @@ -0,0 +1,73 @@ +. + * + * PHP version 5 + * + * @category Payone + * @package Payone_Magento2_Plugin + * @author FATCHIP GmbH + * @copyright 2003 - 2018 Payone GmbH + * @license GNU Lesser General Public License + * @link http://www.payone.de + */ + +namespace Payone\Core\Test\Unit\Model\Handler; + +use Magento\Sales\Model\Order; +use Payone\Core\Model\Handler\TransactionStatus as ClassToTest; +use Magento\Framework\TestFramework\Unit\Helper\ObjectManager; +use Payone\Core\Test\Unit\BaseTestCase; +use Payone\Core\Test\Unit\PayoneObjectManager; + +class TransactionStatusTest extends BaseTestCase +{ + /** + * @var ClassToTest + */ + private $classToTest; + + /** + * @var ObjectManager|PayoneObjectManager + */ + private $objectManager; + + protected function setUp() + { + $this->objectManager = $this->getObjectManager(); + + $this->classToTest = $this->objectManager->getObject(ClassToTest::class); + } + + public function testHandle() + { + $order = $this->getMockBuilder(Order::class)->disableOriginalConstructor()->getMock(); + + $status = ['txaction' => 'appointed']; + + $result = $this->classToTest->handle($order, $status); + $this->assertNull($result); + } + + public function testHandleGetParamNull() + { + $order = $this->getMockBuilder(Order::class)->disableOriginalConstructor()->getMock(); + + $status = []; + + $result = $this->classToTest->handle($order, $status); + $this->assertNull($result); + } +} diff --git a/Test/Unit/Model/Methods/Payolution/DebitTest.php b/Test/Unit/Model/Methods/Payolution/DebitTest.php index 51e3fe0d..b369b1aa 100644 --- a/Test/Unit/Model/Methods/Payolution/DebitTest.php +++ b/Test/Unit/Model/Methods/Payolution/DebitTest.php @@ -24,7 +24,7 @@ * @link http://www.payone.de */ -namespace Payone\Core\Test\Unit\Model\Methods\OnlineBankTransfer; +namespace Payone\Core\Test\Unit\Model\Methods\Payolution; use Payone\Core\Helper\Toolkit; use Payone\Core\Model\Methods\Payolution\Debit as ClassToTest; diff --git a/Test/Unit/Model/Methods/Payolution/InstallmentTest.php b/Test/Unit/Model/Methods/Payolution/InstallmentTest.php index 194ad7fe..f529c0fa 100644 --- a/Test/Unit/Model/Methods/Payolution/InstallmentTest.php +++ b/Test/Unit/Model/Methods/Payolution/InstallmentTest.php @@ -24,7 +24,7 @@ * @link http://www.payone.de */ -namespace Payone\Core\Test\Unit\Model\Methods\OnlineBankTransfer; +namespace Payone\Core\Test\Unit\Model\Methods\Payolution; use Payone\Core\Helper\Toolkit; use Payone\Core\Model\Methods\Payolution\Installment as ClassToTest; diff --git a/Test/Unit/Model/Methods/Payolution/InvoiceTest.php b/Test/Unit/Model/Methods/Payolution/InvoiceTest.php index f080c84b..d180a0fe 100644 --- a/Test/Unit/Model/Methods/Payolution/InvoiceTest.php +++ b/Test/Unit/Model/Methods/Payolution/InvoiceTest.php @@ -24,8 +24,9 @@ * @link http://www.payone.de */ -namespace Payone\Core\Test\Unit\Model\Methods\OnlineBankTransfer; +namespace Payone\Core\Test\Unit\Model\Methods\Payolution; +use Payone\Core\Helper\Shop; use Payone\Core\Helper\Toolkit; use Payone\Core\Model\Methods\Payolution\Invoice as ClassToTest; use Magento\Framework\TestFramework\Unit\Helper\ObjectManager; @@ -77,11 +78,15 @@ protected function setUp() $authorizationRequest = $this->getMockBuilder(Authorization::class)->disableOriginalConstructor()->getMock(); $authorizationRequest->method('sendRequest')->willReturn(['status' => 'APPROVED', 'txid' => '12345']); + $shopHelper = $this->getMockBuilder(Shop::class)->disableOriginalConstructor()->getMock(); + $shopHelper->method('getConfigParam')->willReturn('display'); + $this->classToTest = $this->objectManager->getObject(ClassToTest::class, [ 'toolkitHelper' => $toolkitHelper, 'checkoutSession' => $checkoutSession, 'precheckRequest' => $this->precheckRequest, - 'authorizationRequest' => $authorizationRequest + 'authorizationRequest' => $authorizationRequest, + 'shopHelper' => $shopHelper ]); $this->classToTest->setInfoInstance($info); } diff --git a/Test/Unit/Model/Methods/PayoneMethodTest.php b/Test/Unit/Model/Methods/PayoneMethodTest.php index 95a8d851..028bd71d 100644 --- a/Test/Unit/Model/Methods/PayoneMethodTest.php +++ b/Test/Unit/Model/Methods/PayoneMethodTest.php @@ -32,6 +32,7 @@ use Payone\Core\Model\PayoneConfig; use Payone\Core\Test\Unit\BaseTestCase; use Payone\Core\Test\Unit\PayoneObjectManager; +use Magento\Framework\Url; class PayoneMethodTest extends BaseTestCase { @@ -56,8 +57,12 @@ protected function setUp() $this->shopHelper = $this->getMockBuilder(Shop::class)->disableOriginalConstructor()->getMock(); + $url = $this->getMockBuilder(Url::class)->disableOriginalConstructor()->getMock(); + $url->method('getUrl')->willReturn('http://testdomain.org'); + $this->classToTest = $this->objectManager->getObject(ClassToTest::class, [ - 'shopHelper' => $this->shopHelper + 'shopHelper' => $this->shopHelper, + 'url' => $url ]); } @@ -135,4 +140,12 @@ public function testGetNarrativeTextMaxLength() $expected = 37; $this->assertEquals($expected, $result); } + + public function testGetSuccessUrl() + { + $expected = 'http://testdomain.org'; + + $result = $this->classToTest->getSuccessUrl(); + $this->assertEquals($expected, $result); + } } diff --git a/Test/Unit/Model/ResourceModel/TransactionStatusTest.php b/Test/Unit/Model/ResourceModel/TransactionStatusTest.php index e7e08390..0113e1cc 100644 --- a/Test/Unit/Model/ResourceModel/TransactionStatusTest.php +++ b/Test/Unit/Model/ResourceModel/TransactionStatusTest.php @@ -99,19 +99,12 @@ protected function setUp() public function testAddTransactionLogEntry() { - $post = 15; + $request = [ + 'txaction' => 'appointed', + 'txtime' => time(), + ]; - $request = $this->getMockBuilder(Http::class) - ->disableOriginalConstructor() - ->setMethods(['getPostValue', 'getParam']) - ->getMock(); - $request->method('getPostValue')->willReturn($post); - $request->method('getParam')->willReturn(15); - - $context = $this->getMockBuilder(ActionContext::class)->disableOriginalConstructor()->getMock(); - $context->method('getRequest')->willReturn($request); - - $result = $this->classToTest->addTransactionLogEntry($context); + $result = $this->classToTest->addTransactionLogEntry($request); $this->assertInstanceOf(ClassToTest::class, $result); } diff --git a/Test/Unit/Observer/CancelOrderTest.php b/Test/Unit/Observer/CancelOrderTest.php new file mode 100644 index 00000000..322bec64 --- /dev/null +++ b/Test/Unit/Observer/CancelOrderTest.php @@ -0,0 +1,69 @@ +. + * + * PHP version 5 + * + * @category Payone + * @package Payone_Magento2_Plugin + * @author FATCHIP GmbH + * @copyright 2003 - 2017 Payone GmbH + * @license GNU Lesser General Public License + * @link http://www.payone.de + */ + +namespace Payone\Core\Test\Unit\Observer; + +use Payone\Core\Model\Handler\Cancellation; +use Payone\Core\Observer\CancelOrder as ClassToTest; +use Magento\Framework\TestFramework\Unit\Helper\ObjectManager; +use Magento\Framework\Event\Observer; +use Payone\Core\Test\Unit\BaseTestCase; +use Payone\Core\Test\Unit\PayoneObjectManager; + + +class CancelOrderTest extends BaseTestCase +{ + /** + * @var ClassToTest + */ + private $classToTest; + + /** + * @var ObjectManager|PayoneObjectManager + */ + private $objectManager; + + protected function setUp() + { + $this->objectManager = $this->getObjectManager(); + + $cancellation = $this->getMockBuilder(Cancellation::class) + ->disableOriginalConstructor() + ->getMock(); + + $this->classToTest = $this->objectManager->getObject(ClassToTest::class, [ + 'cancellation' => $cancellation + ]); + } + + public function testExecute() + { + $observer = $this->getMockBuilder(Observer::class)->disableOriginalConstructor()->getMock(); + + $result = $this->classToTest->execute($observer); + $this->assertNull($result); + } +} diff --git a/etc/events.xml b/etc/events.xml index cb9476bf..1751e9fb 100644 --- a/etc/events.xml +++ b/etc/events.xml @@ -35,7 +35,10 @@ - + + + + diff --git a/etc/module.xml b/etc/module.xml index 5fa7e001..646ba7cb 100644 --- a/etc/module.xml +++ b/etc/module.xml @@ -25,7 +25,7 @@ */ --> - +