From 711285dfc294a05c33016b381b4b4f3d556169b5 Mon Sep 17 00:00:00 2001 From: Lucian Turiac Date: Tue, 23 May 2023 11:29:02 +0300 Subject: [PATCH 01/29] BP-2132 - add comments and move lock processing in specific service --- Model/Push.php | 10 ++++- Service/LockPushService.php | 85 +++++++++++++++++++++++++++++++++++++ 2 files changed, 94 insertions(+), 1 deletion(-) create mode 100644 Service/LockPushService.php diff --git a/Model/Push.php b/Model/Push.php index cd8bc11c0..48e7ce79f 100644 --- a/Model/Push.php +++ b/Model/Push.php @@ -287,18 +287,22 @@ public function __construct( */ public function receivePush() { - //Start debug mailing/logging with the postdata. + // Log the push request $this->logging->addDebug(__METHOD__ . '|1|' . var_export($this->pushRequst->getOriginalRequest(), true)); + // Lock Push Processing $this->logging->addDebug(__METHOD__ . '|1_2|'); $lockHandler = $this->lockPushProcessing(); $this->logging->addDebug(__METHOD__ . '|1_3|'); + // Check if is Failed group transaction execute specific handler + // Handler criteri.handle if ($this->isFailedGroupTransaction()) { $this->handleGroupTransactionFailed(); return true; } + // Check if is group transaction info if ($this->isGroupTransactionInfo()) { if($this->isCanceledGroupTransaction()) { $this->cancelGroupTransactionOrder(); @@ -311,16 +315,20 @@ public function receivePush() } } + // Load order by transaction id $this->loadOrder(); + // Skip Handle group transaction if ($this->skipHandlingForFailedGroupTransactions()) { return true; } + // skip Push based on specific condition if (!$this->isPushNeeded()) { return true; } + // Validate Signature $store = $this->order ? $this->order->getStore() : null; //Check if the push can be processed and if the order can be updated IMPORTANT => use the original post data. $validSignature = $this->pushRequst->validate($store); diff --git a/Service/LockPushService.php b/Service/LockPushService.php new file mode 100644 index 000000000..829bb89ec --- /dev/null +++ b/Service/LockPushService.php @@ -0,0 +1,85 @@ +helper->getStatusCode('BUCKAROO_MAGENTO2_STATUSCODE_SUCCESS'); + if (!empty($this->pushRequst->getAdditionalInformation('frompayperemail')) + || ( + ($this->pushRequst->hasPostData('statuscode', $statusCodeSuccess)) + && $this->pushRequst->hasPostData('transaction_method', 'ideal') + && $this->pushRequst->hasPostData('transaction_type', self::BUCK_PUSH_IDEAL_PAY) + ) + ) { + return true; + } else { + return false; + } + } + + /** + * Lock the push processing if criteria are met. + * + * @return resource|void + * @throws FileSystemException + */ + private function lockPushProcessing() + { + if ($this->lockPushProcessingCriteria()) { + $this->logging->addDebug(__METHOD__ . '|1|'); + if ($path = $this->getLockPushProcessingFilePath()) { + if ($fp = $this->fileSystemDriver->fileOpen($path, "w+")) { + $this->fileSystemDriver->fileLock($fp, LOCK_EX); + $this->logging->addDebug(__METHOD__ . '|5|'); + return $fp; + } + } + } + } + + /** + * Get the file path for the lock push processing file. + * + * @return string|false + * @throws FileSystemException + */ + private function getLockPushProcessingFilePath() + { + if ($brqOrderId = $this->getOrderIncrementId()) { + return $this->dirList->getPath('tmp') . DIRECTORY_SEPARATOR . 'bk_push_ppe_' . sha1($brqOrderId); + } else { + return false; + } + } + + /** + * Unlock the push processing. + * + * @param resource $lockHandler + * @return void + * @throws FileSystemException + */ + private function unlockPushProcessing($lockHandler) + { + if ($this->lockPushProcessingCriteria()) { + $this->logging->addDebug(__METHOD__ . '|1|'); + $this->fileSystemDriver->fileClose($lockHandler); + if (($path = $this->getLockPushProcessingFilePath()) && $this->fileSystemDriver->isExists($path)) { + $this->fileSystemDriver->deleteFile($path); + $this->logging->addDebug(__METHOD__ . '|5|'); + } + } + } +} \ No newline at end of file From 4d56db26094913f1df3b39e73fa246815c5a89a2 Mon Sep 17 00:00:00 2001 From: Lucian Turiac Date: Wed, 24 May 2023 18:37:49 +0300 Subject: [PATCH 02/29] BP-2132 - refactor push move locker process into separate service and create the structure of push processors. --- Api/PushProcessorInterface.php | 15 +++++ Model/Push.php | 22 ++++++- Model/Push/DefaultProcessor.php | 49 +++++++++++++++ Model/Push/IdealProcessor.php | 78 +++++++++++++++++++++++ Model/Push/PayPerEmailProcessor.php | 57 +++++++++++++++++ Model/Push/PushProcessorsFactory.php | 71 +++++++++++++++++++++ Service/LockPushService.php | 85 ------------------------- Service/LockerProcess.php | 93 ++++++++++++++++++++++++++++ etc/di.xml | 10 +++ 9 files changed, 393 insertions(+), 87 deletions(-) create mode 100644 Api/PushProcessorInterface.php create mode 100644 Model/Push/DefaultProcessor.php create mode 100644 Model/Push/IdealProcessor.php create mode 100644 Model/Push/PayPerEmailProcessor.php create mode 100644 Model/Push/PushProcessorsFactory.php delete mode 100644 Service/LockPushService.php create mode 100644 Service/LockerProcess.php diff --git a/Api/PushProcessorInterface.php b/Api/PushProcessorInterface.php new file mode 100644 index 000000000..61a497667 --- /dev/null +++ b/Api/PushProcessorInterface.php @@ -0,0 +1,15 @@ +order = $order; $this->transaction = $transaction; @@ -274,11 +287,13 @@ public function __construct( $this->afterpayConfig = $afterpayConfig; $this->fileSystemDriver = $fileSystemDriver; $this->pushRequst = $requestPushFactory->create(); + $this->pushProcessorsFactory = $pushProcessorsFactory; } /** * @inheritdoc * + * @throws BuckarooException * @todo Once Magento supports variable parameters, modify this method to no longer require a Request object * * @SuppressWarnings(PHPMD.CyclomaticComplexity) @@ -290,13 +305,16 @@ public function receivePush() // Log the push request $this->logging->addDebug(__METHOD__ . '|1|' . var_export($this->pushRequst->getOriginalRequest(), true)); + $this->pushProcessor = $this->pushProcessorsFactory->get($this->pushRequst); + $this->pushProcessor->processPush($this->pushRequst); + // Lock Push Processing $this->logging->addDebug(__METHOD__ . '|1_2|'); $lockHandler = $this->lockPushProcessing(); $this->logging->addDebug(__METHOD__ . '|1_3|'); // Check if is Failed group transaction execute specific handler - // Handler criteri.handle + // criteria.handle if ($this->isFailedGroupTransaction()) { $this->handleGroupTransactionFailed(); return true; diff --git a/Model/Push/DefaultProcessor.php b/Model/Push/DefaultProcessor.php new file mode 100644 index 000000000..904b88fa3 --- /dev/null +++ b/Model/Push/DefaultProcessor.php @@ -0,0 +1,49 @@ +pushRequest = $pushRequest; + } + + /** + * Get the order increment ID based on the invoice number or order number. + * + * @return string|false + */ + protected function getOrderIncrementId() + { + $brqOrderId = false; + + if (!empty($this->pushRequest->getInvoiceNumber()) && strlen($this->pushRequest->getInvoiceNumber()) > 0) { + $brqOrderId = $this->pushRequest->getInvoiceNumber(); + } + + if (!empty($this->pushRequest->getOrderNumber()) && strlen($this->pushRequest->getOrderNumber()) > 0) { + $brqOrderId = $this->pushRequest->getOrderNumber(); + } + + return $brqOrderId; + } +} \ No newline at end of file diff --git a/Model/Push/IdealProcessor.php b/Model/Push/IdealProcessor.php new file mode 100644 index 000000000..1a1bedf09 --- /dev/null +++ b/Model/Push/IdealProcessor.php @@ -0,0 +1,78 @@ +lockerProcess = $lockerProcess; + $this->helper = $helper; + } + + /** + * @throws FileSystemException + */ + public function processPush(PushRequestInterface $pushRequest): void + { + $this->pushRequest = $pushRequest; + + if ($this->lockPushProcessingCriteria()) { + $this->lockerProcess->lockProcess($this->getOrderIncrementId()); + } + parent::processPush($pushRequest); + + $this->lockerProcess->unlockProcess(); + } + + /** + * Determine if the lock push processing criteria are met. + * + * @return bool + */ + private function lockPushProcessingCriteria(): bool + { + $statusCodeSuccess = $this->helper->getStatusCode('BUCKAROO_MAGENTO2_STATUSCODE_SUCCESS'); + + return ($this->pushRequest->hasPostData('statuscode', $statusCodeSuccess) + && $this->pushRequest->hasPostData('transaction_type', self::BUCK_PUSH_IDEAL_PAY)); + } + + public function processSucceded() + { + $statusCodeSuccess = $this->helper->getStatusCode('BUCKAROO_MAGENTO2_STATUSCODE_SUCCESS'); + + if ($this->pushRequest->hasPostData('statuscode', $statusCodeSuccess) + && $this->pushRequest->hasPostData('transaction_method', 'ideal') + && $this->pushRequest->hasPostData('transaction_type', self::BUCK_PUSH_IDEAL_PAY) + ) { + return true; + } + } + + public function processFailed() + { + // TODO: Implement processFailed() method. + } + + +} \ No newline at end of file diff --git a/Model/Push/PayPerEmailProcessor.php b/Model/Push/PayPerEmailProcessor.php new file mode 100644 index 000000000..9a21dbac0 --- /dev/null +++ b/Model/Push/PayPerEmailProcessor.php @@ -0,0 +1,57 @@ +lockerProcess = $lockerProcess; + } + + public function processSucceded() + { + + } + + public function processFailed() + { + // TODO: Implement processFailed() method. + } + + + /** + * @throws FileSystemException + */ + public function processPush(PushRequestInterface $pushRequest): void + { + $this->pushRequest = $pushRequest; + + if ($this->lockPushProcessingCriteria()) { + $this->lockerProcess->lockProcess($this->getOrderIncrementId()); + } + parent::processPush($pushRequest); + } + + /** + * Determine if the lock push processing criteria are met. + * + * @return bool + */ + private function lockPushProcessingCriteria(): bool + { + return !empty($this->pushRequest->getAdditionalInformation('frompayperemail')); + } +} \ No newline at end of file diff --git a/Model/Push/PushProcessorsFactory.php b/Model/Push/PushProcessorsFactory.php new file mode 100644 index 000000000..bad83eecf --- /dev/null +++ b/Model/Push/PushProcessorsFactory.php @@ -0,0 +1,71 @@ +objectManager = $objectManager; + $this->pushProcessors = $pushProcessors; + } + + /** + * Retrieve proper push processor for the specified transaction method. + * + * @param PushRequestInterface|null $pushRequest + * @return ?PushProcessorInterface + * @throws BuckarooException + */ + public function get(?PushRequestInterface $pushRequest): ?PushProcessorInterface + { + if (!$this->pushProcessor instanceof PushProcessorInterface) { + if (empty($this->pushProcessors)) { + throw new \LogicException('Push processors is not set.'); + } + + $transactionMethod = $pushRequest->getTransactionMethod(); + + $pushProcessorClass = $this->pushProcessors[$transactionMethod] ?? + $this->pushProcessors['default'] ?? ''; + + if (empty($pushProcessorClass)) { + throw new BuckarooException( + new Phrase( + 'Unknown ConfigProvider type requested: %1.', + [$transactionMethod] + ) + ); + } + $this->pushProcessor = $this->objectManager->get($pushProcessorClass); + + } + return $this->pushProcessor; + } +} \ No newline at end of file diff --git a/Service/LockPushService.php b/Service/LockPushService.php deleted file mode 100644 index 829bb89ec..000000000 --- a/Service/LockPushService.php +++ /dev/null @@ -1,85 +0,0 @@ -helper->getStatusCode('BUCKAROO_MAGENTO2_STATUSCODE_SUCCESS'); - if (!empty($this->pushRequst->getAdditionalInformation('frompayperemail')) - || ( - ($this->pushRequst->hasPostData('statuscode', $statusCodeSuccess)) - && $this->pushRequst->hasPostData('transaction_method', 'ideal') - && $this->pushRequst->hasPostData('transaction_type', self::BUCK_PUSH_IDEAL_PAY) - ) - ) { - return true; - } else { - return false; - } - } - - /** - * Lock the push processing if criteria are met. - * - * @return resource|void - * @throws FileSystemException - */ - private function lockPushProcessing() - { - if ($this->lockPushProcessingCriteria()) { - $this->logging->addDebug(__METHOD__ . '|1|'); - if ($path = $this->getLockPushProcessingFilePath()) { - if ($fp = $this->fileSystemDriver->fileOpen($path, "w+")) { - $this->fileSystemDriver->fileLock($fp, LOCK_EX); - $this->logging->addDebug(__METHOD__ . '|5|'); - return $fp; - } - } - } - } - - /** - * Get the file path for the lock push processing file. - * - * @return string|false - * @throws FileSystemException - */ - private function getLockPushProcessingFilePath() - { - if ($brqOrderId = $this->getOrderIncrementId()) { - return $this->dirList->getPath('tmp') . DIRECTORY_SEPARATOR . 'bk_push_ppe_' . sha1($brqOrderId); - } else { - return false; - } - } - - /** - * Unlock the push processing. - * - * @param resource $lockHandler - * @return void - * @throws FileSystemException - */ - private function unlockPushProcessing($lockHandler) - { - if ($this->lockPushProcessingCriteria()) { - $this->logging->addDebug(__METHOD__ . '|1|'); - $this->fileSystemDriver->fileClose($lockHandler); - if (($path = $this->getLockPushProcessingFilePath()) && $this->fileSystemDriver->isExists($path)) { - $this->fileSystemDriver->deleteFile($path); - $this->logging->addDebug(__METHOD__ . '|5|'); - } - } - } -} \ No newline at end of file diff --git a/Service/LockerProcess.php b/Service/LockerProcess.php new file mode 100644 index 000000000..bec64b735 --- /dev/null +++ b/Service/LockerProcess.php @@ -0,0 +1,93 @@ +fileSystemDriver = $fileSystemDriver; + $this->dirList = $dirList; + } + + /** + * Lock the process + * + * @return resource|void + * @throws FileSystemException + */ + public function lockProcess($lockName) + { + if ($this->lockFilePath = $this->getLockProcessingFilePath($lockName)) { + if ($fp = $this->fileSystemDriver->fileOpen($this->lockFilePath, "w+")) { + $this->fileSystemDriver->fileLock($fp); + return $fp; + } + } + } + + /** + * Unlock the process. + * + * @throws FileSystemException + */ + public function unlockProcess(): void + { + if ($this->lockFilePath && $this->fileSystemDriver->isExists($this->lockFilePath)) { + $this->fileSystemDriver->deleteFile($this->lockFilePath); + } + } + + /** + * Get the file path for the lock push processing file. + * + * @param string $lockName + * @return string + * @throws FileSystemException + */ + private function getLockProcessingFilePath(string $lockName): string + { + return $this->dirList->getPath('tmp') . DIRECTORY_SEPARATOR . 'bk_push_ppe_' . sha1($lockName); + } + + /** + * Determine if the lock push processing criteria are met. + * + * @return bool + */ + private function lockPushProcessingCriteria(): bool + { + $statusCodeSuccess = $this->helper->getStatusCode('BUCKAROO_MAGENTO2_STATUSCODE_SUCCESS'); + if (!empty($this->pushRequst->getAdditionalInformation('frompayperemail')) + || ( + ($this->pushRequst->hasPostData('statuscode', $statusCodeSuccess)) + && $this->pushRequst->hasPostData('transaction_method', 'ideal') + && $this->pushRequst->hasPostData('transaction_type', self::BUCK_PUSH_IDEAL_PAY) + ) + ) { + return true; + } else { + return false; + } + } +} \ No newline at end of file diff --git a/etc/di.xml b/etc/di.xml index f896162ae..14c64dd3a 100644 --- a/etc/di.xml +++ b/etc/di.xml @@ -503,6 +503,16 @@ + + + + + Buckaroo\Magento2\Model\Push\DefaultProcessor + Buckaroo\Magento2\Model\Push\IdealProcessor + + + + From 7d93db7ede873d7d6332e2baac7f4fad9020884d Mon Sep 17 00:00:00 2001 From: Lucian Turiac Date: Thu, 25 May 2023 11:53:32 +0300 Subject: [PATCH 03/29] BP-2132 - refactor push working --- Model/Push.php | 4 +- Model/Push/DefaultProcessor.php | 107 ++++++++++++++++++++++++++++++- Model/Push/IdealProcessor.php | 11 ++++ Model/Push/KlarnaKpProcessor.php | 23 +++++++ Model/Push/KlarnaProcessor.php | 29 +++++++++ 5 files changed, 169 insertions(+), 5 deletions(-) create mode 100644 Model/Push/KlarnaKpProcessor.php create mode 100644 Model/Push/KlarnaProcessor.php diff --git a/Model/Push.php b/Model/Push.php index 48f8deaeb..5bcb55638 100644 --- a/Model/Push.php +++ b/Model/Push.php @@ -1088,7 +1088,7 @@ private function getTransactionKey(): string * by using its own transaction key. * * @return Payment - * @throws Exception + * @throws \Exception */ protected function getOrderByTransactionKey(): Payment { @@ -1098,7 +1098,7 @@ protected function getOrderByTransactionKey(): Payment $order = $this->transaction->getOrder(); if (!$order) { - throw new Exception(__('There was no order found by transaction Id')); + throw new \Exception(__('There was no order found by transaction Id')); } return $order; diff --git a/Model/Push/DefaultProcessor.php b/Model/Push/DefaultProcessor.php index 904b88fa3..9a86ac571 100644 --- a/Model/Push/DefaultProcessor.php +++ b/Model/Push/DefaultProcessor.php @@ -4,6 +4,11 @@ use Buckaroo\Magento2\Api\PushProcessorInterface; use Buckaroo\Magento2\Api\PushRequestInterface; +use Buckaroo\Magento2\Logging\Log; +use Magento\Sales\Api\Data\TransactionInterface; +use Magento\Sales\Model\Order; +use Magento\Sales\Model\Order\Payment as OrderPayment; +use Magento\Sales\Model\Order\Payment\Transaction; class DefaultProcessor implements PushProcessorInterface { @@ -12,6 +17,29 @@ class DefaultProcessor implements PushProcessorInterface */ public PushRequestInterface $pushRequest; + /** + * @var Log $logging + */ + public Log $logging; + + /** + * @var Order|OrderPayment $order + */ + public $order; + + /** + * @var Transaction + */ + private $transaction; + + public function __construct( + Log $logging, + TransactionInterface $transaction + ) { + $this->logging = $logging; + $this->transaction = $transaction; + } + public function processSucceded() { // TODO: Implement processSucceded() method. @@ -25,16 +53,44 @@ public function processFailed() public function processPush(PushRequestInterface $pushRequest): void { $this->pushRequest = $pushRequest; + + // Load order by transaction id + $this->loadOrder(); + + // Validate Signature + $store = $this->order?->getStore(); + //Check if the push can be processed and if the order can be updated IMPORTANT => use the original post data. + $validSignature = $this->pushRequest->validate($store); + + } + + /** + * Load the order from the Push Data based on the Order Increment ID or transaction key. + * + * @return void + * @throws \Exception + */ + protected function loadOrder(): void + { + $brqOrderId = $this->getOrderIncrementId(); + + $this->order->loadByIncrementId((string)$brqOrderId); + + if (!$this->order->getId()) { + $this->logging->addDebug('Order could not be loaded by Invoice Number or Order Number'); + // Try to get order by transaction id on payment. + $this->order = $this->getOrderByTransactionKey(); + } } /** * Get the order increment ID based on the invoice number or order number. * - * @return string|false + * @return string|null */ - protected function getOrderIncrementId() + protected function getOrderIncrementId(): ?string { - $brqOrderId = false; + $brqOrderId = null; if (!empty($this->pushRequest->getInvoiceNumber()) && strlen($this->pushRequest->getInvoiceNumber()) > 0) { $brqOrderId = $this->pushRequest->getInvoiceNumber(); @@ -46,4 +102,49 @@ protected function getOrderIncrementId() return $brqOrderId; } + + /** + * Sometimes the push does not contain the order id, when that's the case try to get the order by his payment, + * by using its own transaction key. + * + * @return OrderPayment + * @throws \Exception + */ + protected function getOrderByTransactionKey(): OrderPayment + { + $trxId = $this->getTransactionKey(); + + $this->transaction->load($trxId, 'txn_id'); + $order = $this->transaction->getOrder(); + + if (!$order) { + throw new \Exception(__('There was no order found by transaction Id')); + } + + return $order; + } + + /** + * Retrieves the transaction key from the push request. + * + * @return string + */ + protected function getTransactionKey(): string + { + $trxId = ''; + + if (!empty($this->pushRequest->getTransactions())) { + $trxId = $this->pushRequest->getTransactions(); + } + + if (!empty($this->pushRequest->getDatarequest())) { + $trxId = $this->pushRequest->getDatarequest(); + } + + if (!empty($this->pushRequest->getRelatedtransactionRefund())) { + $trxId = $this->pushRequest->getRelatedtransactionRefund(); + } + + return $trxId; + } } \ No newline at end of file diff --git a/Model/Push/IdealProcessor.php b/Model/Push/IdealProcessor.php index 1a1bedf09..753d54932 100644 --- a/Model/Push/IdealProcessor.php +++ b/Model/Push/IdealProcessor.php @@ -4,6 +4,7 @@ use Buckaroo\Magento2\Api\PushRequestInterface; use Buckaroo\Magento2\Helper\Data; +use Buckaroo\Magento2\Logging\Log; use Buckaroo\Magento2\Service\LockerProcess; use Magento\Framework\Exception\FileSystemException; @@ -22,9 +23,11 @@ class IdealProcessor extends DefaultProcessor private LockerProcess $lockerProcess; public function __construct( + Log $logging, LockerProcess $lockerProcess, Data $helper ) { + parent::__construct($logging); $this->lockerProcess = $lockerProcess; $this->helper = $helper; } @@ -36,6 +39,14 @@ public function processPush(PushRequestInterface $pushRequest): void { $this->pushRequest = $pushRequest; + // Load order by transaction id + $this->loadOrder(); + + // Validate Signature + $store = $this->order ? $this->order->getStore() : null; + //Check if the push can be processed and if the order can be updated IMPORTANT => use the original post data. + $validSignature = $this->pushRequest->validate($store); + if ($this->lockPushProcessingCriteria()) { $this->lockerProcess->lockProcess($this->getOrderIncrementId()); } diff --git a/Model/Push/KlarnaKpProcessor.php b/Model/Push/KlarnaKpProcessor.php new file mode 100644 index 000000000..bafb5329f --- /dev/null +++ b/Model/Push/KlarnaKpProcessor.php @@ -0,0 +1,23 @@ +pushRequest->getServiceKlarnakpAutopaytransactionkey()) + ) { + $trxId = $this->pushRequest->getServiceKlarnakpAutopaytransactionkey(); + } + + return $trxId; + } +} \ No newline at end of file diff --git a/Model/Push/KlarnaProcessor.php b/Model/Push/KlarnaProcessor.php new file mode 100644 index 000000000..6088fc67a --- /dev/null +++ b/Model/Push/KlarnaProcessor.php @@ -0,0 +1,29 @@ +pushRequest->getServiceKlarnaAutopaytransactionkey()) + ) { + $trxId = $this->pushRequest->getServiceKlarnaAutopaytransactionkey(); + } + + return $trxId; + } +} \ No newline at end of file From c2bad48abbb48740a0cd49c18c9fdfd738aa18e9 Mon Sep 17 00:00:00 2001 From: Lucian Turiac Date: Thu, 8 Jun 2023 11:26:30 +0300 Subject: [PATCH 04/29] BP-2132 - Working on Push Refactor --- Api/PushProcessorInterface.php | 4 +- Model/BuckarooStatusCode.php | 22 ++ Model/Method/Afterpay.php | 0 Model/OrderStatusFactory.php | 7 +- Model/Push.php | 45 ++-- Model/Push/DefaultProcessor.php | 365 +++++++++++++++++++++++++++- Model/Push/IdealProcessor.php | 44 +--- Model/Push/PayPerEmailProcessor.php | 12 +- 8 files changed, 420 insertions(+), 79 deletions(-) create mode 100644 Model/BuckarooStatusCode.php delete mode 100644 Model/Method/Afterpay.php diff --git a/Api/PushProcessorInterface.php b/Api/PushProcessorInterface.php index 61a497667..0867bff2d 100644 --- a/Api/PushProcessorInterface.php +++ b/Api/PushProcessorInterface.php @@ -9,7 +9,7 @@ public function processFailed(); /** * @param PushRequestInterface $pushRequest - * @return void + * @return bool */ - public function processPush(PushRequestInterface $pushRequest): void; + public function processPush(PushRequestInterface $pushRequest): bool; } \ No newline at end of file diff --git a/Model/BuckarooStatusCode.php b/Model/BuckarooStatusCode.php new file mode 100644 index 000000000..3daaeb3b7 --- /dev/null +++ b/Model/BuckarooStatusCode.php @@ -0,0 +1,22 @@ +getPayment()->getMethodInstance(); - if ($paymentMethodInstance instanceof BuckarooAdapter) { - $paymentMethod = $paymentMethodInstance->getCode(); - } else { - $paymentMethod = $paymentMethodInstance->buckarooPaymentMethodCode; - } - + $paymentMethod = $paymentMethodInstance->getCode(); if ($this->configProviderMethodFactory->has($paymentMethod)) { /** diff --git a/Model/Push.php b/Model/Push.php index 5bcb55638..dd1299339 100644 --- a/Model/Push.php +++ b/Model/Push.php @@ -431,12 +431,10 @@ public function receivePush() $this->logging->addDebug('Invalid push signature'); throw new BuckarooException(__('Signature from push is incorrect')); //If the signature is valid but the order cant be updated, try to add a notification to the order comments. - } elseif ($validSignature && !$canUpdateOrder) { + } elseif ($validSignature && !$canUpdateOrder) { $this->logging->addDebug('Order can not receive updates'); if ($receivePushCheckPayPerEmailResult) { - $config = $this->configProviderMethodFactory->get( - PayPerEmail::CODE - ); + $config = $this->configProviderMethodFactory->get(PayPerEmail::CODE); if ($config->isEnabledB2B()) { $this->logging->addDebug(__METHOD__ . '|$this->order->getState()|' . $this->order->getState()); if ($this->order->getState() === Order::STATE_COMPLETE) { @@ -455,6 +453,7 @@ public function receivePush() if (!$this->isGroupTransactionInfo()) { $this->setTransactionKey(); } + $statusCodeSuccess = $this->helper->getStatusCode('BUCKAROO_MAGENTO2_STATUSCODE_SUCCESS'); if (!empty($this->pushRequst->getStatusmessage())) { if ($this->order->getState() === Order::STATE_NEW @@ -530,17 +529,20 @@ private function receivePushCheckDuplicates(int $receivedStatusCode = null, stri } $receivedStatusCode = $this->pushRequst->getStatusCode(); } + if (!$trxId) { if (empty($this->pushRequst->getTransactions())) { return false; } $trxId = $this->pushRequst->getTransactions(); } - $payment = $this->order->getPayment(); + + $payment = $this->order->getPayment(); $ignoredPaymentMethods = [ Giftcards::CODE, Transfer::CODE ]; + if ($payment && $payment->getMethod() && $receivedStatusCode @@ -599,12 +601,12 @@ private function isPushNeeded(): bool if ($this->pushRequst->hasAdditionalInformation('initiated_by_magento', 1) && $this->pushRequst->hasAdditionalInformation('service_action_from_magento', ['refund']) ) { - $statusCodeSuccess = $this->helper->getStatusCode('BUCKAROO_MAGENTO2_STATUSCODE_SUCCESS'); + $statusCodeSuccess = BuckarooStatusCode::SUCCESS; if ($this->pushRequst->hasPostData('statuscode', $statusCodeSuccess) && !empty($this->pushRequst->getRelatedtransactionRefund()) ) { if ($this->receivePushCheckDuplicates( - $this->helper->getStatusCode('BUCKAROO_MAGENTO2_STATUSCODE_PENDING_APPROVAL'), + BuckarooStatusCode::PENDING_APPROVAL, $this->pushRequst->getRelatedtransactionRefund() ) ) { @@ -757,7 +759,7 @@ public function processCancelAuthorize(): bool { try { $this->setTransactionKey(); - } catch (Exception $e) { + } catch (\Exception $e) { $this->logging->addDebug($e->getLogMessage()); } @@ -811,11 +813,10 @@ public function processPush(array $response) break; case 'BUCKAROO_MAGENTO2_STATUSCODE_SUCCESS': if ($this->order->getPayment()->getMethod() == Paypal::CODE) { - $paypalConfig = $this->configProviderMethodFactory - ->get(Paypal::CODE); + $paypalConfig = $this->configProviderMethodFactory->get(Paypal::CODE); /** - * @var \Buckaroo\Magento2\Model\ConfigProvider\Method\Paypal $paypalConfig + * @var Paypal $paypalConfig */ $newSellersProtectionStatus = $paypalConfig->getSellersProtectionIneligible(); if ($paypalConfig->getSellersProtection() && !empty($newSellersProtectionStatus)) { @@ -860,6 +861,7 @@ public function processCm3Push() * Update the Credit Management invoice status based on push request data and save invoice if required. * * @return bool + * @throws LocalizedException */ private function updateCm3InvoiceStatus(): bool { @@ -1272,7 +1274,6 @@ public function processSucceededPush(string $newStatus, string $message): bool } $store = $this->order->getStore(); - $payment = $this->order->getPayment(); /** @@ -1476,11 +1477,15 @@ public function processPendingPaymentPush(): bool // Transfer has a slightly different flow where a successful order has a 792 status code instead of an 190 one if (!$this->order->getEmailSent() - && in_array($payment->getMethod(), [Transfer::CODE, - SepaDirectDebit::CODE, - Sofortbanking::CODE, - PayPerEmail::CODE, - ]) + && in_array( + $payment->getMethod(), + [ + Transfer::CODE, + SepaDirectDebit::CODE, + Sofortbanking::CODE, + PayPerEmail::CODE, + ] + ) && ($this->configAccount->getOrderConfirmationEmail($store) || $paymentMethod->getConfigData('order_email', $store) ) @@ -1781,6 +1786,7 @@ private function isGroupTransactionFailed() * Save the part group transaction. * * @return void + * @throws \Exception */ private function savePartGroupTransaction() { @@ -2282,6 +2288,7 @@ protected function createOrderFromQuote(string $reservedOrderId) * Cancel order when group transaction is canceled * * @return void + * @throws LocalizedException */ public function cancelGroupTransactionOrder() { @@ -2303,11 +2310,11 @@ public function cancelGroupTransactionOrder() */ public function isCanceledGroupTransaction() { - return $this->hasPostData( + return $this->pushRequst->hasPostData( 'brq_transaction_type', self::BUCK_PUSH_GROUPTRANSACTION_TYPE ) && - $this->hasPostData( + $this->pushRequst->hasPostData( 'brq_statuscode', $this->helper->getStatusCode('BUCKAROO_MAGENTO2_STATUSCODE_CANCELLED_BY_USER') ); diff --git a/Model/Push/DefaultProcessor.php b/Model/Push/DefaultProcessor.php index 9a86ac571..5177223bb 100644 --- a/Model/Push/DefaultProcessor.php +++ b/Model/Push/DefaultProcessor.php @@ -4,7 +4,15 @@ use Buckaroo\Magento2\Api\PushProcessorInterface; use Buckaroo\Magento2\Api\PushRequestInterface; +use Buckaroo\Magento2\Exception as BuckarooException; +use Buckaroo\Magento2\Helper\Data; use Buckaroo\Magento2\Logging\Log; +use Buckaroo\Magento2\Model\BuckarooStatusCode; +use Buckaroo\Magento2\Model\ConfigProvider\Method\Giftcards; +use Buckaroo\Magento2\Model\ConfigProvider\Method\Transfer; +use Buckaroo\Magento2\Model\Validator\Push as ValidatorPush; +use Buckaroo\Magento2\Service\LockerProcess; +use Magento\Framework\Exception\FileSystemException; use Magento\Sales\Api\Data\TransactionInterface; use Magento\Sales\Model\Order; use Magento\Sales\Model\Order\Payment as OrderPayment; @@ -12,6 +20,11 @@ class DefaultProcessor implements PushProcessorInterface { + public const BUCK_PUSH_TYPE_TRANSACTION = 'transaction_push'; + public const BUCK_PUSH_TYPE_INVOICE = 'invoice_push'; + public const BUCK_PUSH_TYPE_INVOICE_INCOMPLETE = 'incomplete_invoice_push'; + public const BUCK_PUSH_TYPE_DATAREQUEST = 'datarequest_push'; + /** * @var PushRequestInterface */ @@ -32,12 +45,33 @@ class DefaultProcessor implements PushProcessorInterface */ private $transaction; + /** + * @var Data + */ + public Data $helper; + + /** + * @var LockerProcess + */ + private LockerProcess $lockerProcess; + + /** + * @var ValidatorPush $validator + */ + protected ValidatorPush $validator; + public function __construct( Log $logging, - TransactionInterface $transaction + TransactionInterface $transaction, + LockerProcess $lockerProcess, + Data $helper, + ValidatorPush $validator ) { $this->logging = $logging; $this->transaction = $transaction; + $this->lockerProcess = $lockerProcess; + $this->helper = $helper; + $this->validator = $validator; } public function processSucceded() @@ -50,18 +84,50 @@ public function processFailed() // TODO: Implement processFailed() method. } - public function processPush(PushRequestInterface $pushRequest): void + /** + * @throws BuckarooException + * @throws FileSystemException + */ + public function processPush(PushRequestInterface $pushRequest): bool { $this->pushRequest = $pushRequest; - // Load order by transaction id + // Load Order by Transaction id $this->loadOrder(); // Validate Signature $store = $this->order?->getStore(); - //Check if the push can be processed and if the order can be updated IMPORTANT => use the original post data. $validSignature = $this->pushRequest->validate($store); + if (!$validSignature) { + $this->logging->addDebug('Invalid push signature'); + throw new BuckarooException(__('Signature from push is incorrect')); + } + + // Lock Processing + if ($this->lockPushProcessingCriteria()) { + $this->lockerProcess->lockProcess($this->getOrderIncrementId()); + } + + // Skip Push + if ($this->skipPush()) { + return true; + } + + + // Handle Group Transaction + + + + $transactionType = $this->getTransactionType(); + $postDataStatusCode = $this->getStatusCode(); + $this->logging->addDebug(__METHOD__ . '|1_5|' . var_export($postDataStatusCode, true)); + $this->logging->addDebug(__METHOD__ . '|1_10|' . var_export($transactionType, true)); + + $response = $this->validator->validateStatusCode($postDataStatusCode); + + + $this->lockerProcess->unlockProcess(); } /** @@ -147,4 +213,295 @@ protected function getTransactionKey(): string return $trxId; } + + /** + * Determine if the lock push processing criteria are met. + * + * @return bool + */ + protected function lockPushProcessingCriteria(): bool + { + return false; + } + + + /** + * Skip the push if the conditions are met. + * + * @return bool + * @throws \Exception + */ + protected function skipPush() + { + // Skip Handle group transaction + if ($this->skipHandlingForFailedGroupTransactions()) { + return true; + } + + if ($this->skipPendingRefundPush()) { + return true; + } + + if ($this->skipKlarnaCapture()) { + return true; + } + + // Skip Push based on specific condition + if (!$this->skipSpecificTypesOfRequsts()) { + return true; + } + + return false; + } + + + /** + * Ship push handling for a failed transaction + * + * @return bool + */ + protected function skipHandlingForFailedGroupTransactions(): bool + { + return + $this->order !== null && + $this->order->getId() !== null && + $this->order->getState() == Order::STATE_CANCELED && + ( + $this->pushRequest->hasPostData( + 'brq_transaction_type', + 'V202' + ) || + + $this->pushRequest->hasPostData( + 'brq_transaction_type', + 'V203' + ) || + $this->pushRequest->hasPostData( + 'brq_transaction_type', + 'V204' + ) + ); + } + + /** + * Check if it is needed to handle the push message based on postdata + * + * @return bool + * @throws \Exception + * + * @SuppressWarnings(PHPMD.CyclomaticComplexity) + */ + private function skipSpecificTypesOfRequsts(): bool + { + $this->logging->addDebug(__METHOD__ . '|1|'); + + $types = ['capture', 'cancelauthorize', 'cancelreservation']; + if ($this->pushRequest->hasAdditionalInformation('initiated_by_magento', 1) + && $this->pushRequest->hasAdditionalInformation('service_action_from_magento', $types) + && empty($this->pushRequest->getRelatedtransactionRefund()) + ) { + return true; + } + + return false; + } + + /** + * Skip Pending Refund Push + * + * @return bool + * @throws \Exception + */ + protected function skipPendingRefundPush(): bool + { + if ($this->pushRequest->hasAdditionalInformation('initiated_by_magento', 1) + && $this->pushRequest->hasAdditionalInformation('service_action_from_magento', ['refund']) + ) { + if ($this->pushRequest->hasPostData('statuscode', BuckarooStatusCode::SUCCESS) + && !empty($this->pushRequest->getRelatedtransactionRefund()) + && $this->receivePushCheckDuplicates( + BuckarooStatusCode::PENDING_APPROVAL, + $this->pushRequest->getRelatedtransactionRefund() + )) { + $this->logging->addDebug(__METHOD__ . '|4|'); + return false; + } + $this->logging->addDebug(__METHOD__ . '|5|'); + return true; + } + + return false; + } + + protected function skipKlarnaCapture() { + if ($this->pushRequest->hasAdditionalInformation('initiated_by_magento', 1) + && $this->pushRequest->hasPostData('transaction_method', ['klarnakp', 'KlarnaKp']) + && $this->pushRequest->hasAdditionalInformation('service_action_from_magento', 'pay') + && !empty($this->pushRequest->getServiceKlarnakpCaptureid()) + ) { + return true; + } + + return false; + } + + /** + * Check for duplicate transaction pushes from Buckaroo and update the payment transaction statuses accordingly. + * + * @param int|null $receivedStatusCode + * @param string|null $trxId + * @return bool + * @throws \Exception + * + * @SuppressWarnings(PHPMD.CyclomaticComplexity) + * @SuppressWarnings(PHPMD.NPathComplexity) + */ + private function receivePushCheckDuplicates(int $receivedStatusCode = null, string $trxId = null): bool + { + $this->logging->addDebug(__METHOD__ . '|1|' . var_export($this->order->getPayment()->getMethod(), true)); + + $save = false; + if (!$receivedStatusCode) { + $save = true; + if (empty($this->pushRequest->getStatusCode())) { + return false; + } + $receivedStatusCode = $this->pushRequest->getStatusCode(); + } + if (!$trxId) { + if (empty($this->pushRequest->getTransactions())) { + return false; + } + $trxId = $this->pushRequest->getTransactions(); + } + $payment = $this->order->getPayment(); + $ignoredPaymentMethods = [ + Giftcards::CODE, + Transfer::CODE + ]; + if ($payment + && $payment->getMethod() + && $receivedStatusCode + && ($this->getTransactionType() == self::BUCK_PUSH_TYPE_TRANSACTION) + && (!in_array($payment->getMethod(), $ignoredPaymentMethods)) + ) { + $this->logging->addDebug(__METHOD__ . '|5|'); + + $receivedTrxStatuses = $payment->getAdditionalInformation( + self::BUCKAROO_RECEIVED_TRANSACTIONS_STATUSES + ); + $this->logging->addDebug(__METHOD__ . '|10|' . + var_export([$receivedTrxStatuses, $receivedStatusCode], true)); + if ($receivedTrxStatuses + && is_array($receivedTrxStatuses) + && !empty($trxId) + && isset($receivedTrxStatuses[$trxId]) + && ($receivedTrxStatuses[$trxId] == $receivedStatusCode) + ) { + $orderStatus = $this->helper->getOrderStatusByState($this->order, Order::STATE_NEW); + $statusCode = $this->helper->getStatusCode('BUCKAROO_MAGENTO2_STATUSCODE_SUCCESS'); + if (($this->order->getState() == Order::STATE_NEW) + && ($this->order->getStatus() == $orderStatus) + && ($receivedStatusCode == $statusCode) + ) { + //allow duplicated pushes for 190 statuses in case if order stills to be new/pending + $this->logging->addDebug(__METHOD__ . '|13|'); + return false; + } + + $this->logging->addDebug(__METHOD__ . '|15|'); + return true; + } + if ($save) { + $this->logging->addDebug(__METHOD__ . '|17|'); + $this->setReceivedTransactionStatuses(); + $payment->save(); + } + } + $this->logging->addDebug(__METHOD__ . '|20|'); + + return false; + } + + /** + * Determine the transaction type based on push request data and the saved invoice key. + * + * @return bool|string + * + * @SuppressWarnings(PHPMD.CyclomaticComplexity) + */ + public function getTransactionType() + { + //If an order has an invoice key, then it should only be processed by invoice pushes + $savedInvoiceKey = (string)$this->order->getPayment()->getAdditionalInformation('buckaroo_cm3_invoice_key'); + + if (!empty($this->pushRequest->getInvoicekey()) + && !empty($this->pushRequest->getSchemekey()) + && strlen($savedInvoiceKey) > 0 + ) { + return self::BUCK_PUSH_TYPE_INVOICE; + } + + if (!empty($this->pushRequest->getInvoicekey()) + && !empty($this->pushRequest->getSchemekey()) + && strlen($savedInvoiceKey) == 0 + ) { + return self::BUCK_PUSH_TYPE_INVOICE_INCOMPLETE; + } + + if (!empty($this->pushRequest->getDatarequest())) { + return self::BUCK_PUSH_TYPE_DATAREQUEST; + } + + if (empty($this->pushRequest->getInvoicekey()) + && empty($this->pushRequest->getServiceCreditmanagement3Invoicekey()) + && empty($this->pushRequest->getDatarequest()) + && strlen($savedInvoiceKey) <= 0 + ) { + return self::BUCK_PUSH_TYPE_TRANSACTION; + } + + return false; + } + + /** + * Retrieve the status code from the push request based on the transaction type. + * + * @return int|string + * + * @SuppressWarnings(PHPMD.CyclomaticComplexity) + */ + private function getStatusCode() + { + $transactionType = $this->getTransactionType(); + $statusCode = 0; + switch ($transactionType) { + case self::BUCK_PUSH_TYPE_TRANSACTION: + case self::BUCK_PUSH_TYPE_DATAREQUEST: + if ($this->pushRequest->getStatusCode() !== null) { + $statusCode = $this->pushRequest->getStatusCode(); + } + break; + case self::BUCK_PUSH_TYPE_INVOICE: + case self::BUCK_PUSH_TYPE_INVOICE_INCOMPLETE: + if (!empty($this->pushRequest->getEventparametersStatuscode())) { + $statusCode = $this->pushRequest->getEventparametersStatuscode(); + } + + if (!empty($this->pushRequest->getEventparametersTransactionstatuscode())) { + $statusCode = $this->pushRequest->getEventparametersTransactionstatuscode(); + } + break; + } + + $statusCodeSuccess = $this->helper->getStatusCode('BUCKAROO_MAGENTO2_STATUSCODE_SUCCESS'); + if ($this->pushRequest->getStatusCode() !== null + && ($this->pushRequest->getStatusCode() == $statusCodeSuccess) + && !$statusCode + ) { + $statusCode = $statusCodeSuccess; + } + + return $statusCode; + } } \ No newline at end of file diff --git a/Model/Push/IdealProcessor.php b/Model/Push/IdealProcessor.php index 753d54932..d1d43677c 100644 --- a/Model/Push/IdealProcessor.php +++ b/Model/Push/IdealProcessor.php @@ -3,56 +3,20 @@ namespace Buckaroo\Magento2\Model\Push; use Buckaroo\Magento2\Api\PushRequestInterface; -use Buckaroo\Magento2\Helper\Data; -use Buckaroo\Magento2\Logging\Log; -use Buckaroo\Magento2\Service\LockerProcess; +use Buckaroo\Magento2\Exception as BuckarooException; use Magento\Framework\Exception\FileSystemException; class IdealProcessor extends DefaultProcessor { public const BUCK_PUSH_IDEAL_PAY = 'C021'; - /** - * @var Data - */ - public Data $helper; - - /** - * @var LockerProcess - */ - private LockerProcess $lockerProcess; - - public function __construct( - Log $logging, - LockerProcess $lockerProcess, - Data $helper - ) { - parent::__construct($logging); - $this->lockerProcess = $lockerProcess; - $this->helper = $helper; - } - /** * @throws FileSystemException + * @throws BuckarooException */ - public function processPush(PushRequestInterface $pushRequest): void + public function processPush(PushRequestInterface $pushRequest): bool { - $this->pushRequest = $pushRequest; - - // Load order by transaction id - $this->loadOrder(); - - // Validate Signature - $store = $this->order ? $this->order->getStore() : null; - //Check if the push can be processed and if the order can be updated IMPORTANT => use the original post data. - $validSignature = $this->pushRequest->validate($store); - - if ($this->lockPushProcessingCriteria()) { - $this->lockerProcess->lockProcess($this->getOrderIncrementId()); - } parent::processPush($pushRequest); - - $this->lockerProcess->unlockProcess(); } /** @@ -60,7 +24,7 @@ public function processPush(PushRequestInterface $pushRequest): void * * @return bool */ - private function lockPushProcessingCriteria(): bool + protected function lockPushProcessingCriteria(): bool { $statusCodeSuccess = $this->helper->getStatusCode('BUCKAROO_MAGENTO2_STATUSCODE_SUCCESS'); diff --git a/Model/Push/PayPerEmailProcessor.php b/Model/Push/PayPerEmailProcessor.php index 9a21dbac0..a73b1ed5d 100644 --- a/Model/Push/PayPerEmailProcessor.php +++ b/Model/Push/PayPerEmailProcessor.php @@ -15,11 +15,6 @@ class PayPerEmailProcessor extends DefaultProcessor */ private LockerProcess $lockerProcess; - public function __construct( - LockerProcess $lockerProcess - ) { - $this->lockerProcess = $lockerProcess; - } public function processSucceded() { @@ -35,14 +30,15 @@ public function processFailed() /** * @throws FileSystemException */ - public function processPush(PushRequestInterface $pushRequest): void + public function processPush(PushRequestInterface $pushRequest): bool { $this->pushRequest = $pushRequest; if ($this->lockPushProcessingCriteria()) { $this->lockerProcess->lockProcess($this->getOrderIncrementId()); } - parent::processPush($pushRequest); + + return true; } /** @@ -50,7 +46,7 @@ public function processPush(PushRequestInterface $pushRequest): void * * @return bool */ - private function lockPushProcessingCriteria(): bool + protected function lockPushProcessingCriteria(): bool { return !empty($this->pushRequest->getAdditionalInformation('frompayperemail')); } From 2085638e5da7b4b70711ea3c08fe145d6ff952e4 Mon Sep 17 00:00:00 2001 From: Lucian Turiac Date: Mon, 19 Jun 2023 11:38:01 +0300 Subject: [PATCH 05/29] BP-2132 - Working on Push --- Model/Push.php | 20 +++- Model/Push/DefaultProcessor.php | 11 +-- Model/Push/PushProcessorsFactory.php | 80 +++++++++++++++- Service/Push/OrderRequestService.php | 133 +++++++++++++++++++++++++++ 4 files changed, 231 insertions(+), 13 deletions(-) create mode 100644 Service/Push/OrderRequestService.php diff --git a/Model/Push.php b/Model/Push.php index dd1299339..c519cd70f 100644 --- a/Model/Push.php +++ b/Model/Push.php @@ -46,6 +46,7 @@ use Buckaroo\Magento2\Model\Refund\Push as RefundPush; use Buckaroo\Magento2\Model\RequestPush\RequestPushFactory; use Buckaroo\Magento2\Model\Validator\Push as ValidatorPush; +use Buckaroo\Magento2\Service\Push\OrderRequestService; use Magento\Framework\App\ResourceConnection; use Magento\Framework\Exception\FileSystemException; use Magento\Framework\Exception\LocalizedException; @@ -220,6 +221,11 @@ class Push implements PushInterface */ private PushProcessorInterface $pushProcessor; + /** + * @var OrderRequestService + */ + private OrderRequestService $orderRequestService; + /** * @param Order $order * @param TransactionInterface $transaction @@ -264,7 +270,8 @@ public function __construct( Afterpay20 $afterpayConfig, File $fileSystemDriver, RequestPushFactory $requestPushFactory, - PushProcessorsFactory $pushProcessorsFactory + PushProcessorsFactory $pushProcessorsFactory, + OrderRequestService $orderRequestService ) { $this->order = $order; $this->transaction = $transaction; @@ -288,6 +295,7 @@ public function __construct( $this->fileSystemDriver = $fileSystemDriver; $this->pushRequst = $requestPushFactory->create(); $this->pushProcessorsFactory = $pushProcessorsFactory; + $this->orderRequestService = $orderRequestService; } /** @@ -305,6 +313,16 @@ public function receivePush() // Log the push request $this->logging->addDebug(__METHOD__ . '|1|' . var_export($this->pushRequst->getOriginalRequest(), true)); + // Validate Signature + $store = $this->order?->getStore(); + $validSignature = $this->pushRequst->validate($store); + + if (!$validSignature) { + $this->logging->addDebug('Invalid push signature'); + throw new BuckarooException(__('Signature from push is incorrect')); + } + + // Process Push $this->pushProcessor = $this->pushProcessorsFactory->get($this->pushRequst); $this->pushProcessor->processPush($this->pushRequst); diff --git a/Model/Push/DefaultProcessor.php b/Model/Push/DefaultProcessor.php index 5177223bb..14e8406df 100644 --- a/Model/Push/DefaultProcessor.php +++ b/Model/Push/DefaultProcessor.php @@ -93,16 +93,7 @@ public function processPush(PushRequestInterface $pushRequest): bool $this->pushRequest = $pushRequest; // Load Order by Transaction id - $this->loadOrder(); - - // Validate Signature - $store = $this->order?->getStore(); - $validSignature = $this->pushRequest->validate($store); - - if (!$validSignature) { - $this->logging->addDebug('Invalid push signature'); - throw new BuckarooException(__('Signature from push is incorrect')); - } + $this->order = $this->loadOrder(); // Lock Processing if ($this->lockPushProcessingCriteria()) { diff --git a/Model/Push/PushProcessorsFactory.php b/Model/Push/PushProcessorsFactory.php index bad83eecf..cd047eec3 100644 --- a/Model/Push/PushProcessorsFactory.php +++ b/Model/Push/PushProcessorsFactory.php @@ -5,10 +5,16 @@ use Buckaroo\Magento2\Api\PushRequestInterface; use Buckaroo\Magento2\Exception as BuckarooException; use Buckaroo\Magento2\Api\PushProcessorInterface; +use Buckaroo\Magento2\Service\Push\OrderRequestService; use Magento\Framework\ObjectManagerInterface; class PushProcessorsFactory { + private const BUCK_PUSH_TYPE_TRANSACTION = 'transaction_push'; + private const BUCK_PUSH_TYPE_INVOICE = 'invoice_push'; + private const BUCK_PUSH_TYPE_INVOICE_INCOMPLETE = 'incomplete_invoice_push'; + private const BUCK_PUSH_TYPE_DATAREQUEST = 'datarequest_push'; + /** * @var ObjectManagerInterface */ @@ -25,15 +31,23 @@ class PushProcessorsFactory protected ?PushProcessorInterface $pushProcessor = null; /** + * @var OrderRequestService + */ + private OrderRequestService $orderRequestService; + + /** + * @param OrderRequestService $orderRequestService * @param ObjectManagerInterface $objectManager * @param array $pushProcessors */ public function __construct( + OrderRequestService $orderRequestService, ObjectManagerInterface $objectManager, array $pushProcessors = [] ) { $this->objectManager = $objectManager; $this->pushProcessors = $pushProcessors; + $this->orderRequestService = $orderRequestService; } /** @@ -50,10 +64,23 @@ public function get(?PushRequestInterface $pushRequest): ?PushProcessorInterface throw new \LogicException('Push processors is not set.'); } + $pushProcessorClass = $this->getProcessorClass($pushRequest); + + $order = $this->orderRequestService->getOrderByRequest($pushRequest); + + $transactionType = $this->getTransactionType($pushRequest, $order); + + if ($transactionType == self::BUCK_PUSH_TYPE_INVOICE) { + $pushProcessorClass = $this->pushProcessors['credit_managment']; + } elseif ($transactionType == self::BUCK_PUSH_TYPE_INVOICE_INCOMPLETE) { + throw new BuckarooException( + __('Skipped handling this invoice push because it is too soon.') + ); + } + $transactionMethod = $pushRequest->getTransactionMethod(); - $pushProcessorClass = $this->pushProcessors[$transactionMethod] ?? - $this->pushProcessors['default'] ?? ''; + $pushProcessorClass = $this->pushProcessors[$transactionMethod] ?? $pushProcessorClass; if (empty($pushProcessorClass)) { throw new BuckarooException( @@ -68,4 +95,53 @@ public function get(?PushRequestInterface $pushRequest): ?PushProcessorInterface } return $this->pushProcessor; } + + /** + * @param PushRequestInterface|null $pushRequest + * @return void + */ + private function getProcessorClass($pushRequest) { + $pushProcessorClass = $this->pushProcessors['default']; + } + + /** + * Determine the transaction type based on push request data and the saved invoice key. + * + * @return bool|string + * + * @SuppressWarnings(PHPMD.CyclomaticComplexity) + */ + public function getTransactionType($pushRequest, $order) + { + //If an order has an invoice key, then it should only be processed by invoice pushes + $savedInvoiceKey = (string)$order->getPayment()->getAdditionalInformation('buckaroo_cm3_invoice_key'); + + if (!empty($pushRequest->getInvoicekey()) + && !empty($pushRequest->getSchemekey()) + && strlen($savedInvoiceKey) > 0 + ) { + return self::BUCK_PUSH_TYPE_INVOICE; + } + + if (!empty($pushRequest->getInvoicekey()) + && !empty($pushRequest->getSchemekey()) + && strlen($savedInvoiceKey) == 0 + ) { + return self::BUCK_PUSH_TYPE_INVOICE_INCOMPLETE; + } + + if (!empty($pushRequest->getDatarequest())) { + return self::BUCK_PUSH_TYPE_DATAREQUEST; + } + + if (empty($pushRequest->getInvoicekey()) + && empty($pushRequest->getServiceCreditmanagement3Invoicekey()) + && empty($pushRequest->getDatarequest()) + && strlen($savedInvoiceKey) <= 0 + ) { + return self::BUCK_PUSH_TYPE_TRANSACTION; + } + + return false; + } } \ No newline at end of file diff --git a/Service/Push/OrderRequestService.php b/Service/Push/OrderRequestService.php new file mode 100644 index 000000000..23d20cd86 --- /dev/null +++ b/Service/Push/OrderRequestService.php @@ -0,0 +1,133 @@ +logging = $logging; + $this->transaction = $transaction; + } + + /** + * Load the order from the Push Data based on the Order Increment ID or transaction key. + * + * @param $pushRequest + * @return Order|OrderPayment + * @throws \Exception + */ + public function getOrderByRequest($pushRequest): Order|OrderPayment + { + if ($this->order) { + return $this->order; + } else { + $brqOrderId = $this->getOrderIncrementIdFromRequest($pushRequest); + + $this->order->loadByIncrementId((string)$brqOrderId); + + if (!$this->order->getId()) { + $this->logging->addDebug('Order could not be loaded by Invoice Number or Order Number'); + // Try to get order by transaction id on payment. + $this->order = $this->getOrderByTransactionKey($pushRequest); + } + } + + return $this->order; + } + + /** + * Get the order increment ID based on the invoice number or order number. + * + * @param $pushRequest + * @return string|null + */ + protected function getOrderIncrementIdFromRequest($pushRequest): ?string + { + $brqOrderId = null; + + if (!empty($pushRequest->getInvoiceNumber()) && strlen($pushRequest->getInvoiceNumber()) > 0) { + $brqOrderId = $pushRequest->getInvoiceNumber(); + } + + if (!empty($pushRequest->getOrderNumber()) && strlen($pushRequest->getOrderNumber()) > 0) { + $brqOrderId = $pushRequest->getOrderNumber(); + } + + return $brqOrderId; + } + + /** + * Sometimes the push does not contain the order id, when that's the case try to get the order by his payment, + * by using its own transaction key. + * + * @param $pushRequest + * @return OrderPayment + * @throws \Exception + */ + protected function getOrderByTransactionKey($pushRequest): OrderPayment + { + $trxId = $this->getTransactionKey($pushRequest); + + $this->transaction->load($trxId, 'txn_id'); + $order = $this->transaction->getOrder(); + + if (!$order) { + throw new \Exception(__('There was no order found by transaction Id')); + } + + return $order; + } + + /** + * Retrieves the transaction key from the push request. + * + * @param $pushRequest + * @return string + */ + protected function getTransactionKey($pushRequest): string + { + $trxId = ''; + + if (!empty($pushRequest->getTransactions())) { + $trxId = $pushRequest->getTransactions(); + } + + if (!empty($pushRequest->getDatarequest())) { + $trxId = $pushRequest->getDatarequest(); + } + + if (!empty($pushRequest->getRelatedtransactionRefund())) { + $trxId = $pushRequest->getRelatedtransactionRefund(); + } + + return $trxId; + } +} \ No newline at end of file From abcb57b1fe51efd5222efc29db0618a60db92397 Mon Sep 17 00:00:00 2001 From: Lucian Turiac Date: Wed, 5 Jul 2023 18:10:45 +0300 Subject: [PATCH 06/29] Buckaroo Push Refactor - Fix PayPerEmail Message, work in progress refactor push --- Api/PushProcessorInterface.php | 21 +- .../BasicParameter/InvoiceDataBuilder.php | 4 +- Model/BuckarooStatusCode.php | 106 ++++- Model/ConfigProvider/Method/PayLink.php | 2 +- Model/Push.php | 18 +- Model/Push/DefaultProcessor.php | 135 ++++++- ...GroupTransactionPushProcessorDecorator.php | 8 + Model/Push/PushProcessorsFactory.php | 29 +- Model/Push/PushTransactionType.php | 362 ++++++++++++++++++ Model/Push/TransactionFactory.php | 169 ++++++++ Model/RequestPush/HttppostPushRequest.php | 3 + Model/RequestPush/JsonPushRequest.php | 3 + Service/Push/OrderRequestService.php | 10 +- etc/config.xml | 2 +- etc/di.xml | 25 ++ 15 files changed, 838 insertions(+), 59 deletions(-) create mode 100644 Model/Push/GroupTransactionPushProcessorDecorator.php create mode 100644 Model/Push/PushTransactionType.php create mode 100644 Model/Push/TransactionFactory.php diff --git a/Api/PushProcessorInterface.php b/Api/PushProcessorInterface.php index 0867bff2d..e4b06737e 100644 --- a/Api/PushProcessorInterface.php +++ b/Api/PushProcessorInterface.php @@ -4,12 +4,27 @@ interface PushProcessorInterface { - public function processSucceded(); - public function processFailed(); - /** * @param PushRequestInterface $pushRequest * @return bool */ public function processPush(PushRequestInterface $pushRequest): bool; + + /** + * @param PushRequestInterface $pushRequest + * @return bool + */ + public function processSucceededPush(PushRequestInterface $pushRequest): bool; + + /** + * @param PushRequestInterface $pushRequest + * @return bool + */ + public function processFailedPush(PushRequestInterface $pushRequest): bool; + + /** + * @param PushRequestInterface $pushRequest + * @return bool + */ + public function processPendingPaymentPush(PushRequestInterface $pushRequest): bool; } \ No newline at end of file diff --git a/Gateway/Request/BasicParameter/InvoiceDataBuilder.php b/Gateway/Request/BasicParameter/InvoiceDataBuilder.php index b93727a69..3e033a3af 100644 --- a/Gateway/Request/BasicParameter/InvoiceDataBuilder.php +++ b/Gateway/Request/BasicParameter/InvoiceDataBuilder.php @@ -51,8 +51,8 @@ public function build(array $buildSubject): array $this->setOrder($paymentDO->getOrder()->getOrder()); return [ - 'invoice' => $this->getInvoiceId(), - 'order' => $this->getOrder()->getIncrementId() + 'invoice' => 'LT' . $this->getInvoiceId(), + 'order' => 'LT' . $this->getOrder()->getIncrementId() ]; } diff --git a/Model/BuckarooStatusCode.php b/Model/BuckarooStatusCode.php index 3daaeb3b7..a12c5d1c8 100644 --- a/Model/BuckarooStatusCode.php +++ b/Model/BuckarooStatusCode.php @@ -1,22 +1,100 @@ 'Success', + 490 => 'Payment failure', + 491 => 'Validation error', + 492 => 'Technical error', + 690 => 'Payment rejected', + 790 => 'Waiting for user input', + 791 => 'Waiting for processor', + 792 => 'Waiting on consumer action', + 793 => 'Payment on hold', + 890 => 'Cancelled by consumer', + 891 => 'Cancelled by merchant' + ]; + /** + * Buckaroo_Magento2 status codes + * + * @var array $statusCode + */ + private array $statusCodes = [ + 'BUCKAROO_MAGENTO2_STATUSCODE_SUCCESS' => 190, + 'BUCKAROO_MAGENTO2_STATUSCODE_FAILED' => 490, + 'BUCKAROO_MAGENTO2_STATUSCODE_VALIDATION_FAILURE' => 491, + 'BUCKAROO_MAGENTO2_STATUSCODE_TECHNICAL_ERROR' => 492, + 'BUCKAROO_MAGENTO2_STATUSCODE_REJECTED' => 690, + 'BUCKAROO_MAGENTO2_STATUSCODE_WAITING_ON_USER_INPUT' => 790, + 'BUCKAROO_MAGENTO2_STATUSCODE_PENDING_PROCESSING' => 791, + 'BUCKAROO_MAGENTO2_STATUSCODE_WAITING_ON_CONSUMER' => 792, + 'BUCKAROO_MAGENTO2_STATUSCODE_PAYMENT_ON_HOLD' => 793, + 'BUCKAROO_MAGENTO2_STATUSCODE_PENDING_APPROVAL' => 794, + 'BUCKAROO_MAGENTO2_STATUSCODE_CANCELLED_BY_USER' => 890, + 'BUCKAROO_MAGENTO2_STATUSCODE_CANCELLED_BY_MERCHANT' => 891, + + /** + * Codes below are created by dev, not by Buckaroo. + */ + 'BUCKAROO_MAGENTO2_ORDER_FAILED' => 11014, + ]; + + /** + * Get Response Message by Response Code + * + * @param int $responseCode + * @return string + */ + public function getResponseMessage(int $responseCode): string + { + return self::BPE_RESPONSE_MESSAGES[$responseCode] ?? 'Onbekende responsecode: ' . $responseCode; + } + + /** + * Return the requested status key with the value, or null if not found + * + * @param int $responseCode + * @return string + */ + public function getStatusKey(int $responseCode): string + { + return array_search($responseCode, $this->statusCodes) ?? 'BUCKAROO_MAGENTO2_STATUSCODE_NEUTRAL'; + } +} \ No newline at end of file diff --git a/Model/ConfigProvider/Method/PayLink.php b/Model/ConfigProvider/Method/PayLink.php index 246be48ff..dd85ee405 100644 --- a/Model/ConfigProvider/Method/PayLink.php +++ b/Model/ConfigProvider/Method/PayLink.php @@ -24,7 +24,7 @@ use Buckaroo\Magento2\Exception; use Magento\Store\Model\ScopeInterface; -class PayLink extends AbstractConfigProvider +class PayLink extends AbstractConfigProvider { public const CODE = 'buckaroo_magento2_paylink'; diff --git a/Model/Push.php b/Model/Push.php index 9a805391c..0affc4e86 100644 --- a/Model/Push.php +++ b/Model/Push.php @@ -43,6 +43,7 @@ use Buckaroo\Magento2\Model\ConfigProvider\Method\Voucher; use Buckaroo\Magento2\Model\Method\BuckarooAdapter; use Buckaroo\Magento2\Model\Push\PushProcessorsFactory; +use Buckaroo\Magento2\Model\Push\PushTransactionType; use Buckaroo\Magento2\Model\Refund\Push as RefundPush; use Buckaroo\Magento2\Model\RequestPush\RequestPushFactory; use Buckaroo\Magento2\Model\Validator\Push as ValidatorPush; @@ -271,7 +272,8 @@ public function __construct( File $fileSystemDriver, RequestPushFactory $requestPushFactory, PushProcessorsFactory $pushProcessorsFactory, - OrderRequestService $orderRequestService + OrderRequestService $orderRequestService, + PushTransactionType $pushTransactionType ) { $this->order = $order; $this->transaction = $transaction; @@ -296,12 +298,14 @@ public function __construct( $this->pushRequst = $requestPushFactory->create(); $this->pushProcessorsFactory = $pushProcessorsFactory; $this->orderRequestService = $orderRequestService; + $this->pushTransactionType = $pushTransactionType; } /** * @inheritdoc * * @throws BuckarooException + * @throws \Exception * @todo Once Magento supports variable parameters, modify this method to no longer require a Request object * * @SuppressWarnings(PHPMD.CyclomaticComplexity) @@ -313,8 +317,11 @@ public function receivePush() // Log the push request $this->logging->addDebug(__METHOD__ . '|1|' . var_export($this->pushRequst->getOriginalRequest(), true)); + // Load Order + $this->order = $this->orderRequestService->getOrderByRequest($this->pushRequst); + // Validate Signature - $store = $this->order?->getStore(); + $store = $this->order->getStore(); $validSignature = $this->pushRequst->validate($store); if (!$validSignature) { @@ -322,9 +329,12 @@ public function receivePush() throw new BuckarooException(__('Signature from push is incorrect')); } + // Get Push Transaction Type + $pushTransactionType = $this->pushTransactionType->getPushTransactionType($this->pushRequst, $this->order); + // Process Push - $this->pushProcessor = $this->pushProcessorsFactory->get($this->pushRequst); - $this->pushProcessor->processPush($this->pushRequst); +// $this->pushProcessor = $this->pushProcessorsFactory->get($this->pushRequst); +// $this->pushProcessor->processPush($this->pushRequst); // Lock Push Processing $this->logging->addDebug(__METHOD__ . '|1_2|'); diff --git a/Model/Push/DefaultProcessor.php b/Model/Push/DefaultProcessor.php index 14e8406df..a63fb8df4 100644 --- a/Model/Push/DefaultProcessor.php +++ b/Model/Push/DefaultProcessor.php @@ -13,8 +13,10 @@ use Buckaroo\Magento2\Model\Validator\Push as ValidatorPush; use Buckaroo\Magento2\Service\LockerProcess; use Magento\Framework\Exception\FileSystemException; +use Magento\Framework\Exception\LocalizedException; use Magento\Sales\Api\Data\TransactionInterface; use Magento\Sales\Model\Order; +use Magento\Sales\Model\Order\Payment; use Magento\Sales\Model\Order\Payment as OrderPayment; use Magento\Sales\Model\Order\Payment\Transaction; @@ -74,16 +76,6 @@ public function __construct( $this->validator = $validator; } - public function processSucceded() - { - // TODO: Implement processSucceded() method. - } - - public function processFailed() - { - // TODO: Implement processFailed() method. - } - /** * @throws BuckarooException * @throws FileSystemException @@ -121,6 +113,114 @@ public function processPush(PushRequestInterface $pushRequest): bool $this->lockerProcess->unlockProcess(); } + /** + * Creates and saves the invoice and adds for each invoice the buckaroo transaction keys + * Only when the order can be invoiced and has not been invoiced before. + * + * @return bool + * @throws BuckarooException + * @throws LocalizedException + * + * @SuppressWarnings(PHPMD.CyclomaticComplexity) + * @SuppressWarnings(PHPMD.NPathComplexity) + */ + protected function saveInvoice(): bool + { + $this->logging->addDebug(__METHOD__ . '|1|'); + if (!$this->forceInvoice + && (!$this->order->canInvoice() || $this->order->hasInvoices())) { + $this->logging->addDebug('Order can not be invoiced'); + //throw new BuckarooException(__('Order can not be invoiced')); + return false; + + } + + $this->logging->addDebug(__METHOD__ . '|5|'); + + /** + * Only when the order can be invoiced and has not been invoiced before. + */ + if (!$this->isGroupTransactionInfoType()) { + $this->addTransactionData(); + } + + /** + * @var Payment $payment + */ + $payment = $this->order->getPayment(); + + $invoiceAmount = 0; + if (!empty($this->pushRequst->getAmount())) { + $invoiceAmount = floatval($this->pushRequst->getAmount()); + } + if (($payment->getMethod() == Giftcards::CODE) + && $invoiceAmount != $this->order->getGrandTotal() + ) { + $this->setReceivedPaymentFromBuckaroo(); + + $payment->registerCaptureNotification($invoiceAmount, true); + $payment->save(); + + $receivedPaymentsArray = $payment->getAdditionalInformation(self::BUCKAROO_RECEIVED_TRANSACTIONS); + + if (!is_array($receivedPaymentsArray)) { + return false; + } + + $payment->capture(); //creates invoice + $payment->save(); + } elseif ($this->isPayPerEmailB2BModePushInitial) { + $this->logging->addDebug(__METHOD__ . '|10|'); + $invoice = $this->order->prepareInvoice()->register(); + $invoice->setOrder($this->order); + $this->order->addRelatedObject($invoice); + $payment->setCreatedInvoice($invoice); + $payment->setShouldCloseParentTransaction(true); + } else { + $this->logging->addDebug(__METHOD__ . '|15|'); + //Fix for suspected fraud when the order currency does not match with the payment's currency + $amount = ($payment->isSameCurrency() + && $payment->isCaptureFinal($this->order->getGrandTotal())) ? + $this->order->getGrandTotal() : $this->order->getBaseTotalDue(); + $payment->registerCaptureNotification($amount); + $payment->save(); + } + + $this->logging->addDebug(__METHOD__ . '|20|'); + + $transactionKey = $this->getTransactionKey(); + + if (strlen($transactionKey) <= 0) { + return true; + } + + $this->logging->addDebug(__METHOD__ . '|25|'); + + /** @var \Magento\Sales\Model\Order\Invoice $invoice */ + foreach ($this->order->getInvoiceCollection() as $invoice) { + $invoice->setTransactionId($transactionKey)->save(); + + if (!empty($this->pushRequst->getInvoiceNumber()) + && $this->groupTransaction->isGroupTransaction($this->pushRequst->getInvoiceNumber())) { + $this->logging->addDebug(__METHOD__ . '|27|'); + $invoice->setState(2); + } + + if (!$invoice->getEmailSent() && $this->configAccount->getInvoiceEmail($this->order->getStore())) { + $this->logging->addDebug(__METHOD__ . '|30|sendinvoiceemail'); + $this->invoiceSender->send($invoice, true); + } + } + + $this->logging->addDebug(__METHOD__ . '|35|'); + + $this->order->setIsInProcess(true); + $this->order->save(); + + $this->dontSaveOrderUponSuccessPush = true; + + return true; + } /** * Load the order from the Push Data based on the Order Increment ID or transaction key. * @@ -495,4 +595,19 @@ private function getStatusCode() return $statusCode; } + + public function processSucceededPush(PushRequestInterface $pushRequest): bool + { + // TODO: Implement processSucceededPush() method. + } + + public function processFailedPush(PushRequestInterface $pushRequest): bool + { + // TODO: Implement processFailedPush() method. + } + + public function processPendingPaymentPush(PushRequestInterface $pushRequest): bool + { + // TODO: Implement processPendingPaymentPush() method. + } } \ No newline at end of file diff --git a/Model/Push/GroupTransactionPushProcessorDecorator.php b/Model/Push/GroupTransactionPushProcessorDecorator.php new file mode 100644 index 000000000..3a5bab1bf --- /dev/null +++ b/Model/Push/GroupTransactionPushProcessorDecorator.php @@ -0,0 +1,8 @@ +pushProcessor instanceof PushProcessorInterface) { if (empty($this->pushProcessors)) { throw new \LogicException('Push processors is not set.'); } - $pushProcessorClass = $this->getProcessorClass($pushRequest); + $pushProcessorClass = $this->pushProcessors['default']; - $order = $this->orderRequestService->getOrderByRequest($pushRequest); - - $transactionType = $this->getTransactionType($pushRequest, $order); + $transactionType = $pushTransactionType->getTransactionType(); if ($transactionType == self::BUCK_PUSH_TYPE_INVOICE) { $pushProcessorClass = $this->pushProcessors['credit_managment']; @@ -78,16 +77,12 @@ public function get(?PushRequestInterface $pushRequest): ?PushProcessorInterface ); } - $transactionMethod = $pushRequest->getTransactionMethod(); - - $pushProcessorClass = $this->pushProcessors[$transactionMethod] ?? $pushProcessorClass; + $paymentMethod = $pushTransactionType->getPaymentMethod(); + $pushProcessorClass = $this->pushProcessors[$paymentMethod] ?? $pushProcessorClass; if (empty($pushProcessorClass)) { throw new BuckarooException( - new Phrase( - 'Unknown ConfigProvider type requested: %1.', - [$transactionMethod] - ) + new Phrase('Unknown ConfigProvider type requested: %1.', [$paymentMethod]) ); } $this->pushProcessor = $this->objectManager->get($pushProcessorClass); @@ -96,14 +91,6 @@ public function get(?PushRequestInterface $pushRequest): ?PushProcessorInterface return $this->pushProcessor; } - /** - * @param PushRequestInterface|null $pushRequest - * @return void - */ - private function getProcessorClass($pushRequest) { - $pushProcessorClass = $this->pushProcessors['default']; - } - /** * Determine the transaction type based on push request data and the saved invoice key. * diff --git a/Model/Push/PushTransactionType.php b/Model/Push/PushTransactionType.php new file mode 100644 index 000000000..871e86cd4 --- /dev/null +++ b/Model/Push/PushTransactionType.php @@ -0,0 +1,362 @@ +buckarooStatusCode = $buckarooStatusCode; + } + + /** + * @param PushRequestInterface|null $pushRequest + * @param Order|null $order + * @return array + */ + public function getPushTransactionType(?PushRequestInterface $pushRequest, ?Order $order): array + { + if(empty($this->pushTransactionType)) { + $this->paymentMethod = $pushRequest->getTransactionMethod(); + $this->transactionType = $this->getTransactionTypeByInvoiceKey($pushRequest, $order); + $this->statusCode = $this->getStatusCodeByTransactionType($this->transactionType, $pushRequest); + $this->statusMessage = $this->buckarooStatusCode->getResponseMessage($this->statusCode); + $this->statusKey = $this->buckarooStatusCode->getStatusKey($this->statusCode); + + + $this->pushTransactionType = [ + 'paymentMethod' => $this->paymentMethod, + 'transactionType' => $this->transactionType, + 'statusCode' => $this->statusCode, + 'statusMessage' => $this->statusMessage, + 'statusKey' => $this->statusKey + ]; + + } + + return $this->pushTransactionType; + + + } + + /** + * @return string + */ + public function getPaymentMethod(): string + { + return $this->paymentMethod; + } + + /** + * @param string $paymentMethod + */ + public function setPaymentMethod(string $paymentMethod): void + { + $this->paymentMethod = $paymentMethod; + } + + /** + * @return string + */ + public function getServiceAction(): string + { + return $this->serviceAction; + } + + /** + * @param string $serviceAction + */ + public function setServiceAction(string $serviceAction): void + { + $this->serviceAction = $serviceAction; + } + + /** + * @return string + */ + public function getStatusCode(): string + { + return $this->statusCode; + } + + /** + * @param string $statusCode + */ + public function setStatusCode(string $statusCode): void + { + $this->statusCode = $statusCode; + } + + /** + * @return string + */ + public function getStatusMessage(): string + { + return $this->statusMessage; + } + + /** + * @param string $statusMessage + */ + public function setStatusMessage(string $statusMessage): void + { + $this->statusMessage = $statusMessage; + } + + /** + * @return BuckarooStatusCode + */ + public function getBuckarooStatusCode(): BuckarooStatusCode + { + return $this->buckarooStatusCode; + } + + /** + * @param BuckarooStatusCode $buckarooStatusCode + */ + public function setBuckarooStatusCode(BuckarooStatusCode $buckarooStatusCode): void + { + $this->buckarooStatusCode = $buckarooStatusCode; + } + + /** + * @return bool + */ + public function isGroupTransaction(): bool + { + return $this->groupTransaction; + } + + /** + * @param bool $groupTransaction + */ + public function setGroupTransaction(bool $groupTransaction): void + { + $this->groupTransaction = $groupTransaction; + } + + /** + * @return bool + */ + public function isCreditManagment(): bool + { + return $this->creditManagment; + } + + /** + * @param bool $creditManagment + */ + public function setCreditManagment(bool $creditManagment): void + { + $this->creditManagment = $creditManagment; + } + + /** + * @return string + */ + public function getTransactionType(): string + { + return $this->transactionType; + } + + /** + * @param string $transactionType + */ + public function setTransactionType(string $transactionType): void + { + $this->transactionType = $transactionType; + } + + /** + * @return Order + */ + public function getOrder(): Order + { + return $this->order; + } + + /** + * @param Order $order + */ + public function setOrder(Order $order): void + { + $this->order = $order; + } + + /** + * Determine the transaction type based on push request data and the saved invoice key. + * + * @return bool|string + * + * @SuppressWarnings(PHPMD.CyclomaticComplexity) + */ + public function getTransactionTypeByInvoiceKey($pushRequest, $order) + { + //If an order has an invoice key, then it should only be processed by invoice pushes + $savedInvoiceKey = (string)$order->getPayment()->getAdditionalInformation('buckaroo_cm3_invoice_key'); + + if (!empty($pushRequest->getInvoicekey()) + && !empty($pushRequest->getSchemekey()) + && strlen($savedInvoiceKey) > 0 + ) { + return self::BUCK_PUSH_TYPE_INVOICE; + } + + if (!empty($pushRequest->getInvoicekey()) + && !empty($pushRequest->getSchemekey()) + && strlen($savedInvoiceKey) == 0 + ) { + return self::BUCK_PUSH_TYPE_INVOICE_INCOMPLETE; + } + + if (!empty($pushRequest->getDatarequest())) { + return self::BUCK_PUSH_TYPE_DATAREQUEST; + } + + if (empty($pushRequest->getInvoicekey()) + && empty($pushRequest->getServiceCreditmanagement3Invoicekey()) + && empty($pushRequest->getDatarequest()) + && strlen($savedInvoiceKey) <= 0 + ) { + return self::BUCK_PUSH_TYPE_TRANSACTION; + } + + return false; + } + + /** + * Retrieve the status code from the push request based on the transaction type. + * + * @param string $transactionType + * @param PushRequestInterface $pushRequest + * @return int + * + * @SuppressWarnings(PHPMD.CyclomaticComplexity) + */ + private function getStatusCodeByTransactionType( + string $transactionType, + PushRequestInterface $pushRequest + ): int { + $statusCode = 0; + switch ($transactionType) { + case self::BUCK_PUSH_TYPE_TRANSACTION: + case self::BUCK_PUSH_TYPE_DATAREQUEST: + if ($pushRequest->getStatusCode() !== null) { + $statusCode = $pushRequest->getStatusCode(); + } + break; + case self::BUCK_PUSH_TYPE_INVOICE: + case self::BUCK_PUSH_TYPE_INVOICE_INCOMPLETE: + if (!empty($pushRequest->getEventparametersStatuscode())) { + $statusCode = $pushRequest->getEventparametersStatuscode(); + } + + if (!empty($pushRequest->getEventparametersTransactionstatuscode())) { + $statusCode = $pushRequest->getEventparametersTransactionstatuscode(); + } + break; + default: + $statusCode = BuckarooStatusCode::FAILED; + } + + $statusCodeSuccess = BuckarooStatusCode::SUCCESS; + if ($pushRequest->getStatusCode() !== null + && ($pushRequest->getStatusCode() == $statusCodeSuccess) + && !$statusCode + ) { + $statusCode = $statusCodeSuccess; + } + + return (int)$statusCode; + } + + +} \ No newline at end of file diff --git a/Model/Push/TransactionFactory.php b/Model/Push/TransactionFactory.php new file mode 100644 index 000000000..46fa0fe22 --- /dev/null +++ b/Model/Push/TransactionFactory.php @@ -0,0 +1,169 @@ +objectManager = $objectManager; + $this->pushProcessors = $pushProcessors; + $this->orderRequestService = $orderRequestService; + } + + /** + * Retrieve proper push processor for the specified transaction method. + * + * @param PushRequestInterface|null $pushRequest + * @return ?PushProcessorInterface + * @throws BuckarooException + */ + public function createTransaction(?PushRequestInterface $pushRequest): ?PushProcessorInterface + { + // Determine which payment method to use + $paymentMethod = PaymentMethodFactory::getPaymentMethod($postParams['brq_transaction_method']); + + // Determine which state to use + $paymentState = PaymentStateFactory::getPaymentState($postParams['brq_statuscode']); + + // Determine which command to use + $paymentCommand = PaymentCommandFactory::getPaymentCommand($postParams['ADD_service_action_from_magento']); + + // Create the transaction + $transaction = new Transaction($paymentMethod, $paymentState, $paymentCommand); + + // Apply any decorators based on the post parameters + $transaction = $this->applyDecorators($transaction, $postParams); + + return $transaction; + + if (!$this->pushProcessor instanceof PushProcessorInterface) { + if (empty($this->pushProcessors)) { + throw new \LogicException('Push processors is not set.'); + } + + $pushProcessorClass = $this->pushProcessors['default']; + + $order = $this->orderRequestService->getOrderByRequest($pushRequest); + + $transactionType = $this->getTransactionType($pushRequest, $order); + + if ($transactionType == self::BUCK_PUSH_TYPE_INVOICE) { + $pushProcessorClass = $this->pushProcessors['credit_managment']; + } elseif ($transactionType == self::BUCK_PUSH_TYPE_INVOICE_INCOMPLETE) { + throw new BuckarooException( + __('Skipped handling this invoice push because it is too soon.') + ); + } + + $transactionMethod = $pushRequest->getTransactionMethod(); + + $pushProcessorClass = $this->pushProcessors[$transactionMethod] ?? $pushProcessorClass; + + if (empty($pushProcessorClass)) { + throw new BuckarooException( + new Phrase( + 'Unknown ConfigProvider type requested: %1.', + [$transactionMethod] + ) + ); + } + $this->pushProcessor = $this->objectManager->get($pushProcessorClass); + + } + return $this->pushProcessor; + } + + private static function applyDecorators($transaction, $postParams) { + if (isset($postParams['ADD_group_transaction'])) { + $transaction = new GroupTransactionDecorator($transaction); + } + + if (isset($postParams['ADD_credit_management'])) { + $transaction = new CreditManagementDecorator($transaction); + } + + return $transaction; + } + + /** + * Determine the transaction type based on push request data and the saved invoice key. + * + * @return bool|string + * + * @SuppressWarnings(PHPMD.CyclomaticComplexity) + */ + public function getTransactionType($pushRequest, $order) + { + //If an order has an invoice key, then it should only be processed by invoice pushes + $savedInvoiceKey = (string)$order->getPayment()->getAdditionalInformation('buckaroo_cm3_invoice_key'); + + if (!empty($pushRequest->getInvoicekey()) + && !empty($pushRequest->getSchemekey()) + && strlen($savedInvoiceKey) > 0 + ) { + return self::BUCK_PUSH_TYPE_INVOICE; + } + + if (!empty($pushRequest->getInvoicekey()) + && !empty($pushRequest->getSchemekey()) + && strlen($savedInvoiceKey) == 0 + ) { + return self::BUCK_PUSH_TYPE_INVOICE_INCOMPLETE; + } + + if (!empty($pushRequest->getDatarequest())) { + return self::BUCK_PUSH_TYPE_DATAREQUEST; + } + + if (empty($pushRequest->getInvoicekey()) + && empty($pushRequest->getServiceCreditmanagement3Invoicekey()) + && empty($pushRequest->getDatarequest()) + && strlen($savedInvoiceKey) <= 0 + ) { + return self::BUCK_PUSH_TYPE_TRANSACTION; + } + + return false; + } +} \ No newline at end of file diff --git a/Model/RequestPush/HttppostPushRequest.php b/Model/RequestPush/HttppostPushRequest.php index 4ff6f7d3b..90f3dcbe8 100644 --- a/Model/RequestPush/HttppostPushRequest.php +++ b/Model/RequestPush/HttppostPushRequest.php @@ -32,6 +32,9 @@ * @method getSchemekey() * @method getServiceCreditmanagement3Invoicekey() * @method getEventparametersStatuscode() + * @method getEventparametersTransactionstatuscode() + * @method getIspaid() + * @method getInvoicestatuscode() */ class HttppostPushRequest extends AbstractPushRequest implements PushRequestInterface { diff --git a/Model/RequestPush/JsonPushRequest.php b/Model/RequestPush/JsonPushRequest.php index ff82a3693..1cce2cec0 100644 --- a/Model/RequestPush/JsonPushRequest.php +++ b/Model/RequestPush/JsonPushRequest.php @@ -33,6 +33,9 @@ * @method getSchemekey() * @method getServiceCreditmanagement3Invoicekey() * @method getEventparametersStatuscode() + * @method getEventparametersTransactionstatuscode() + * @method getIspaid() + * @method getInvoicestatuscode() */ class JsonPushRequest extends AbstractPushRequest implements PushRequestInterface { diff --git a/Service/Push/OrderRequestService.php b/Service/Push/OrderRequestService.php index 23d20cd86..2c46b8c0d 100644 --- a/Service/Push/OrderRequestService.php +++ b/Service/Push/OrderRequestService.php @@ -2,6 +2,7 @@ namespace Buckaroo\Magento2\Service\Push; +use Buckaroo\Magento2\Api\PushRequestInterface; use Buckaroo\Magento2\Logging\Log; use Magento\Sales\Api\Data\TransactionInterface; use Magento\Sales\Model\Order; @@ -26,13 +27,16 @@ class OrderRequestService private TransactionInterface $transaction; /** + * @param Order $order * @param Log $logging * @param TransactionInterface $transaction */ public function __construct( + Order $order, Log $logging, TransactionInterface $transaction ) { + $this->order = $order; $this->logging = $logging; $this->transaction = $transaction; } @@ -40,13 +44,13 @@ public function __construct( /** * Load the order from the Push Data based on the Order Increment ID or transaction key. * - * @param $pushRequest + * @param PushRequestInterface|null $pushRequest * @return Order|OrderPayment * @throws \Exception */ - public function getOrderByRequest($pushRequest): Order|OrderPayment + public function getOrderByRequest(?PushRequestInterface $pushRequest = null): Order|OrderPayment { - if ($this->order) { + if ($this->order->getId()) { return $this->order; } else { $brqOrderId = $this->getOrderIncrementIdFromRequest($pushRequest); diff --git a/etc/config.xml b/etc/config.xml index 52d00fac7..73b5fe965 100644 --- a/etc/config.xml +++ b/etc/config.xml @@ -476,7 +476,7 @@ 0 - PayPerEmailFacade + PayLinkFacade pending Buckaroo PayLink 0 diff --git a/etc/di.xml b/etc/di.xml index 62a7af4d6..3e285f001 100644 --- a/etc/di.xml +++ b/etc/di.xml @@ -509,6 +509,7 @@ Buckaroo\Magento2\Model\Push\DefaultProcessor Buckaroo\Magento2\Model\Push\IdealProcessor + Buckaroo\Magento2\Model\Push\CreditManagmentPushProcessor @@ -3122,6 +3123,30 @@ + + + + Buckaroo\Magento2\Model\ConfigProvider\Method\PayLink::CODE + PayLinkValueHandlerPool + + + + + + + PayLinkConfigValueHandler + + + + + + + Buckaroo\Magento2\Model\ConfigProvider\Method\PayLink + + + + + From cd8d4b41b9f51b87e162edfc4f9684d3b999ab0b Mon Sep 17 00:00:00 2001 From: Lucian Turiac Date: Thu, 6 Jul 2023 11:49:30 +0300 Subject: [PATCH 07/29] Buckaroo Push Refactor - work in progress refactor push --- Model/Push.php | 11 +++++++++-- Model/Push/PushTransactionType.php | 16 +++++++--------- Service/Push/OrderRequestService.php | 2 ++ 3 files changed, 18 insertions(+), 11 deletions(-) diff --git a/Model/Push.php b/Model/Push.php index 0affc4e86..95465b2d4 100644 --- a/Model/Push.php +++ b/Model/Push.php @@ -227,6 +227,11 @@ class Push implements PushInterface */ private OrderRequestService $orderRequestService; + /** + * @var PushTransactionType + */ + private PushTransactionType $pushTransactionType; + /** * @param Order $order * @param TransactionInterface $transaction @@ -333,8 +338,10 @@ public function receivePush() $pushTransactionType = $this->pushTransactionType->getPushTransactionType($this->pushRequst, $this->order); // Process Push -// $this->pushProcessor = $this->pushProcessorsFactory->get($this->pushRequst); -// $this->pushProcessor->processPush($this->pushRequst); + $this->pushProcessor = $this->pushProcessorsFactory->get($pushTransactionType); + $this->pushProcessor->processPush($this->pushRequst); + + // Lock Push Processing $this->logging->addDebug(__METHOD__ . '|1_2|'); diff --git a/Model/Push/PushTransactionType.php b/Model/Push/PushTransactionType.php index 871e86cd4..910ce9a63 100644 --- a/Model/Push/PushTransactionType.php +++ b/Model/Push/PushTransactionType.php @@ -69,9 +69,9 @@ class PushTransactionType private bool $creditManagment; /** - * @var string + * @var bool|string */ - private string $transactionType; + private string|bool $transactionType; /** @@ -100,9 +100,9 @@ public function __construct(BuckarooStatusCode $buckarooStatusCode) /** * @param PushRequestInterface|null $pushRequest * @param Order|null $order - * @return array + * @return PushTransactionType */ - public function getPushTransactionType(?PushRequestInterface $pushRequest, ?Order $order): array + public function getPushTransactionType(?PushRequestInterface $pushRequest, ?Order $order): PushTransactionType { if(empty($this->pushTransactionType)) { $this->paymentMethod = $pushRequest->getTransactionMethod(); @@ -122,9 +122,7 @@ public function getPushTransactionType(?PushRequestInterface $pushRequest, ?Orde } - return $this->pushTransactionType; - - + return $this; } /** @@ -274,7 +272,7 @@ public function setOrder(Order $order): void /** * Determine the transaction type based on push request data and the saved invoice key. * - * @return bool|string + * @return string * * @SuppressWarnings(PHPMD.CyclomaticComplexity) */ @@ -309,7 +307,7 @@ public function getTransactionTypeByInvoiceKey($pushRequest, $order) return self::BUCK_PUSH_TYPE_TRANSACTION; } - return false; + return ''; } /** diff --git a/Service/Push/OrderRequestService.php b/Service/Push/OrderRequestService.php index 2c46b8c0d..ad39160ed 100644 --- a/Service/Push/OrderRequestService.php +++ b/Service/Push/OrderRequestService.php @@ -85,6 +85,8 @@ protected function getOrderIncrementIdFromRequest($pushRequest): ?string $brqOrderId = $pushRequest->getOrderNumber(); } + $brqOrderId = str_replace('LT', '', $brqOrderId); + return $brqOrderId; } From d0452fca046de423317aba2b864a5880df192064 Mon Sep 17 00:00:00 2001 From: Lucian Turiac Date: Tue, 11 Jul 2023 11:08:36 +0300 Subject: [PATCH 08/29] BP-2132 - Working on Push Refactor --- Helper/PaymentGroupTransaction.php | 8 +- Model/Push.php | 2 +- Model/Push/DefaultProcessor.php | 67 +--- Model/Push/GroupTransactionPushProcessor.php | 319 ++++++++++++++++++ ...GroupTransactionPushProcessorDecorator.php | 8 - Model/Push/IdealProcessor.php | 20 +- Model/Push/PayPerEmailProcessor.php | 2 +- Model/Push/PushProcessorsFactory.php | 67 +--- Model/Push/PushTransactionType.php | 318 +++++++++-------- etc/di.xml | 1 + 10 files changed, 537 insertions(+), 275 deletions(-) create mode 100644 Model/Push/GroupTransactionPushProcessor.php delete mode 100644 Model/Push/GroupTransactionPushProcessorDecorator.php diff --git a/Helper/PaymentGroupTransaction.php b/Helper/PaymentGroupTransaction.php index 52ea8d561..8b75f9d56 100644 --- a/Helper/PaymentGroupTransaction.php +++ b/Helper/PaymentGroupTransaction.php @@ -326,12 +326,8 @@ public function setGroupTransactionsStatus(string $groupTransactionId, string $s ->getConnection() ->update( $this->resourceModel->getTable('buckaroo_magento2_group_transaction'), - [ - 'status' => $status - ], - [ - 'relatedtransaction = ?' => $groupTransactionId - ] + ['status' => $status], + ['relatedtransaction = ?' => $groupTransactionId] ); } } diff --git a/Model/Push.php b/Model/Push.php index 95465b2d4..84adb8eb9 100644 --- a/Model/Push.php +++ b/Model/Push.php @@ -1801,7 +1801,7 @@ private function isGroupTransactionPart() } /** - * Check if the group transaction has failed. + * Check if the group transaction has failed. same as: isFailedGroupTransaction * * @return bool */ diff --git a/Model/Push/DefaultProcessor.php b/Model/Push/DefaultProcessor.php index a63fb8df4..e5cbcac64 100644 --- a/Model/Push/DefaultProcessor.php +++ b/Model/Push/DefaultProcessor.php @@ -12,6 +12,7 @@ use Buckaroo\Magento2\Model\ConfigProvider\Method\Transfer; use Buckaroo\Magento2\Model\Validator\Push as ValidatorPush; use Buckaroo\Magento2\Service\LockerProcess; +use Buckaroo\Magento2\Service\Push\OrderRequestService; use Magento\Framework\Exception\FileSystemException; use Magento\Framework\Exception\LocalizedException; use Magento\Sales\Api\Data\TransactionInterface; @@ -22,40 +23,40 @@ class DefaultProcessor implements PushProcessorInterface { - public const BUCK_PUSH_TYPE_TRANSACTION = 'transaction_push'; - public const BUCK_PUSH_TYPE_INVOICE = 'invoice_push'; - public const BUCK_PUSH_TYPE_INVOICE_INCOMPLETE = 'incomplete_invoice_push'; - public const BUCK_PUSH_TYPE_DATAREQUEST = 'datarequest_push'; - + /** + * @var OrderRequestService + */ + private OrderRequestService $orderService; + /** * @var PushRequestInterface */ - public PushRequestInterface $pushRequest; + protected PushRequestInterface $pushRequest; /** * @var Log $logging */ - public Log $logging; + protected Log $logging; /** * @var Order|OrderPayment $order */ - public $order; + protected $order; /** * @var Transaction */ - private $transaction; + protected $transaction; /** * @var Data */ - public Data $helper; + protected Data $helper; /** * @var LockerProcess */ - private LockerProcess $lockerProcess; + protected LockerProcess $lockerProcess; /** * @var ValidatorPush $validator @@ -63,12 +64,14 @@ class DefaultProcessor implements PushProcessorInterface protected ValidatorPush $validator; public function __construct( + OrderRequestService $orderRequestService, Log $logging, TransactionInterface $transaction, LockerProcess $lockerProcess, Data $helper, ValidatorPush $validator ) { + $this->order = $orderRequestService->getOrderByRequest(); $this->logging = $logging; $this->transaction = $transaction; $this->lockerProcess = $lockerProcess; @@ -84,14 +87,6 @@ public function processPush(PushRequestInterface $pushRequest): bool { $this->pushRequest = $pushRequest; - // Load Order by Transaction id - $this->order = $this->loadOrder(); - - // Lock Processing - if ($this->lockPushProcessingCriteria()) { - $this->lockerProcess->lockProcess($this->getOrderIncrementId()); - } - // Skip Push if ($this->skipPush()) { return true; @@ -324,11 +319,6 @@ protected function lockPushProcessingCriteria(): bool */ protected function skipPush() { - // Skip Handle group transaction - if ($this->skipHandlingForFailedGroupTransactions()) { - return true; - } - if ($this->skipPendingRefundPush()) { return true; } @@ -345,35 +335,6 @@ protected function skipPush() return false; } - - /** - * Ship push handling for a failed transaction - * - * @return bool - */ - protected function skipHandlingForFailedGroupTransactions(): bool - { - return - $this->order !== null && - $this->order->getId() !== null && - $this->order->getState() == Order::STATE_CANCELED && - ( - $this->pushRequest->hasPostData( - 'brq_transaction_type', - 'V202' - ) || - - $this->pushRequest->hasPostData( - 'brq_transaction_type', - 'V203' - ) || - $this->pushRequest->hasPostData( - 'brq_transaction_type', - 'V204' - ) - ); - } - /** * Check if it is needed to handle the push message based on postdata * diff --git a/Model/Push/GroupTransactionPushProcessor.php b/Model/Push/GroupTransactionPushProcessor.php new file mode 100644 index 000000000..740bf460d --- /dev/null +++ b/Model/Push/GroupTransactionPushProcessor.php @@ -0,0 +1,319 @@ +groupTransaction = $groupTransaction; + $this->logging = $logging; + $this->orderRequestService = $orderRequestService; + $this->orderManagement = $orderManagement; + $this->quoteManagement = $quoteManagement; + $this->quoteFactory = $quoteFactory; + $this->quoteResource = $quoteResource; + } + + /** + * @inheritdoc + * + * @throws LocalizedException + * @throws \Exception + */ + public function processPush(PushRequestInterface $pushRequest): bool + { + $this->pushRequest = $pushRequest; + $this->order = $this->orderRequestService->getOrderByRequest($pushRequest); + + if ($this->isFailedGroupTransaction()) { + $this->handleGroupTransactionFailed(); + return true; + } + + if($this->isCanceledGroupTransaction()) { + $this->cancelGroupTransactionOrder(); + return true; + } + + // Check if is group transaction info + if ($this->isGroupTransactionInfo()) { + return true; + } + + // Skip Handle group transaction + if ($this->skipHandlingForFailedGroupTransactions()) { + return true; + } + + return false; + } + + public function processSucceededPush(PushRequestInterface $pushRequest): bool + { + // TODO: Implement processSucceededPush() method. + } + + public function processFailedPush(PushRequestInterface $pushRequest): bool + { + // TODO: Implement processFailedPush() method. + } + + public function processPendingPaymentPush(PushRequestInterface $pushRequest): bool + { + // TODO: Implement processPendingPaymentPush() method. + } + + /** + * Check if is a failed transaction + * + * @return boolean + */ + protected function isFailedGroupTransaction(): bool + { + return $this->pushRequest->hasPostData('statuscode', BuckarooStatusCode::FAILED); + } + + /** + * Checks if the group transaction is an info transaction + * + * @return bool + */ + private function isGroupTransactionInfo() + { + return $this->pushRequest->getStatusCode() != BuckarooStatusCode::SUCCESS; + } + + /** + * Check if the request is a canceled group transaction + * + * @return boolean + */ + public function isCanceledGroupTransaction() + { + return $this->pushRequest->hasPostData('brq_statuscode', BuckarooStatusCode::CANCELLED_BY_USER); + } + + /** + * Handle push from main group transaction fail + * + * @return void + */ + protected function handleGroupTransactionFailed() + { + try { + $this->cancelOrder($this->pushRequest->getInvoiceNumber()); + $this->groupTransaction->setGroupTransactionsStatus( + $this->pushRequest->getTransactions(), + $this->pushRequest->getStatusCode() + ); + + $this->savePartGroupTransaction(); + } catch (\Throwable $th) { + $this->logging->addDebug(__METHOD__ . '|' . (string)$th); + } + } + + /** + * Cancel order when group transaction is canceled + * + * @return void + * @throws LocalizedException + */ + public function cancelGroupTransactionOrder(): void + { + if (is_string($this->pushRequest->getInvoiceNumber())) { + $this->cancelOrder( + $this->pushRequest->getInvoiceNumber(), + 'Inline giftcard order was canceled' + ); + } + } + + /** + * Ship push handling for a failed transaction + * + * @return bool + */ + protected function skipHandlingForFailedGroupTransactions(): bool + { + return + $this->order->getId() !== null && + $this->order->getState() == Order::STATE_CANCELED && + $this->pushRequest->hasPostData('transaction_type', ['V202','V203', 'V204']); + } + + /** + * Cancel order for failed group transaction + * + * @param string $reservedOrderId + * @param string $historyComment + * @return void + * @throws LocalizedException + */ + protected function cancelOrder(string $reservedOrderId, string $historyComment = 'Giftcard has expired'): void + { + $order = $this->order->loadByIncrementId($reservedOrderId); + + if ($order->getEntityId() === null) { + $order = $this->createOrderFromQuote($reservedOrderId); + } + + if ($order instanceof OrderInterface && + $order->getEntityId() !== null && + $order->getState() !== Order::STATE_CANCELED + ) { + $this->orderManagement->cancel($order->getEntityId()); + + $order->addCommentToStatusHistory(__($historyComment)) + ->setIsCustomerNotified(false) + ->setEntityName('invoice') + ->save(); + } + } + + /** + * Create order from quote + * + * @param string $reservedOrderId + * @return AbstractExtensibleModel|OrderInterface|object|null + * @throws \Exception + * @throws LocalizedException + */ + protected function createOrderFromQuote(string $reservedOrderId) + { + $quote = $this->getQuoteByReservedOrderId($reservedOrderId); + if (!$quote instanceof Quote) { + return null; + } + + // fix missing email validation + if ($quote->getCustomerEmail() == null) { + $quote->setCustomerEmail( + $quote->getBillingAddress()->getEmail() + ); + } + + $order = $this->quoteManagement->submit($quote); + + // keep the quote active but remove the canceled order from it + $quote->setIsActive(true); + $quote->setOrigOrderId(0); + $quote->setReservedOrderId(null); + $quote->save(); + return $order; + } + + /** + * Get quote by increment/reserved order id + * + * @param string $reservedOrderId + * @return Quote|null + */ + protected function getQuoteByReservedOrderId(string $reservedOrderId): ?Quote + { + $quote = $this->quoteFactory->create(); + + $this->quoteResource->load($quote, $reservedOrderId, 'reserved_order_id'); + if (!$quote->isEmpty()) { + return $quote; + } + + return null; + } + + /** + * Save the part group transaction. + * + * @return void + * @throws \Exception + */ + private function savePartGroupTransaction() + { + $items = $this->groupTransaction->getGroupTransactionByTrxId($this->pushRequest->getTransactions()); + if (is_array($items) && count($items) > 0) { + foreach ($items as $item) { + $item2['status'] = $this->pushRequest->getStatusCode(); + $item2['entity_id'] = $item['entity_id']; + $this->groupTransaction->updateGroupTransaction($item2); + } + } + } +} \ No newline at end of file diff --git a/Model/Push/GroupTransactionPushProcessorDecorator.php b/Model/Push/GroupTransactionPushProcessorDecorator.php deleted file mode 100644 index 3a5bab1bf..000000000 --- a/Model/Push/GroupTransactionPushProcessorDecorator.php +++ /dev/null @@ -1,8 +0,0 @@ -pushRequest = $pushRequest; + + // Lock Processing + if ($this->lockPushProcessingCriteria()) { + $this->lockerProcess->lockProcess($this->getOrderIncrementId()); + } + parent::processPush($pushRequest); + + $this->lockerProcess->unlockProcess(); } /** @@ -26,17 +36,15 @@ public function processPush(PushRequestInterface $pushRequest): bool */ protected function lockPushProcessingCriteria(): bool { - $statusCodeSuccess = $this->helper->getStatusCode('BUCKAROO_MAGENTO2_STATUSCODE_SUCCESS'); - - return ($this->pushRequest->hasPostData('statuscode', $statusCodeSuccess) - && $this->pushRequest->hasPostData('transaction_type', self::BUCK_PUSH_IDEAL_PAY)); + return $this->pushRequest->hasPostData('statuscode', BuckarooStatusCode::SUCCESS) + && $this->pushRequest->hasPostData('transaction_type', self::BUCK_PUSH_IDEAL_PAY); } public function processSucceded() { - $statusCodeSuccess = $this->helper->getStatusCode('BUCKAROO_MAGENTO2_STATUSCODE_SUCCESS'); + $statusCodeSuccess = BuckarooStatusCode::SUCCESS; - if ($this->pushRequest->hasPostData('statuscode', $statusCodeSuccess) + if ($this->pushRequest->hasPostData('statuscode', BuckarooStatusCode::SUCCESS) && $this->pushRequest->hasPostData('transaction_method', 'ideal') && $this->pushRequest->hasPostData('transaction_type', self::BUCK_PUSH_IDEAL_PAY) ) { diff --git a/Model/Push/PayPerEmailProcessor.php b/Model/Push/PayPerEmailProcessor.php index a73b1ed5d..13ebd1bd8 100644 --- a/Model/Push/PayPerEmailProcessor.php +++ b/Model/Push/PayPerEmailProcessor.php @@ -13,7 +13,7 @@ class PayPerEmailProcessor extends DefaultProcessor /** * @var LockerProcess */ - private LockerProcess $lockerProcess; + protected LockerProcess $lockerProcess; public function processSucceded() diff --git a/Model/Push/PushProcessorsFactory.php b/Model/Push/PushProcessorsFactory.php index ae215864d..2a0808bdc 100644 --- a/Model/Push/PushProcessorsFactory.php +++ b/Model/Push/PushProcessorsFactory.php @@ -11,11 +11,6 @@ class PushProcessorsFactory { - private const BUCK_PUSH_TYPE_TRANSACTION = 'transaction_push'; - private const BUCK_PUSH_TYPE_INVOICE = 'invoice_push'; - private const BUCK_PUSH_TYPE_INVOICE_INCOMPLETE = 'incomplete_invoice_push'; - private const BUCK_PUSH_TYPE_DATAREQUEST = 'datarequest_push'; - /** * @var ObjectManagerInterface */ @@ -67,16 +62,6 @@ public function get(?PushTransactionType $pushTransactionType): ?PushProcessorIn $pushProcessorClass = $this->pushProcessors['default']; - $transactionType = $pushTransactionType->getTransactionType(); - - if ($transactionType == self::BUCK_PUSH_TYPE_INVOICE) { - $pushProcessorClass = $this->pushProcessors['credit_managment']; - } elseif ($transactionType == self::BUCK_PUSH_TYPE_INVOICE_INCOMPLETE) { - throw new BuckarooException( - __('Skipped handling this invoice push because it is too soon.') - ); - } - $paymentMethod = $pushTransactionType->getPaymentMethod(); $pushProcessorClass = $this->pushProcessors[$paymentMethod] ?? $pushProcessorClass; @@ -85,50 +70,24 @@ public function get(?PushTransactionType $pushTransactionType): ?PushProcessorIn new Phrase('Unknown ConfigProvider type requested: %1.', [$paymentMethod]) ); } - $this->pushProcessor = $this->objectManager->get($pushProcessorClass); - } - return $this->pushProcessor; - } + if ($pushTransactionType->isGroupTransaction()) { + $pushProcessorClass = $this->pushProcessors['group_transaction']; + } - /** - * Determine the transaction type based on push request data and the saved invoice key. - * - * @return bool|string - * - * @SuppressWarnings(PHPMD.CyclomaticComplexity) - */ - public function getTransactionType($pushRequest, $order) - { - //If an order has an invoice key, then it should only be processed by invoice pushes - $savedInvoiceKey = (string)$order->getPayment()->getAdditionalInformation('buckaroo_cm3_invoice_key'); - - if (!empty($pushRequest->getInvoicekey()) - && !empty($pushRequest->getSchemekey()) - && strlen($savedInvoiceKey) > 0 - ) { - return self::BUCK_PUSH_TYPE_INVOICE; - } + $transactionType = $pushTransactionType->getTransactionType(); - if (!empty($pushRequest->getInvoicekey()) - && !empty($pushRequest->getSchemekey()) - && strlen($savedInvoiceKey) == 0 - ) { - return self::BUCK_PUSH_TYPE_INVOICE_INCOMPLETE; - } + if ($transactionType == PushTransactionType::BUCK_PUSH_TYPE_INVOICE) { + $pushProcessorClass = $this->pushProcessors['credit_managment']; + } elseif ($transactionType == PushTransactionType::BUCK_PUSH_TYPE_INVOICE_INCOMPLETE) { + throw new BuckarooException( + __('Skipped handling this invoice push because it is too soon.') + ); + } - if (!empty($pushRequest->getDatarequest())) { - return self::BUCK_PUSH_TYPE_DATAREQUEST; - } + $this->pushProcessor = $this->objectManager->get($pushProcessorClass); - if (empty($pushRequest->getInvoicekey()) - && empty($pushRequest->getServiceCreditmanagement3Invoicekey()) - && empty($pushRequest->getDatarequest()) - && strlen($savedInvoiceKey) <= 0 - ) { - return self::BUCK_PUSH_TYPE_TRANSACTION; } - - return false; + return $this->pushProcessor; } } \ No newline at end of file diff --git a/Model/Push/PushTransactionType.php b/Model/Push/PushTransactionType.php index 910ce9a63..6b6d4916f 100644 --- a/Model/Push/PushTransactionType.php +++ b/Model/Push/PushTransactionType.php @@ -28,15 +28,20 @@ class PushTransactionType { - public const BUCK_PUSH_TYPE_TRANSACTION = 'transaction_push'; - public const BUCK_PUSH_TYPE_INVOICE = 'invoice_push'; + public const BUCK_PUSH_CANCEL_AUTHORIZE_TYPE = 'I014'; + public const BUCK_PUSH_ACCEPT_AUTHORIZE_TYPE = 'I013'; + public const BUCK_PUSH_GROUPTRANSACTION_TYPE = 'I150'; + public const BUCK_PUSH_IDEAL_PAY = 'C021'; + + public const BUCK_PUSH_TYPE_TRANSACTION = 'transaction_push'; + public const BUCK_PUSH_TYPE_INVOICE = 'invoice_push'; public const BUCK_PUSH_TYPE_INVOICE_INCOMPLETE = 'incomplete_invoice_push'; - public const BUCK_PUSH_TYPE_DATAREQUEST = 'datarequest_push'; + public const BUCK_PUSH_TYPE_DATAREQUEST = 'datarequest_push'; /** - * @var string + * @var string|null */ - private string $paymentMethod; + private ?string $paymentMethod; /** * @var string @@ -44,9 +49,9 @@ class PushTransactionType private string $serviceAction; /** - * @var string + * @var int */ - private string $statusCode; + private int $statusCode; /** * @var string|null @@ -66,18 +71,22 @@ class PushTransactionType /** * @var bool */ - private bool $creditManagment; + private bool $creditManagement; + + /** + * @var string + */ + private string $pushType; /** * @var bool|string */ private string|bool $transactionType; - /** * @var array */ - private array $pushTransactionType = []; + private bool $isSet = false; /** * @var Order @@ -89,6 +98,11 @@ class PushTransactionType */ private OrderRequestService $orderRequestService; + /** + * @var BuckarooStatusCode + */ + private BuckarooStatusCode $buckarooStatusCode; + /** * @param BuckarooStatusCode $buckarooStatusCode */ @@ -104,73 +118,190 @@ public function __construct(BuckarooStatusCode $buckarooStatusCode) */ public function getPushTransactionType(?PushRequestInterface $pushRequest, ?Order $order): PushTransactionType { - if(empty($this->pushTransactionType)) { - $this->paymentMethod = $pushRequest->getTransactionMethod(); - $this->transactionType = $this->getTransactionTypeByInvoiceKey($pushRequest, $order); - $this->statusCode = $this->getStatusCodeByTransactionType($this->transactionType, $pushRequest); + if (!$this->isSet) { + $this->paymentMethod = $pushRequest->getTransactionMethod() ?? ''; + $this->pushType = $this->getPushTypeByInvoiceKey($pushRequest, $order); + $this->statusCode = $this->getStatusCodeByTransactionType($this->pushType, $pushRequest); $this->statusMessage = $this->buckarooStatusCode->getResponseMessage($this->statusCode); $this->statusKey = $this->buckarooStatusCode->getStatusKey($this->statusCode); + $this->transactionType = $pushRequest->getTransactionType(); + $this->groupTransaction = $this->transactionType === self::BUCK_PUSH_GROUPTRANSACTION_TYPE; + $this->creditManagement = $this->pushType === self::BUCK_PUSH_TYPE_INVOICE; + $this->serviceAction = $pushRequest->getAdditionalInformation('service_action_from_magento'); + + $this->isSet = true; + } + + return $this; + } + + /** + * Determine the transaction type based on push request data and the saved invoice key. + * + * @param PushRequestInterface $pushRequest + * @param Order $order + * @return string + * + * @SuppressWarnings(PHPMD.CyclomaticComplexity) + */ + public function getPushTypeByInvoiceKey(PushRequestInterface $pushRequest, Order $order): string + { + //If an order has an invoice key, then it should only be processed by invoice pushes + $savedInvoiceKey = (string)$order->getPayment()->getAdditionalInformation('buckaroo_cm3_invoice_key'); + + if (!empty($pushRequest->getInvoicekey()) + && !empty($pushRequest->getSchemekey()) + && strlen($savedInvoiceKey) > 0 + ) { + return self::BUCK_PUSH_TYPE_INVOICE; + } + if (!empty($pushRequest->getInvoicekey()) + && !empty($pushRequest->getSchemekey()) + && strlen($savedInvoiceKey) == 0 + ) { + return self::BUCK_PUSH_TYPE_INVOICE_INCOMPLETE; + } - $this->pushTransactionType = [ - 'paymentMethod' => $this->paymentMethod, - 'transactionType' => $this->transactionType, - 'statusCode' => $this->statusCode, - 'statusMessage' => $this->statusMessage, - 'statusKey' => $this->statusKey - ]; + if (!empty($pushRequest->getDatarequest())) { + return self::BUCK_PUSH_TYPE_DATAREQUEST; + } + if (empty($pushRequest->getInvoicekey()) + && empty($pushRequest->getServiceCreditmanagement3Invoicekey()) + && empty($pushRequest->getDatarequest()) + && strlen($savedInvoiceKey) <= 0 + ) { + return self::BUCK_PUSH_TYPE_TRANSACTION; } - return $this; + return ''; + } + + /** + * Retrieve the status code from the push request based on the transaction type. + * + * @param string $transactionType + * @param PushRequestInterface $pushRequest + * @return int + * + * @SuppressWarnings(PHPMD.CyclomaticComplexity) + */ + private function getStatusCodeByTransactionType( + string $transactionType, + PushRequestInterface $pushRequest + ): int { + $statusCode = 0; + switch ($transactionType) { + case self::BUCK_PUSH_TYPE_TRANSACTION: + case self::BUCK_PUSH_TYPE_DATAREQUEST: + if ($pushRequest->getStatusCode() !== null) { + $statusCode = $pushRequest->getStatusCode(); + } + break; + case self::BUCK_PUSH_TYPE_INVOICE: + case self::BUCK_PUSH_TYPE_INVOICE_INCOMPLETE: + if (!empty($pushRequest->getEventparametersStatuscode())) { + $statusCode = $pushRequest->getEventparametersStatuscode(); + } + + if (!empty($pushRequest->getEventparametersTransactionstatuscode())) { + $statusCode = $pushRequest->getEventparametersTransactionstatuscode(); + } + break; + default: + $statusCode = BuckarooStatusCode::FAILED; + } + + $statusCodeSuccess = BuckarooStatusCode::SUCCESS; + if ($pushRequest->getStatusCode() !== null + && ($pushRequest->getStatusCode() == $statusCodeSuccess) + && !$statusCode + ) { + $statusCode = $statusCodeSuccess; + } + + return (int)$statusCode; + } + + /** + * @return int + */ + public function getStatusCode(): int + { + return $this->statusCode; + } + + /** + * @param int $statusCode + */ + public function setStatusCode(int $statusCode): void + { + $this->statusCode = $statusCode; } /** * @return string */ - public function getPaymentMethod(): string + public function getTransactionType(): string { - return $this->paymentMethod; + return $this->transactionType; } /** - * @param string $paymentMethod + * @param string $transactionType */ - public function setPaymentMethod(string $paymentMethod): void + public function setTransactionType(string $transactionType): void { - $this->paymentMethod = $paymentMethod; + $this->transactionType = $transactionType; } /** * @return string */ - public function getServiceAction(): string + public function getPushType(): string { - return $this->serviceAction; + return $this->pushType; } /** - * @param string $serviceAction + * @param string $pushType */ - public function setServiceAction(string $serviceAction): void + public function setPushType(string $pushType): void { - $this->serviceAction = $serviceAction; + $this->pushType = $pushType; } /** * @return string */ - public function getStatusCode(): string + public function getPaymentMethod(): string { - return $this->statusCode; + return $this->paymentMethod; } /** - * @param string $statusCode + * @param string $paymentMethod */ - public function setStatusCode(string $statusCode): void + public function setPaymentMethod(string $paymentMethod): void { - $this->statusCode = $statusCode; + $this->paymentMethod = $paymentMethod; + } + + /** + * @return string + */ + public function getServiceAction(): string + { + return $this->serviceAction; + } + + /** + * @param string $serviceAction + */ + public function setServiceAction(string $serviceAction): void + { + $this->serviceAction = $serviceAction; } /** @@ -226,31 +357,15 @@ public function setGroupTransaction(bool $groupTransaction): void */ public function isCreditManagment(): bool { - return $this->creditManagment; - } - - /** - * @param bool $creditManagment - */ - public function setCreditManagment(bool $creditManagment): void - { - $this->creditManagment = $creditManagment; - } - - /** - * @return string - */ - public function getTransactionType(): string - { - return $this->transactionType; + return $this->creditManagement; } /** - * @param string $transactionType + * @param bool $creditManagement */ - public function setTransactionType(string $transactionType): void + public function setCreditManagment(bool $creditManagement): void { - $this->transactionType = $transactionType; + $this->creditManagement = $creditManagement; } /** @@ -268,93 +383,4 @@ public function setOrder(Order $order): void { $this->order = $order; } - - /** - * Determine the transaction type based on push request data and the saved invoice key. - * - * @return string - * - * @SuppressWarnings(PHPMD.CyclomaticComplexity) - */ - public function getTransactionTypeByInvoiceKey($pushRequest, $order) - { - //If an order has an invoice key, then it should only be processed by invoice pushes - $savedInvoiceKey = (string)$order->getPayment()->getAdditionalInformation('buckaroo_cm3_invoice_key'); - - if (!empty($pushRequest->getInvoicekey()) - && !empty($pushRequest->getSchemekey()) - && strlen($savedInvoiceKey) > 0 - ) { - return self::BUCK_PUSH_TYPE_INVOICE; - } - - if (!empty($pushRequest->getInvoicekey()) - && !empty($pushRequest->getSchemekey()) - && strlen($savedInvoiceKey) == 0 - ) { - return self::BUCK_PUSH_TYPE_INVOICE_INCOMPLETE; - } - - if (!empty($pushRequest->getDatarequest())) { - return self::BUCK_PUSH_TYPE_DATAREQUEST; - } - - if (empty($pushRequest->getInvoicekey()) - && empty($pushRequest->getServiceCreditmanagement3Invoicekey()) - && empty($pushRequest->getDatarequest()) - && strlen($savedInvoiceKey) <= 0 - ) { - return self::BUCK_PUSH_TYPE_TRANSACTION; - } - - return ''; - } - - /** - * Retrieve the status code from the push request based on the transaction type. - * - * @param string $transactionType - * @param PushRequestInterface $pushRequest - * @return int - * - * @SuppressWarnings(PHPMD.CyclomaticComplexity) - */ - private function getStatusCodeByTransactionType( - string $transactionType, - PushRequestInterface $pushRequest - ): int { - $statusCode = 0; - switch ($transactionType) { - case self::BUCK_PUSH_TYPE_TRANSACTION: - case self::BUCK_PUSH_TYPE_DATAREQUEST: - if ($pushRequest->getStatusCode() !== null) { - $statusCode = $pushRequest->getStatusCode(); - } - break; - case self::BUCK_PUSH_TYPE_INVOICE: - case self::BUCK_PUSH_TYPE_INVOICE_INCOMPLETE: - if (!empty($pushRequest->getEventparametersStatuscode())) { - $statusCode = $pushRequest->getEventparametersStatuscode(); - } - - if (!empty($pushRequest->getEventparametersTransactionstatuscode())) { - $statusCode = $pushRequest->getEventparametersTransactionstatuscode(); - } - break; - default: - $statusCode = BuckarooStatusCode::FAILED; - } - - $statusCodeSuccess = BuckarooStatusCode::SUCCESS; - if ($pushRequest->getStatusCode() !== null - && ($pushRequest->getStatusCode() == $statusCodeSuccess) - && !$statusCode - ) { - $statusCode = $statusCodeSuccess; - } - - return (int)$statusCode; - } - - } \ No newline at end of file diff --git a/etc/di.xml b/etc/di.xml index 3e285f001..c76a6f778 100644 --- a/etc/di.xml +++ b/etc/di.xml @@ -510,6 +510,7 @@ Buckaroo\Magento2\Model\Push\DefaultProcessor Buckaroo\Magento2\Model\Push\IdealProcessor Buckaroo\Magento2\Model\Push\CreditManagmentPushProcessor + Buckaroo\Magento2\Model\Push\GroupTransactionPushProcessor From 0c26ab4ad71dc71e4306601439f6bd387baa79ba Mon Sep 17 00:00:00 2001 From: Lucian Turiac Date: Thu, 13 Jul 2023 10:22:12 +0300 Subject: [PATCH 09/29] BP-2132 - Working on Push Refactor --- Api/PushProcessorInterface.php | 18 - Model/Push.php | 9 +- Model/Push/CancelAuthorizeProcessor.php | 27 ++ Model/Push/DefaultProcessor.php | 426 ++++++++-------------- Model/Push/PushProcessorsFactory.php | 61 ++-- Model/Push/PushTransactionType.php | 124 +++++-- Model/Push/RefundProcessor.php | 96 +++++ Model/RequestPush/AbstractPushRequest.php | 15 +- Model/RequestPush/HttppostPushRequest.php | 1 + Model/RequestPush/JsonPushRequest.php | 1 + Service/Push/OrderRequestService.php | 17 + etc/di.xml | 3 + 12 files changed, 448 insertions(+), 350 deletions(-) create mode 100644 Model/Push/CancelAuthorizeProcessor.php create mode 100644 Model/Push/RefundProcessor.php diff --git a/Api/PushProcessorInterface.php b/Api/PushProcessorInterface.php index e4b06737e..5b7b0fcdc 100644 --- a/Api/PushProcessorInterface.php +++ b/Api/PushProcessorInterface.php @@ -9,22 +9,4 @@ interface PushProcessorInterface * @return bool */ public function processPush(PushRequestInterface $pushRequest): bool; - - /** - * @param PushRequestInterface $pushRequest - * @return bool - */ - public function processSucceededPush(PushRequestInterface $pushRequest): bool; - - /** - * @param PushRequestInterface $pushRequest - * @return bool - */ - public function processFailedPush(PushRequestInterface $pushRequest): bool; - - /** - * @param PushRequestInterface $pushRequest - * @return bool - */ - public function processPendingPaymentPush(PushRequestInterface $pushRequest): bool; } \ No newline at end of file diff --git a/Model/Push.php b/Model/Push.php index 84adb8eb9..79e5be06f 100644 --- a/Model/Push.php +++ b/Model/Push.php @@ -253,6 +253,9 @@ class Push implements PushInterface * @param Afterpay20 $afterpayConfig * @param File $fileSystemDriver * @param RequestPushFactory $requestPushFactory + * @param PushProcessorsFactory $pushProcessorsFactory + * @param OrderRequestService $orderRequestService + * @param PushTransactionType $pushTransactionType * @SuppressWarnings(PHPMD.ExcessiveParameterList) */ public function __construct( @@ -339,7 +342,7 @@ public function receivePush() // Process Push $this->pushProcessor = $this->pushProcessorsFactory->get($pushTransactionType); - $this->pushProcessor->processPush($this->pushRequst); +// $this->pushProcessor->processPush($this->pushRequst); @@ -1535,10 +1538,10 @@ public function processPendingPaymentPush(): bool /** * Try to add a notification note to the order comments. * - * @param Phrase|string $message + * @param string|Phrase $message * @throws \Exception */ - protected function setOrderNotificationNote(string $message) + protected function setOrderNotificationNote(Phrase|string $message) { $note = 'Buckaroo attempted to update this order, but failed: ' . $message; try { diff --git a/Model/Push/CancelAuthorizeProcessor.php b/Model/Push/CancelAuthorizeProcessor.php new file mode 100644 index 000000000..7e216c0a2 --- /dev/null +++ b/Model/Push/CancelAuthorizeProcessor.php @@ -0,0 +1,27 @@ +setTransactionKey(); + } catch (\Exception $e) { + $this->logging->addDebug($e->getLogMessage()); + } + + $this->logging->addDebug('Order autorize has been canceld, trying to update payment transactions'); + + return true; + } +} \ No newline at end of file diff --git a/Model/Push/DefaultProcessor.php b/Model/Push/DefaultProcessor.php index e5cbcac64..08b332279 100644 --- a/Model/Push/DefaultProcessor.php +++ b/Model/Push/DefaultProcessor.php @@ -9,9 +9,9 @@ use Buckaroo\Magento2\Logging\Log; use Buckaroo\Magento2\Model\BuckarooStatusCode; use Buckaroo\Magento2\Model\ConfigProvider\Method\Giftcards; +use Buckaroo\Magento2\Model\ConfigProvider\Method\PayPerEmail; use Buckaroo\Magento2\Model\ConfigProvider\Method\Transfer; -use Buckaroo\Magento2\Model\Validator\Push as ValidatorPush; -use Buckaroo\Magento2\Service\LockerProcess; +use Buckaroo\Magento2\Model\Method\BuckarooAdapter; use Buckaroo\Magento2\Service\Push\OrderRequestService; use Magento\Framework\Exception\FileSystemException; use Magento\Framework\Exception\LocalizedException; @@ -23,10 +23,13 @@ class DefaultProcessor implements PushProcessorInterface { + public const BUCKAROO_RECEIVED_TRANSACTIONS = 'buckaroo_received_transactions'; + public const BUCKAROO_RECEIVED_TRANSACTIONS_STATUSES = 'buckaroo_received_transactions_statuses'; + /** * @var OrderRequestService */ - private OrderRequestService $orderService; + protected OrderRequestService $orderRequestService; /** * @var PushRequestInterface @@ -54,185 +57,67 @@ class DefaultProcessor implements PushProcessorInterface protected Data $helper; /** - * @var LockerProcess + * @var Payment|null + */ + protected ?Payment $payment; + + /** + * @var PushTransactionType */ - protected LockerProcess $lockerProcess; + protected PushTransactionType $pushTransactionType; /** - * @var ValidatorPush $validator + * @var bool */ - protected ValidatorPush $validator; + protected bool $forceInvoice = false; public function __construct( OrderRequestService $orderRequestService, + PushTransactionType $pushTransactionType, Log $logging, TransactionInterface $transaction, - LockerProcess $lockerProcess, - Data $helper, - ValidatorPush $validator + Data $helper ) { - $this->order = $orderRequestService->getOrderByRequest(); + $this->orderRequestService = $orderRequestService; $this->logging = $logging; $this->transaction = $transaction; - $this->lockerProcess = $lockerProcess; $this->helper = $helper; - $this->validator = $validator; + $this->pushTransactionType = $pushTransactionType; } /** * @throws BuckarooException * @throws FileSystemException + * @throws \Exception */ public function processPush(PushRequestInterface $pushRequest): bool { $this->pushRequest = $pushRequest; + $this->order = $this->orderRequestService->getOrderByRequest(); + $this->payment = $this->order->getPayment(); // Skip Push if ($this->skipPush()) { return true; } - - // Handle Group Transaction - - - - $transactionType = $this->getTransactionType(); - $postDataStatusCode = $this->getStatusCode(); - $this->logging->addDebug(__METHOD__ . '|1_5|' . var_export($postDataStatusCode, true)); - $this->logging->addDebug(__METHOD__ . '|1_10|' . var_export($transactionType, true)); - - $response = $this->validator->validateStatusCode($postDataStatusCode); - - - $this->lockerProcess->unlockProcess(); - } - - /** - * Creates and saves the invoice and adds for each invoice the buckaroo transaction keys - * Only when the order can be invoiced and has not been invoiced before. - * - * @return bool - * @throws BuckarooException - * @throws LocalizedException - * - * @SuppressWarnings(PHPMD.CyclomaticComplexity) - * @SuppressWarnings(PHPMD.NPathComplexity) - */ - protected function saveInvoice(): bool - { - $this->logging->addDebug(__METHOD__ . '|1|'); - if (!$this->forceInvoice - && (!$this->order->canInvoice() || $this->order->hasInvoices())) { - $this->logging->addDebug('Order can not be invoiced'); - //throw new BuckarooException(__('Order can not be invoiced')); - return false; - - } - - $this->logging->addDebug(__METHOD__ . '|5|'); - - /** - * Only when the order can be invoiced and has not been invoiced before. - */ - if (!$this->isGroupTransactionInfoType()) { - $this->addTransactionData(); - } - - /** - * @var Payment $payment - */ - $payment = $this->order->getPayment(); - - $invoiceAmount = 0; - if (!empty($this->pushRequst->getAmount())) { - $invoiceAmount = floatval($this->pushRequst->getAmount()); - } - if (($payment->getMethod() == Giftcards::CODE) - && $invoiceAmount != $this->order->getGrandTotal() - ) { - $this->setReceivedPaymentFromBuckaroo(); - - $payment->registerCaptureNotification($invoiceAmount, true); - $payment->save(); - - $receivedPaymentsArray = $payment->getAdditionalInformation(self::BUCKAROO_RECEIVED_TRANSACTIONS); - - if (!is_array($receivedPaymentsArray)) { - return false; - } - - $payment->capture(); //creates invoice - $payment->save(); - } elseif ($this->isPayPerEmailB2BModePushInitial) { - $this->logging->addDebug(__METHOD__ . '|10|'); - $invoice = $this->order->prepareInvoice()->register(); - $invoice->setOrder($this->order); - $this->order->addRelatedObject($invoice); - $payment->setCreatedInvoice($invoice); - $payment->setShouldCloseParentTransaction(true); - } else { - $this->logging->addDebug(__METHOD__ . '|15|'); - //Fix for suspected fraud when the order currency does not match with the payment's currency - $amount = ($payment->isSameCurrency() - && $payment->isCaptureFinal($this->order->getGrandTotal())) ? - $this->order->getGrandTotal() : $this->order->getBaseTotalDue(); - $payment->registerCaptureNotification($amount); - $payment->save(); - } - - $this->logging->addDebug(__METHOD__ . '|20|'); - - $transactionKey = $this->getTransactionKey(); - - if (strlen($transactionKey) <= 0) { - return true; + // Check Push Dublicates + if ($this->receivePushCheckDuplicates()) { + throw new BuckarooException(__('Skipped handling this push, duplicate')); } - $this->logging->addDebug(__METHOD__ . '|25|'); - - /** @var \Magento\Sales\Model\Order\Invoice $invoice */ - foreach ($this->order->getInvoiceCollection() as $invoice) { - $invoice->setTransactionId($transactionKey)->save(); - - if (!empty($this->pushRequst->getInvoiceNumber()) - && $this->groupTransaction->isGroupTransaction($this->pushRequst->getInvoiceNumber())) { - $this->logging->addDebug(__METHOD__ . '|27|'); - $invoice->setState(2); - } - - if (!$invoice->getEmailSent() && $this->configAccount->getInvoiceEmail($this->order->getStore())) { - $this->logging->addDebug(__METHOD__ . '|30|sendinvoiceemail'); - $this->invoiceSender->send($invoice, true); - } + // Check if the order can be updated + if (!$this->canUpdateOrderStatus()) { + $this->logging->addDebug('Order can not receive updates'); + $this->orderRequestService->setOrderNotificationNote(__('The order has already been processed.')); + throw new BuckarooException( + __('Signature from push is correct but the order can not receive updates') + ); } - $this->logging->addDebug(__METHOD__ . '|35|'); - - $this->order->setIsInProcess(true); - $this->order->save(); - - $this->dontSaveOrderUponSuccessPush = true; + $this->setTransactionKey(); - return true; - } - /** - * Load the order from the Push Data based on the Order Increment ID or transaction key. - * - * @return void - * @throws \Exception - */ - protected function loadOrder(): void - { - $brqOrderId = $this->getOrderIncrementId(); - - $this->order->loadByIncrementId((string)$brqOrderId); - - if (!$this->order->getId()) { - $this->logging->addDebug('Order could not be loaded by Invoice Number or Order Number'); - // Try to get order by transaction id on payment. - $this->order = $this->getOrderByTransactionKey(); - } + $this->setOrderStatusMessage(); } /** @@ -255,27 +140,6 @@ protected function getOrderIncrementId(): ?string return $brqOrderId; } - /** - * Sometimes the push does not contain the order id, when that's the case try to get the order by his payment, - * by using its own transaction key. - * - * @return OrderPayment - * @throws \Exception - */ - protected function getOrderByTransactionKey(): OrderPayment - { - $trxId = $this->getTransactionKey(); - - $this->transaction->load($trxId, 'txn_id'); - $order = $this->transaction->getOrder(); - - if (!$order) { - throw new \Exception(__('There was no order found by transaction Id')); - } - - return $order; - } - /** * Retrieves the transaction key from the push request. * @@ -300,6 +164,22 @@ protected function getTransactionKey(): string return $trxId; } + /** + * Sets the transaction key in the payment's additional information if it's not already set. + * + * @return void + */ + protected function setTransactionKey() + { + $payment = $this->order->getPayment(); + $originalKey = BuckarooAdapter::BUCKAROO_ORIGINAL_TRANSACTION_KEY_KEY; + $transactionKey = $this->getTransactionKey(); + + if (!$payment->getAdditionalInformation($originalKey) && strlen($transactionKey) > 0) { + $payment->setAdditionalInformation($originalKey, $transactionKey); + } + } + /** * Determine if the lock push processing criteria are met. * @@ -310,7 +190,6 @@ protected function lockPushProcessingCriteria(): bool return false; } - /** * Skip the push if the conditions are met. * @@ -319,10 +198,6 @@ protected function lockPushProcessingCriteria(): bool */ protected function skipPush() { - if ($this->skipPendingRefundPush()) { - return true; - } - if ($this->skipKlarnaCapture()) { return true; } @@ -332,6 +207,12 @@ protected function skipPush() return true; } + if ($this->skipFirstPush()) { + throw new BuckarooException( + __('Skipped handling this push, first handle response, action will be taken on the next push.') + ); + } + return false; } @@ -359,38 +240,37 @@ private function skipSpecificTypesOfRequsts(): bool } /** - * Skip Pending Refund Push - * * @return bool - * @throws \Exception */ - protected function skipPendingRefundPush(): bool + protected function skipKlarnaCapture(): bool { if ($this->pushRequest->hasAdditionalInformation('initiated_by_magento', 1) - && $this->pushRequest->hasAdditionalInformation('service_action_from_magento', ['refund']) + && $this->pushRequest->hasPostData('transaction_method', ['klarnakp', 'KlarnaKp']) + && $this->pushRequest->hasAdditionalInformation('service_action_from_magento', 'pay') + && !empty($this->pushRequest->getServiceKlarnakpCaptureid()) ) { - if ($this->pushRequest->hasPostData('statuscode', BuckarooStatusCode::SUCCESS) - && !empty($this->pushRequest->getRelatedtransactionRefund()) - && $this->receivePushCheckDuplicates( - BuckarooStatusCode::PENDING_APPROVAL, - $this->pushRequest->getRelatedtransactionRefund() - )) { - $this->logging->addDebug(__METHOD__ . '|4|'); - return false; - } - $this->logging->addDebug(__METHOD__ . '|5|'); return true; } return false; } - protected function skipKlarnaCapture() { - if ($this->pushRequest->hasAdditionalInformation('initiated_by_magento', 1) - && $this->pushRequest->hasPostData('transaction_method', ['klarnakp', 'KlarnaKp']) - && $this->pushRequest->hasAdditionalInformation('service_action_from_magento', 'pay') - && !empty($this->pushRequest->getServiceKlarnakpCaptureid()) - ) { + /** + * Buckaroo Push is send before Response, for correct flow we skip the first push + * for some payment methods + * + * @return bool + * @throws LocalizedException + */ + protected function skipFirstPush(): bool + { + $skipFirstPush = $this->payment->getAdditionalInformation('skip_push'); + $this->logging->addDebug(__METHOD__ . '|1_20|' . var_export($skipFirstPush, true)); + + + if ($skipFirstPush > 0) { + $this->payment->setAdditionalInformation('skip_push', (int)$skipFirstPush - 1); + $this->payment->save(); return true; } @@ -408,10 +288,8 @@ protected function skipKlarnaCapture() { * @SuppressWarnings(PHPMD.CyclomaticComplexity) * @SuppressWarnings(PHPMD.NPathComplexity) */ - private function receivePushCheckDuplicates(int $receivedStatusCode = null, string $trxId = null): bool + protected function receivePushCheckDuplicates(int $receivedStatusCode = null, string $trxId = null): bool { - $this->logging->addDebug(__METHOD__ . '|1|' . var_export($this->order->getPayment()->getMethod(), true)); - $save = false; if (!$receivedStatusCode) { $save = true; @@ -420,26 +298,27 @@ private function receivePushCheckDuplicates(int $receivedStatusCode = null, stri } $receivedStatusCode = $this->pushRequest->getStatusCode(); } + if (!$trxId) { if (empty($this->pushRequest->getTransactions())) { return false; } $trxId = $this->pushRequest->getTransactions(); } - $payment = $this->order->getPayment(); + $ignoredPaymentMethods = [ Giftcards::CODE, Transfer::CODE ]; - if ($payment - && $payment->getMethod() + if ($this->payment + && $this->payment->getMethod() && $receivedStatusCode - && ($this->getTransactionType() == self::BUCK_PUSH_TYPE_TRANSACTION) - && (!in_array($payment->getMethod(), $ignoredPaymentMethods)) + && ($this->pushTransactionType->getPushType() == PushTransactionType::BUCK_PUSH_TYPE_TRANSACTION) + && (!in_array($this->payment->getMethod(), $ignoredPaymentMethods)) ) { $this->logging->addDebug(__METHOD__ . '|5|'); - $receivedTrxStatuses = $payment->getAdditionalInformation( + $receivedTrxStatuses = $this->payment->getAdditionalInformation( self::BUCKAROO_RECEIVED_TRANSACTIONS_STATUSES ); $this->logging->addDebug(__METHOD__ . '|10|' . @@ -451,10 +330,9 @@ private function receivePushCheckDuplicates(int $receivedStatusCode = null, stri && ($receivedTrxStatuses[$trxId] == $receivedStatusCode) ) { $orderStatus = $this->helper->getOrderStatusByState($this->order, Order::STATE_NEW); - $statusCode = $this->helper->getStatusCode('BUCKAROO_MAGENTO2_STATUSCODE_SUCCESS'); if (($this->order->getState() == Order::STATE_NEW) && ($this->order->getStatus() == $orderStatus) - && ($receivedStatusCode == $statusCode) + && ($receivedStatusCode == BuckarooStatusCode::SUCCESS) ) { //allow duplicated pushes for 190 statuses in case if order stills to be new/pending $this->logging->addDebug(__METHOD__ . '|13|'); @@ -467,7 +345,7 @@ private function receivePushCheckDuplicates(int $receivedStatusCode = null, stri if ($save) { $this->logging->addDebug(__METHOD__ . '|17|'); $this->setReceivedTransactionStatuses(); - $payment->save(); + $this->payment->save(); } } $this->logging->addDebug(__METHOD__ . '|20|'); @@ -476,85 +354,101 @@ private function receivePushCheckDuplicates(int $receivedStatusCode = null, stri } /** - * Determine the transaction type based on push request data and the saved invoice key. + * It updates the BUCKAROO_RECEIVED_TRANSACTIONS_STATUSES payment additional information + * with the current received tx status. * - * @return bool|string - * - * @SuppressWarnings(PHPMD.CyclomaticComplexity) + * @return void + * @throws LocalizedException */ - public function getTransactionType() + protected function setReceivedTransactionStatuses(): void { - //If an order has an invoice key, then it should only be processed by invoice pushes - $savedInvoiceKey = (string)$this->order->getPayment()->getAdditionalInformation('buckaroo_cm3_invoice_key'); + $txId = $this->pushRequest->getTransactions(); + $statusCode = $this->pushRequest->getStatusCode(); - if (!empty($this->pushRequest->getInvoicekey()) - && !empty($this->pushRequest->getSchemekey()) - && strlen($savedInvoiceKey) > 0 - ) { - return self::BUCK_PUSH_TYPE_INVOICE; + if (empty($txId) || empty($statusCode)) { + return; } - if (!empty($this->pushRequest->getInvoicekey()) - && !empty($this->pushRequest->getSchemekey()) - && strlen($savedInvoiceKey) == 0 - ) { - return self::BUCK_PUSH_TYPE_INVOICE_INCOMPLETE; - } + $receivedTxStatuses = $this->payment->getAdditionalInformation( + self::BUCKAROO_RECEIVED_TRANSACTIONS_STATUSES) ?? []; + $receivedTxStatuses[$txId] = $statusCode; - if (!empty($this->pushRequest->getDatarequest())) { - return self::BUCK_PUSH_TYPE_DATAREQUEST; - } - - if (empty($this->pushRequest->getInvoicekey()) - && empty($this->pushRequest->getServiceCreditmanagement3Invoicekey()) - && empty($this->pushRequest->getDatarequest()) - && strlen($savedInvoiceKey) <= 0 - ) { - return self::BUCK_PUSH_TYPE_TRANSACTION; - } - - return false; + $this->payment->setAdditionalInformation(self::BUCKAROO_RECEIVED_TRANSACTIONS_STATUSES, $receivedTxStatuses); } /** - * Retrieve the status code from the push request based on the transaction type. + * Checks if the order can be updated by checking its state and status. * - * @return int|string + * @return bool * * @SuppressWarnings(PHPMD.CyclomaticComplexity) */ - private function getStatusCode() + protected function canUpdateOrderStatus(): bool { - $transactionType = $this->getTransactionType(); - $statusCode = 0; - switch ($transactionType) { - case self::BUCK_PUSH_TYPE_TRANSACTION: - case self::BUCK_PUSH_TYPE_DATAREQUEST: - if ($this->pushRequest->getStatusCode() !== null) { - $statusCode = $this->pushRequest->getStatusCode(); - } - break; - case self::BUCK_PUSH_TYPE_INVOICE: - case self::BUCK_PUSH_TYPE_INVOICE_INCOMPLETE: - if (!empty($this->pushRequest->getEventparametersStatuscode())) { - $statusCode = $this->pushRequest->getEventparametersStatuscode(); - } + /** + * Types of statusses + */ + $completedStateAndStatus = [Order::STATE_COMPLETE, Order::STATE_COMPLETE]; + $cancelledStateAndStatus = [Order::STATE_CANCELED, Order::STATE_CANCELED]; + $holdedStateAndStatus = [Order::STATE_HOLDED, Order::STATE_HOLDED]; + $closedStateAndStatus = [Order::STATE_CLOSED, Order::STATE_CLOSED]; + /** + * Get current state and status of order + */ + $currentStateAndStatus = [$this->order->getState(), $this->order->getStatus()]; + $this->logging->addDebug(__METHOD__ . '|1|' . var_export($currentStateAndStatus, true)); - if (!empty($this->pushRequest->getEventparametersTransactionstatuscode())) { - $statusCode = $this->pushRequest->getEventparametersTransactionstatuscode(); - } - break; + /** + * If the types are not the same and the order can receive an invoice the order can be udpated by BPE. + */ + if ($completedStateAndStatus != $currentStateAndStatus + && $cancelledStateAndStatus != $currentStateAndStatus + && $holdedStateAndStatus != $currentStateAndStatus + && $closedStateAndStatus != $currentStateAndStatus + ) { + return true; } - $statusCodeSuccess = $this->helper->getStatusCode('BUCKAROO_MAGENTO2_STATUSCODE_SUCCESS'); - if ($this->pushRequest->getStatusCode() !== null - && ($this->pushRequest->getStatusCode() == $statusCodeSuccess) - && !$statusCode + if (($this->order->getState() === Order::STATE_CANCELED) + && ($this->order->getStatus() === Order::STATE_CANCELED) + && ($this->pushTransactionType->getStatusKey() === 'BUCKAROO_MAGENTO2_STATUSCODE_SUCCESS') + && $this->pushRequest->getRelatedtransactionPartialpayment() == null ) { - $statusCode = $statusCodeSuccess; + $this->logging->addDebug(__METHOD__ . '|2|'); + + $this->order->setState(Order::STATE_NEW); + $this->order->setStatus('pending'); + + foreach ($this->order->getAllItems() as $item) { + $item->setQtyCanceled(0); + } + + $this->forceInvoice = true; + return true; } - return $statusCode; + return false; + } + + /** + * @return void + */ + protected function setOrderStatusMessage(): void + { + if (!empty($this->pushRequest->getStatusmessage())) { + if ($this->order->getState() === Order::STATE_NEW + && empty($this->pushRequest->getRelatedtransactionPartialpayment()) + && $this->pushRequest->hasPostData('statuscode', BuckarooStatusCode::SUCCESS) + ) { + $this->order->setState(Order::STATE_PROCESSING); + $this->order->addStatusHistoryComment( + $this->pushRequest->getStatusmessage(), + $this->helper->getOrderStatusByState($this->order, Order::STATE_PROCESSING) + ); + } else { + $this->order->addStatusHistoryComment($this->pushRequest->getStatusmessage()); + } + } } public function processSucceededPush(PushRequestInterface $pushRequest): bool diff --git a/Model/Push/PushProcessorsFactory.php b/Model/Push/PushProcessorsFactory.php index 2a0808bdc..5fc8e1421 100644 --- a/Model/Push/PushProcessorsFactory.php +++ b/Model/Push/PushProcessorsFactory.php @@ -60,34 +60,53 @@ public function get(?PushTransactionType $pushTransactionType): ?PushProcessorIn throw new \LogicException('Push processors is not set.'); } - $pushProcessorClass = $this->pushProcessors['default']; - - $paymentMethod = $pushTransactionType->getPaymentMethod(); - $pushProcessorClass = $this->pushProcessors[$paymentMethod] ?? $pushProcessorClass; - + $pushProcessorClass = $this->getPushProcessorClass($pushTransactionType); if (empty($pushProcessorClass)) { - throw new BuckarooException( - new Phrase('Unknown ConfigProvider type requested: %1.', [$paymentMethod]) - ); + throw new BuckarooException(new Phrase('Unknown Push Processor type')); } - if ($pushTransactionType->isGroupTransaction()) { - $pushProcessorClass = $this->pushProcessors['group_transaction']; - } + $this->pushProcessor = $this->objectManager->get($pushProcessorClass); - $transactionType = $pushTransactionType->getTransactionType(); + } + return $this->pushProcessor; + } - if ($transactionType == PushTransactionType::BUCK_PUSH_TYPE_INVOICE) { - $pushProcessorClass = $this->pushProcessors['credit_managment']; - } elseif ($transactionType == PushTransactionType::BUCK_PUSH_TYPE_INVOICE_INCOMPLETE) { - throw new BuckarooException( - __('Skipped handling this invoice push because it is too soon.') - ); - } + /** + * @param PushTransactionType|null $pushTransactionType + * @return mixed + * @throws BuckarooException + */ + private function getPushProcessorClass(?PushTransactionType $pushTransactionType) + { + // Set Default Push Processor + $pushProcessorClass = $this->pushProcessors['default']; - $this->pushProcessor = $this->objectManager->get($pushProcessorClass); + // Set Push Processor by Payment Method + $paymentMethod = $pushTransactionType->getPaymentMethod(); + $pushProcessorClass = $this->pushProcessors[$paymentMethod] ?? $pushProcessorClass; + // Check if is Group Transaction Push + if ($pushTransactionType->isGroupTransaction()) { + $pushProcessorClass = $this->pushProcessors['group_transaction']; } - return $this->pushProcessor; + + // Check if is Credit Management Push + $pushType = $pushTransactionType->getPushType(); + if ($pushType == PushTransactionType::BUCK_PUSH_TYPE_INVOICE) { + $pushProcessorClass = $this->pushProcessors['credit_managment']; + } elseif ($pushType == PushTransactionType::BUCK_PUSH_TYPE_INVOICE_INCOMPLETE) { + throw new BuckarooException( + __('Skipped handling this invoice push because it is too soon.') + ); + } + + // Check if is Refund or Cancel Authorize Push + if ($pushTransactionType->getServiceAction() == 'refund') { + $pushProcessorClass = $this->pushProcessors['refund']; + } elseif ($pushTransactionType->getServiceAction() == 'cancel_authorize') { + $pushProcessorClass = $this->pushProcessors['cancel_authorize']; + } + + return $pushProcessorClass; } } \ No newline at end of file diff --git a/Model/Push/PushTransactionType.php b/Model/Push/PushTransactionType.php index 6b6d4916f..e5ecde0c2 100644 --- a/Model/Push/PushTransactionType.php +++ b/Model/Push/PushTransactionType.php @@ -31,7 +31,7 @@ class PushTransactionType public const BUCK_PUSH_CANCEL_AUTHORIZE_TYPE = 'I014'; public const BUCK_PUSH_ACCEPT_AUTHORIZE_TYPE = 'I013'; public const BUCK_PUSH_GROUPTRANSACTION_TYPE = 'I150'; - public const BUCK_PUSH_IDEAL_PAY = 'C021'; + public const BUCK_PUSH_IDEAL_PAY = 'C021'; public const BUCK_PUSH_TYPE_TRANSACTION = 'transaction_push'; public const BUCK_PUSH_TYPE_INVOICE = 'invoice_push'; @@ -43,6 +43,11 @@ class PushTransactionType */ private ?string $paymentMethod; + /** + * @var string|null + */ + private ?string $magentoServiceAction; + /** * @var string */ @@ -103,6 +108,11 @@ class PushTransactionType */ private BuckarooStatusCode $buckarooStatusCode; + /** + * @var PushRequestInterface|null + */ + private ?PushRequestInterface $pushRequest; + /** * @param BuckarooStatusCode $buckarooStatusCode */ @@ -119,15 +129,19 @@ public function __construct(BuckarooStatusCode $buckarooStatusCode) public function getPushTransactionType(?PushRequestInterface $pushRequest, ?Order $order): PushTransactionType { if (!$this->isSet) { - $this->paymentMethod = $pushRequest->getTransactionMethod() ?? ''; - $this->pushType = $this->getPushTypeByInvoiceKey($pushRequest, $order); - $this->statusCode = $this->getStatusCodeByTransactionType($this->pushType, $pushRequest); + $this->pushRequest = $pushRequest; + $this->order = $order; + + $this->paymentMethod = $this->pushRequest->getTransactionMethod() ?? ''; + $this->pushType = $this->getPushTypeByInvoiceKey(); + $this->statusCode = $this->getStatusCodeByTransactionType($this->pushType); $this->statusMessage = $this->buckarooStatusCode->getResponseMessage($this->statusCode); $this->statusKey = $this->buckarooStatusCode->getStatusKey($this->statusCode); - $this->transactionType = $pushRequest->getTransactionType(); + $this->transactionType = $this->pushRequest->getTransactionType(); $this->groupTransaction = $this->transactionType === self::BUCK_PUSH_GROUPTRANSACTION_TYPE; $this->creditManagement = $this->pushType === self::BUCK_PUSH_TYPE_INVOICE; - $this->serviceAction = $pushRequest->getAdditionalInformation('service_action_from_magento'); + $this->magentoServiceAction = $this->pushRequest->getAdditionalInformation('service_action_from_magento'); + $this->serviceAction = $this->getServiceAction($pushRequest, $order); $this->isSet = true; } @@ -144,32 +158,32 @@ public function getPushTransactionType(?PushRequestInterface $pushRequest, ?Orde * * @SuppressWarnings(PHPMD.CyclomaticComplexity) */ - public function getPushTypeByInvoiceKey(PushRequestInterface $pushRequest, Order $order): string + public function getPushTypeByInvoiceKey(): string { //If an order has an invoice key, then it should only be processed by invoice pushes - $savedInvoiceKey = (string)$order->getPayment()->getAdditionalInformation('buckaroo_cm3_invoice_key'); + $savedInvoiceKey = (string)$this->order->getPayment()->getAdditionalInformation('buckaroo_cm3_invoice_key'); - if (!empty($pushRequest->getInvoicekey()) - && !empty($pushRequest->getSchemekey()) + if (!empty($this->pushRequest->getInvoicekey()) + && !empty($this->pushRequest->getSchemekey()) && strlen($savedInvoiceKey) > 0 ) { return self::BUCK_PUSH_TYPE_INVOICE; } - if (!empty($pushRequest->getInvoicekey()) - && !empty($pushRequest->getSchemekey()) + if (!empty($this->pushRequest->getInvoicekey()) + && !empty($this->pushRequest->getSchemekey()) && strlen($savedInvoiceKey) == 0 ) { return self::BUCK_PUSH_TYPE_INVOICE_INCOMPLETE; } - if (!empty($pushRequest->getDatarequest())) { + if (!empty($this->pushRequest->getDatarequest())) { return self::BUCK_PUSH_TYPE_DATAREQUEST; } - if (empty($pushRequest->getInvoicekey()) - && empty($pushRequest->getServiceCreditmanagement3Invoicekey()) - && empty($pushRequest->getDatarequest()) + if (empty($this->pushRequest->getInvoicekey()) + && empty($this->pushRequest->getServiceCreditmanagement3Invoicekey()) + && empty($this->pushRequest->getDatarequest()) && strlen($savedInvoiceKey) <= 0 ) { return self::BUCK_PUSH_TYPE_TRANSACTION; @@ -182,31 +196,28 @@ public function getPushTypeByInvoiceKey(PushRequestInterface $pushRequest, Order * Retrieve the status code from the push request based on the transaction type. * * @param string $transactionType - * @param PushRequestInterface $pushRequest * @return int * * @SuppressWarnings(PHPMD.CyclomaticComplexity) */ - private function getStatusCodeByTransactionType( - string $transactionType, - PushRequestInterface $pushRequest - ): int { + private function getStatusCodeByTransactionType(string $transactionType): int + { $statusCode = 0; switch ($transactionType) { case self::BUCK_PUSH_TYPE_TRANSACTION: case self::BUCK_PUSH_TYPE_DATAREQUEST: - if ($pushRequest->getStatusCode() !== null) { - $statusCode = $pushRequest->getStatusCode(); + if ($this->pushRequest->getStatusCode() !== null) { + $statusCode = $this->pushRequest->getStatusCode(); } break; case self::BUCK_PUSH_TYPE_INVOICE: case self::BUCK_PUSH_TYPE_INVOICE_INCOMPLETE: - if (!empty($pushRequest->getEventparametersStatuscode())) { - $statusCode = $pushRequest->getEventparametersStatuscode(); + if (!empty($this->pushRequest->getEventparametersStatuscode())) { + $statusCode = $this->pushRequest->getEventparametersStatuscode(); } - if (!empty($pushRequest->getEventparametersTransactionstatuscode())) { - $statusCode = $pushRequest->getEventparametersTransactionstatuscode(); + if (!empty($this->pushRequest->getEventparametersTransactionstatuscode())) { + $statusCode = $this->pushRequest->getEventparametersTransactionstatuscode(); } break; default: @@ -214,8 +225,8 @@ private function getStatusCodeByTransactionType( } $statusCodeSuccess = BuckarooStatusCode::SUCCESS; - if ($pushRequest->getStatusCode() !== null - && ($pushRequest->getStatusCode() == $statusCodeSuccess) + if ($this->pushRequest->getStatusCode() !== null + && ($this->pushRequest->getStatusCode() == $statusCodeSuccess) && !$statusCode ) { $statusCode = $statusCodeSuccess; @@ -240,6 +251,22 @@ public function setStatusCode(int $statusCode): void $this->statusCode = $statusCode; } + /** + * @return string + */ + public function getStatusKey(): string + { + return $this->statusKey; + } + + /** + * @param string $statusKey + */ + public function setStatusKey(string $statusKey): void + { + $this->statusKey = $statusKey; + } + /** * @return string */ @@ -256,6 +283,35 @@ public function setTransactionType(string $transactionType): void $this->transactionType = $transactionType; } + /** + * @return string + */ + public function getServiceAction(): string + { + $this->serviceAction = $this->magentoServiceAction; + + if (!empty($this->pushRequest->getAmountCredit())) { + if ($this->getStatusKey() !== 'BUCKAROO_MAGENTO2_STATUSCODE_SUCCESS' + && $this->order->isCanceled() + && $this->getTransactionType() == self::BUCK_PUSH_CANCEL_AUTHORIZE_TYPE + ) { + $this->serviceAction = 'cancel_authorize'; + } else { + $this->serviceAction = 'refund'; + } + } + + return $this->serviceAction; + } + + /** + * @param string $serviceAction + */ + public function setServiceAction(string $serviceAction): void + { + $this->serviceAction = $serviceAction; + } + /** * @return string */ @@ -291,17 +347,17 @@ public function setPaymentMethod(string $paymentMethod): void /** * @return string */ - public function getServiceAction(): string + public function getMagentoServiceAction(): string { - return $this->serviceAction; + return $this->magentoServiceAction; } /** - * @param string $serviceAction + * @param string $magentoServiceAction */ - public function setServiceAction(string $serviceAction): void + public function setMagentoServiceAction(string $magentoServiceAction): void { - $this->serviceAction = $serviceAction; + $this->magentoServiceAction = $magentoServiceAction; } /** diff --git a/Model/Push/RefundProcessor.php b/Model/Push/RefundProcessor.php new file mode 100644 index 000000000..e5bee73d7 --- /dev/null +++ b/Model/Push/RefundProcessor.php @@ -0,0 +1,96 @@ +refundPush = $refundPush; + + } + + /** + * @throws BuckarooException + * @throws \Exception + */ + public function processPush(PushRequestInterface $pushRequest): bool + { + $order = $this->orderRequestService->getOrderByRequest($pushRequest); + + if ($this->skipPendingRefundPush($pushRequest)) { + return true; + } + + if ($this->pushTransactionType->getStatusKey() !== 'BUCKAROO_MAGENTO2_STATUSCODE_SUCCESS' + && !$order->hasInvoices() + ) { + throw new BuckarooException( + __('Refund failed ! Status : %1 and the order does not contain an invoice', + $this->pushTransactionType->getStatusKey()) + ); + } elseif ($this->pushTransactionType->getStatusKey() !== 'BUCKAROO_MAGENTO2_STATUSCODE_SUCCESS' + && $order->hasInvoices() + ) { + //don't proceed failed refund push + $this->logging->addDebug(__METHOD__ . '|10|'); + $this->orderRequestService->setOrderNotificationNote( + __('Push notification for refund has no success status, ignoring.') + ); + return true; + } + + return $this->refundPush->receiveRefundPush($pushRequest, true, $order); + } + + /** + * Skip Pending Refund Push + * + * @param PushRequestInterface $pushRequest + * @return bool + */ + private function skipPendingRefundPush(PushRequestInterface $pushRequest): bool + { + if ($pushRequest->hasAdditionalInformation('initiated_by_magento', 1) + && $pushRequest->hasAdditionalInformation('service_action_from_magento', ['refund']) + ) { + if ($pushRequest->hasPostData('statuscode', BuckarooStatusCode::SUCCESS) + && !empty($pushRequest->getRelatedtransactionRefund()) + && $this->receivePushCheckDuplicates( + BuckarooStatusCode::PENDING_APPROVAL, + $pushRequest->getRelatedtransactionRefund() + )) { + $this->logging->addDebug(__METHOD__ . '|4|'); + return false; + } + $this->logging->addDebug(__METHOD__ . '|5|'); + return true; + } + + return false; + } +} \ No newline at end of file diff --git a/Model/RequestPush/AbstractPushRequest.php b/Model/RequestPush/AbstractPushRequest.php index 9a34e0b88..72484ac04 100644 --- a/Model/RequestPush/AbstractPushRequest.php +++ b/Model/RequestPush/AbstractPushRequest.php @@ -84,16 +84,15 @@ public function __call(string $methodName, array $args) */ public function hasAdditionalInformation(string $name, $value): bool { - $fieldValue = $this->getAdditionalInformation($name); /** @phpstan-ignore-line */ - if (is_array($value) && - isset($fieldValue) && - in_array($fieldValue, $value) + $fieldValue = $this->getAdditionalInformation($name); + /** @phpstan-ignore-line */ + if (is_array($value) + && isset($fieldValue) + && in_array($fieldValue, $value) ) { return true; - } - - if (isset($fieldValue) && - $fieldValue == $value + } elseif (isset($fieldValue) + && $fieldValue == $value ) { return true; } diff --git a/Model/RequestPush/HttppostPushRequest.php b/Model/RequestPush/HttppostPushRequest.php index 90f3dcbe8..f17c48d88 100644 --- a/Model/RequestPush/HttppostPushRequest.php +++ b/Model/RequestPush/HttppostPushRequest.php @@ -35,6 +35,7 @@ * @method getEventparametersTransactionstatuscode() * @method getIspaid() * @method getInvoicestatuscode() + * @method getRelatedtransactionPartialpayment() */ class HttppostPushRequest extends AbstractPushRequest implements PushRequestInterface { diff --git a/Model/RequestPush/JsonPushRequest.php b/Model/RequestPush/JsonPushRequest.php index 1cce2cec0..4f0851f37 100644 --- a/Model/RequestPush/JsonPushRequest.php +++ b/Model/RequestPush/JsonPushRequest.php @@ -36,6 +36,7 @@ * @method getEventparametersTransactionstatuscode() * @method getIspaid() * @method getInvoicestatuscode() + * @method getRelatedtransactionPartialpayment() */ class JsonPushRequest extends AbstractPushRequest implements PushRequestInterface { diff --git a/Service/Push/OrderRequestService.php b/Service/Push/OrderRequestService.php index ad39160ed..e3c9e54b1 100644 --- a/Service/Push/OrderRequestService.php +++ b/Service/Push/OrderRequestService.php @@ -4,6 +4,7 @@ use Buckaroo\Magento2\Api\PushRequestInterface; use Buckaroo\Magento2\Logging\Log; +use Magento\Framework\Phrase; use Magento\Sales\Api\Data\TransactionInterface; use Magento\Sales\Model\Order; use Magento\Sales\Model\Order\Payment as OrderPayment; @@ -136,4 +137,20 @@ protected function getTransactionKey($pushRequest): string return $trxId; } + + /** + * Try to add a notification note to the order comments. + * + * @param Phrase|string $message + */ + public function setOrderNotificationNote(Phrase|string $message): void + { + $note = 'Buckaroo attempted to update this order, but failed: ' . $message; + try { + $this->order->addStatusToHistory($note); + $this->order->save(); + } catch (\Exception $e) { + $this->logging->addDebug($e->getLogMessage()); + } + } } \ No newline at end of file diff --git a/etc/di.xml b/etc/di.xml index c76a6f778..6be8d2f47 100644 --- a/etc/di.xml +++ b/etc/di.xml @@ -511,6 +511,9 @@ Buckaroo\Magento2\Model\Push\IdealProcessor Buckaroo\Magento2\Model\Push\CreditManagmentPushProcessor Buckaroo\Magento2\Model\Push\GroupTransactionPushProcessor + Buckaroo\Magento2\Model\Push\RefundProcessor + Buckaroo\Magento2\Model\Push\CancelAuthorizeProcessor + From 24c87dee26034e8fc844d78ce472226d8d51c1d5 Mon Sep 17 00:00:00 2001 From: Lucian Turiac Date: Thu, 13 Jul 2023 18:36:47 +0300 Subject: [PATCH 10/29] BP-2132 - Working on Push Refactor --- Model/BuckarooStatusCode.php | 32 ++ Model/Push.php | 2 +- Model/Push/DefaultProcessor.php | 543 +++++++++++++++++++++++-- Model/Push/IdealProcessor.php | 29 ++ Model/Push/PartialPaymentProcessor.php | 8 + Model/Push/RefundProcessor.php | 10 +- 6 files changed, 595 insertions(+), 29 deletions(-) create mode 100644 Model/Push/PartialPaymentProcessor.php diff --git a/Model/BuckarooStatusCode.php b/Model/BuckarooStatusCode.php index a12c5d1c8..2ab943617 100644 --- a/Model/BuckarooStatusCode.php +++ b/Model/BuckarooStatusCode.php @@ -97,4 +97,36 @@ public function getStatusKey(int $responseCode): string { return array_search($responseCode, $this->statusCodes) ?? 'BUCKAROO_MAGENTO2_STATUSCODE_NEUTRAL'; } + + /** + * Get failed statuses + * + * @return string[] + */ + public function getFailedStatuses(): array + { + return [ + 'BUCKAROO_MAGENTO2_STATUSCODE_TECHNICAL_ERROR', + 'BUCKAROO_MAGENTO2_STATUSCODE_VALIDATION_FAILURE', + 'BUCKAROO_MAGENTO2_STATUSCODE_CANCELLED_BY_MERCHANT', + 'BUCKAROO_MAGENTO2_STATUSCODE_CANCELLED_BY_USER', + 'BUCKAROO_MAGENTO2_STATUSCODE_FAILED', + 'BUCKAROO_MAGENTO2_STATUSCODE_REJECTED' + ]; + } + + /** + * Get pending statuses + * + * @return string[] + */ + public function getPendingStatuses(): array + { + return [ + 'BUCKAROO_MAGENTO2_STATUSCODE_PAYMENT_ON_HOLD', + 'BUCKAROO_MAGENTO2_STATUSCODE_WAITING_ON_CONSUMER', + 'BUCKAROO_MAGENTO2_STATUSCODE_PENDING_PROCESSING', + 'BUCKAROO_MAGENTO2_STATUSCODE_WAITING_ON_USER_INPUT' + ]; + } } \ No newline at end of file diff --git a/Model/Push.php b/Model/Push.php index 79e5be06f..50ffcb7bc 100644 --- a/Model/Push.php +++ b/Model/Push.php @@ -342,7 +342,7 @@ public function receivePush() // Process Push $this->pushProcessor = $this->pushProcessorsFactory->get($pushTransactionType); -// $this->pushProcessor->processPush($this->pushRequst); + $this->pushProcessor->processPush($this->pushRequst); diff --git a/Model/Push/DefaultProcessor.php b/Model/Push/DefaultProcessor.php index 08b332279..61d7da755 100644 --- a/Model/Push/DefaultProcessor.php +++ b/Model/Push/DefaultProcessor.php @@ -1,4 +1,23 @@ pushTransactionType = $pushTransactionType; $this->orderRequestService = $orderRequestService; $this->logging = $logging; - $this->transaction = $transaction; $this->helper = $helper; - $this->pushTransactionType = $pushTransactionType; + $this->transaction = $transaction; + $this->groupTransaction = $groupTransaction; + $this->buckarooStatusCode = $buckarooStatusCode; + $this->orderStatusFactory = $orderStatusFactory; } /** @@ -118,10 +161,35 @@ public function processPush(PushRequestInterface $pushRequest): bool $this->setTransactionKey(); $this->setOrderStatusMessage(); + + if ((!in_array($this->payment->getMethod(), [Giftcards::CODE, Voucher::CODE])) + && $this->isGroupTransactionPart()) { + $this->savePartGroupTransaction(); + return true; + } + + + if (!$this->canProcessPostData()) { + return true; + } + + if ($this->giftcardPartialPayment()) { + return true; + } + + $this->processPushByStatus(); + + $this->logging->addDebug(__METHOD__ . '|5|'); + if (!$this->dontSaveOrderUponSuccessPush) { + $this->logging->addDebug(__METHOD__ . '|5-1|'); + $this->order->save(); + } + + return true; } /** - * Get the order increment ID based on the invoice number or order number. + * Get the order increment ID based on the invoice number or order number from push * * @return string|null */ @@ -203,7 +271,7 @@ protected function skipPush() } // Skip Push based on specific condition - if (!$this->skipSpecificTypesOfRequsts()) { + if ($this->skipSpecificTypesOfRequsts()) { return true; } @@ -451,18 +519,443 @@ protected function setOrderStatusMessage(): void } } - public function processSucceededPush(PushRequestInterface $pushRequest): bool + /** + * Process the push according the response status + * + * @return bool + * @throws BuckarooException + * @throws LocalizedException + * + * @SuppressWarnings(PHPMD.CyclomaticComplexity) + */ + public function processPushByStatus() + { + $newStatus = $this->orderStatusFactory->get($this->pushRequest->getStatusCode(), $this->order); + $this->logging->addDebug(__METHOD__ . '|5|' . var_export($newStatus, true)); + + $statusKey = $this->pushTransactionType->getStatusKey(); + $statusMessage = $this->pushTransactionType->getStatusMessage(); + + if ($statusKey == 'BUCKAROO_MAGENTO2_STATUSCODE_SUCCESS') { + return $this->processSucceededPush($newStatus, $statusMessage); + } elseif (in_array($statusKey, $this->buckarooStatusCode->getFailedStatuses())) { + return $this->processFailedPush($newStatus, $statusMessage); + } elseif (in_array($statusKey, $this->buckarooStatusCode->getPendingStatuses())) { + return $this->processPendingPaymentPush(); + } else { + return $this->orderRequestService->setOrderNotificationNote($statusMessage); + } + } + + /** + * + * @return true + */ + protected function canProcessPostData() { + return true; + } + + /** + * Process the successful push response from Buckaroo and update the order accordingly. + * + * @param string $newStatus + * @param string $message + * @return bool + * @throws LocalizedException + * + * @SuppressWarnings(PHPMD.CyclomaticComplexity) + * @SuppressWarnings(PHPMD.NPathComplexity) + * @SuppressWarnings(PHPMD.ExcessiveMethodLength) + */ + public function processSucceededPush(string $newStatus, string $message): bool + { + $this->logging->addDebug(__METHOD__ . '|1|' . var_export($newStatus, true)); + + $amount = $this->order->getTotalDue(); + + if (!empty($this->pushRequest->getAmount())) { + $this->logging->addDebug(__METHOD__ . '|11|'); + $amount = floatval($this->pushRequest->getAmount()); + } + + if (!empty($this->pushRequest->getServiceKlarnaReservationnumber())) { + $this->order->setBuckarooReservationNumber($this->pushRequest->getServiceKlarnaReservationnumber()); + $this->order->save(); + } + + if (!empty($this->pushRequest->getServiceKlarnakpReservationnumber())) { + $this->order->setBuckarooReservationNumber($this->pushRequest->getServiceKlarnakpReservationnumber()); + $this->order->save(); + } + + $store = $this->order->getStore(); + $payment = $this->order->getPayment(); + + /** + * @var \Magento\Payment\Model\MethodInterface $paymentMethod + */ + $paymentMethod = $payment->getMethodInstance(); + + if (!$this->order->getEmailSent() + && ($this->configAccount->getOrderConfirmationEmail($store) + || $paymentMethod->getConfigData('order_email', $store) + ) + ) { + $this->logging->addDebug(__METHOD__ . '|sendemail|' . + var_export($this->configAccount->getOrderConfirmationEmailSync($store), true)); + $this->orderSender->send($this->order, $this->configAccount->getOrderConfirmationEmailSync($store)); + } + + /** force state eventhough this can lead to a transition of the order + * like new -> processing + */ + $forceState = false; + $state = Order::STATE_PROCESSING; + + $this->logging->addDebug(__METHOD__ . '|2|'); + + if ($paymentMethod->canPushInvoice($this->pushRequest)) { + $this->logging->addDebug(__METHOD__ . '|3|'); + $description = 'Payment status : ' . $message . "
"; + if ($this->pushRequest->hasPostData('transaction_method', 'transfer')) { + //keep amount fetched from brq_amount + $description .= 'Amount of ' . $this->order->getBaseCurrency()->formatTxt($amount) . ' has been paid'; + } else { + $amount = $this->order->getBaseTotalDue(); + $description .= 'Total amount of ' . + $this->order->getBaseCurrency()->formatTxt($amount) . ' has been paid'; + } + } else { + $description = 'Authorization status : ' . $message . "
"; + $description .= 'Total amount of ' . $this->order->getBaseCurrency()->formatTxt($this->order->getTotalDue()) + . ' has been authorized. Please create an invoice to capture the authorized amount.'; + $forceState = true; + } + + if ($this->isPayPerEmailB2BModePushInitial) { + $description = ''; + } + + $this->dontSaveOrderUponSuccessPush = false; + if ($paymentMethod->canPushInvoice($this->pushRequest)) { + $this->logging->addDebug(__METHOD__ . '|4|'); + + if (!$this->isPayPerEmailB2BModePushInitial && $this->isPayPerEmailB2BModePushPaid()) { + $this->logging->addDebug(__METHOD__ . '|4_1|'); + //Fix for suspected fraud when the order currency does not match with the payment's currency + $amount = ($payment->isSameCurrency() && $payment->isCaptureFinal($this->order->getGrandTotal())) ? + $this->order->getGrandTotal() : $this->order->getBaseTotalDue(); + $payment->registerCaptureNotification($amount); + $payment->save(); + $this->order->setState('complete'); + $this->order->addStatusHistoryComment($description, 'complete'); + $this->order->save(); + + if ($transactionKey = $this->getTransactionKey()) { + foreach ($this->order->getInvoiceCollection() as $invoice) { + $invoice->setTransactionId($transactionKey)->save(); + } + } + return true; + } + + if ($this->pushRequest->hasAdditionalInformation('initiated_by_magento', 1) && + ( + $this->pushRequest->hasPostData('transaction_method', 'KlarnaKp') && + $this->pushRequest->hasAdditionalInformation('service_action_from_magento', 'pay') && + empty($this->pushRequest->getServiceKlarnakpReservationnumber()) && + $this->klarnakpConfig->isInvoiceCreatedAfterShipment() + ) || + ( + $this->pushRequest->hasPostData('transaction_method', 'afterpay') && + $this->pushRequest->hasAdditionalInformation('service_action_from_magento', 'capture') && + $this->afterpayConfig->isInvoiceCreatedAfterShipment() + ) + ) { + $this->logging->addDebug(__METHOD__ . '|5_1|'); + $this->dontSaveOrderUponSuccessPush = true; + return true; + } else { + $this->logging->addDebug(__METHOD__ . '|6|'); + + if ($this->pushRequest->hasPostData('transaction_method', 'transfer')) { + //invoice only in case of full or last remained amount + $this->logging->addDebug(__METHOD__ . '|61|' . var_export([ + $this->order->getId(), + $amount, + $this->order->getTotalDue(), + $this->order->getTotalPaid(), + ], true)); + + $saveInvoice = true; + if (($amount < $this->order->getTotalDue()) + || (($amount == $this->order->getTotalDue()) && ($this->order->getTotalPaid() > 0)) + ) { + $this->logging->addDebug(__METHOD__ . '|64|'); + + $forceState = true; + if ($amount < $this->order->getTotalDue()) { + $this->logging->addDebug(__METHOD__ . '|65|'); + $state = Order::STATE_NEW; + $newStatus = $this->orderStatusFactory->get( + BuckarooStatusCode::PENDING_PROCESSING, + $this->order + ); + $saveInvoice = false; + } + + $this->saveAndReloadOrder(); + + $this->order->setTotalDue($this->order->getTotalDue() - $amount); + $this->order->setBaseTotalDue($this->order->getTotalDue() - $amount); + + $totalPaid = $this->order->getTotalPaid() + $amount; + $this->order->setTotalPaid( + $totalPaid > $this->order->getGrandTotal() ? $this->order->getGrandTotal() : $totalPaid + ); + + $baseTotalPaid = $this->order->getBaseTotalPaid() + $amount; + $this->order->setBaseTotalPaid( + $baseTotalPaid > $this->order->getBaseGrandTotal() ? + $this->order->getBaseGrandTotal() : $baseTotalPaid + ); + + $this->saveAndReloadOrder(); + + $connection = $this->resourceConnection->getConnection(); + $connection->update( + $connection->getTableName('sales_order'), + [ + 'total_due' => $this->order->getTotalDue(), + 'base_total_due' => $this->order->getTotalDue(), + 'total_paid' => $this->order->getTotalPaid(), + 'base_total_paid' => $this->order->getBaseTotalPaid(), + ], + $connection->quoteInto('entity_id = ?', $this->order->getId()) + ); + } + + if ($saveInvoice) { + if (!$this->saveInvoice()) { + return false; + } + } + } else { + if (!$this->saveInvoice()) { + return false; + } + } + } + } + + if (!empty($this->pushRequst->getServiceKlarnaAutopaytransactionkey()) + && ($this->pushRequst->getStatusCode() == 190) + ) { + $this->saveInvoice(); + } + + if (!empty($this->pushRequst->getServiceKlarnakpAutopaytransactionkey()) + && ($this->pushRequst->getStatusCode() == 190) + ) { + $this->saveInvoice(); + } + + if ($this->groupTransaction->isGroupTransaction($this->pushRequst->getInvoiceNumber())) { + $forceState = true; + } + + $this->logging->addDebug(__METHOD__ . '|8|'); + + $this->processSucceededPushAuth($payment); + + $this->updateOrderStatus($state, $newStatus, $description, $forceState); + + $this->logging->addDebug(__METHOD__ . '|9|'); + + return true; + } + + /** + * Process the failed push response from Buckaroo and update the order accordingly. + * + * @param string $newStatus + * @param string $message + * @return bool + * @throws LocalizedException + * + * @SuppressWarnings(PHPMD.CyclomaticComplexity) + */ + public function processFailedPush(string $newStatus, string $message): bool { - // TODO: Implement processSucceededPush() method. + $this->logging->addDebug(__METHOD__ . '|1|' . var_export($newStatus, true)); + + if (($this->order->getState() === Order::STATE_PROCESSING) + && ($this->order->getStatus() === Order::STATE_PROCESSING) + ) { + //do not update to failed if we had a success already + $this->logging->addDebug(__METHOD__ . '|2|'); + return false; + } + + $description = 'Payment status : ' . $message; + + if (!empty($this->pushRequst->getServiceAntifraudAction())) { + $description .= $this->pushRequst->getServiceAntifraudAction() . + ' ' . + $this->pushRequst->getServiceAntifraudCheck() . + ' ' . + $this->pushRequst->getServiceAntifraudDetails(); + } + + $store = $this->order->getStore(); + + $buckarooCancelOnFailed = $this->configAccount->getCancelOnFailed($store); + + $payment = $this->order->getPayment(); + + if ($buckarooCancelOnFailed && $this->order->canCancel()) { + $this->logging->addDebug(__METHOD__ . '|' . 'Buckaroo push failed : ' . $message . ' : Cancel order.'); + + // BUCKM2-78: Never automatically cancelauthorize via push for afterpay + // setting parameter which will cause to stop the cancel process on + // Buckaroo/Model/Method/BuckarooAdapter.php:880 + $methods = [ + 'buckaroo_magento2_afterpay', + 'buckaroo_magento2_afterpay2', + 'buckaroo_magento2_klarna', + 'buckaroo_magento2_klarnakp' + ]; + if (in_array($payment->getMethodInstance()->getCode(), $methods)) { + $payment->setAdditionalInformation('buckaroo_failed_authorize', 1); + $payment->save(); + } + + $this->updateOrderStatus(Order::STATE_CANCELED, $newStatus, $description); + + try { + $this->order->cancel()->save(); + } catch (\Throwable $t) { + $this->logging->addDebug(__METHOD__ . '|3|'); + // SignifydGateway/Gateway error on line 208" + } + return true; + } + + $this->logging->addDebug(__METHOD__ . '|4|'); + $force = false; + if (($payment->getMethodInstance()->getCode() == 'buckaroo_magento2_mrcash') + && ($this->order->getState() === Order::STATE_NEW) + && ($this->order->getStatus() === 'pending') + ) { + $force = true; + } + $this->updateOrderStatus(Order::STATE_CANCELED, $newStatus, $description, $force); + + return true; } - public function processFailedPush(PushRequestInterface $pushRequest): bool + protected function processPendingPaymentPush(): bool { - // TODO: Implement processFailedPush() method. + return true; } - public function processPendingPaymentPush(PushRequestInterface $pushRequest): bool + + /** + * @todo GIFTCARD PARTIAL PAYMENT TO BE MOVED in a separate class + */ + + + /** + * Checks if the push request is a group transaction with a non-success status code. + * + * @return false|mixed + */ + private function isGroupTransactionPart() + { + if (!is_null($this->pushRequest->getTransactions())) { + return $this->groupTransaction->getGroupTransactionByTrxId($this->pushRequest->getTransactions()); + } + return false; + } + + /** + * Save the part group transaction. + * + * @return void + * @throws \Exception + */ + private function savePartGroupTransaction() { - // TODO: Implement processPendingPaymentPush() method. + $items = $this->groupTransaction->getGroupTransactionByTrxId($this->pushRequest->getTransactions()); + if (is_array($items) && count($items) > 0) { + foreach ($items as $item) { + $item2['status'] = $this->pushRequest->getStatusCode(); + $item2['entity_id'] = $item['entity_id']; + $this->groupTransaction->updateGroupTransaction($item2); + } + } + } + + /** + * Checks if the payment is a partial payment using a gift card. + * + * @return bool + */ + private function giftcardPartialPayment(): bool + { + $payment = $this->order->getPayment(); + + if ($payment->getMethod() != Giftcards::CODE + || (!empty($this->pushRequest->getAmount()) + && $this->pushRequest->getAmount() >= $this->order->getGrandTotal()) + || empty($this->pushRequest->getRelatedtransactionPartialpayment()) + ) { + return false; + } + + if ($this->groupTransaction->isGroupTransaction($this->pushRequest->getInvoiceNumber())) { + return false; + } + + if (!$this->pushTransactionType->getTransactionType() == PushTransactionType::BUCK_PUSH_GROUPTRANSACTION_TYPE) { + $payment->setAdditionalInformation( + BuckarooAdapter::BUCKAROO_ORIGINAL_TRANSACTION_KEY_KEY, + $this->pushRequest->getRelatedtransactionPartialpayment() + ); + + $this->addGiftcardPartialPaymentToPaymentInformation(); + } + + return true; + } + + /** + * Adds the gift card partial payment information to the payment's additional information. + * + * @return void + */ + protected function addGiftcardPartialPaymentToPaymentInformation() + { + $payment = $this->order->getPayment(); + + $transactionAmount = $this->pushRequest->getAmount(); + $transactionKey = $this->pushRequest->getTransactions(); + $transactionMethod = $this->pushRequest->getTransactionMethod(); + + $transactionData = $payment->getAdditionalInformation(BuckarooAdapter::BUCKAROO_ALL_TRANSACTIONS); + + $transactionArray = []; + if (is_array($transactionData) && count($transactionData) > 0) { + $transactionArray = $transactionData; + } + + if (!empty($transactionKey) && $transactionAmount > 0) { + $transactionArray[$transactionKey] = [$transactionMethod, $transactionAmount]; + + $payment->setAdditionalInformation( + BuckarooAdapter::BUCKAROO_ALL_TRANSACTIONS, + $transactionArray + ); + } } } \ No newline at end of file diff --git a/Model/Push/IdealProcessor.php b/Model/Push/IdealProcessor.php index 7a07d983f..f40ddaca7 100644 --- a/Model/Push/IdealProcessor.php +++ b/Model/Push/IdealProcessor.php @@ -4,13 +4,42 @@ use Buckaroo\Magento2\Api\PushRequestInterface; use Buckaroo\Magento2\Exception as BuckarooException; +use Buckaroo\Magento2\Helper\Data; +use Buckaroo\Magento2\Helper\PaymentGroupTransaction; +use Buckaroo\Magento2\Logging\Log; use Buckaroo\Magento2\Model\BuckarooStatusCode; +use Buckaroo\Magento2\Model\OrderStatusFactory; +use Buckaroo\Magento2\Service\LockerProcess; +use Buckaroo\Magento2\Service\Push\OrderRequestService; use Magento\Framework\Exception\FileSystemException; +use Magento\Sales\Api\Data\TransactionInterface; class IdealProcessor extends DefaultProcessor { public const BUCK_PUSH_IDEAL_PAY = 'C021'; + /** + * @var LockerProcess + */ + private LockerProcess $lockerProcess; + + public function __construct( + OrderRequestService $orderRequestService, + PushTransactionType $pushTransactionType, + Log $logging, + Data $helper, + TransactionInterface $transaction, + PaymentGroupTransaction $groupTransaction, + BuckarooStatusCode $buckarooStatusCode, + LockerProcess $lockerProcess, + OrderStatusFactory $orderStatusFactory + ) { + parent::__construct($orderRequestService, $pushTransactionType, $logging, $helper, $transaction, + $groupTransaction, $buckarooStatusCode,$orderStatusFactory); + $this->lockerProcess = $lockerProcess; + + } + /** * @throws FileSystemException * @throws BuckarooException diff --git a/Model/Push/PartialPaymentProcessor.php b/Model/Push/PartialPaymentProcessor.php new file mode 100644 index 000000000..66853644d --- /dev/null +++ b/Model/Push/PartialPaymentProcessor.php @@ -0,0 +1,8 @@ +refundPush = $refundPush; } From 977e16c870a10245f4fb23abae158ba9e479961b Mon Sep 17 00:00:00 2001 From: Lucian Turiac Date: Mon, 17 Jul 2023 00:12:19 +0300 Subject: [PATCH 11/29] BP-2132 - Working on Push Refactor --- Model/Push/DefaultProcessor.php | 295 ++++++++++++--------------- Model/Push/IdealProcessor.php | 6 +- Model/Push/RefundProcessor.php | 6 +- Service/Push/OrderRequestService.php | 46 ++++- 4 files changed, 185 insertions(+), 168 deletions(-) diff --git a/Model/Push/DefaultProcessor.php b/Model/Push/DefaultProcessor.php index 61d7da755..8e1eba415 100644 --- a/Model/Push/DefaultProcessor.php +++ b/Model/Push/DefaultProcessor.php @@ -28,6 +28,7 @@ use Buckaroo\Magento2\Helper\PaymentGroupTransaction; use Buckaroo\Magento2\Logging\Log; use Buckaroo\Magento2\Model\BuckarooStatusCode; +use Buckaroo\Magento2\Model\ConfigProvider\Account; use Buckaroo\Magento2\Model\ConfigProvider\Method\Giftcards; use Buckaroo\Magento2\Model\ConfigProvider\Method\Transfer; use Buckaroo\Magento2\Model\ConfigProvider\Method\Voucher; @@ -38,6 +39,8 @@ use Magento\Framework\Exception\LocalizedException; use Magento\Sales\Api\Data\TransactionInterface; use Magento\Sales\Model\Order; +use Magento\Sales\Model\Order\Invoice; +use Magento\Sales\Model\Order\Payment; use Magento\Sales\Model\Order\Payment as OrderPayment; use Magento\Sales\Model\Order\Payment\Transaction; @@ -106,8 +109,26 @@ class DefaultProcessor implements PushProcessorInterface */ private BuckarooStatusCode $buckarooStatusCode; + /** + * @var OrderStatusFactory + */ private OrderStatusFactory $orderStatusFactory; + /** + * @var Account + */ + public Account $configAccount; + + /** + * @param OrderRequestService $orderRequestService + * @param PushTransactionType $pushTransactionType + * @param Log $logging + * @param Data $helper + * @param TransactionInterface $transaction + * @param PaymentGroupTransaction $groupTransaction + * @param BuckarooStatusCode $buckarooStatusCode + * @param OrderStatusFactory $orderStatusFactory + */ public function __construct( OrderRequestService $orderRequestService, PushTransactionType $pushTransactionType, @@ -117,6 +138,7 @@ public function __construct( PaymentGroupTransaction $groupTransaction, BuckarooStatusCode $buckarooStatusCode, OrderStatusFactory $orderStatusFactory, + Account $configAccount ) { $this->pushTransactionType = $pushTransactionType; $this->orderRequestService = $orderRequestService; @@ -126,6 +148,7 @@ public function __construct( $this->groupTransaction = $groupTransaction; $this->buckarooStatusCode = $buckarooStatusCode; $this->orderStatusFactory = $orderStatusFactory; + $this->configAccount = $configAccount; } /** @@ -571,31 +594,16 @@ public function processSucceededPush(string $newStatus, string $message): bool { $this->logging->addDebug(__METHOD__ . '|1|' . var_export($newStatus, true)); + // Set amount $amount = $this->order->getTotalDue(); - if (!empty($this->pushRequest->getAmount())) { - $this->logging->addDebug(__METHOD__ . '|11|'); $amount = floatval($this->pushRequest->getAmount()); } - if (!empty($this->pushRequest->getServiceKlarnaReservationnumber())) { - $this->order->setBuckarooReservationNumber($this->pushRequest->getServiceKlarnaReservationnumber()); - $this->order->save(); - } - - if (!empty($this->pushRequest->getServiceKlarnakpReservationnumber())) { - $this->order->setBuckarooReservationNumber($this->pushRequest->getServiceKlarnakpReservationnumber()); - $this->order->save(); - } - $store = $this->order->getStore(); - $payment = $this->order->getPayment(); - - /** - * @var \Magento\Payment\Model\MethodInterface $paymentMethod - */ - $paymentMethod = $payment->getMethodInstance(); + $paymentMethod = $this->payment->getMethodInstance(); + // Send email if is not sent if (!$this->order->getEmailSent() && ($this->configAccount->getOrderConfirmationEmail($store) || $paymentMethod->getConfigData('order_email', $store) @@ -603,174 +611,133 @@ public function processSucceededPush(string $newStatus, string $message): bool ) { $this->logging->addDebug(__METHOD__ . '|sendemail|' . var_export($this->configAccount->getOrderConfirmationEmailSync($store), true)); - $this->orderSender->send($this->order, $this->configAccount->getOrderConfirmationEmailSync($store)); + $this->orderRequestService->sendOrderEmail( + (bool)$this->configAccount->getOrderConfirmationEmailSync($store) + ); } - /** force state eventhough this can lead to a transition of the order - * like new -> processing + /** + * force state eventhough this can lead to a transition of the order + * like new -> processing */ $forceState = false; $state = Order::STATE_PROCESSING; - $this->logging->addDebug(__METHOD__ . '|2|'); - - if ($paymentMethod->canPushInvoice($this->pushRequest)) { - $this->logging->addDebug(__METHOD__ . '|3|'); + if ($this->canPushInvoice()) { $description = 'Payment status : ' . $message . "
"; - if ($this->pushRequest->hasPostData('transaction_method', 'transfer')) { - //keep amount fetched from brq_amount - $description .= 'Amount of ' . $this->order->getBaseCurrency()->formatTxt($amount) . ' has been paid'; - } else { - $amount = $this->order->getBaseTotalDue(); - $description .= 'Total amount of ' . - $this->order->getBaseCurrency()->formatTxt($amount) . ' has been paid'; + $amount = $this->order->getBaseTotalDue(); + $description .= 'Total amount of ' . + $this->order->getBaseCurrency()->formatTxt($amount) . ' has been paid'; + + $this->logging->addDebug(__METHOD__ . '|4|'); + if (!$this->saveInvoice()) { + return false; } } else { $description = 'Authorization status : ' . $message . "
"; - $description .= 'Total amount of ' . $this->order->getBaseCurrency()->formatTxt($this->order->getTotalDue()) + $description .= 'Total amount of ' . $this->order->getBaseCurrency()->formatTxt($amount) . ' has been authorized. Please create an invoice to capture the authorized amount.'; $forceState = true; } - if ($this->isPayPerEmailB2BModePushInitial) { - $description = ''; + $this->dontSaveOrderUponSuccessPush = false; + + if ($this->groupTransaction->isGroupTransaction($this->pushRequest->getInvoiceNumber())) { + $forceState = true; } - $this->dontSaveOrderUponSuccessPush = false; - if ($paymentMethod->canPushInvoice($this->pushRequest)) { - $this->logging->addDebug(__METHOD__ . '|4|'); + $this->logging->addDebug(__METHOD__ . '|8|'); - if (!$this->isPayPerEmailB2BModePushInitial && $this->isPayPerEmailB2BModePushPaid()) { - $this->logging->addDebug(__METHOD__ . '|4_1|'); - //Fix for suspected fraud when the order currency does not match with the payment's currency - $amount = ($payment->isSameCurrency() && $payment->isCaptureFinal($this->order->getGrandTotal())) ? - $this->order->getGrandTotal() : $this->order->getBaseTotalDue(); - $payment->registerCaptureNotification($amount); - $payment->save(); - $this->order->setState('complete'); - $this->order->addStatusHistoryComment($description, 'complete'); - $this->order->save(); - - if ($transactionKey = $this->getTransactionKey()) { - foreach ($this->order->getInvoiceCollection() as $invoice) { - $invoice->setTransactionId($transactionKey)->save(); - } - } - return true; - } + $this->processSucceededPushAuth($payment); - if ($this->pushRequest->hasAdditionalInformation('initiated_by_magento', 1) && - ( - $this->pushRequest->hasPostData('transaction_method', 'KlarnaKp') && - $this->pushRequest->hasAdditionalInformation('service_action_from_magento', 'pay') && - empty($this->pushRequest->getServiceKlarnakpReservationnumber()) && - $this->klarnakpConfig->isInvoiceCreatedAfterShipment() - ) || - ( - $this->pushRequest->hasPostData('transaction_method', 'afterpay') && - $this->pushRequest->hasAdditionalInformation('service_action_from_magento', 'capture') && - $this->afterpayConfig->isInvoiceCreatedAfterShipment() - ) - ) { - $this->logging->addDebug(__METHOD__ . '|5_1|'); - $this->dontSaveOrderUponSuccessPush = true; - return true; - } else { - $this->logging->addDebug(__METHOD__ . '|6|'); - - if ($this->pushRequest->hasPostData('transaction_method', 'transfer')) { - //invoice only in case of full or last remained amount - $this->logging->addDebug(__METHOD__ . '|61|' . var_export([ - $this->order->getId(), - $amount, - $this->order->getTotalDue(), - $this->order->getTotalPaid(), - ], true)); - - $saveInvoice = true; - if (($amount < $this->order->getTotalDue()) - || (($amount == $this->order->getTotalDue()) && ($this->order->getTotalPaid() > 0)) - ) { - $this->logging->addDebug(__METHOD__ . '|64|'); - - $forceState = true; - if ($amount < $this->order->getTotalDue()) { - $this->logging->addDebug(__METHOD__ . '|65|'); - $state = Order::STATE_NEW; - $newStatus = $this->orderStatusFactory->get( - BuckarooStatusCode::PENDING_PROCESSING, - $this->order - ); - $saveInvoice = false; - } - - $this->saveAndReloadOrder(); - - $this->order->setTotalDue($this->order->getTotalDue() - $amount); - $this->order->setBaseTotalDue($this->order->getTotalDue() - $amount); - - $totalPaid = $this->order->getTotalPaid() + $amount; - $this->order->setTotalPaid( - $totalPaid > $this->order->getGrandTotal() ? $this->order->getGrandTotal() : $totalPaid - ); - - $baseTotalPaid = $this->order->getBaseTotalPaid() + $amount; - $this->order->setBaseTotalPaid( - $baseTotalPaid > $this->order->getBaseGrandTotal() ? - $this->order->getBaseGrandTotal() : $baseTotalPaid - ); - - $this->saveAndReloadOrder(); - - $connection = $this->resourceConnection->getConnection(); - $connection->update( - $connection->getTableName('sales_order'), - [ - 'total_due' => $this->order->getTotalDue(), - 'base_total_due' => $this->order->getTotalDue(), - 'total_paid' => $this->order->getTotalPaid(), - 'base_total_paid' => $this->order->getBaseTotalPaid(), - ], - $connection->quoteInto('entity_id = ?', $this->order->getId()) - ); - } - - if ($saveInvoice) { - if (!$this->saveInvoice()) { - return false; - } - } - } else { - if (!$this->saveInvoice()) { - return false; - } - } - } - } + $this->orderRequestService->updateOrderStatus($state, $newStatus, $description, $forceState); - if (!empty($this->pushRequst->getServiceKlarnaAutopaytransactionkey()) - && ($this->pushRequst->getStatusCode() == 190) - ) { - $this->saveInvoice(); + $this->logging->addDebug(__METHOD__ . '|9|'); + + return true; + } + + /** + * Can create invoice on push + * + * @return bool + * + * @SuppressWarnings(PHPMD.UnusedFormalParameter) + * @throws LocalizedException + */ + protected function canPushInvoice(): bool + { + if ($this->payment->getMethodInstance()->getConfigData('payment_action') == 'authorize') { + return false; } - if (!empty($this->pushRequst->getServiceKlarnakpAutopaytransactionkey()) - && ($this->pushRequst->getStatusCode() == 190) - ) { - $this->saveInvoice(); + return true; + } + + /** + * Creates and saves the invoice and adds for each invoice the buckaroo transaction keys + * Only when the order can be invoiced and has not been invoiced before. + * + * @return bool + * @throws BuckarooException + * @throws LocalizedException + * @throws \Exception + * + * @SuppressWarnings(PHPMD.CyclomaticComplexity) + * @SuppressWarnings(PHPMD.NPathComplexity) + */ + protected function saveInvoice(): bool + { + $this->logging->addDebug(__METHOD__ . '|1|'); + if (!$this->forceInvoice + && (!$this->order->canInvoice() || $this->order->hasInvoices())) { + $this->logging->addDebug('Order can not be invoiced'); + return false; } - if ($this->groupTransaction->isGroupTransaction($this->pushRequst->getInvoiceNumber())) { - $forceState = true; + /** + * @var Payment $payment + */ + $payment = $this->order->getPayment(); + + $this->logging->addDebug(__METHOD__ . '|15|'); + //Fix for suspected fraud when the order currency does not match with the payment's currency + $amount = ($payment->isSameCurrency() + && $payment->isCaptureFinal($this->order->getGrandTotal())) ? + $this->order->getGrandTotal() : $this->order->getBaseTotalDue(); + $payment->registerCaptureNotification($amount); + $payment->save(); + + $transactionKey = $this->getTransactionKey(); + + if (strlen($transactionKey) <= 0) { + return true; } - $this->logging->addDebug(__METHOD__ . '|8|'); + $this->logging->addDebug(__METHOD__ . '|25|'); - $this->processSucceededPushAuth($payment); + /** @var Invoice $invoice */ + foreach ($this->order->getInvoiceCollection() as $invoice) { + $invoice->setTransactionId($transactionKey)->save(); - $this->updateOrderStatus($state, $newStatus, $description, $forceState); + if (!empty($this->pushRequest->getInvoiceNumber()) + && $this->groupTransaction->isGroupTransaction($this->pushRequest->getInvoiceNumber())) { + $this->logging->addDebug(__METHOD__ . '|27|'); + $invoice->setState(2); + } - $this->logging->addDebug(__METHOD__ . '|9|'); + if (!$invoice->getEmailSent() && $this->configAccount->getInvoiceEmail($this->order->getStore())) { + $this->logging->addDebug(__METHOD__ . '|30|sendinvoiceemail'); + $this->orderRequestService->sendInvoiceEmail($invoice, true); + } + } + + $this->logging->addDebug(__METHOD__ . '|35|'); + + $this->order->setIsInProcess(true); + $this->order->save(); + + $this->dontSaveOrderUponSuccessPush = true; return true; } @@ -799,12 +766,12 @@ public function processFailedPush(string $newStatus, string $message): bool $description = 'Payment status : ' . $message; - if (!empty($this->pushRequst->getServiceAntifraudAction())) { - $description .= $this->pushRequst->getServiceAntifraudAction() . + if (!empty($this->pushRequest->getServiceAntifraudAction())) { + $description .= $this->pushRequest->getServiceAntifraudAction() . ' ' . - $this->pushRequst->getServiceAntifraudCheck() . + $this->pushRequest->getServiceAntifraudCheck() . ' ' . - $this->pushRequst->getServiceAntifraudDetails(); + $this->pushRequest->getServiceAntifraudDetails(); } $store = $this->order->getStore(); @@ -905,7 +872,7 @@ private function giftcardPartialPayment(): bool { $payment = $this->order->getPayment(); - if ($payment->getMethod() != Giftcards::CODE + if ($this->payment->getMethod() != Giftcards::CODE || (!empty($this->pushRequest->getAmount()) && $this->pushRequest->getAmount() >= $this->order->getGrandTotal()) || empty($this->pushRequest->getRelatedtransactionPartialpayment()) @@ -918,7 +885,7 @@ private function giftcardPartialPayment(): bool } if (!$this->pushTransactionType->getTransactionType() == PushTransactionType::BUCK_PUSH_GROUPTRANSACTION_TYPE) { - $payment->setAdditionalInformation( + $this->payment->setAdditionalInformation( BuckarooAdapter::BUCKAROO_ORIGINAL_TRANSACTION_KEY_KEY, $this->pushRequest->getRelatedtransactionPartialpayment() ); diff --git a/Model/Push/IdealProcessor.php b/Model/Push/IdealProcessor.php index f40ddaca7..59f8651db 100644 --- a/Model/Push/IdealProcessor.php +++ b/Model/Push/IdealProcessor.php @@ -8,6 +8,7 @@ use Buckaroo\Magento2\Helper\PaymentGroupTransaction; use Buckaroo\Magento2\Logging\Log; use Buckaroo\Magento2\Model\BuckarooStatusCode; +use Buckaroo\Magento2\Model\ConfigProvider\Account; use Buckaroo\Magento2\Model\OrderStatusFactory; use Buckaroo\Magento2\Service\LockerProcess; use Buckaroo\Magento2\Service\Push\OrderRequestService; @@ -31,11 +32,12 @@ public function __construct( TransactionInterface $transaction, PaymentGroupTransaction $groupTransaction, BuckarooStatusCode $buckarooStatusCode, + OrderStatusFactory $orderStatusFactory, + Account $configAccount, LockerProcess $lockerProcess, - OrderStatusFactory $orderStatusFactory ) { parent::__construct($orderRequestService, $pushTransactionType, $logging, $helper, $transaction, - $groupTransaction, $buckarooStatusCode,$orderStatusFactory); + $groupTransaction, $buckarooStatusCode,$orderStatusFactory, $configAccount); $this->lockerProcess = $lockerProcess; } diff --git a/Model/Push/RefundProcessor.php b/Model/Push/RefundProcessor.php index 91cca5729..84cb704aa 100644 --- a/Model/Push/RefundProcessor.php +++ b/Model/Push/RefundProcessor.php @@ -9,6 +9,8 @@ use Buckaroo\Magento2\Helper\PaymentGroupTransaction; use Buckaroo\Magento2\Logging\Log; use Buckaroo\Magento2\Model\BuckarooStatusCode; +use Buckaroo\Magento2\Model\ConfigProvider\Account; +use Buckaroo\Magento2\Model\OrderStatusFactory; use Buckaroo\Magento2\Model\Refund\Push as RefundPush; use Buckaroo\Magento2\Model\Validator\Push as ValidatorPush; use Buckaroo\Magento2\Service\Push\OrderRequestService; @@ -30,10 +32,12 @@ public function __construct( TransactionInterface $transaction, PaymentGroupTransaction $groupTransaction, BuckarooStatusCode $buckarooStatusCode, + OrderStatusFactory $orderStatusFactory, + Account $configAccount, RefundPush $refundPush ) { parent::__construct($orderRequestService, $pushTransactionType, $logging, $helper, $transaction, - $groupTransaction, $buckarooStatusCode); + $groupTransaction, $buckarooStatusCode,$orderStatusFactory, $configAccount); $this->refundPush = $refundPush; } diff --git a/Service/Push/OrderRequestService.php b/Service/Push/OrderRequestService.php index e3c9e54b1..8722a0ca9 100644 --- a/Service/Push/OrderRequestService.php +++ b/Service/Push/OrderRequestService.php @@ -7,6 +7,9 @@ use Magento\Framework\Phrase; use Magento\Sales\Api\Data\TransactionInterface; use Magento\Sales\Model\Order; +use Magento\Sales\Model\Order\Email\Sender\InvoiceSender; +use Magento\Sales\Model\Order\Email\Sender\OrderSender; +use Magento\Sales\Model\Order\Invoice; use Magento\Sales\Model\Order\Payment as OrderPayment; use Magento\Sales\Model\Order\Payment\Transaction; @@ -27,19 +30,35 @@ class OrderRequestService */ private TransactionInterface $transaction; + /** + * @var OrderSender + */ + private OrderSender $orderSender; + + /** + * @var InvoiceSender + */ + private InvoiceSender $invoiceSender; + /** * @param Order $order * @param Log $logging * @param TransactionInterface $transaction + * @param OrderSender $orderSender + * @param InvoiceSender $invoiceSender */ public function __construct( Order $order, Log $logging, - TransactionInterface $transaction + TransactionInterface $transaction, + OrderSender $orderSender, + InvoiceSender $invoiceSender, ) { $this->order = $order; $this->logging = $logging; $this->transaction = $transaction; + $this->orderSender = $orderSender; + $this->invoiceSender = $invoiceSender; } /** @@ -153,4 +172,29 @@ public function setOrderNotificationNote(Phrase|string $message): void $this->logging->addDebug($e->getLogMessage()); } } + + /** + * Sends order email to the customer. + * + * @param bool $forceSyncMode + * @return bool + */ + public function sendOrderEmail(bool $forceSyncMode = false): bool + { + return $this->orderSender->send($this->order, $forceSyncMode); + } + + /** + * Sends order invoice email to the customer. + * + * @param Invoice $invoice + * @param bool $forceSyncMode + * @return bool + * + * @throws \Exception + */ + public function sendInvoiceEmail(Invoice $invoice, bool $forceSyncMode = false): bool + { + return $this->invoiceSender->send($invoice, $forceSyncMode); + } } \ No newline at end of file From 362a289d4cfd5f1a52ddbde6faad00b7dea6c38d Mon Sep 17 00:00:00 2001 From: Lucian Turiac Date: Mon, 17 Jul 2023 15:06:04 +0300 Subject: [PATCH 12/29] BP-2132 - Working on Push Refactor --- Model/Push.php | 7 +-- Model/Push/DefaultProcessor.php | 11 ++--- Model/Push/GroupTransactionPushProcessor.php | 30 ++++++------- Model/Push/IdealProcessor.php | 43 ++++++++++--------- Model/Push/PartialPaymentProcessor.php | 18 +++++++- Model/Push/PushTransactionType.php | 32 +++++++------- Service/Push/OrderRequestService.php | 45 ++++++++++++++++++++ 7 files changed, 121 insertions(+), 65 deletions(-) diff --git a/Model/Push.php b/Model/Push.php index 50ffcb7bc..da35e6e17 100644 --- a/Model/Push.php +++ b/Model/Push.php @@ -337,10 +337,10 @@ public function receivePush() throw new BuckarooException(__('Signature from push is incorrect')); } - // Get Push Transaction Type +// Get Push Transaction Type $pushTransactionType = $this->pushTransactionType->getPushTransactionType($this->pushRequst, $this->order); - // Process Push +// Process Push $this->pushProcessor = $this->pushProcessorsFactory->get($pushTransactionType); $this->pushProcessor->processPush($this->pushRequst); @@ -510,7 +510,8 @@ public function receivePush() } } - if ((!in_array($payment->getMethod(), [Giftcards::CODE, Voucher::CODE])) && $this->isGroupTransactionPart()) { + if (!in_array($payment->getMethod(), [Giftcards::CODE, Voucher::CODE]) + && $this->isGroupTransactionPart()) { $this->savePartGroupTransaction(); return true; } diff --git a/Model/Push/DefaultProcessor.php b/Model/Push/DefaultProcessor.php index 8e1eba415..54b86079b 100644 --- a/Model/Push/DefaultProcessor.php +++ b/Model/Push/DefaultProcessor.php @@ -622,6 +622,7 @@ public function processSucceededPush(string $newStatus, string $message): bool */ $forceState = false; $state = Order::STATE_PROCESSING; + $this->dontSaveOrderUponSuccessPush = false; if ($this->canPushInvoice()) { $description = 'Payment status : ' . $message . "
"; @@ -640,17 +641,14 @@ public function processSucceededPush(string $newStatus, string $message): bool $forceState = true; } - $this->dontSaveOrderUponSuccessPush = false; - if ($this->groupTransaction->isGroupTransaction($this->pushRequest->getInvoiceNumber())) { $forceState = true; } $this->logging->addDebug(__METHOD__ . '|8|'); - $this->processSucceededPushAuth($payment); - - $this->orderRequestService->updateOrderStatus($state, $newStatus, $description, $forceState); + $this->orderRequestService->updateOrderStatus($state, $newStatus, $description, $forceState, + $this->dontSaveOrderUponSuccessPush); $this->logging->addDebug(__METHOD__ . '|9|'); @@ -867,11 +865,10 @@ private function savePartGroupTransaction() * Checks if the payment is a partial payment using a gift card. * * @return bool + * @throws LocalizedException */ private function giftcardPartialPayment(): bool { - $payment = $this->order->getPayment(); - if ($this->payment->getMethod() != Giftcards::CODE || (!empty($this->pushRequest->getAmount()) && $this->pushRequest->getAmount() >= $this->order->getGrandTotal()) diff --git a/Model/Push/GroupTransactionPushProcessor.php b/Model/Push/GroupTransactionPushProcessor.php index 740bf460d..f9adbd9b7 100644 --- a/Model/Push/GroupTransactionPushProcessor.php +++ b/Model/Push/GroupTransactionPushProcessor.php @@ -2,6 +2,7 @@ namespace Buckaroo\Magento2\Model\Push; +use AllowDynamicProperties; use Buckaroo\Magento2\Api\PushProcessorInterface; use Buckaroo\Magento2\Api\PushRequestInterface; use Buckaroo\Magento2\Helper\PaymentGroupTransaction; @@ -18,7 +19,7 @@ use Magento\Sales\Model\Order; use Magento\Quote\Model\ResourceModel\Quote as ResourceQuote; -class GroupTransactionPushProcessor implements PushProcessorInterface +#[AllowDynamicProperties] class GroupTransactionPushProcessor implements PushProcessorInterface { /** * @var PushRequestInterface @@ -65,6 +66,11 @@ class GroupTransactionPushProcessor implements PushProcessorInterface */ private ResourceQuote $quoteResource; + /** + * @var DefaultProcessor + */ + private DefaultProcessor $defaultProcessor; + /** * @param PaymentGroupTransaction $groupTransaction * @param BuckarooLogger $logging @@ -73,6 +79,7 @@ class GroupTransactionPushProcessor implements PushProcessorInterface * @param QuoteManagement $quoteManagement * @param QuoteFactory $quoteFactory * @param ResourceQuote $quoteResource + * @param DefaultProcessor $defaultProcessor */ public function __construct( PaymentGroupTransaction $groupTransaction, @@ -81,7 +88,8 @@ public function __construct( OrderManagementInterface $orderManagement, QuoteManagement $quoteManagement, QuoteFactory $quoteFactory, - ResourceQuote $quoteResource + ResourceQuote $quoteResource, + DefaultProcessor $defaultProcessor ) { $this->groupTransaction = $groupTransaction; $this->logging = $logging; @@ -90,6 +98,7 @@ public function __construct( $this->quoteManagement = $quoteManagement; $this->quoteFactory = $quoteFactory; $this->quoteResource = $quoteResource; + $this->defaultProcessor = $defaultProcessor; } /** @@ -123,22 +132,7 @@ public function processPush(PushRequestInterface $pushRequest): bool return true; } - return false; - } - - public function processSucceededPush(PushRequestInterface $pushRequest): bool - { - // TODO: Implement processSucceededPush() method. - } - - public function processFailedPush(PushRequestInterface $pushRequest): bool - { - // TODO: Implement processFailedPush() method. - } - - public function processPendingPaymentPush(PushRequestInterface $pushRequest): bool - { - // TODO: Implement processPendingPaymentPush() method. + return $this->defaultProcessor->processPush($pushRequest); } /** diff --git a/Model/Push/IdealProcessor.php b/Model/Push/IdealProcessor.php index 59f8651db..4f05ac19a 100644 --- a/Model/Push/IdealProcessor.php +++ b/Model/Push/IdealProcessor.php @@ -1,4 +1,23 @@ lockerProcess = $lockerProcess; } @@ -50,7 +69,6 @@ public function processPush(PushRequestInterface $pushRequest): bool { $this->pushRequest = $pushRequest; - // Lock Processing if ($this->lockPushProcessingCriteria()) { $this->lockerProcess->lockProcess($this->getOrderIncrementId()); } @@ -58,6 +76,8 @@ public function processPush(PushRequestInterface $pushRequest): bool parent::processPush($pushRequest); $this->lockerProcess->unlockProcess(); + + return true; } /** @@ -70,23 +90,4 @@ protected function lockPushProcessingCriteria(): bool return $this->pushRequest->hasPostData('statuscode', BuckarooStatusCode::SUCCESS) && $this->pushRequest->hasPostData('transaction_type', self::BUCK_PUSH_IDEAL_PAY); } - - public function processSucceded() - { - $statusCodeSuccess = BuckarooStatusCode::SUCCESS; - - if ($this->pushRequest->hasPostData('statuscode', BuckarooStatusCode::SUCCESS) - && $this->pushRequest->hasPostData('transaction_method', 'ideal') - && $this->pushRequest->hasPostData('transaction_type', self::BUCK_PUSH_IDEAL_PAY) - ) { - return true; - } - } - - public function processFailed() - { - // TODO: Implement processFailed() method. - } - - } \ No newline at end of file diff --git a/Model/Push/PartialPaymentProcessor.php b/Model/Push/PartialPaymentProcessor.php index 66853644d..fb221ce0b 100644 --- a/Model/Push/PartialPaymentProcessor.php +++ b/Model/Push/PartialPaymentProcessor.php @@ -2,7 +2,23 @@ namespace Buckaroo\Magento2\Model\Push; -class PartialPaymentProcessor +use Buckaroo\Magento2\Api\PushProcessorInterface; +use Buckaroo\Magento2\Api\PushRequestInterface; +use Buckaroo\Magento2\Exception as BuckarooException; + +class PartialPaymentProcessor extends DefaultProcessor { + public function processPush(PushRequestInterface $pushRequest): bool + { + $this->pushRequest = $pushRequest; + $this->order = $this->orderRequestService->getOrderByRequest(); + $this->payment = $this->order->getPayment(); + + // Check Push Dublicates + if ($this->receivePushCheckDuplicates()) { + throw new BuckarooException(__('Skipped handling this push, duplicate')); + } + // TODO: Implement processPush() method. + } } \ No newline at end of file diff --git a/Model/Push/PushTransactionType.php b/Model/Push/PushTransactionType.php index e5ecde0c2..3f2e06384 100644 --- a/Model/Push/PushTransactionType.php +++ b/Model/Push/PushTransactionType.php @@ -49,9 +49,9 @@ class PushTransactionType private ?string $magentoServiceAction; /** - * @var string + * @var string|null */ - private string $serviceAction; + private ?string $serviceAction; /** * @var int @@ -141,7 +141,7 @@ public function getPushTransactionType(?PushRequestInterface $pushRequest, ?Orde $this->groupTransaction = $this->transactionType === self::BUCK_PUSH_GROUPTRANSACTION_TYPE; $this->creditManagement = $this->pushType === self::BUCK_PUSH_TYPE_INVOICE; $this->magentoServiceAction = $this->pushRequest->getAdditionalInformation('service_action_from_magento'); - $this->serviceAction = $this->getServiceAction($pushRequest, $order); + $this->serviceAction = $this->getServiceAction(); $this->isSet = true; } @@ -284,20 +284,22 @@ public function setTransactionType(string $transactionType): void } /** - * @return string + * @return string|null */ - public function getServiceAction(): string + public function getServiceAction(): ?string { - $this->serviceAction = $this->magentoServiceAction; - - if (!empty($this->pushRequest->getAmountCredit())) { - if ($this->getStatusKey() !== 'BUCKAROO_MAGENTO2_STATUSCODE_SUCCESS' - && $this->order->isCanceled() - && $this->getTransactionType() == self::BUCK_PUSH_CANCEL_AUTHORIZE_TYPE - ) { - $this->serviceAction = 'cancel_authorize'; - } else { - $this->serviceAction = 'refund'; + if (empty($this->serviceAction)) { + $this->serviceAction = $this->magentoServiceAction; + + if (!empty($this->pushRequest->getAmountCredit())) { + if ($this->getStatusKey() !== 'BUCKAROO_MAGENTO2_STATUSCODE_SUCCESS' + && $this->order->isCanceled() + && $this->getTransactionType() == self::BUCK_PUSH_CANCEL_AUTHORIZE_TYPE + ) { + $this->serviceAction = 'cancel_authorize'; + } else { + $this->serviceAction = 'refund'; + } } } diff --git a/Service/Push/OrderRequestService.php b/Service/Push/OrderRequestService.php index 8722a0ca9..79a7c70f5 100644 --- a/Service/Push/OrderRequestService.php +++ b/Service/Push/OrderRequestService.php @@ -173,6 +173,51 @@ public function setOrderNotificationNote(Phrase|string $message): void } } + /** + * Updates the order state and add a comment. + * + * @param string $orderState + * @param string $newStatus + * @param string $description + * @param bool $force + * @param bool $dontSaveOrderUponSuccessPush + * + * @throws \Exception + */ + public function updateOrderStatus( + string $orderState, + string $newStatus, + string $description, + bool $force = false, + bool $dontSaveOrderUponSuccessPush = false + ): void { + $this->logging->addDebug(__METHOD__ . '|0|' . var_export([$orderState, $newStatus, $description], true)); + if ($this->order->getState() == $orderState || $force) { + $this->logging->addDebug(__METHOD__ . '|1|'); + $this->logging->addDebug('||| $orderState: ' . '|1|' . $orderState); + if ($dontSaveOrderUponSuccessPush) { + $this->order->addCommentToStatusHistory($description) + ->setIsCustomerNotified(false) + ->setEntityName('invoice') + ->setStatus($newStatus) + ->save(); + } else { + $this->order->addCommentToStatusHistory($description, $newStatus); + } + } else { + $this->logging->addDebug(__METHOD__ . '|2|'); + $this->logging->addDebug('||| $orderState: ' . '|2|' . $orderState); + if ($dontSaveOrderUponSuccessPush) { + $this->order->addCommentToStatusHistory($description) + ->setIsCustomerNotified(false) + ->setEntityName('invoice') + ->save(); + } else { + $this->order->addCommentToStatusHistory($description); + } + } + } + /** * Sends order email to the customer. * From 151f1a7a78129067ad253aa9369ac36b6faf7a6b Mon Sep 17 00:00:00 2001 From: Lucian Turiac Date: Wed, 19 Jul 2023 18:20:59 +0300 Subject: [PATCH 13/29] BP-2132 - Working on Push Refactor --- Model/Push.php | 6 +- Model/Push/DefaultProcessor.php | 82 ++++++++-- Model/Push/PayPerEmailProcessor.php | 230 +++++++++++++++++++++++++-- Model/Push/PushProcessorsFactory.php | 3 + Model/Push/PushTransactionType.php | 24 +++ Model/Push/RefundProcessor.php | 10 +- etc/di.xml | 1 + 7 files changed, 321 insertions(+), 35 deletions(-) diff --git a/Model/Push.php b/Model/Push.php index da35e6e17..1550edc9c 100644 --- a/Model/Push.php +++ b/Model/Push.php @@ -341,10 +341,8 @@ public function receivePush() $pushTransactionType = $this->pushTransactionType->getPushTransactionType($this->pushRequst, $this->order); // Process Push - $this->pushProcessor = $this->pushProcessorsFactory->get($pushTransactionType); - $this->pushProcessor->processPush($this->pushRequst); - - +// $this->pushProcessor = $this->pushProcessorsFactory->get($pushTransactionType); +// return $this->pushProcessor->processPush($this->pushRequst); // Lock Push Processing $this->logging->addDebug(__METHOD__ . '|1_2|'); diff --git a/Model/Push/DefaultProcessor.php b/Model/Push/DefaultProcessor.php index 54b86079b..40d3741d7 100644 --- a/Model/Push/DefaultProcessor.php +++ b/Model/Push/DefaultProcessor.php @@ -107,7 +107,7 @@ class DefaultProcessor implements PushProcessorInterface /** * @var BuckarooStatusCode */ - private BuckarooStatusCode $buckarooStatusCode; + protected BuckarooStatusCode $buckarooStatusCode; /** * @var OrderStatusFactory @@ -158,9 +158,7 @@ public function __construct( */ public function processPush(PushRequestInterface $pushRequest): bool { - $this->pushRequest = $pushRequest; - $this->order = $this->orderRequestService->getOrderByRequest(); - $this->payment = $this->order->getPayment(); + $this->initializeFields($pushRequest); // Skip Push if ($this->skipPush()) { @@ -315,7 +313,7 @@ protected function skipPush() * * @SuppressWarnings(PHPMD.CyclomaticComplexity) */ - private function skipSpecificTypesOfRequsts(): bool + protected function skipSpecificTypesOfRequsts(): bool { $this->logging->addDebug(__METHOD__ . '|1|'); @@ -693,18 +691,15 @@ protected function saveInvoice(): bool return false; } - /** - * @var Payment $payment - */ - $payment = $this->order->getPayment(); + $this->addTransactionData(); $this->logging->addDebug(__METHOD__ . '|15|'); //Fix for suspected fraud when the order currency does not match with the payment's currency - $amount = ($payment->isSameCurrency() - && $payment->isCaptureFinal($this->order->getGrandTotal())) ? + $amount = ($this->payment->isSameCurrency() + && $this->payment->isCaptureFinal($this->order->getGrandTotal())) ? $this->order->getGrandTotal() : $this->order->getBaseTotalDue(); - $payment->registerCaptureNotification($amount); - $payment->save(); + $this->payment->registerCaptureNotification($amount); + $this->payment->save(); $transactionKey = $this->getTransactionKey(); @@ -835,7 +830,7 @@ protected function processPendingPaymentPush(): bool * * @return false|mixed */ - private function isGroupTransactionPart() + protected function isGroupTransactionPart() { if (!is_null($this->pushRequest->getTransactions())) { return $this->groupTransaction->getGroupTransactionByTrxId($this->pushRequest->getTransactions()); @@ -849,7 +844,7 @@ private function isGroupTransactionPart() * @return void * @throws \Exception */ - private function savePartGroupTransaction() + protected function savePartGroupTransaction() { $items = $this->groupTransaction->getGroupTransactionByTrxId($this->pushRequest->getTransactions()); if (is_array($items) && count($items) > 0) { @@ -867,7 +862,7 @@ private function savePartGroupTransaction() * @return bool * @throws LocalizedException */ - private function giftcardPartialPayment(): bool + protected function giftcardPartialPayment(): bool { if ($this->payment->getMethod() != Giftcards::CODE || (!empty($this->pushRequest->getAmount()) @@ -922,4 +917,59 @@ protected function addGiftcardPartialPaymentToPaymentInformation() ); } } + + /** + * Adds transaction data to the order payment with the given transaction key and data. + * + * @param bool $transactionKey + * @param bool $data + * @return Payment + * @throws LocalizedException + * @throws \Exception + */ + public function addTransactionData(bool $transactionKey = false, bool $data = false): Payment + { + $this->payment = $this->order->getPayment(); + $transactionKey = $transactionKey ?: $this->getTransactionKey(); + + if (strlen($transactionKey) <= 0) { + throw new BuckarooException(__('There was no transaction ID found')); + } + + /** + * Save the transaction's response as additional info for the transaction. + */ + $postData = $data ?: $this->pushRequest->getData(); + $rawInfo = $this->helper->getTransactionAdditionalInfo($postData); + + $this->payment->setTransactionAdditionalInfo( + Transaction::RAW_DETAILS, + $rawInfo + ); + + /** + * Save the payment's transaction key. + */ + $this->payment->setTransactionId($transactionKey . '-capture'); + + $this->payment->setParentTransactionId($transactionKey); + $this->payment->setAdditionalInformation( + BuckarooAdapter::BUCKAROO_ORIGINAL_TRANSACTION_KEY_KEY, + $transactionKey + ); + + return $this->payment; + } + + /** + * @param PushRequestInterface $pushRequest + * @return void + * @throws \Exception + */ + protected function initializeFields(PushRequestInterface $pushRequest): void + { + $this->pushRequest = $pushRequest; + $this->order = $this->orderRequestService->getOrderByRequest(); + $this->payment = $this->order->getPayment(); + } } \ No newline at end of file diff --git a/Model/Push/PayPerEmailProcessor.php b/Model/Push/PayPerEmailProcessor.php index 13ebd1bd8..960abeedc 100644 --- a/Model/Push/PayPerEmailProcessor.php +++ b/Model/Push/PayPerEmailProcessor.php @@ -2,42 +2,131 @@ namespace Buckaroo\Magento2\Model\Push; -use Buckaroo\Magento2\Api\PushProcessorInterface; use Buckaroo\Magento2\Api\PushRequestInterface; +use Buckaroo\Magento2\Exception as BuckarooException; use Buckaroo\Magento2\Helper\Data; +use Buckaroo\Magento2\Helper\PaymentGroupTransaction; +use Buckaroo\Magento2\Logging\Log; +use Buckaroo\Magento2\Model\BuckarooStatusCode; +use Buckaroo\Magento2\Model\ConfigProvider\Account; +use Buckaroo\Magento2\Model\ConfigProvider\Method\Giftcards; +use Buckaroo\Magento2\Model\ConfigProvider\Method\PayPerEmail; +use Buckaroo\Magento2\Model\ConfigProvider\Method\Voucher; +use Buckaroo\Magento2\Model\Method\BuckarooAdapter; +use Buckaroo\Magento2\Model\OrderStatusFactory; use Buckaroo\Magento2\Service\LockerProcess; +use Buckaroo\Magento2\Service\Push\OrderRequestService; use Magento\Framework\Exception\FileSystemException; +use Magento\Payment\Model\InfoInterface; +use Magento\Sales\Api\Data\TransactionInterface; +use Magento\Sales\Model\Order; class PayPerEmailProcessor extends DefaultProcessor { /** * @var LockerProcess */ - protected LockerProcess $lockerProcess; + private LockerProcess $lockerProcess; + /** + * @var PayPerEmail + */ + public PayPerEmail $configPayPerEmail; - public function processSucceded() - { - - } + public function __construct( + OrderRequestService $orderRequestService, + PushTransactionType $pushTransactionType, + Log $logging, + Data $helper, + TransactionInterface $transaction, + PaymentGroupTransaction $groupTransaction, + BuckarooStatusCode $buckarooStatusCode, + OrderStatusFactory $orderStatusFactory, + Account $configAccount, + LockerProcess $lockerProcess, + PayPerEmail $configPayPerEmail + ) { + parent::__construct($orderRequestService, $pushTransactionType, $logging, $helper, $transaction, + $groupTransaction, $buckarooStatusCode, $orderStatusFactory, $configAccount); + $this->lockerProcess = $lockerProcess; + $this->configPayPerEmail = $configPayPerEmail; - public function processFailed() - { - // TODO: Implement processFailed() method. } - /** * @throws FileSystemException + * @throws \Exception */ public function processPush(PushRequestInterface $pushRequest): bool { - $this->pushRequest = $pushRequest; + $this->initializeFields($pushRequest); if ($this->lockPushProcessingCriteria()) { $this->lockerProcess->lockProcess($this->getOrderIncrementId()); } + //Check if the push is PayLink request + $this->receivePushCheckPayLink(); + + // Skip Push + if ($this->skipPush()) { + return true; + } + + //Check second push for PayPerEmail + $isDifferentPaymentMethod = $this->setPaymentMethodIfDifferent(); + + // Check Push Dublicates + if ($this->receivePushCheckDuplicates()) { + throw new BuckarooException(__('Skipped handling this push, duplicate')); + } + + // Check if the order can be updated + if (!$this->canUpdateOrderStatus()) { + if ($isDifferentPaymentMethod && $this->configPayPerEmail->isEnabledB2B()) { + $this->logging->addDebug(__METHOD__ . '|$this->order->getState()|' . $this->order->getState()); + if ($this->order->getState() === Order::STATE_COMPLETE) { + $this->order->setState(Order::STATE_PROCESSING); + $this->order->save(); + } + return true; + } + $this->logging->addDebug('Order can not receive updates'); + $this->orderRequestService->setOrderNotificationNote(__('The order has already been processed.')); + throw new BuckarooException( + __('Signature from push is correct but the order can not receive updates') + ); + } + + $this->setTransactionKey(); + + $this->setOrderStatusMessage(); + + if ((!in_array($this->payment->getMethod(), [Giftcards::CODE, Voucher::CODE])) + && $this->isGroupTransactionPart()) { + $this->savePartGroupTransaction(); + return true; + } + + + if (!$this->canProcessPostData()) { + return true; + } + + if ($this->giftcardPartialPayment()) { + return true; + } + + $this->processPushByStatus(); + + $this->logging->addDebug(__METHOD__ . '|5|'); + if (!$this->dontSaveOrderUponSuccessPush) { + $this->logging->addDebug(__METHOD__ . '|5-1|'); + $this->order->save(); + } + + $this->lockerProcess->unlockProcess(); + return true; } @@ -50,4 +139,123 @@ protected function lockPushProcessingCriteria(): bool { return !empty($this->pushRequest->getAdditionalInformation('frompayperemail')); } + + /** + * Set Payment method as PayPerEmail if the push request is PayLink + * + * @return void + * @throws \Exception + */ + private function receivePushCheckPayLink(): void + { + if (!empty($this->pushRequest->getAdditionalInformation('frompaylink')) + && $this->pushTransactionType->getStatusKey() == 'BUCKAROO_MAGENTO2_STATUSCODE_SUCCESS' + ) { + $this->payment->setMethod('buckaroo_magento2_payperemail'); + $this->payment->save(); + $this->order->save(); + } + } + + /** + * Skip the push if the conditions are met. + * + * @return bool + * @throws \Exception + */ + protected function skipPush(): bool + { + if ($this->skipPayPerEmailCancel()) { + return true; + } + + // Skip Push based on specific condition + if ($this->skipSpecificTypesOfRequsts()) { + return true; + } + + if ($this->skipFirstPush()) { + throw new BuckarooException( + __('Skipped handling this push, first handle response, action will be taken on the next push.') + ); + } + + return false; + } + + /** + * Skip Process PayPerEmail cancel request if cron is enabled + * + * @return bool + */ + private function skipPayPerEmailCancel(): bool + { + $failedStatuses = $this->buckarooStatusCode->getFailedStatuses(); + if (!empty($this->pushRequest->getTransactionMethod()) + && in_array($this->pushTransactionType->getStatusKey(), $failedStatuses) + && $this->configPayPerEmail->getEnabledCronCancelPPE() + ) { + return true; + } + return false; + } + + /** + * Set the payment method if the request is from Pay Per Email + * + * @return bool + * @throws \Exception + */ + private function setPaymentMethodIfDifferent(): bool + { + $status = $this->pushTransactionType->getStatusKey(); + if (!empty($this->pushRequest->getTransactionMethod()) + && $status == 'BUCKAROO_MAGENTO2_STATUSCODE_SUCCESS' + && $this->pushRequest->getTransactionMethod() != 'payperemail') { + + $transactionMethod = strtolower($this->pushRequest->getTransactionMethod()); + $this->payment->setAdditionalInformation('isPayPerEmail', $transactionMethod); + + $options = new \Buckaroo\Magento2\Model\Config\Source\PaymentMethods\PayPerEmail(); + foreach ($options->toOptionArray() as $item) { + if (($item['value'] == $transactionMethod) && isset($item['code'])) { + $this->payment->setMethod($item['code']); + $this->payment->setAdditionalInformation( + BuckarooAdapter::BUCKAROO_ORIGINAL_TRANSACTION_KEY_KEY, + $this->getTransactionKey() + ); + if ($item['code'] == 'buckaroo_magento2_creditcards') { + $this->payment->setAdditionalInformation('card_type', $transactionMethod); + } + } + } + $this->payment->save(); + $this->order->save(); + return true; + } + + return false; + } + + /** + * @return void + */ + protected function setOrderStatusMessage(): void + { + if (!empty($this->pushRequest->getStatusmessage())) { + if ($this->order->getState() === Order::STATE_NEW + && empty($this->pushRequest->getAdditionalInformation('frompayperemail')) + && empty($this->pushRequest->getRelatedtransactionPartialpayment()) + && $this->pushRequest->hasPostData('statuscode', BuckarooStatusCode::SUCCESS) + ) { + $this->order->setState(Order::STATE_PROCESSING); + $this->order->addStatusHistoryComment( + $this->pushRequest->getStatusmessage(), + $this->helper->getOrderStatusByState($this->order, Order::STATE_PROCESSING) + ); + } else { + $this->order->addStatusHistoryComment($this->pushRequest->getStatusmessage()); + } + } + } } \ No newline at end of file diff --git a/Model/Push/PushProcessorsFactory.php b/Model/Push/PushProcessorsFactory.php index 5fc8e1421..aab09a15f 100644 --- a/Model/Push/PushProcessorsFactory.php +++ b/Model/Push/PushProcessorsFactory.php @@ -84,6 +84,9 @@ private function getPushProcessorClass(?PushTransactionType $pushTransactionType // Set Push Processor by Payment Method $paymentMethod = $pushTransactionType->getPaymentMethod(); $pushProcessorClass = $this->pushProcessors[$paymentMethod] ?? $pushProcessorClass; + if ($pushTransactionType->isFromPayPerEmail()) { + $this->pushProcessors['group_transaction']; + } // Check if is Group Transaction Push if ($pushTransactionType->isGroupTransaction()) { diff --git a/Model/Push/PushTransactionType.php b/Model/Push/PushTransactionType.php index 3f2e06384..79d918643 100644 --- a/Model/Push/PushTransactionType.php +++ b/Model/Push/PushTransactionType.php @@ -113,6 +113,11 @@ class PushTransactionType */ private ?PushRequestInterface $pushRequest; + /** + * @var bool + */ + private bool $isFromPayPerEmail; + /** * @param BuckarooStatusCode $buckarooStatusCode */ @@ -142,6 +147,9 @@ public function getPushTransactionType(?PushRequestInterface $pushRequest, ?Orde $this->creditManagement = $this->pushType === self::BUCK_PUSH_TYPE_INVOICE; $this->magentoServiceAction = $this->pushRequest->getAdditionalInformation('service_action_from_magento'); $this->serviceAction = $this->getServiceAction(); + $this->isFromPayPerEmail = (bool)$this->pushRequest->getAdditionalInformation('frompayperemail') + ?? (bool)$this->pushRequest->getAdditionalInformation('frompayperemail') + ?? false; $this->isSet = true; } @@ -441,4 +449,20 @@ public function setOrder(Order $order): void { $this->order = $order; } + + /** + * @return bool + */ + public function isFromPayPerEmail(): bool + { + return $this->isFromPayPerEmail; + } + + /** + * @param Order $order + */ + public function setIsFromPayPerEmail(bool $isFromPayPerEmail): void + { + $this->isFromPayPerEmail = $isFromPayPerEmail; + } } \ No newline at end of file diff --git a/Model/Push/RefundProcessor.php b/Model/Push/RefundProcessor.php index 84cb704aa..176db1253 100644 --- a/Model/Push/RefundProcessor.php +++ b/Model/Push/RefundProcessor.php @@ -48,21 +48,23 @@ public function __construct( */ public function processPush(PushRequestInterface $pushRequest): bool { - $order = $this->orderRequestService->getOrderByRequest($pushRequest); + $this->pushRequest = $pushRequest; + $this->order = $this->orderRequestService->getOrderByRequest($pushRequest); + $this->payment = $this->order->getPayment(); if ($this->skipPendingRefundPush($pushRequest)) { return true; } if ($this->pushTransactionType->getStatusKey() !== 'BUCKAROO_MAGENTO2_STATUSCODE_SUCCESS' - && !$order->hasInvoices() + && !$this->order->hasInvoices() ) { throw new BuckarooException( __('Refund failed ! Status : %1 and the order does not contain an invoice', $this->pushTransactionType->getStatusKey()) ); } elseif ($this->pushTransactionType->getStatusKey() !== 'BUCKAROO_MAGENTO2_STATUSCODE_SUCCESS' - && $order->hasInvoices() + && $this->order->hasInvoices() ) { //don't proceed failed refund push $this->logging->addDebug(__METHOD__ . '|10|'); @@ -72,7 +74,7 @@ public function processPush(PushRequestInterface $pushRequest): bool return true; } - return $this->refundPush->receiveRefundPush($pushRequest, true, $order); + return $this->refundPush->receiveRefundPush($this->pushRequest, true, $this->order); } /** diff --git a/etc/di.xml b/etc/di.xml index 6be8d2f47..539dda484 100644 --- a/etc/di.xml +++ b/etc/di.xml @@ -509,6 +509,7 @@ Buckaroo\Magento2\Model\Push\DefaultProcessor Buckaroo\Magento2\Model\Push\IdealProcessor + Buckaroo\Magento2\Model\Push\PayPerEmailProcessor Buckaroo\Magento2\Model\Push\CreditManagmentPushProcessor Buckaroo\Magento2\Model\Push\GroupTransactionPushProcessor Buckaroo\Magento2\Model\Push\RefundProcessor From 45396e24fa15e686dcc64230af20d4573c568a73 Mon Sep 17 00:00:00 2001 From: Lucian Turiac Date: Mon, 24 Jul 2023 14:05:14 +0300 Subject: [PATCH 14/29] BP-2132 - Working on Push Refactor --- Model/Push.php | 2 +- Model/Push/AfterpayProcessor.php | 61 +++ Model/Push/DefaultProcessor.php | 673 +++++++++++++++------------ Model/Push/KlarnaKpProcessor.php | 73 +++ Model/Push/KlarnaProcessor.php | 29 ++ Model/Push/PayPerEmailProcessor.php | 134 +++++- Model/Push/PaypalProcessor.php | 78 ++++ Model/Push/TransferProcessor.php | 104 +++++ Service/Push/OrderRequestService.php | 63 +++ etc/di.xml | 6 +- 10 files changed, 924 insertions(+), 299 deletions(-) create mode 100644 Model/Push/AfterpayProcessor.php create mode 100644 Model/Push/PaypalProcessor.php create mode 100644 Model/Push/TransferProcessor.php diff --git a/Model/Push.php b/Model/Push.php index 1550edc9c..3162c93c5 100644 --- a/Model/Push.php +++ b/Model/Push.php @@ -494,7 +494,7 @@ public function receivePush() if (!empty($this->pushRequst->getStatusmessage())) { if ($this->order->getState() === Order::STATE_NEW && empty($this->pushRequst->getAdditionalInformation('frompayperemail')) - && !$this->pushRequst->hasPostData('brq_transaction_method', 'transfer') + && !$this->pushRequst->hasPostData('transaction_method', 'transfer') && empty($this->pushRequst->getRelatedtransactionPartialpayment()) && $this->pushRequst->hasPostData('statuscode', $statusCodeSuccess) ) { diff --git a/Model/Push/AfterpayProcessor.php b/Model/Push/AfterpayProcessor.php new file mode 100644 index 000000000..b2244b929 --- /dev/null +++ b/Model/Push/AfterpayProcessor.php @@ -0,0 +1,61 @@ +afterpayConfig = $afterpayConfig; + } + + /** + * @param array $paymentDetails + * @return bool + * @throws \Exception + */ + protected function invoiceShouldBeSaved(array &$paymentDetails): bool + { + if ($this->pushRequest->hasAdditionalInformation('initiated_by_magento', 1) && + ( + $this->pushRequest->hasPostData('transaction_method', 'afterpay') && + $this->pushRequest->hasAdditionalInformation('service_action_from_magento', 'capture') && + $this->afterpayConfig->isInvoiceCreatedAfterShipment() + )) { + $this->logging->addDebug(__METHOD__ . '|5_1|'); + $this->dontSaveOrderUponSuccessPush = true; + return false; + } + return true; + } +} \ No newline at end of file diff --git a/Model/Push/DefaultProcessor.php b/Model/Push/DefaultProcessor.php index 40d3741d7..75274669b 100644 --- a/Model/Push/DefaultProcessor.php +++ b/Model/Push/DefaultProcessor.php @@ -29,7 +29,12 @@ use Buckaroo\Magento2\Logging\Log; use Buckaroo\Magento2\Model\BuckarooStatusCode; use Buckaroo\Magento2\Model\ConfigProvider\Account; +use Buckaroo\Magento2\Model\ConfigProvider\Method\Afterpay; +use Buckaroo\Magento2\Model\ConfigProvider\Method\Afterpay2; +use Buckaroo\Magento2\Model\ConfigProvider\Method\Afterpay20; +use Buckaroo\Magento2\Model\ConfigProvider\Method\Creditcard; use Buckaroo\Magento2\Model\ConfigProvider\Method\Giftcards; +use Buckaroo\Magento2\Model\ConfigProvider\Method\Klarnakp; use Buckaroo\Magento2\Model\ConfigProvider\Method\Transfer; use Buckaroo\Magento2\Model\ConfigProvider\Method\Voucher; use Buckaroo\Magento2\Model\Method\BuckarooAdapter; @@ -37,6 +42,7 @@ use Buckaroo\Magento2\Service\Push\OrderRequestService; use Magento\Framework\Exception\FileSystemException; use Magento\Framework\Exception\LocalizedException; +use Magento\Payment\Model\InfoInterface; use Magento\Sales\Api\Data\TransactionInterface; use Magento\Sales\Model\Order; use Magento\Sales\Model\Order\Invoice; @@ -46,78 +52,64 @@ class DefaultProcessor implements PushProcessorInterface { - public const BUCKAROO_RECEIVED_TRANSACTIONS = 'buckaroo_received_transactions'; + public const BUCKAROO_RECEIVED_TRANSACTIONS = 'buckaroo_received_transactions'; public const BUCKAROO_RECEIVED_TRANSACTIONS_STATUSES = 'buckaroo_received_transactions_statuses'; - + /** + * @var Account + */ + public Account $configAccount; /** * @var PushRequestInterface */ protected PushRequestInterface $pushRequest; - /** * @var PushTransactionType */ protected PushTransactionType $pushTransactionType; - /** * @var OrderRequestService */ protected OrderRequestService $orderRequestService; - /** * @var Order|OrderPayment $order */ protected $order; - /** * @var OrderPayment|null */ protected ?OrderPayment $payment; - /** * @var Log $logging */ protected Log $logging; - /** * @var Data */ protected Data $helper; - /** * @var Transaction */ protected Transaction $transaction; - /** * @var PaymentGroupTransaction */ protected PaymentGroupTransaction $groupTransaction; - /** * @var bool */ protected bool $forceInvoice = false; - /** * @var bool */ protected bool $dontSaveOrderUponSuccessPush = false; - /** * @var BuckarooStatusCode */ protected BuckarooStatusCode $buckarooStatusCode; - /** * @var OrderStatusFactory */ - private OrderStatusFactory $orderStatusFactory; - - /** - * @var Account - */ - public Account $configAccount; + protected OrderStatusFactory $orderStatusFactory; /** * @param OrderRequestService $orderRequestService @@ -198,7 +190,10 @@ public function processPush(PushRequestInterface $pushRequest): bool return true; } - $this->processPushByStatus(); + $newStatus = $this->orderStatusFactory->get($this->pushRequest->getStatusCode(), $this->order); + $this->logging->addDebug(__METHOD__ . '|5|' . var_export($newStatus, true)); + + $this->processPushByStatus($newStatus); $this->logging->addDebug(__METHOD__ . '|5|'); if (!$this->dontSaveOrderUponSuccessPush) { @@ -210,73 +205,15 @@ public function processPush(PushRequestInterface $pushRequest): bool } /** - * Get the order increment ID based on the invoice number or order number from push - * - * @return string|null - */ - protected function getOrderIncrementId(): ?string - { - $brqOrderId = null; - - if (!empty($this->pushRequest->getInvoiceNumber()) && strlen($this->pushRequest->getInvoiceNumber()) > 0) { - $brqOrderId = $this->pushRequest->getInvoiceNumber(); - } - - if (!empty($this->pushRequest->getOrderNumber()) && strlen($this->pushRequest->getOrderNumber()) > 0) { - $brqOrderId = $this->pushRequest->getOrderNumber(); - } - - return $brqOrderId; - } - - /** - * Retrieves the transaction key from the push request. - * - * @return string - */ - protected function getTransactionKey(): string - { - $trxId = ''; - - if (!empty($this->pushRequest->getTransactions())) { - $trxId = $this->pushRequest->getTransactions(); - } - - if (!empty($this->pushRequest->getDatarequest())) { - $trxId = $this->pushRequest->getDatarequest(); - } - - if (!empty($this->pushRequest->getRelatedtransactionRefund())) { - $trxId = $this->pushRequest->getRelatedtransactionRefund(); - } - - return $trxId; - } - - /** - * Sets the transaction key in the payment's additional information if it's not already set. - * + * @param PushRequestInterface $pushRequest * @return void + * @throws \Exception */ - protected function setTransactionKey() - { - $payment = $this->order->getPayment(); - $originalKey = BuckarooAdapter::BUCKAROO_ORIGINAL_TRANSACTION_KEY_KEY; - $transactionKey = $this->getTransactionKey(); - - if (!$payment->getAdditionalInformation($originalKey) && strlen($transactionKey) > 0) { - $payment->setAdditionalInformation($originalKey, $transactionKey); - } - } - - /** - * Determine if the lock push processing criteria are met. - * - * @return bool - */ - protected function lockPushProcessingCriteria(): bool + protected function initializeFields(PushRequestInterface $pushRequest): void { - return false; + $this->pushRequest = $pushRequest; + $this->order = $this->orderRequestService->getOrderByRequest(); + $this->payment = $this->order->getPayment(); } /** @@ -306,21 +243,14 @@ protected function skipPush() } /** - * Check if it is needed to handle the push message based on postdata - * * @return bool - * @throws \Exception - * - * @SuppressWarnings(PHPMD.CyclomaticComplexity) */ - protected function skipSpecificTypesOfRequsts(): bool + protected function skipKlarnaCapture(): bool { - $this->logging->addDebug(__METHOD__ . '|1|'); - - $types = ['capture', 'cancelauthorize', 'cancelreservation']; if ($this->pushRequest->hasAdditionalInformation('initiated_by_magento', 1) - && $this->pushRequest->hasAdditionalInformation('service_action_from_magento', $types) - && empty($this->pushRequest->getRelatedtransactionRefund()) + && $this->pushRequest->hasPostData('transaction_method', ['klarnakp', 'KlarnaKp']) + && $this->pushRequest->hasAdditionalInformation('service_action_from_magento', 'pay') + && !empty($this->pushRequest->getServiceKlarnakpCaptureid()) ) { return true; } @@ -329,14 +259,21 @@ protected function skipSpecificTypesOfRequsts(): bool } /** + * Check if it is needed to handle the push message based on postdata + * * @return bool + * @throws \Exception + * + * @SuppressWarnings(PHPMD.CyclomaticComplexity) */ - protected function skipKlarnaCapture(): bool + protected function skipSpecificTypesOfRequsts(): bool { + $this->logging->addDebug(__METHOD__ . '|1|'); + + $types = ['capture', 'cancelauthorize', 'cancelreservation']; if ($this->pushRequest->hasAdditionalInformation('initiated_by_magento', 1) - && $this->pushRequest->hasPostData('transaction_method', ['klarnakp', 'KlarnaKp']) - && $this->pushRequest->hasAdditionalInformation('service_action_from_magento', 'pay') - && !empty($this->pushRequest->getServiceKlarnakpCaptureid()) + && $this->pushRequest->hasAdditionalInformation('service_action_from_magento', $types) + && empty($this->pushRequest->getRelatedtransactionRefund()) ) { return true; } @@ -519,6 +456,46 @@ protected function canUpdateOrderStatus(): bool return false; } + /** + * Sets the transaction key in the payment's additional information if it's not already set. + * + * @return void + */ + protected function setTransactionKey() + { + $payment = $this->order->getPayment(); + $originalKey = BuckarooAdapter::BUCKAROO_ORIGINAL_TRANSACTION_KEY_KEY; + $transactionKey = $this->getTransactionKey(); + + if (!$payment->getAdditionalInformation($originalKey) && strlen($transactionKey) > 0) { + $payment->setAdditionalInformation($originalKey, $transactionKey); + } + } + + /** + * Retrieves the transaction key from the push request. + * + * @return string + */ + protected function getTransactionKey(): string + { + $trxId = ''; + + if (!empty($this->pushRequest->getTransactions())) { + $trxId = $this->pushRequest->getTransactions(); + } + + if (!empty($this->pushRequest->getDatarequest())) { + $trxId = $this->pushRequest->getDatarequest(); + } + + if (!empty($this->pushRequest->getRelatedtransactionRefund())) { + $trxId = $this->pushRequest->getRelatedtransactionRefund(); + } + + return $trxId; + } + /** * @return void */ @@ -541,30 +518,33 @@ protected function setOrderStatusMessage(): void } /** - * Process the push according the response status - * - * @return bool - * @throws BuckarooException - * @throws LocalizedException + * Checks if the push request is a group transaction with a non-success status code. * - * @SuppressWarnings(PHPMD.CyclomaticComplexity) + * @return false|mixed */ - public function processPushByStatus() + protected function isGroupTransactionPart() { - $newStatus = $this->orderStatusFactory->get($this->pushRequest->getStatusCode(), $this->order); - $this->logging->addDebug(__METHOD__ . '|5|' . var_export($newStatus, true)); - - $statusKey = $this->pushTransactionType->getStatusKey(); - $statusMessage = $this->pushTransactionType->getStatusMessage(); + if (!is_null($this->pushRequest->getTransactions())) { + return $this->groupTransaction->getGroupTransactionByTrxId($this->pushRequest->getTransactions()); + } + return false; + } - if ($statusKey == 'BUCKAROO_MAGENTO2_STATUSCODE_SUCCESS') { - return $this->processSucceededPush($newStatus, $statusMessage); - } elseif (in_array($statusKey, $this->buckarooStatusCode->getFailedStatuses())) { - return $this->processFailedPush($newStatus, $statusMessage); - } elseif (in_array($statusKey, $this->buckarooStatusCode->getPendingStatuses())) { - return $this->processPendingPaymentPush(); - } else { - return $this->orderRequestService->setOrderNotificationNote($statusMessage); + /** + * Save the part group transaction. + * + * @return void + * @throws \Exception + */ + protected function savePartGroupTransaction() + { + $items = $this->groupTransaction->getGroupTransactionByTrxId($this->pushRequest->getTransactions()); + if (is_array($items) && count($items) > 0) { + foreach ($items as $item) { + $item2['status'] = $this->pushRequest->getStatusCode(); + $item2['entity_id'] = $item['entity_id']; + $this->groupTransaction->updateGroupTransaction($item2); + } } } @@ -572,87 +552,226 @@ public function processPushByStatus() * * @return true */ - protected function canProcessPostData() { + protected function canProcessPostData() + { return true; } /** - * Process the successful push response from Buckaroo and update the order accordingly. + * Checks if the payment is a partial payment using a gift card. * - * @param string $newStatus - * @param string $message * @return bool * @throws LocalizedException - * - * @SuppressWarnings(PHPMD.CyclomaticComplexity) - * @SuppressWarnings(PHPMD.NPathComplexity) - * @SuppressWarnings(PHPMD.ExcessiveMethodLength) */ - public function processSucceededPush(string $newStatus, string $message): bool + protected function giftcardPartialPayment(): bool { - $this->logging->addDebug(__METHOD__ . '|1|' . var_export($newStatus, true)); - - // Set amount - $amount = $this->order->getTotalDue(); - if (!empty($this->pushRequest->getAmount())) { - $amount = floatval($this->pushRequest->getAmount()); + if ($this->payment->getMethod() != Giftcards::CODE + || (!empty($this->pushRequest->getAmount()) + && $this->pushRequest->getAmount() >= $this->order->getGrandTotal()) + || empty($this->pushRequest->getRelatedtransactionPartialpayment()) + ) { + return false; } - $store = $this->order->getStore(); - $paymentMethod = $this->payment->getMethodInstance(); + if ($this->groupTransaction->isGroupTransaction($this->pushRequest->getInvoiceNumber())) { + return false; + } - // Send email if is not sent - if (!$this->order->getEmailSent() - && ($this->configAccount->getOrderConfirmationEmail($store) - || $paymentMethod->getConfigData('order_email', $store) - ) - ) { - $this->logging->addDebug(__METHOD__ . '|sendemail|' . - var_export($this->configAccount->getOrderConfirmationEmailSync($store), true)); - $this->orderRequestService->sendOrderEmail( - (bool)$this->configAccount->getOrderConfirmationEmailSync($store) + if (!$this->pushTransactionType->getTransactionType() == PushTransactionType::BUCK_PUSH_GROUPTRANSACTION_TYPE) { + $this->payment->setAdditionalInformation( + BuckarooAdapter::BUCKAROO_ORIGINAL_TRANSACTION_KEY_KEY, + $this->pushRequest->getRelatedtransactionPartialpayment() ); - } - /** - * force state eventhough this can lead to a transition of the order - * like new -> processing - */ - $forceState = false; - $state = Order::STATE_PROCESSING; - $this->dontSaveOrderUponSuccessPush = false; + $this->addGiftcardPartialPaymentToPaymentInformation(); + } - if ($this->canPushInvoice()) { - $description = 'Payment status : ' . $message . "
"; - $amount = $this->order->getBaseTotalDue(); - $description .= 'Total amount of ' . - $this->order->getBaseCurrency()->formatTxt($amount) . ' has been paid'; + return true; + } - $this->logging->addDebug(__METHOD__ . '|4|'); - if (!$this->saveInvoice()) { + /** + * Adds the gift card partial payment information to the payment's additional information. + * + * @return void + */ + protected function addGiftcardPartialPaymentToPaymentInformation() + { + $payment = $this->order->getPayment(); + + $transactionAmount = $this->pushRequest->getAmount(); + $transactionKey = $this->pushRequest->getTransactions(); + $transactionMethod = $this->pushRequest->getTransactionMethod(); + + $transactionData = $payment->getAdditionalInformation(BuckarooAdapter::BUCKAROO_ALL_TRANSACTIONS); + + $transactionArray = []; + if (is_array($transactionData) && count($transactionData) > 0) { + $transactionArray = $transactionData; + } + + if (!empty($transactionKey) && $transactionAmount > 0) { + $transactionArray[$transactionKey] = [$transactionMethod, $transactionAmount]; + + $payment->setAdditionalInformation( + BuckarooAdapter::BUCKAROO_ALL_TRANSACTIONS, + $transactionArray + ); + } + } + + /** + * Process the push according the response status + * + * @return bool + * @throws LocalizedException + * @SuppressWarnings(PHPMD.CyclomaticComplexity) + */ + protected function processPushByStatus(): bool + { + $newStatus = $this->getNewStatus(); + $statusKey = $this->pushTransactionType->getStatusKey(); + $statusMessage = $this->pushTransactionType->getStatusMessage(); + + if ($statusKey == 'BUCKAROO_MAGENTO2_STATUSCODE_SUCCESS') { + return $this->processSucceededPush($newStatus, $statusMessage); + } elseif (in_array($statusKey, $this->buckarooStatusCode->getFailedStatuses())) { + return $this->processFailedPush($newStatus, $statusMessage); + } elseif (in_array($statusKey, $this->buckarooStatusCode->getPendingStatuses())) { + return $this->processPendingPaymentPush(); + } else { + $this->orderRequestService->setOrderNotificationNote($statusMessage); + return true; + } + } + + /** + * @return false|string|null + * @throws LocalizedException + */ + protected function getNewStatus() + { + return $this->orderStatusFactory->get($this->pushRequest->getStatusCode(), $this->order); + } + + /** + * Process the successful push response from Buckaroo and update the order accordingly. + * + * @param string $newStatus + * @param string $message + * @return bool + * @throws LocalizedException + * + * @SuppressWarnings(PHPMD.CyclomaticComplexity) + * @SuppressWarnings(PHPMD.NPathComplexity) + * @SuppressWarnings(PHPMD.ExcessiveMethodLength) + */ + public function processSucceededPush(string $newStatus, string $message): bool + { + $this->logging->addDebug(__METHOD__ . '|1|' . var_export($newStatus, true)); + + $this->setBuckarooReservationNumber(); + + $this->sendOrderEmail(); + + $paymentDetails = $this->getPaymentDetails($message); + $paymentDetails['state'] = Order::STATE_PROCESSING; + $paymentDetails['newStatus'] = $newStatus; + + $this->dontSaveOrderUponSuccessPush = false; + + if ($this->canPushInvoice()) { + $saveInvoice = $this->invoiceShouldBeSaved($paymentDetails); + if ($saveInvoice && !$this->saveInvoice()) { return false; } - } else { - $description = 'Authorization status : ' . $message . "
"; - $description .= 'Total amount of ' . $this->order->getBaseCurrency()->formatTxt($amount) - . ' has been authorized. Please create an invoice to capture the authorized amount.'; - $forceState = true; } if ($this->groupTransaction->isGroupTransaction($this->pushRequest->getInvoiceNumber())) { - $forceState = true; + $paymentDetails['forceState'] = true; } $this->logging->addDebug(__METHOD__ . '|8|'); - $this->orderRequestService->updateOrderStatus($state, $newStatus, $description, $forceState, - $this->dontSaveOrderUponSuccessPush); + $this->processSucceededPushAuthorization(); + + $this->orderRequestService->updateOrderStatus( + $paymentDetails['state'], + $paymentDetails['newStatus'], + $paymentDetails['description'], + $paymentDetails['forceState'], + $this->dontSaveOrderUponSuccessPush + ); $this->logging->addDebug(__METHOD__ . '|9|'); return true; } + /** + * Process succeeded push authorization. + * + * @return void + */ + private function processSucceededPushAuthorization(): void + { + $authPpaymentMethods = [ + Afterpay::CODE, + Afterpay2::CODE, + Afterpay20::CODE, + Creditcard::CODE, + Klarnakp::CODE + ]; + + if (in_array($this->payment->getMethod(), $authPpaymentMethods)) { + if ((($this->payment->getMethod() == Klarnakp::CODE) + || ( + !empty($this->pushRequest->getTransactionType()) + && in_array($this->pushRequest->getTransactionType(), ['I038', 'I880']) + ) + ) && !empty($this->pushRequest->getStatusCode()) + && ($this->pushRequest->getStatusCode() == 190) + ) { + $this->logging->addDebug(__METHOD__ . '|88|' . var_export($this->payment->getMethod(), true)); + $this->order->setState(Order::STATE_PROCESSING); + $this->order->save(); + } + } + } + + protected function setBuckarooReservationNumber(): bool + { + return false; + } + + + /** + * @todo GIFTCARD PARTIAL PAYMENT TO BE MOVED in a separate class + */ + + /** + * Send Order email if was not sent + * + * @return void + * @throws LocalizedException + */ + protected function sendOrderEmail(): void + { + $store = $this->order->getStore(); + $paymentMethod = $this->payment->getMethodInstance(); + + if (!$this->order->getEmailSent() + && ($this->configAccount->getOrderConfirmationEmail($store) + || $paymentMethod->getConfigData('order_email', $store) + ) + ) { + $this->logging->addDebug(__METHOD__ . '|sendemail|' . + var_export($this->configAccount->getOrderConfirmationEmailSync($store), true)); + $this->orderRequestService->sendOrderEmail( + (bool)$this->configAccount->getOrderConfirmationEmailSync($store) + ); + } + } + /** * Can create invoice on push * @@ -720,7 +839,7 @@ protected function saveInvoice(): bool } if (!$invoice->getEmailSent() && $this->configAccount->getInvoiceEmail($this->order->getStore())) { - $this->logging->addDebug(__METHOD__ . '|30|sendinvoiceemail'); + $this->logging->addDebug(__METHOD__ . '|30|sendinvoiceemail'); $this->orderRequestService->sendInvoiceEmail($invoice, true); } } @@ -735,6 +854,49 @@ protected function saveInvoice(): bool return true; } + /** + * Adds transaction data to the order payment with the given transaction key and data. + * + * @param bool $transactionKey + * @param bool $data + * @return Payment + * @throws LocalizedException + * @throws \Exception + */ + public function addTransactionData(bool $transactionKey = false, bool $data = false): Payment + { + $this->payment = $this->order->getPayment(); + $transactionKey = $transactionKey ?: $this->getTransactionKey(); + + if (strlen($transactionKey) <= 0) { + throw new BuckarooException(__('There was no transaction ID found')); + } + + /** + * Save the transaction's response as additional info for the transaction. + */ + $postData = $data ?: $this->pushRequest->getData(); + $rawInfo = $this->helper->getTransactionAdditionalInfo($postData); + + $this->payment->setTransactionAdditionalInfo( + Transaction::RAW_DETAILS, + $rawInfo + ); + + /** + * Save the payment's transaction key. + */ + $this->payment->setTransactionId($transactionKey . '-capture'); + + $this->payment->setParentTransactionId($transactionKey); + $this->payment->setAdditionalInformation( + BuckarooAdapter::BUCKAROO_ORIGINAL_TRANSACTION_KEY_KEY, + $transactionKey + ); + + return $this->payment; + } + /** * Process the failed push response from Buckaroo and update the order accordingly. * @@ -790,7 +952,7 @@ public function processFailedPush(string $newStatus, string $message): bool $payment->save(); } - $this->updateOrderStatus(Order::STATE_CANCELED, $newStatus, $description); + $this->orderRequestService->updateOrderStatus(Order::STATE_CANCELED, $newStatus, $description); try { $this->order->cancel()->save(); @@ -809,7 +971,7 @@ public function processFailedPush(string $newStatus, string $message): bool ) { $force = true; } - $this->updateOrderStatus(Order::STATE_CANCELED, $newStatus, $description, $force); + $this->orderRequestService->updateOrderStatus(Order::STATE_CANCELED, $newStatus, $description, $force); return true; } @@ -819,157 +981,78 @@ protected function processPendingPaymentPush(): bool return true; } - /** - * @todo GIFTCARD PARTIAL PAYMENT TO BE MOVED in a separate class - */ - - - /** - * Checks if the push request is a group transaction with a non-success status code. - * - * @return false|mixed - */ - protected function isGroupTransactionPart() - { - if (!is_null($this->pushRequest->getTransactions())) { - return $this->groupTransaction->getGroupTransactionByTrxId($this->pushRequest->getTransactions()); - } - return false; - } - - /** - * Save the part group transaction. - * - * @return void - * @throws \Exception - */ - protected function savePartGroupTransaction() - { - $items = $this->groupTransaction->getGroupTransactionByTrxId($this->pushRequest->getTransactions()); - if (is_array($items) && count($items) > 0) { - foreach ($items as $item) { - $item2['status'] = $this->pushRequest->getStatusCode(); - $item2['entity_id'] = $item['entity_id']; - $this->groupTransaction->updateGroupTransaction($item2); - } - } - } - - /** - * Checks if the payment is a partial payment using a gift card. + * Get the order increment ID based on the invoice number or order number from push * - * @return bool - * @throws LocalizedException + * @return string|null */ - protected function giftcardPartialPayment(): bool + protected function getOrderIncrementId(): ?string { - if ($this->payment->getMethod() != Giftcards::CODE - || (!empty($this->pushRequest->getAmount()) - && $this->pushRequest->getAmount() >= $this->order->getGrandTotal()) - || empty($this->pushRequest->getRelatedtransactionPartialpayment()) - ) { - return false; - } + $brqOrderId = null; - if ($this->groupTransaction->isGroupTransaction($this->pushRequest->getInvoiceNumber())) { - return false; + if (!empty($this->pushRequest->getInvoiceNumber()) && strlen($this->pushRequest->getInvoiceNumber()) > 0) { + $brqOrderId = $this->pushRequest->getInvoiceNumber(); } - if (!$this->pushTransactionType->getTransactionType() == PushTransactionType::BUCK_PUSH_GROUPTRANSACTION_TYPE) { - $this->payment->setAdditionalInformation( - BuckarooAdapter::BUCKAROO_ORIGINAL_TRANSACTION_KEY_KEY, - $this->pushRequest->getRelatedtransactionPartialpayment() - ); - - $this->addGiftcardPartialPaymentToPaymentInformation(); + if (!empty($this->pushRequest->getOrderNumber()) && strlen($this->pushRequest->getOrderNumber()) > 0) { + $brqOrderId = $this->pushRequest->getOrderNumber(); } - return true; + return $brqOrderId; } /** - * Adds the gift card partial payment information to the payment's additional information. + * Determine if the lock push processing criteria are met. * - * @return void + * @return bool */ - protected function addGiftcardPartialPaymentToPaymentInformation() + protected function lockPushProcessingCriteria(): bool { - $payment = $this->order->getPayment(); - - $transactionAmount = $this->pushRequest->getAmount(); - $transactionKey = $this->pushRequest->getTransactions(); - $transactionMethod = $this->pushRequest->getTransactionMethod(); - - $transactionData = $payment->getAdditionalInformation(BuckarooAdapter::BUCKAROO_ALL_TRANSACTIONS); - - $transactionArray = []; - if (is_array($transactionData) && count($transactionData) > 0) { - $transactionArray = $transactionData; - } - - if (!empty($transactionKey) && $transactionAmount > 0) { - $transactionArray[$transactionKey] = [$transactionMethod, $transactionAmount]; - - $payment->setAdditionalInformation( - BuckarooAdapter::BUCKAROO_ALL_TRANSACTIONS, - $transactionArray - ); - } + return false; } - /** - * Adds transaction data to the order payment with the given transaction key and data. - * - * @param bool $transactionKey - * @param bool $data - * @return Payment - * @throws LocalizedException - * @throws \Exception - */ - public function addTransactionData(bool $transactionKey = false, bool $data = false): Payment + protected function getPaymentDetails($message) { - $this->payment = $this->order->getPayment(); - $transactionKey = $transactionKey ?: $this->getTransactionKey(); - - if (strlen($transactionKey) <= 0) { - throw new BuckarooException(__('There was no transaction ID found')); + // Set amount + $amount = $this->order->getTotalDue(); + if (!empty($this->pushRequest->getAmount())) { + $amount = floatval($this->pushRequest->getAmount()); } /** - * Save the transaction's response as additional info for the transaction. + * force state eventhough this can lead to a transition of the order + * like new -> processing */ - $postData = $data ?: $this->pushRequest->getData(); - $rawInfo = $this->helper->getTransactionAdditionalInfo($postData); - - $this->payment->setTransactionAdditionalInfo( - Transaction::RAW_DETAILS, - $rawInfo - ); + $forceState = false; + $this->dontSaveOrderUponSuccessPush = false; - /** - * Save the payment's transaction key. - */ - $this->payment->setTransactionId($transactionKey . '-capture'); + if ($this->canPushInvoice()) { + $description = 'Payment status : ' . $message . "
"; + $amount = $this->order->getBaseTotalDue(); + $description .= 'Total amount of ' . + $this->order->getBaseCurrency()->formatTxt($amount) . ' has been paid'; - $this->payment->setParentTransactionId($transactionKey); - $this->payment->setAdditionalInformation( - BuckarooAdapter::BUCKAROO_ORIGINAL_TRANSACTION_KEY_KEY, - $transactionKey - ); + $this->logging->addDebug(__METHOD__ . '|4|'); + } else { + $description = 'Authorization status : ' . $message . "
"; + $description .= 'Total amount of ' . $this->order->getBaseCurrency()->formatTxt($amount) + . ' has been authorized. Please create an invoice to capture the authorized amount.'; + $forceState = true; + } - return $this->payment; + return [ + 'amount' => $amount, + 'description' => $description, + 'forceState' => $forceState + ]; } /** - * @param PushRequestInterface $pushRequest - * @return void - * @throws \Exception + * @param array $paymentDetails + * @return bool */ - protected function initializeFields(PushRequestInterface $pushRequest): void + protected function invoiceShouldBeSaved(array &$paymentDetails): bool { - $this->pushRequest = $pushRequest; - $this->order = $this->orderRequestService->getOrderByRequest(); - $this->payment = $this->order->getPayment(); + return true; } } \ No newline at end of file diff --git a/Model/Push/KlarnaKpProcessor.php b/Model/Push/KlarnaKpProcessor.php index bafb5329f..45e53eff6 100644 --- a/Model/Push/KlarnaKpProcessor.php +++ b/Model/Push/KlarnaKpProcessor.php @@ -2,8 +2,42 @@ namespace Buckaroo\Magento2\Model\Push; +use Buckaroo\Magento2\Helper\Data; +use Buckaroo\Magento2\Helper\PaymentGroupTransaction; +use Buckaroo\Magento2\Logging\Log; +use Buckaroo\Magento2\Model\BuckarooStatusCode; +use Buckaroo\Magento2\Model\ConfigProvider\Account; +use Buckaroo\Magento2\Model\ConfigProvider\Method\Klarnakp; +use Buckaroo\Magento2\Model\ConfigProvider\Method\PayPerEmail; +use Buckaroo\Magento2\Model\OrderStatusFactory; +use Buckaroo\Magento2\Service\LockerProcess; +use Buckaroo\Magento2\Service\Push\OrderRequestService; +use Magento\Sales\Api\Data\TransactionInterface; + class KlarnaKpProcessor extends DefaultProcessor { + /** + * @var Klarnakp + */ + private Klarnakp $klarnakpConfig; + + public function __construct( + OrderRequestService $orderRequestService, + PushTransactionType $pushTransactionType, + Log $logging, + Data $helper, + TransactionInterface $transaction, + PaymentGroupTransaction $groupTransaction, + BuckarooStatusCode $buckarooStatusCode, + OrderStatusFactory $orderStatusFactory, + Account $configAccount, + Klarnakp $klarnakpConfig + ) { + parent::__construct($orderRequestService, $pushTransactionType, $logging, $helper, $transaction, + $groupTransaction, $buckarooStatusCode, $orderStatusFactory, $configAccount); + $this->klarnakpConfig = $klarnakpConfig; + } + /** * Retrieves the transaction key from the push request. * @@ -20,4 +54,43 @@ protected function getTransactionKey(): string return $trxId; } + + protected function setBuckarooReservationNumber(): bool + { + if (!empty($this->pushRequest->getServiceKlarnakpReservationnumber())) { + $this->order->setBuckarooReservationNumber($this->pushRequest->getServiceKlarnakpReservationnumber()); + $this->order->save(); + return true; + } + + return false; + } + + /** + * @param array $paymentDetails + * @return bool + * @throws \Exception + */ + protected function invoiceShouldBeSaved(array &$paymentDetails): bool + { + if ($this->pushRequest->hasAdditionalInformation('initiated_by_magento', 1) && + ( + $this->pushRequest->hasPostData('transaction_method', 'KlarnaKp') && + $this->pushRequest->hasAdditionalInformation('service_action_from_magento', 'pay') && + empty($this->pushRequest->getServiceKlarnakpReservationnumber()) && + $this->klarnakpConfig->isInvoiceCreatedAfterShipment() + )) { + $this->logging->addDebug(__METHOD__ . '|5_1|'); + $this->dontSaveOrderUponSuccessPush = true; + return false; + } + + if (!empty($this->pushRequest->getServiceKlarnakpAutopaytransactionkey()) + && ($this->pushRequest->getStatusCode() == 190) + ) { + return true; + } + + return true; + } } \ No newline at end of file diff --git a/Model/Push/KlarnaProcessor.php b/Model/Push/KlarnaProcessor.php index 6088fc67a..42fdade42 100644 --- a/Model/Push/KlarnaProcessor.php +++ b/Model/Push/KlarnaProcessor.php @@ -7,6 +7,8 @@ use Buckaroo\Magento2\Logging\Log; use Buckaroo\Magento2\Service\LockerProcess; use Magento\Framework\Exception\FileSystemException; +use Magento\Framework\Exception\LocalizedException; +use Magento\Sales\Model\Order; class KlarnaProcessor extends DefaultProcessor { @@ -26,4 +28,31 @@ protected function getTransactionKey(): string return $trxId; } + + protected function setBuckarooReservationNumber(): bool + { + if (!empty($this->pushRequest->getServiceKlarnaReservationnumber())) { + $this->order->setBuckarooReservationNumber($this->pushRequest->getServiceKlarnaReservationnumber()); + $this->order->save(); + return true; + } + + return false; + } + + /** + * @param array $paymentDetails + * @return bool + * @throws \Exception + */ + protected function invoiceShouldBeSaved(array &$paymentDetails): bool + { + if (!empty($this->pushRequest->getServiceKlarnakpAutopaytransactionkey()) + && ($this->pushRequest->getStatusCode() == 190) + ) { + return true; + } + + return true; + } } \ No newline at end of file diff --git a/Model/Push/PayPerEmailProcessor.php b/Model/Push/PayPerEmailProcessor.php index 960abeedc..84622e7f6 100644 --- a/Model/Push/PayPerEmailProcessor.php +++ b/Model/Push/PayPerEmailProcessor.php @@ -17,7 +17,7 @@ use Buckaroo\Magento2\Service\LockerProcess; use Buckaroo\Magento2\Service\Push\OrderRequestService; use Magento\Framework\Exception\FileSystemException; -use Magento\Payment\Model\InfoInterface; +use Magento\Framework\Exception\LocalizedException; use Magento\Sales\Api\Data\TransactionInterface; use Magento\Sales\Model\Order; @@ -31,7 +31,12 @@ class PayPerEmailProcessor extends DefaultProcessor /** * @var PayPerEmail */ - public PayPerEmail $configPayPerEmail; + private PayPerEmail $configPayPerEmail; + + /** + * @var bool + */ + private bool $isPayPerEmailB2BModePushInitial; public function __construct( OrderRequestService $orderRequestService, @@ -258,4 +263,129 @@ protected function setOrderStatusMessage(): void } } } + + /** + * Check if the Pay Per Email payment is in B2B mode. + * + * @return bool + */ + public function isPayPerEmailB2BModePush(): bool + { + if (!isset($this->isPayPerEmailB2BModePushInitial)) { + if (!empty($this->pushRequest->getAdditionalInformation('frompayperemail')) + && !empty($this->pushRequest->getTransactionMethod()) + && ($this->pushRequest->getTransactionMethod() == 'payperemail') + && $this->configPayPerEmail->isEnabledB2B()) { + $this->logging->addDebug(__METHOD__ . '|5|'); + $this->isPayPerEmailB2BModePushInitial = true; + } + } else { + $this->isPayPerEmailB2BModePushInitial = false; + } + + return $this->isPayPerEmailB2BModePushInitial; + } + + /** + * Check if the Pay Per Email payment is in B2B mode and in the initial push. + * + * @return bool + */ + public function isPayPerEmailB2BModePushInitial(): bool + { + return $this->isPayPerEmailB2BModePush() + && ($this->pushTransactionType->getStatusKey() == 'BUCKAROO_MAGENTO2_STATUSCODE_WAITING_ON_CONSUMER'); + } + + /** + * @return false|string|null + * @throws BuckarooException + * @throws LocalizedException + */ + protected function getNewStatus() + { + $newStatus = $this->orderStatusFactory->get($this->pushRequest->getStatusCode(), $this->order); + $this->logging->addDebug(__METHOD__ . '|5|' . var_export($newStatus, true)); + + if ($this->isPayPerEmailB2BModePushInitial()) { + $this->pushTransactionType->setStatusKey('BUCKAROO_MAGENTO2_STATUSCODE_SUCCESS'); + $newStatus = $this->configAccount->getOrderStatusSuccess(); + $this->logging->addDebug(__METHOD__ . '|15|' . var_export( + [$this->pushTransactionType->getStatusKey(), $newStatus], + true + ) + ); + } + + return $newStatus; + } + + protected function getPaymentDetails($message) + { + // Set amount + $amount = $this->order->getTotalDue(); + if (!empty($this->pushRequest->getAmount())) { + $amount = floatval($this->pushRequest->getAmount()); + } + + /** + * force state eventhough this can lead to a transition of the order + * like new -> processing + */ + $forceState = false; + $this->dontSaveOrderUponSuccessPush = false; + + if ($this->canPushInvoice()) { + $description = 'Payment status : ' . $message . "
"; + $amount = $this->order->getBaseTotalDue(); + $description .= 'Total amount of ' . + $this->order->getBaseCurrency()->formatTxt($amount) . ' has been paid'; + + $this->logging->addDebug(__METHOD__ . '|4|'); + } else { + $description = 'Authorization status : ' . $message . "
"; + $description .= 'Total amount of ' . $this->order->getBaseCurrency()->formatTxt($amount) + . ' has been authorized. Please create an invoice to capture the authorized amount.'; + $forceState = true; + } + + if ($this->isPayPerEmailB2BModePushInitial) { + $description = ''; + } + + return [ + 'amount' => $amount, + 'description' => $description, + 'forceState' => $forceState + ]; + } + + /** + * @param array $paymentDetails + * @return bool + * @throws \Exception + */ + protected function invoiceShouldBeSaved(array &$paymentDetails): bool + { + if (!$this->isPayPerEmailB2BModePushInitial && $this->isPayPerEmailB2BModePush()) { + $this->logging->addDebug(__METHOD__ . '|4_1|'); + //Fix for suspected fraud when the order currency does not match with the payment's currency + $amount = $this->payment->isSameCurrency() && $this->payment->isCaptureFinal($this->order->getGrandTotal()) + ? $this->order->getGrandTotal() + : $this->order->getBaseTotalDue(); + $this->payment->registerCaptureNotification($amount); + $this->payment->save(); + $this->order->setState('complete'); + $this->order->addStatusHistoryComment($paymentDetails['description'], 'complete'); + $this->order->save(); + + if ($transactionKey = $this->getTransactionKey()) { + foreach ($this->order->getInvoiceCollection() as $invoice) { + $invoice->setTransactionId($transactionKey)->save(); + } + } + return false; + } + return true; + } } \ No newline at end of file diff --git a/Model/Push/PaypalProcessor.php b/Model/Push/PaypalProcessor.php new file mode 100644 index 000000000..0a1ef9243 --- /dev/null +++ b/Model/Push/PaypalProcessor.php @@ -0,0 +1,78 @@ +paypalConfig = $paypalConfig; + + } + + /** + * @return false|string|null + * @throws BuckarooException + * @throws LocalizedException + */ + protected function getNewStatus() + { + $newStatus = $this->orderStatusFactory->get($this->pushRequest->getStatusCode(), $this->order); + $this->logging->addDebug(__METHOD__ . '|5|' . var_export($newStatus, true)); + + if ($this->pushTransactionType->getStatusKey() == 'BUCKAROO_MAGENTO2_STATUSCODE_SUCCESS' + && $this->order->getPayment()->getMethod() == PaypalConfig::CODE) { + $newSellersProtectionStatus = $this->paypalConfig->getSellersProtectionIneligible(); + if ($this->paypalConfig->getSellersProtection() && !empty($newSellersProtectionStatus)) { + $newStatus = $newSellersProtectionStatus; + } + } + + return $newStatus; + } +} \ No newline at end of file diff --git a/Model/Push/TransferProcessor.php b/Model/Push/TransferProcessor.php new file mode 100644 index 000000000..4152ee8be --- /dev/null +++ b/Model/Push/TransferProcessor.php @@ -0,0 +1,104 @@ +order->getTotalDue(); + if (!empty($this->pushRequest->getAmount())) { + $amount = floatval($this->pushRequest->getAmount()); + } + + /** + * force state eventhough this can lead to a transition of the order + * like new -> processing + */ + $forceState = false; + $this->dontSaveOrderUponSuccessPush = false; + + if ($this->canPushInvoice()) { + $description = 'Payment status : ' . $message . "
"; + if ($this->pushRequest->hasPostData('transaction_method', 'transfer')) { + //keep amount fetched from brq_amount + $description .= 'Amount of ' . $this->order->getBaseCurrency()->formatTxt($amount) . ' has been paid'; + } + $this->logging->addDebug(__METHOD__ . '|4|'); + } else { + $description = 'Authorization status : ' . $message . "
"; + $description .= 'Total amount of ' . $this->order->getBaseCurrency()->formatTxt($amount) + . ' has been authorized. Please create an invoice to capture the authorized amount.'; + $forceState = true; + } + + return [ + 'amount' => $amount, + 'description' => $description, + 'forceState' => $forceState + ]; + } + + /** + * @param array $paymentDetails + * @return bool + * @throws LocalizedException + */ + protected function invoiceShouldBeSaved(array &$paymentDetails): bool + { + $amount = $paymentDetails['amount']; + //invoice only in case of full or last remained amount + $this->logging->addDebug(__METHOD__ . '|61|' . var_export([ + $this->order->getId(), + $paymentDetails['amount'], + $this->order->getTotalDue(), + $this->order->getTotalPaid(), + ], true)); + + $saveInvoice = true; + + if (($paymentDetails['amount'] < $this->order->getTotalDue()) + || (($paymentDetails['amount'] == $this->order->getTotalDue()) && ($this->order->getTotalPaid() > 0)) + ) { + $this->logging->addDebug(__METHOD__ . '|64|'); + + $paymentDetails['forceState'] = true; + if ($amount < $this->order->getTotalDue()) { + $this->logging->addDebug(__METHOD__ . '|65|'); + $paymentDetails['state'] = Order::STATE_NEW; + $paymentDetails['newStatus'] = $this->orderStatusFactory->get( + BuckarooStatusCode::PENDING_PROCESSING, + $this->order + ); + $saveInvoice = false; + } + + $this->orderRequestService->saveAndReloadOrder(); + + $this->order->setTotalDue($this->order->getTotalDue() - $amount); + $this->order->setBaseTotalDue($this->order->getTotalDue() - $amount); + + $totalPaid = $this->order->getTotalPaid() + $amount; + $this->order->setTotalPaid( + $totalPaid > $this->order->getGrandTotal() ? $this->order->getGrandTotal() : $totalPaid + ); + + $baseTotalPaid = $this->order->getBaseTotalPaid() + $amount; + $this->order->setBaseTotalPaid( + $baseTotalPaid > $this->order->getBaseGrandTotal() ? + $this->order->getBaseGrandTotal() : $baseTotalPaid + ); + + $this->orderRequestService->saveAndReloadOrder(); + + $this->orderRequestService->updateTotalOnOrder($this->order); + } + + return $saveInvoice; + } +} \ No newline at end of file diff --git a/Service/Push/OrderRequestService.php b/Service/Push/OrderRequestService.php index 79a7c70f5..9b3b46aa6 100644 --- a/Service/Push/OrderRequestService.php +++ b/Service/Push/OrderRequestService.php @@ -4,6 +4,7 @@ use Buckaroo\Magento2\Api\PushRequestInterface; use Buckaroo\Magento2\Logging\Log; +use Magento\Framework\App\ResourceConnection; use Magento\Framework\Phrase; use Magento\Sales\Api\Data\TransactionInterface; use Magento\Sales\Model\Order; @@ -40,12 +41,18 @@ class OrderRequestService */ private InvoiceSender $invoiceSender; + /** + * @var ResourceConnection + */ + protected ResourceConnection $resourceConnection; + /** * @param Order $order * @param Log $logging * @param TransactionInterface $transaction * @param OrderSender $orderSender * @param InvoiceSender $invoiceSender + * @param ResourceConnection $resourceConnection */ public function __construct( Order $order, @@ -53,12 +60,14 @@ public function __construct( TransactionInterface $transaction, OrderSender $orderSender, InvoiceSender $invoiceSender, + ResourceConnection $resourceConnection ) { $this->order = $order; $this->logging = $logging; $this->transaction = $transaction; $this->orderSender = $orderSender; $this->invoiceSender = $invoiceSender; + $this->resourceConnection = $resourceConnection; } /** @@ -242,4 +251,58 @@ public function sendInvoiceEmail(Invoice $invoice, bool $forceSyncMode = false): { return $this->invoiceSender->send($invoice, $forceSyncMode); } + + public function updateTotalOnOrder($order) { + + try { + $connection = $this->resourceConnection->getConnection(); + $connection->update( + $connection->getTableName('sales_order'), + [ + 'total_due' => $order->getTotalDue(), + 'base_total_due' => $order->getTotalDue(), + 'total_paid' => $order->getTotalPaid(), + 'base_total_paid' => $order->getBaseTotalPaid(), + ], + $connection->quoteInto('entity_id = ?', $order->getId()) + ); + + return true; + } catch (\Exception $exception) { + return false; + } + + } + + /** + * Save the current order and reload it from the database. + * + * @return void + * @throws \Exception + */ + public function saveAndReloadOrder() + { + $this->order->save(); + $this->loadOrder(); + } + + /** + * Load the order from the Push Data based on the Order Increment ID or transaction key. + * + * @return void + * @throws \Exception + */ + private function loadOrder() + { + $brqOrderId = $this->getOrderIncrementId(); + + //Check if the order can receive further status updates + $this->order->loadByIncrementId((string)$brqOrderId); + + if (!$this->order->getId()) { + $this->logging->addDebug('Order could not be loaded by Invoice Number or Order Number'); + // try to get order by transaction id on payment. + $this->order = $this->getOrderByTransactionKey(); + } + } } \ No newline at end of file diff --git a/etc/di.xml b/etc/di.xml index 539dda484..ab54b47ae 100644 --- a/etc/di.xml +++ b/etc/di.xml @@ -509,12 +509,16 @@ Buckaroo\Magento2\Model\Push\DefaultProcessor Buckaroo\Magento2\Model\Push\IdealProcessor + Buckaroo\Magento2\Model\Push\PaypalProcessor Buckaroo\Magento2\Model\Push\PayPerEmailProcessor + Buckaroo\Magento2\Model\Push\TransferProcessor + Buckaroo\Magento2\Model\Push\AfterpayProcessor + Buckaroo\Magento2\Model\Push\KlarnaProcessor + Buckaroo\Magento2\Model\Push\KlarnaKpProcessor- Buckaroo\Magento2\Model\Push\CreditManagmentPushProcessor Buckaroo\Magento2\Model\Push\GroupTransactionPushProcessor Buckaroo\Magento2\Model\Push\RefundProcessor Buckaroo\Magento2\Model\Push\CancelAuthorizeProcessor - From 71f40321952cc971e57866bc80aa92b91b14883e Mon Sep 17 00:00:00 2001 From: Lucian Turiac Date: Tue, 25 Jul 2023 16:31:52 +0300 Subject: [PATCH 15/29] BP-2132 - Working on Push Refactor --- Model/Push.php | 7 +- Model/Push/AfterpayProcessor.php | 4 - Model/Push/CreditManagmentProcessor.php | 100 ++++++++++++++++++++++++ Model/Push/DefaultProcessor.php | 21 +---- Model/Push/KlarnaKpProcessor.php | 20 ++++- Model/Push/KlarnaProcessor.php | 17 ++++ Service/Push/OrderRequestService.php | 5 +- etc/di.xml | 14 ++-- 8 files changed, 154 insertions(+), 34 deletions(-) create mode 100644 Model/Push/CreditManagmentProcessor.php diff --git a/Model/Push.php b/Model/Push.php index 3162c93c5..a1e254b34 100644 --- a/Model/Push.php +++ b/Model/Push.php @@ -341,8 +341,9 @@ public function receivePush() $pushTransactionType = $this->pushTransactionType->getPushTransactionType($this->pushRequst, $this->order); // Process Push -// $this->pushProcessor = $this->pushProcessorsFactory->get($pushTransactionType); -// return $this->pushProcessor->processPush($this->pushRequst); + $this->pushProcessor = $this->pushProcessorsFactory->get($pushTransactionType); + return true; + return $this->pushProcessor->processPush($this->pushRequst); // Lock Push Processing $this->logging->addDebug(__METHOD__ . '|1_2|'); @@ -1497,6 +1498,8 @@ public function processSucceededPush(string $newStatus, string $message): bool return true; } + // Create a function that process push request for Paypal + /** * Process the pending payment push response from Buckaroo and update the order accordingly. * diff --git a/Model/Push/AfterpayProcessor.php b/Model/Push/AfterpayProcessor.php index b2244b929..996330a4b 100644 --- a/Model/Push/AfterpayProcessor.php +++ b/Model/Push/AfterpayProcessor.php @@ -8,10 +8,7 @@ use Buckaroo\Magento2\Model\BuckarooStatusCode; use Buckaroo\Magento2\Model\ConfigProvider\Account; use Buckaroo\Magento2\Model\ConfigProvider\Method\Afterpay20; -use Buckaroo\Magento2\Model\ConfigProvider\Method\Klarnakp; -use Buckaroo\Magento2\Model\ConfigProvider\Method\PayPerEmail; use Buckaroo\Magento2\Model\OrderStatusFactory; -use Buckaroo\Magento2\Service\LockerProcess; use Buckaroo\Magento2\Service\Push\OrderRequestService; use Magento\Sales\Api\Data\TransactionInterface; @@ -48,7 +45,6 @@ protected function invoiceShouldBeSaved(array &$paymentDetails): bool { if ($this->pushRequest->hasAdditionalInformation('initiated_by_magento', 1) && ( - $this->pushRequest->hasPostData('transaction_method', 'afterpay') && $this->pushRequest->hasAdditionalInformation('service_action_from_magento', 'capture') && $this->afterpayConfig->isInvoiceCreatedAfterShipment() )) { diff --git a/Model/Push/CreditManagmentProcessor.php b/Model/Push/CreditManagmentProcessor.php new file mode 100644 index 000000000..26f5044a1 --- /dev/null +++ b/Model/Push/CreditManagmentProcessor.php @@ -0,0 +1,100 @@ +initializeFields($pushRequest); + $invoiceKey = $this->pushRequest->getInvoicekey(); + $savedInvoiceKey = $this->order->getPayment()->getAdditionalInformation('buckaroo_cm3_invoice_key'); + + if ($invoiceKey != $savedInvoiceKey) { + return false; + } + + if ($this->updateCm3InvoiceStatus()) { + $this->sendCm3ConfirmationMail(); + return true; + } + return false; + + } + + /** + * Update the Credit Management invoice status based on push request data and save invoice if required. + * + * @return bool + * @throws LocalizedException + */ + private function updateCm3InvoiceStatus(): bool + { + $isPaid = filter_var(strtolower($this->pushRequest->getIspaid()), FILTER_VALIDATE_BOOLEAN); + $canInvoice = ($this->order->canInvoice() && !$this->order->hasInvoices()); + + $amount = floatval($this->pushRequest->getAmountDebit()); + $amount = $this->order->getBaseCurrency()->formatTxt($amount); + $statusMessage = 'Payment push status : Creditmanagement invoice with a total amount of ' + . $amount . ' has been paid'; + + if (!$isPaid && !$canInvoice) { + $statusMessage = 'Payment push status : Creditmanagement invoice has been (partially) refunded'; + } + + if (!$isPaid && $canInvoice) { + $statusMessage = 'Payment push status : Waiting for consumer'; + } + + if ($isPaid && $canInvoice) { + $originalKey = BuckarooAdapter::BUCKAROO_ORIGINAL_TRANSACTION_KEY_KEY; + $this->pushRequest->setTransactions($this->order->getPayment()->getAdditionalInformation($originalKey)); + $this->pushRequest->setAmount($this->pushRequest->getAmountDebit()); + + if (!$this->saveInvoice()) { + return false; + } + } + + $this->orderRequestService->updateOrderStatus( + $this->order->getState(), + $this->order->getStatus(), + $statusMessage + ); + + return true; + } + + /** + * Sends the CM3 confirmation email if the CM3 status code is 10 and the order email has not been sent. + * + * @return void + * @throws LocalizedException + */ + private function sendCm3ConfirmationMail(): void + { + $store = $this->order->getStore(); + $cm3StatusCode = 0; + + if (!empty($this->pushRequest->getInvoicestatuscode())) { + $cm3StatusCode = $this->pushRequest->getInvoicestatuscode(); + } + + $paymentMethod = $this->order->getPayment()->getMethodInstance(); + $configOrderMail = $this->configAccount->getOrderConfirmationEmail($store) + || $paymentMethod->getConfigData('order_email', $store); + + if (!$this->order->getEmailSent() && $cm3StatusCode == 10 && $configOrderMail) { + $this->orderRequestService->sendOrderEmail($this->order); + } + } +} \ No newline at end of file diff --git a/Model/Push/DefaultProcessor.php b/Model/Push/DefaultProcessor.php index 75274669b..93c29c055 100644 --- a/Model/Push/DefaultProcessor.php +++ b/Model/Push/DefaultProcessor.php @@ -42,7 +42,6 @@ use Buckaroo\Magento2\Service\Push\OrderRequestService; use Magento\Framework\Exception\FileSystemException; use Magento\Framework\Exception\LocalizedException; -use Magento\Payment\Model\InfoInterface; use Magento\Sales\Api\Data\TransactionInterface; use Magento\Sales\Model\Order; use Magento\Sales\Model\Order\Invoice; @@ -120,6 +119,7 @@ class DefaultProcessor implements PushProcessorInterface * @param PaymentGroupTransaction $groupTransaction * @param BuckarooStatusCode $buckarooStatusCode * @param OrderStatusFactory $orderStatusFactory + * @param Account $configAccount */ public function __construct( OrderRequestService $orderRequestService, @@ -181,7 +181,6 @@ public function processPush(PushRequestInterface $pushRequest): bool return true; } - if (!$this->canProcessPostData()) { return true; } @@ -190,10 +189,7 @@ public function processPush(PushRequestInterface $pushRequest): bool return true; } - $newStatus = $this->orderStatusFactory->get($this->pushRequest->getStatusCode(), $this->order); - $this->logging->addDebug(__METHOD__ . '|5|' . var_export($newStatus, true)); - - $this->processPushByStatus($newStatus); + $this->processPushByStatus(); $this->logging->addDebug(__METHOD__ . '|5|'); if (!$this->dontSaveOrderUponSuccessPush) { @@ -222,7 +218,7 @@ protected function initializeFields(PushRequestInterface $pushRequest): void * @return bool * @throws \Exception */ - protected function skipPush() + protected function skipPush(): bool { if ($this->skipKlarnaCapture()) { return true; @@ -767,6 +763,7 @@ protected function sendOrderEmail(): void $this->logging->addDebug(__METHOD__ . '|sendemail|' . var_export($this->configAccount->getOrderConfirmationEmailSync($store), true)); $this->orderRequestService->sendOrderEmail( + $this->order, (bool)$this->configAccount->getOrderConfirmationEmailSync($store) ); } @@ -1001,16 +998,6 @@ protected function getOrderIncrementId(): ?string return $brqOrderId; } - /** - * Determine if the lock push processing criteria are met. - * - * @return bool - */ - protected function lockPushProcessingCriteria(): bool - { - return false; - } - protected function getPaymentDetails($message) { // Set amount diff --git a/Model/Push/KlarnaKpProcessor.php b/Model/Push/KlarnaKpProcessor.php index 45e53eff6..a01cfa59a 100644 --- a/Model/Push/KlarnaKpProcessor.php +++ b/Model/Push/KlarnaKpProcessor.php @@ -8,9 +8,7 @@ use Buckaroo\Magento2\Model\BuckarooStatusCode; use Buckaroo\Magento2\Model\ConfigProvider\Account; use Buckaroo\Magento2\Model\ConfigProvider\Method\Klarnakp; -use Buckaroo\Magento2\Model\ConfigProvider\Method\PayPerEmail; use Buckaroo\Magento2\Model\OrderStatusFactory; -use Buckaroo\Magento2\Service\LockerProcess; use Buckaroo\Magento2\Service\Push\OrderRequestService; use Magento\Sales\Api\Data\TransactionInterface; @@ -38,6 +36,24 @@ public function __construct( $this->klarnakpConfig = $klarnakpConfig; } + /** + * Skip the push if the conditions are met. + * + * @return bool + * @throws \Exception + */ + protected function skipPush(): bool + { + if ($this->pushRequest->hasAdditionalInformation('initiated_by_magento', 1) + && $this->pushRequest->hasAdditionalInformation('service_action_from_magento', 'pay') + && !empty($this->pushRequest->getServiceKlarnakpCaptureid()) + ) { + return true; + } + + return parent::skipPush(); + } + /** * Retrieves the transaction key from the push request. * diff --git a/Model/Push/KlarnaProcessor.php b/Model/Push/KlarnaProcessor.php index 42fdade42..2b15cb715 100644 --- a/Model/Push/KlarnaProcessor.php +++ b/Model/Push/KlarnaProcessor.php @@ -3,6 +3,7 @@ namespace Buckaroo\Magento2\Model\Push; use Buckaroo\Magento2\Api\PushRequestInterface; +use Buckaroo\Magento2\Exception as BuckarooException; use Buckaroo\Magento2\Helper\Data; use Buckaroo\Magento2\Logging\Log; use Buckaroo\Magento2\Service\LockerProcess; @@ -40,6 +41,22 @@ protected function setBuckarooReservationNumber(): bool return false; } + /** + * @return bool + */ + protected function skipKlarnaCapture(): bool + { + if ($this->pushRequest->hasAdditionalInformation('initiated_by_magento', 1) + && $this->pushRequest->hasPostData('transaction_method', ['klarnakp', 'KlarnaKp']) + && $this->pushRequest->hasAdditionalInformation('service_action_from_magento', 'pay') + && !empty($this->pushRequest->getServiceKlarnakpCaptureid()) + ) { + return true; + } + + return false; + } + /** * @param array $paymentDetails * @return bool diff --git a/Service/Push/OrderRequestService.php b/Service/Push/OrderRequestService.php index 9b3b46aa6..8412deabb 100644 --- a/Service/Push/OrderRequestService.php +++ b/Service/Push/OrderRequestService.php @@ -230,12 +230,13 @@ public function updateOrderStatus( /** * Sends order email to the customer. * + * @param Order $order * @param bool $forceSyncMode * @return bool */ - public function sendOrderEmail(bool $forceSyncMode = false): bool + public function sendOrderEmail(Order $order, bool $forceSyncMode = false): bool { - return $this->orderSender->send($this->order, $forceSyncMode); + return $this->orderSender->send($order, $forceSyncMode); } /** diff --git a/etc/di.xml b/etc/di.xml index c02a2e2c8..77a9734bf 100644 --- a/etc/di.xml +++ b/etc/di.xml @@ -470,17 +470,17 @@ Buckaroo\Magento2\Model\Push\DefaultProcessor + Buckaroo\Magento2\Model\Push\CreditManagmentProcessor + Buckaroo\Magento2\Model\Push\GroupTransactionPushProcessor + Buckaroo\Magento2\Model\Push\RefundProcessor + Buckaroo\Magento2\Model\Push\CancelAuthorizeProcessor Buckaroo\Magento2\Model\Push\IdealProcessor Buckaroo\Magento2\Model\Push\PaypalProcessor - Buckaroo\Magento2\Model\Push\PayPerEmailProcessor - Buckaroo\Magento2\Model\Push\TransferProcessor Buckaroo\Magento2\Model\Push\AfterpayProcessor Buckaroo\Magento2\Model\Push\KlarnaProcessor - Buckaroo\Magento2\Model\Push\KlarnaKpProcessor- - Buckaroo\Magento2\Model\Push\CreditManagmentPushProcessor - Buckaroo\Magento2\Model\Push\GroupTransactionPushProcessor - Buckaroo\Magento2\Model\Push\RefundProcessor - Buckaroo\Magento2\Model\Push\CancelAuthorizeProcessor + Buckaroo\Magento2\Model\Push\KlarnaKpProcessor + Buckaroo\Magento2\Model\Push\PayPerEmailProcessor + Buckaroo\Magento2\Model\Push\TransferProcessor From a5fd821df252d9244ad4d6910b5f23f9c2607214 Mon Sep 17 00:00:00 2001 From: Lucian Turiac Date: Thu, 27 Jul 2023 12:30:57 +0300 Subject: [PATCH 16/29] Fix bugs on refactor push --- Model/Push.php | 1 - Model/Push/DefaultProcessor.php | 4 - Model/Push/GroupTransactionPushProcessor.php | 2 +- Model/Push/KlarnaProcessor.php | 16 -- Model/Push/PushTransactionType.php | 12 +- Model/Push/TransactionFactory.php | 169 ------------------- 6 files changed, 7 insertions(+), 197 deletions(-) delete mode 100644 Model/Push/TransactionFactory.php diff --git a/Model/Push.php b/Model/Push.php index a1e254b34..c3d1f22f1 100644 --- a/Model/Push.php +++ b/Model/Push.php @@ -342,7 +342,6 @@ public function receivePush() // Process Push $this->pushProcessor = $this->pushProcessorsFactory->get($pushTransactionType); - return true; return $this->pushProcessor->processPush($this->pushRequst); // Lock Push Processing diff --git a/Model/Push/DefaultProcessor.php b/Model/Push/DefaultProcessor.php index 93c29c055..acaa28a34 100644 --- a/Model/Push/DefaultProcessor.php +++ b/Model/Push/DefaultProcessor.php @@ -220,10 +220,6 @@ protected function initializeFields(PushRequestInterface $pushRequest): void */ protected function skipPush(): bool { - if ($this->skipKlarnaCapture()) { - return true; - } - // Skip Push based on specific condition if ($this->skipSpecificTypesOfRequsts()) { return true; diff --git a/Model/Push/GroupTransactionPushProcessor.php b/Model/Push/GroupTransactionPushProcessor.php index f9adbd9b7..2181f1e10 100644 --- a/Model/Push/GroupTransactionPushProcessor.php +++ b/Model/Push/GroupTransactionPushProcessor.php @@ -19,7 +19,7 @@ use Magento\Sales\Model\Order; use Magento\Quote\Model\ResourceModel\Quote as ResourceQuote; -#[AllowDynamicProperties] class GroupTransactionPushProcessor implements PushProcessorInterface +class GroupTransactionPushProcessor implements PushProcessorInterface { /** * @var PushRequestInterface diff --git a/Model/Push/KlarnaProcessor.php b/Model/Push/KlarnaProcessor.php index 2b15cb715..e0a5f7072 100644 --- a/Model/Push/KlarnaProcessor.php +++ b/Model/Push/KlarnaProcessor.php @@ -41,22 +41,6 @@ protected function setBuckarooReservationNumber(): bool return false; } - /** - * @return bool - */ - protected function skipKlarnaCapture(): bool - { - if ($this->pushRequest->hasAdditionalInformation('initiated_by_magento', 1) - && $this->pushRequest->hasPostData('transaction_method', ['klarnakp', 'KlarnaKp']) - && $this->pushRequest->hasAdditionalInformation('service_action_from_magento', 'pay') - && !empty($this->pushRequest->getServiceKlarnakpCaptureid()) - ) { - return true; - } - - return false; - } - /** * @param array $paymentDetails * @return bool diff --git a/Model/Push/PushTransactionType.php b/Model/Push/PushTransactionType.php index 79d918643..2239b0cec 100644 --- a/Model/Push/PushTransactionType.php +++ b/Model/Push/PushTransactionType.php @@ -84,9 +84,9 @@ class PushTransactionType private string $pushType; /** - * @var bool|string + * @var string */ - private string|bool $transactionType; + private ?string $transactionType; /** * @var array @@ -276,17 +276,17 @@ public function setStatusKey(string $statusKey): void } /** - * @return string + * @return string|null */ - public function getTransactionType(): string + public function getTransactionType(): ?string { return $this->transactionType; } /** - * @param string $transactionType + * @param string|null $transactionType */ - public function setTransactionType(string $transactionType): void + public function setTransactionType(?string $transactionType): void { $this->transactionType = $transactionType; } diff --git a/Model/Push/TransactionFactory.php b/Model/Push/TransactionFactory.php deleted file mode 100644 index 46fa0fe22..000000000 --- a/Model/Push/TransactionFactory.php +++ /dev/null @@ -1,169 +0,0 @@ -objectManager = $objectManager; - $this->pushProcessors = $pushProcessors; - $this->orderRequestService = $orderRequestService; - } - - /** - * Retrieve proper push processor for the specified transaction method. - * - * @param PushRequestInterface|null $pushRequest - * @return ?PushProcessorInterface - * @throws BuckarooException - */ - public function createTransaction(?PushRequestInterface $pushRequest): ?PushProcessorInterface - { - // Determine which payment method to use - $paymentMethod = PaymentMethodFactory::getPaymentMethod($postParams['brq_transaction_method']); - - // Determine which state to use - $paymentState = PaymentStateFactory::getPaymentState($postParams['brq_statuscode']); - - // Determine which command to use - $paymentCommand = PaymentCommandFactory::getPaymentCommand($postParams['ADD_service_action_from_magento']); - - // Create the transaction - $transaction = new Transaction($paymentMethod, $paymentState, $paymentCommand); - - // Apply any decorators based on the post parameters - $transaction = $this->applyDecorators($transaction, $postParams); - - return $transaction; - - if (!$this->pushProcessor instanceof PushProcessorInterface) { - if (empty($this->pushProcessors)) { - throw new \LogicException('Push processors is not set.'); - } - - $pushProcessorClass = $this->pushProcessors['default']; - - $order = $this->orderRequestService->getOrderByRequest($pushRequest); - - $transactionType = $this->getTransactionType($pushRequest, $order); - - if ($transactionType == self::BUCK_PUSH_TYPE_INVOICE) { - $pushProcessorClass = $this->pushProcessors['credit_managment']; - } elseif ($transactionType == self::BUCK_PUSH_TYPE_INVOICE_INCOMPLETE) { - throw new BuckarooException( - __('Skipped handling this invoice push because it is too soon.') - ); - } - - $transactionMethod = $pushRequest->getTransactionMethod(); - - $pushProcessorClass = $this->pushProcessors[$transactionMethod] ?? $pushProcessorClass; - - if (empty($pushProcessorClass)) { - throw new BuckarooException( - new Phrase( - 'Unknown ConfigProvider type requested: %1.', - [$transactionMethod] - ) - ); - } - $this->pushProcessor = $this->objectManager->get($pushProcessorClass); - - } - return $this->pushProcessor; - } - - private static function applyDecorators($transaction, $postParams) { - if (isset($postParams['ADD_group_transaction'])) { - $transaction = new GroupTransactionDecorator($transaction); - } - - if (isset($postParams['ADD_credit_management'])) { - $transaction = new CreditManagementDecorator($transaction); - } - - return $transaction; - } - - /** - * Determine the transaction type based on push request data and the saved invoice key. - * - * @return bool|string - * - * @SuppressWarnings(PHPMD.CyclomaticComplexity) - */ - public function getTransactionType($pushRequest, $order) - { - //If an order has an invoice key, then it should only be processed by invoice pushes - $savedInvoiceKey = (string)$order->getPayment()->getAdditionalInformation('buckaroo_cm3_invoice_key'); - - if (!empty($pushRequest->getInvoicekey()) - && !empty($pushRequest->getSchemekey()) - && strlen($savedInvoiceKey) > 0 - ) { - return self::BUCK_PUSH_TYPE_INVOICE; - } - - if (!empty($pushRequest->getInvoicekey()) - && !empty($pushRequest->getSchemekey()) - && strlen($savedInvoiceKey) == 0 - ) { - return self::BUCK_PUSH_TYPE_INVOICE_INCOMPLETE; - } - - if (!empty($pushRequest->getDatarequest())) { - return self::BUCK_PUSH_TYPE_DATAREQUEST; - } - - if (empty($pushRequest->getInvoicekey()) - && empty($pushRequest->getServiceCreditmanagement3Invoicekey()) - && empty($pushRequest->getDatarequest()) - && strlen($savedInvoiceKey) <= 0 - ) { - return self::BUCK_PUSH_TYPE_TRANSACTION; - } - - return false; - } -} \ No newline at end of file From 4d29d4f5d3f61cbb9accc7b969a332528894ce5e Mon Sep 17 00:00:00 2001 From: Lucian Turiac Date: Fri, 28 Jul 2023 17:31:56 +0300 Subject: [PATCH 17/29] Fix Payperemail --- Model/BuckarooStatusCode.php | 3 ++- Model/Push/PayPerEmailProcessor.php | 2 +- Model/Push/PushTransactionType.php | 7 ++----- 3 files changed, 5 insertions(+), 7 deletions(-) diff --git a/Model/BuckarooStatusCode.php b/Model/BuckarooStatusCode.php index 2ab943617..91d04fa14 100644 --- a/Model/BuckarooStatusCode.php +++ b/Model/BuckarooStatusCode.php @@ -95,7 +95,8 @@ public function getResponseMessage(int $responseCode): string */ public function getStatusKey(int $responseCode): string { - return array_search($responseCode, $this->statusCodes) ?? 'BUCKAROO_MAGENTO2_STATUSCODE_NEUTRAL'; + $statusKey = array_search($responseCode, $this->statusCodes); + return $statusKey ?: 'BUCKAROO_MAGENTO2_STATUSCODE_NEUTRAL'; } /** diff --git a/Model/Push/PayPerEmailProcessor.php b/Model/Push/PayPerEmailProcessor.php index 84622e7f6..bde42b971 100644 --- a/Model/Push/PayPerEmailProcessor.php +++ b/Model/Push/PayPerEmailProcessor.php @@ -36,7 +36,7 @@ class PayPerEmailProcessor extends DefaultProcessor /** * @var bool */ - private bool $isPayPerEmailB2BModePushInitial; + private bool $isPayPerEmailB2BModePushInitial = false; public function __construct( OrderRequestService $orderRequestService, diff --git a/Model/Push/PushTransactionType.php b/Model/Push/PushTransactionType.php index 2239b0cec..fcd956e93 100644 --- a/Model/Push/PushTransactionType.php +++ b/Model/Push/PushTransactionType.php @@ -228,16 +228,13 @@ private function getStatusCodeByTransactionType(string $transactionType): int $statusCode = $this->pushRequest->getEventparametersTransactionstatuscode(); } break; - default: - $statusCode = BuckarooStatusCode::FAILED; } - $statusCodeSuccess = BuckarooStatusCode::SUCCESS; if ($this->pushRequest->getStatusCode() !== null - && ($this->pushRequest->getStatusCode() == $statusCodeSuccess) + && ($this->pushRequest->getStatusCode() == BuckarooStatusCode::SUCCESS) && !$statusCode ) { - $statusCode = $statusCodeSuccess; + $statusCode = BuckarooStatusCode::SUCCESS; } return (int)$statusCode; From b891151f8312757d980b618c12710240430123fc Mon Sep 17 00:00:00 2001 From: Lucian Turiac Date: Tue, 8 Aug 2023 14:07:56 +0300 Subject: [PATCH 18/29] BP-2133 - Working at Refactor Redirect --- Controller/Payconiq/Process.php | 26 +-- Controller/Redirect/IdinProcess.php | 146 +++++++++++++ Controller/Redirect/Process.php | 295 +++++++-------------------- Gateway/Request/IdinDataBuilder.php | 2 +- Model/Service/RedirectService.php | 84 ++++++++ Service/Push/OrderRequestService.php | 2 +- 6 files changed, 317 insertions(+), 238 deletions(-) create mode 100644 Controller/Redirect/IdinProcess.php create mode 100644 Model/Service/RedirectService.php diff --git a/Controller/Payconiq/Process.php b/Controller/Payconiq/Process.php index 8f34eba00..2d124bb0c 100644 --- a/Controller/Payconiq/Process.php +++ b/Controller/Payconiq/Process.php @@ -23,10 +23,12 @@ use Buckaroo\Magento2\Exception; use Buckaroo\Magento2\Helper\Data; use Buckaroo\Magento2\Logging\Log; +use Buckaroo\Magento2\Model\BuckarooStatusCode; use Buckaroo\Magento2\Model\ConfigProvider\Factory; use Buckaroo\Magento2\Model\OrderStatusFactory; use Buckaroo\Magento2\Model\RequestPush\RequestPushFactory; use Buckaroo\Magento2\Model\Service\Order as OrderService; +use Buckaroo\Magento2\Service\Push\OrderRequestService; use Buckaroo\Magento2\Service\Sales\Quote\Recreate; use Magento\Checkout\Model\Cart; use Magento\Checkout\Model\Session as CheckoutSession; @@ -34,7 +36,6 @@ use Magento\Customer\Model\Customer; use Magento\Customer\Model\ResourceModel\CustomerFactory; use Magento\Customer\Model\Session as CustomerSession; -use Magento\Customer\Model\SessionFactory; use Magento\Framework\Api\SearchCriteriaBuilder; use Magento\Framework\App\Action\Context; use Magento\Framework\App\ResponseInterface; @@ -46,7 +47,6 @@ use Magento\Sales\Api\Data\TransactionSearchResultInterface; use Magento\Sales\Api\TransactionRepositoryInterface; use Magento\Sales\Model\Order; -use Magento\Sales\Model\Order\Email\Sender\OrderSender; use Magento\Sales\Model\Order\Payment\Transaction; /** @@ -71,19 +71,15 @@ class Process extends \Buckaroo\Magento2\Controller\Redirect\Process /** * @param Context $context - * @param Data $helper - * @param Cart $cart * @param Order $order * @param Quote $quote * @param TransactionInterface $transaction * @param Log $logger - * @param Factory $configProviderFactory - * @param OrderSender $orderSender + * @param OrderRequestService $orderRequestService * @param OrderStatusFactory $orderStatusFactory * @param CheckoutSession $checkoutSession * @param CustomerSession $customerSession * @param CustomerRepositoryInterface $customerRepository - * @param SessionFactory $sessionFactory * @param Customer $customerModel * @param CustomerFactory $customerFactory * @param OrderService $orderService @@ -98,19 +94,15 @@ class Process extends \Buckaroo\Magento2\Controller\Redirect\Process */ public function __construct( Context $context, - Data $helper, - Cart $cart, Order $order, Quote $quote, TransactionInterface $transaction, Log $logger, - Factory $configProviderFactory, - OrderSender $orderSender, + OrderRequestService $orderRequestService, OrderStatusFactory $orderStatusFactory, CheckoutSession $checkoutSession, CustomerSession $customerSession, CustomerRepositoryInterface $customerRepository, - SessionFactory $sessionFactory, Customer $customerModel, CustomerFactory $customerFactory, OrderService $orderService, @@ -122,19 +114,15 @@ public function __construct( ) { parent::__construct( $context, - $helper, - $cart, $order, $quote, $transaction, $logger, - $configProviderFactory, - $orderSender, + $orderRequestService, $orderStatusFactory, $checkoutSession, $customerSession, $customerRepository, - $sessionFactory, $customerModel, $customerFactory, $orderService, @@ -181,9 +169,7 @@ public function execute() // @codingStandardsIgnoreStart try { - $this->handleFailed( - $this->helper->getStatusCode('BUCKAROO_MAGENTO2_STATUSCODE_CANCELLED_BY_USER') - ); + $this->handleFailed(BuckarooStatusCode::CANCELLED_BY_USER); } catch (\Exception $exception) { // handle failed exception } diff --git a/Controller/Redirect/IdinProcess.php b/Controller/Redirect/IdinProcess.php new file mode 100644 index 000000000..f6ffde7b0 --- /dev/null +++ b/Controller/Redirect/IdinProcess.php @@ -0,0 +1,146 @@ +order = $order; + $this->quote = $quote; + $this->logger = $logger; + $this->orderRequestService = $orderRequestService; + $this->orderStatusFactory = $orderStatusFactory; + $this->checkoutSession = $checkoutSession; + $this->customerSession = $customerSession; + $this->customerRepository = $customerRepository; + $this->customerModel = $customerModel; + $this->customerResourceFactory = $customerFactory; + $this->accountConfig = $accountConfig; + $this->orderService = $orderService; + $this->eventManager = $eventManager; + $this->quoteRecreate = $quoteRecreate; + + // @codingStandardsIgnoreStart + if (interface_exists("\Magento\Framework\App\CsrfAwareActionInterface")) { + $request = $this->getRequest(); + if ($request instanceof Http && $request->isPost()) { + $request->setParam('isAjax', true); + $request->getHeaders()->addHeaderLine('X_REQUESTED_WITH', 'XMLHttpRequest'); + } + } + $this->redirectRequest = $requestPushFactory->create(); + // @codingStandardsIgnoreEnd + } + + /** + * @return \Magento\Framework\App\ResponseInterface|\Magento\Framework\Controller\ResultInterface|void + * @throws \Buckaroo\Magento2\Exception + */ + public function execute() + { + if ($this->redirectRequest->hasPostData('primary_service', 'IDIN')) { + if ($this->setCustomerIDIN()) { + $this->addSuccessMessage(__('Your iDIN verified succesfully!')); + } else { + $this->addErrorMessage( + __( + 'Unfortunately iDIN not verified!' + ) + ); + } + + return $this->redirectToCheckout(); + } + } + + /** + * Set consumer bin IDIN on customer + * + * @return bool + */ + private function setCustomerIDIN() + { + if (!empty($this->redirectRequest->getServiceIdinConsumerbin()) + && !empty($this->redirectRequest->getServiceIdinIseighteenorolder()) + && $this->redirectRequest->getServiceIdinIseighteenorolder() == 'True' + ) { + $this->checkoutSession->setCustomerIDIN($this->redirectRequest->getServiceIdinConsumerbin()); + $this->checkoutSession->setCustomerIDINIsEighteenOrOlder(true); + if (!empty($this->redirectRequest->getAdditionalInformation('idin_cid'))) { + $customerNew = $this->customerModel->load((int)$this->redirectRequest->getAdditionalInformation('idin_cid')); + $customerData = $customerNew->getDataModel(); + $customerData->setCustomAttribute('buckaroo_idin', $this->redirectRequest->getServiceIdinConsumerbin()); + $customerData->setCustomAttribute('buckaroo_idin_iseighteenorolder', 1); + $customerNew->updateData($customerData); + $customerResource = $this->customerResourceFactory->create(); + $customerResource->saveAttribute($customerNew, 'buckaroo_idin'); + $customerResource->saveAttribute($customerNew, 'buckaroo_idin_iseighteenorolder'); + } + return true; + } + return false; + } +} \ No newline at end of file diff --git a/Controller/Redirect/Process.php b/Controller/Redirect/Process.php index 3c20eff66..214c8776d 100644 --- a/Controller/Redirect/Process.php +++ b/Controller/Redirect/Process.php @@ -22,32 +22,29 @@ use Buckaroo\Magento2\Api\PushRequestInterface; use Buckaroo\Magento2\Exception; -use Buckaroo\Magento2\Helper\Data; use Buckaroo\Magento2\Logging\Log; -use Buckaroo\Magento2\Model\ConfigProvider\Factory; +use Buckaroo\Magento2\Model\BuckarooStatusCode; +use Buckaroo\Magento2\Model\ConfigProvider\Account as AccountConfig; use Buckaroo\Magento2\Model\Method\BuckarooAdapter; use Buckaroo\Magento2\Model\OrderStatusFactory; use Buckaroo\Magento2\Model\RequestPush\RequestPushFactory; use Buckaroo\Magento2\Model\Service\Order as OrderService; +use Buckaroo\Magento2\Service\Push\OrderRequestService; use Buckaroo\Magento2\Service\Sales\Quote\Recreate; -use Magento\Checkout\Model\Cart; -use Magento\Checkout\Model\ConfigProviderInterface; +use Magento\Checkout\Model\Session as CheckoutSession; use Magento\Customer\Api\CustomerRepositoryInterface; use Magento\Customer\Model\Customer; use Magento\Customer\Model\ResourceModel\CustomerFactory; use Magento\Customer\Model\Session as CustomerSession; -use Magento\Checkout\Model\Session as CheckoutSession; -use Magento\Customer\Model\SessionFactory; use Magento\Framework\App\Action\Action; use Magento\Framework\App\Action\Context; use Magento\Framework\App\Request\Http as Http; use Magento\Framework\App\ResponseInterface; use Magento\Framework\Event\ManagerInterface; use Magento\Quote\Model\Quote; +use Magento\Sales\Api\Data\OrderInterface; use Magento\Sales\Api\Data\OrderPaymentInterface; -use Magento\Sales\Api\Data\TransactionInterface; use Magento\Sales\Model\Order; -use Magento\Sales\Model\Order\Email\Sender\OrderSender; /** * @SuppressWarnings(PHPMD.CouplingBetweenObjects) @@ -55,50 +52,35 @@ */ class Process extends Action { - /** - * @var CustomerSession - */ - public $customerSession; - - /** - * @var array - */ - protected $response; - /** * @var Order $order */ - protected $order; + protected Order $order; /** * @var Quote $quote */ - protected $quote; + protected Quote $quote; /** - * @var Data $helper + * @var OrderPaymentInterface|null */ - protected $helper; + protected ?OrderPaymentInterface $payment; /** - * @var Cart + * @var AccountConfig */ - protected $cart; + protected AccountConfig $accountConfig; /** - * @var ConfigProviderInterface + * @var OrderRequestService */ - protected $accountConfig; - - /** - * @var OrderSender - */ - protected $orderSender; + protected OrderRequestService $orderRequestService; /** * @var OrderStatusFactory */ - protected $orderStatusFactory; + protected OrderStatusFactory $orderStatusFactory; /** * @var Log @@ -108,17 +90,17 @@ class Process extends Action /** * @var CheckoutSession */ - protected $checkoutSession; + protected CheckoutSession $checkoutSession; /** - * @var CustomerRepositoryInterface + * @var CustomerSession */ - protected $customerRepository; + public CustomerSession $customerSession; /** - * @var SessionFactory + * @var CustomerRepositoryInterface */ - protected $_sessionFactory; + protected $customerRepository; /** * @var Customer @@ -135,11 +117,6 @@ class Process extends Action */ protected $orderService; - /** - * @var TransactionInterface - */ - private $transaction; - /** * @var ManagerInterface */ @@ -150,51 +127,40 @@ class Process extends Action */ private $quoteRecreate; + protected $quoteRepository; + /** * @var PushRequestInterface */ - private PushRequestInterface $pushRequst; + protected PushRequestInterface $redirectRequest; /** * @param Context $context - * @param Data $helper - * @param Cart $cart - * @param Order $order - * @param Quote $quote - * @param TransactionInterface $transaction * @param Log $logger - * @param Factory $configProviderFactory - * @param OrderSender $orderSender + * @param Quote $quote + * @param AccountConfig $accountConfig + * @param OrderRequestService $orderRequestService * @param OrderStatusFactory $orderStatusFactory * @param CheckoutSession $checkoutSession * @param CustomerSession $customerSession * @param CustomerRepositoryInterface $customerRepository - * @param SessionFactory $sessionFactory - * @param Customer $customerModel * @param CustomerFactory $customerFactory * @param OrderService $orderService * @param ManagerInterface $eventManager * @param Recreate $quoteRecreate * @param RequestPushFactory $requestPushFactory - * @throws Exception * @SuppressWarnings(PHPMD.ExcessiveParameterList) */ public function __construct( Context $context, - Data $helper, - Cart $cart, - Order $order, - Quote $quote, - TransactionInterface $transaction, Log $logger, - Factory $configProviderFactory, - OrderSender $orderSender, + Quote $quote, + AccountConfig $accountConfig, + OrderRequestService $orderRequestService, OrderStatusFactory $orderStatusFactory, CheckoutSession $checkoutSession, CustomerSession $customerSession, CustomerRepositoryInterface $customerRepository, - SessionFactory $sessionFactory, - Customer $customerModel, CustomerFactory $customerFactory, OrderService $orderService, ManagerInterface $eventManager, @@ -202,24 +168,18 @@ public function __construct( RequestPushFactory $requestPushFactory ) { parent::__construct($context); - $this->helper = $helper; - $this->cart = $cart; - $this->order = $order; - $this->quote = $quote; - $this->transaction = $transaction; $this->logger = $logger; - $this->orderSender = $orderSender; + $this->orderRequestService = $orderRequestService; $this->orderStatusFactory = $orderStatusFactory; $this->checkoutSession = $checkoutSession; $this->customerSession = $customerSession; $this->customerRepository = $customerRepository; - $this->_sessionFactory = $sessionFactory; - $this->customerModel = $customerModel; $this->customerResourceFactory = $customerFactory; - $this->accountConfig = $configProviderFactory->get('account'); + $this->accountConfig = $accountConfig; $this->orderService = $orderService; $this->eventManager = $eventManager; $this->quoteRecreate = $quoteRecreate; + $this->quote = $quote; // @codingStandardsIgnoreStart if (interface_exists("\Magento\Framework\App\CsrfAwareActionInterface")) { @@ -229,7 +189,7 @@ public function __construct( $request->getHeaders()->addHeaderLine('X_REQUESTED_WITH', 'XMLHttpRequest'); } } - $this->pushRequst = $requestPushFactory->create(); + $this->redirectRequest = $requestPushFactory->create(); // @codingStandardsIgnoreEnd } @@ -246,85 +206,69 @@ public function __construct( */ public function execute() { - $this->logger->addDebug(__METHOD__ . '|' . var_export($this->pushRequst->getOriginalRequest(), true)); + $this->logger->addDebug(__METHOD__ . '|' . var_export($this->redirectRequest->getOriginalRequest(), true)); /** * Check if there is a valid response. If not, redirect to home. */ - if (count($this->pushRequst->getData()) === 0 || empty($this->pushRequst->getStatusCode())) { + if (count($this->redirectRequest->getData()) === 0 || empty($this->redirectRequest->getStatusCode())) { return $this->handleProcessedResponse('/'); } - if ($this->pushRequst->hasPostData('primary_service', 'IDIN')) { - if ($this->setCustomerIDIN()) { - $this->addSuccessMessage(__('Your iDIN verified succesfully!')); - } else { - $this->addErrorMessage( - __( - 'Unfortunately iDIN not verified!' - ) - ); - } - - return $this->redirectToCheckout(); - } - - $statusCode = (int)$this->pushRequst->getStatusCode(); - - $this->loadOrder(); - $this->helper->setRestoreQuoteLastOrder(false); + // Initialize the order, quote, payment + $this->order = $this->orderRequestService->getOrderByRequest($this->redirectRequest); + $statusCode = (int)$this->redirectRequest->getStatusCode(); if (!$this->order->getId()) { - $statusCode = $this->helper->getStatusCode('BUCKAROO_MAGENTO2_ORDER_FAILED'); + $statusCode = BuckarooStatusCode::ORDER_FAILED; } else { $this->quote->load($this->order->getQuoteId()); } - $payment = $this->order->getPayment(); + $this->payment = $this->order->getPayment(); - if ($payment) { - $this->setPaymentOutOfTransit($payment); + $this->checkoutSession->setRestoreQuoteLastOrder(false); + + if ($this->payment) { + $this->setPaymentOutOfTransit($this->payment); } - if (!method_exists($payment->getMethodInstance(), 'canProcessPostData')) { + if (!method_exists($this->payment->getMethodInstance(), 'canProcessPostData')) { return $this->handleProcessedResponse('/'); } - if (!$payment->getMethodInstance()->canProcessPostData($payment, $this->pushRequst)) { + if (!$this->payment->getMethodInstance()->canProcessPostData($this->payment, $this->redirectRequest)) { return $this->handleProcessedResponse('/'); } $this->logger->addDebug(__METHOD__ . '|2|' . var_export($statusCode, true)); if (($payment->getMethodInstance()->getCode() == 'buckaroo_magento2_paypal') - && ($statusCode == $this->helper->getStatusCode('BUCKAROO_MAGENTO2_STATUSCODE_PENDING_PROCESSING')) + && ($statusCode == BuckarooStatusCode::PENDING_PROCESSING) ) { - $statusCode = $this->helper->getStatusCode('BUCKAROO_MAGENTO2_STATUSCODE_CANCELLED_BY_USER'); + $statusCode = BuckarooStatusCode::CANCELLED_BY_USER; $this->logger->addDebug(__METHOD__ . '|22|' . var_export($statusCode, true)); } switch ($statusCode) { - case $this->helper->getStatusCode('BUCKAROO_MAGENTO2_STATUSCODE_SUCCESS'): - case $this->helper->getStatusCode('BUCKAROO_MAGENTO2_STATUSCODE_PENDING_PROCESSING'): + case BuckarooStatusCode::SUCCESS: + case BuckarooStatusCode::PENDING_PROCESSING: $debugInfo = [ $this->order->getStatus(), - $this->orderStatusFactory->get( - $this->helper->getStatusCode('BUCKAROO_MAGENTO2_STATUSCODE_SUCCESS'), - $this->order - ), + $this->orderStatusFactory->get(BuckarooStatusCode::SUCCESS, $this->order), ]; $this->logger->addDebug(__METHOD__ . '|3|' . var_export($debugInfo, true)); if ($this->order->canInvoice()) { $this->logger->addDebug(__METHOD__ . '|31|'); - if ($statusCode == $this->helper->getStatusCode('BUCKAROO_MAGENTO2_STATUSCODE_SUCCESS')) { + if ($statusCode == BuckarooStatusCode::SUCCESS) { //do nothing - push will change a status $this->logger->addDebug(__METHOD__ . '|32|'); } else { $this->logger->addDebug(__METHOD__ . '|33|'); // Set the 'Pending payment status' here $pendingStatus = $this->orderStatusFactory->get( - $this->helper->getStatusCode('BUCKAROO_MAGENTO2_STATUSCODE_PENDING_PROCESSING'), + BuckarooStatusCode::PENDING_PROCESSING, $this->order ); if ($pendingStatus) { @@ -335,7 +279,7 @@ public function execute() } } - $payment->getMethodInstance()->processCustomPostData($payment, $this->pushRequst->getData()); + $payment->getMethodInstance()->processCustomPostData($payment, $this->redirectRequest->getData()); /** @var \Magento\Payment\Model\MethodInterface $paymentMethod */ $paymentMethod = $this->order->getPayment()->getMethodInstance(); @@ -351,23 +295,23 @@ public function execute() || $paymentMethod->getConfigData('order_email', $store) === "1" ) ) { - $isKlarnaKpReserve = ($this->pushRequst->hasPostData('primary_service', 'KlarnaKp') - && $this->pushRequst->hasAdditionalInformation('service_action_from_magento', 'reserve') - && !empty($this->pushRequst->getServiceKlarnakpReservationnumber())); + $isKlarnaKpReserve = ($this->redirectRequest->hasPostData('primary_service', 'KlarnaKp') + && $this->redirectRequest->hasAdditionalInformation('service_action_from_magento', 'reserve') + && !empty($this->redirectRequest->getServiceKlarnakpReservationnumber())); - if (!($this->pushRequst->hasAdditionalInformation('initiated_by_magento', 1) + if (!($this->redirectRequest->hasAdditionalInformation('initiated_by_magento', 1) && $isKlarnaKpReserve) ) { - if ($statusCode == $this->helper->getStatusCode('BUCKAROO_MAGENTO2_STATUSCODE_SUCCESS')) { + if ($statusCode == BuckarooStatusCode::SUCCESS) { $this->logger->addDebug(__METHOD__ . '|sendemail|'); - $this->orderSender->send($this->order, true); + $this->orderRequestService->sendOrderEmail($this->order, true); } } } - $pendingCode = $this->helper->getStatusCode('BUCKAROO_MAGENTO2_STATUSCODE_PENDING_PROCESSING'); + $pendingCode = BuckarooStatusCode::PENDING_PROCESSING; if (($statusCode == $pendingCode) - && !$this->pushRequst->hasPostData('payment_method', 'sofortueberweisung') + && !$this->redirectRequest->hasPostData('payment_method', 'sofortueberweisung') ) { $this->addErrorMessage( __( @@ -411,10 +355,10 @@ public function execute() $this->logger->addDebug(__METHOD__ . '|6|'); // Redirect to success page return $this->redirectSuccess(); - case $this->helper->getStatusCode('BUCKAROO_MAGENTO2_ORDER_FAILED'): - case $this->helper->getStatusCode('BUCKAROO_MAGENTO2_STATUSCODE_FAILED'): - case $this->helper->getStatusCode('BUCKAROO_MAGENTO2_STATUSCODE_REJECTED'): - case $this->helper->getStatusCode('BUCKAROO_MAGENTO2_STATUSCODE_CANCELLED_BY_USER'): + case BuckarooStatusCode::ORDER_FAILED: + case BuckarooStatusCode::FAILED: + case BuckarooStatusCode::REJECTED: + case BuckarooStatusCode::CANCELLED_BY_USER: return $this->handleFailed($statusCode); //no default } @@ -437,34 +381,6 @@ public function handleProcessedResponse($path, $arguments = []) return $this->_redirect($path, $arguments); } - /** - * Set consumer bin IDIN on customer - * - * @return bool - */ - private function setCustomerIDIN() - { - if (!empty($this->pushRequst->getServiceIdinConsumerbin()) - && !empty($this->pushRequst->getServiceIdinIseighteenorolder()) - && $this->pushRequst->getServiceIdinIseighteenorolder() == 'True' - ) { - $this->checkoutSession->setCustomerIDIN($this->pushRequst->getServiceIdinConsumerbin()); - $this->checkoutSession->setCustomerIDINIsEighteenOrOlder(true); - if (!empty($this->pushRequst->getAdditionalInformation('idin_cid'))) { - $customerNew = $this->customerModel->load((int)$this->pushRequst->getAdditionalInformation('idin_cid')); - $customerData = $customerNew->getDataModel(); - $customerData->setCustomAttribute('buckaroo_idin', $this->pushRequst->getServiceIdinConsumerbin()); - $customerData->setCustomAttribute('buckaroo_idin_iseighteenorolder', 1); - $customerNew->updateData($customerData); - $customerResource = $this->customerResourceFactory->create(); - $customerResource->saveAttribute($customerNew, 'buckaroo_idin'); - $customerResource->saveAttribute($customerNew, 'buckaroo_idin_iseighteenorolder'); - } - return true; - } - return false; - } - /** * Add success message to be displayed to the user * @@ -510,7 +426,7 @@ protected function redirectToCheckout() $this->logger->addDebug(__METHOD__ . '|setLastRealOrderId|'); $this->checkoutSession->restoreQuote(); $this->logger->addDebug(__METHOD__ . '|restoreQuote|'); - } elseif ($this->pushRequst->hasPostData('primary_service', 'IDIN')) { + } elseif ($this->redirectRequest->hasPostData('primary_service', 'IDIN')) { $this->checkoutSession->restoreQuote(); } } catch (\Exception $e) { @@ -522,63 +438,10 @@ protected function redirectToCheckout() return $this->handleProcessedResponse('checkout', ['_query' => ['bk_e' => 1]]); } - /** - * Load order by invoice number, order number or by transaction key - * - * @throws Exception - */ - private function loadOrder() - { - $brqOrderId = false; - - if (!empty($this->pushRequst->getInvoiceNumber())) { - $brqOrderId = $this->pushRequst->getInvoiceNumber(); - } - - if (!empty($this->pushRequst->getOrderNumber())) { - $brqOrderId = $this->pushRequst->getOrderNumber(); - } - - $this->order->loadByIncrementId($brqOrderId); - - if (!$this->order->getId()) { - $this->logger->addDebug('Order could not be loaded by brq_invoicenumber or brq_ordernumber'); - $this->order = $this->getOrderByTransactionKey(); - } - } - - /** - * Get order by transaction key - * - * @return \Magento\Sales\Model\Order\Payment - * @throws Exception - */ - private function getOrderByTransactionKey() - { - $trxId = ''; - - if (!empty($this->pushRequst->getTransactions())) { - $trxId = $this->pushRequst->getTransactions(); - } - - if (!empty($this->pushRequst->getDatarequest())) { - $trxId = $this->pushRequst->getDatarequest(); - } - - $this->transaction->load($trxId, 'txn_id'); - $order = $this->transaction->getOrder(); - - if (!$order) { - throw new Exception(__('There was no order found by transaction Id')); - } - - return $order; - } - /** * Get order * - * @return \Magento\Sales\Api\Data\OrderInterface + * @return OrderInterface */ public function getOrder() { @@ -653,17 +516,17 @@ protected function redirectSuccess() $this->quote->setReservedOrderId(null); - if (!empty($this->pushRequst->getPaymentMethod()) + if (!empty($this->redirectRequest->getPaymentMethod()) && - ($this->pushRequst->getPaymentMethod() == 'applepay') + ($this->redirectRequest->getPaymentMethod() == 'applepay') && - !empty($this->pushRequst->getStatusCode()) + !empty($this->redirectRequest->getStatusCode()) && - ($this->pushRequst->getStatusCode() == '190') + ($this->redirectRequest->getStatusCode() == '190') && - !empty($this->pushRequst->getTest()) + !empty($this->redirectRequest->getTest()) && - ($this->pushRequst->getTest() == 'true') + ($this->redirectRequest->getTest() == 'true') ) { $this->redirectSuccessApplePay(); } @@ -719,17 +582,17 @@ protected function handleFailed($statusCode) // StatusCode specified error messages $statusCodeAddErrorMessage = []; - $statusCodeAddErrorMessage[$this->helper->getStatusCode('BUCKAROO_MAGENTO2_ORDER_FAILED')] = + $statusCodeAddErrorMessage[BuckarooStatusCode::ORDER_FAILED] = 'Unfortunately an error occurred while processing your payment. Please try again. If this' . ' error persists, please choose a different payment method.'; - $statusCodeAddErrorMessage[$this->helper->getStatusCode('BUCKAROO_MAGENTO2_STATUSCODE_FAILED')] = + $statusCodeAddErrorMessage[BuckarooStatusCode::FAILED] = 'Unfortunately an error occurred while processing your payment. Please try again. If this' . ' error persists, please choose a different payment method.'; - $statusCodeAddErrorMessage[$this->helper->getStatusCode('BUCKAROO_MAGENTO2_STATUSCODE_REJECTED')] = + $statusCodeAddErrorMessage[BuckarooStatusCode::REJECTED] = 'Unfortunately an error occurred while processing your payment. Please try again. If this' . ' error persists, please choose a different payment method.'; $statusCodeAddErrorMessage[ - $this->helper->getStatusCode('BUCKAROO_MAGENTO2_STATUSCODE_CANCELLED_BY_USER') + BuckarooStatusCode::CANCELLED_BY_USER ] = 'According to our system, you have canceled the payment. If this' . ' is not the case, please contact us.'; @@ -740,7 +603,7 @@ protected function handleFailed($statusCode) ); //skip cancel order for PPE - if (!empty($this->pushRequst->getAdditionalInformation('frompayperemail'))) { + if (!empty($this->redirectRequest->getAdditionalInformation('frompayperemail'))) { return $this->redirectFailure(); } @@ -832,6 +695,6 @@ protected function cancelOrder($statusCode) */ public function getResponseParameters() { - return $this->pushRequst->getData(); + return $this->redirectRequest->getData(); } } diff --git a/Gateway/Request/IdinDataBuilder.php b/Gateway/Request/IdinDataBuilder.php index 3fb085f15..d1d8f2851 100644 --- a/Gateway/Request/IdinDataBuilder.php +++ b/Gateway/Request/IdinDataBuilder.php @@ -120,7 +120,7 @@ public function getReturnUrl(): string { if ($this->returnUrl === null) { $url = $this->urlBuilder->setScope($this->store->getId()); - $url = $url->getRouteUrl('buckaroo/redirect/process') . '?form_key=' . $this->getFormKey(); + $url = $url->getRouteUrl('buckaroo/redirect/idin-process') . '?form_key=' . $this->getFormKey(); $this->setReturnUrl($url); } diff --git a/Model/Service/RedirectService.php b/Model/Service/RedirectService.php new file mode 100644 index 000000000..e813924ac --- /dev/null +++ b/Model/Service/RedirectService.php @@ -0,0 +1,84 @@ +logger->addDebug('start redirectToCheckout'); + if (!$this->customerSession->isLoggedIn()) { + $this->logger->addDebug('not isLoggedIn'); + if ($this->order->getCustomerId() > 0) { + $this->logger->addDebug('getCustomerId > 0'); + try { + $customer = $this->customerRepository->getById($this->order->getCustomerId()); + $this->customerSession->setCustomerDataAsLoggedIn($customer); + + if (!$this->checkoutSession->getLastRealOrderId() && $this->order->getIncrementId()) { + $this->checkoutSession->setLastRealOrderId($this->order->getIncrementId()); + $this->logger->addDebug(__METHOD__ . '|setLastRealOrderId|'); + $this->checkoutSession->restoreQuote(); + $this->logger->addDebug(__METHOD__ . '|restoreQuote|'); + } elseif ($this->redirectRequest->hasPostData('primary_service', 'IDIN')) { + $this->checkoutSession->restoreQuote(); + } + } catch (\Exception $e) { + $this->logger->addError('Could not load customer'); + } + } + } + $this->logger->addDebug('ready for redirect'); + return $this->handleProcessedResponse('checkout', ['_query' => ['bk_e' => 1]]); + } + + /** + * Redirect to Failure url, which means we've got a problem + * + * @return ResponseInterface + */ + protected function redirectFailure() + { + $store = $this->order->getStore(); + $this->logger->addDebug('start redirectFailure'); + if ($this->accountConfig->getFailureRedirectToCheckout($store)) { + $this->logger->addDebug('getFailureRedirectToCheckout'); + if (!$this->customerSession->isLoggedIn() && ($this->order->getCustomerId() > 0)) { + $this->logger->addDebug('not isLoggedIn'); + $this->logger->addDebug('getCustomerId > 0'); + try { + $customer = $this->customerRepository->getById($this->order->getCustomerId()); + $this->customerSession->setCustomerDataAsLoggedIn($customer); + + if (!$this->checkoutSession->getLastRealOrderId() && $this->order->getIncrementId()) { + $this->checkoutSession->setLastRealOrderId($this->order->getIncrementId()); + $this->logger->addDebug(__METHOD__ . '|setLastRealOrderId|'); + if (!$this->getSkipHandleFailedRecreate()) { + $this->checkoutSession->restoreQuote(); + $this->logger->addDebug(__METHOD__ . '|restoreQuote|'); + } + } + $this->setSkipHandleFailedRecreate(); + } catch (\Exception $e) { + $this->logger->addError('Could not load customer'); + } + } + $this->logger->addDebug('ready for redirect'); + return $this->handleProcessedResponse('checkout', ['_fragment' => 'payment', '_query' => ['bk_e' => 1]]); + } + + /** + * @noinspection PhpUndefinedMethodInspection + */ + $url = $this->accountConfig->getFailureRedirect($store); + + return $this->handleProcessedResponse($url); + } +} \ No newline at end of file diff --git a/Service/Push/OrderRequestService.php b/Service/Push/OrderRequestService.php index 8412deabb..6743e2e14 100644 --- a/Service/Push/OrderRequestService.php +++ b/Service/Push/OrderRequestService.php @@ -293,7 +293,7 @@ public function saveAndReloadOrder() * @return void * @throws \Exception */ - private function loadOrder() + public function loadOrder() { $brqOrderId = $this->getOrderIncrementId(); From f0d1ea7cf8298f095fa72bdd97e5bad76d3e30c5 Mon Sep 17 00:00:00 2001 From: Lucian Turiac Date: Wed, 9 Aug 2023 23:31:55 +0300 Subject: [PATCH 19/29] BP-2133 - Working at Refactor Redirect --- Controller/Redirect/IdinProcess.php | 1 + Controller/Redirect/Process.php | 320 +++++++++++++++------------- Model/Method/BuckarooAdapter.php | 23 -- 3 files changed, 174 insertions(+), 170 deletions(-) diff --git a/Controller/Redirect/IdinProcess.php b/Controller/Redirect/IdinProcess.php index f6ffde7b0..5d4c6bf46 100644 --- a/Controller/Redirect/IdinProcess.php +++ b/Controller/Redirect/IdinProcess.php @@ -14,6 +14,7 @@ use Magento\Customer\Api\CustomerRepositoryInterface; use Magento\Customer\Model\Customer; use Magento\Customer\Model\Session as CustomerSession; +use Magento\Customer\Model\ResourceModel\CustomerFactory; use Magento\Framework\App\Action\Context; use Magento\Framework\App\Request\Http as Http; use Magento\Framework\Event\ManagerInterface; diff --git a/Controller/Redirect/Process.php b/Controller/Redirect/Process.php index 214c8776d..7bfa35951 100644 --- a/Controller/Redirect/Process.php +++ b/Controller/Redirect/Process.php @@ -41,6 +41,8 @@ use Magento\Framework\App\Request\Http as Http; use Magento\Framework\App\ResponseInterface; use Magento\Framework\Event\ManagerInterface; +use Magento\Framework\Exception\LocalizedException; +use Magento\Framework\Exception\NoSuchEntityException; use Magento\Quote\Model\Quote; use Magento\Sales\Api\Data\OrderInterface; use Magento\Sales\Api\Data\OrderPaymentInterface; @@ -107,11 +109,6 @@ class Process extends Action */ protected $customerModel; - /** - * @var CustomerFactory - */ - protected $customerResourceFactory; - /** * @var OrderService */ @@ -144,7 +141,6 @@ class Process extends Action * @param CheckoutSession $checkoutSession * @param CustomerSession $customerSession * @param CustomerRepositoryInterface $customerRepository - * @param CustomerFactory $customerFactory * @param OrderService $orderService * @param ManagerInterface $eventManager * @param Recreate $quoteRecreate @@ -161,7 +157,6 @@ public function __construct( CheckoutSession $checkoutSession, CustomerSession $customerSession, CustomerRepositoryInterface $customerRepository, - CustomerFactory $customerFactory, OrderService $orderService, ManagerInterface $eventManager, Recreate $quoteRecreate, @@ -174,7 +169,6 @@ public function __construct( $this->checkoutSession = $checkoutSession; $this->customerSession = $customerSession; $this->customerRepository = $customerRepository; - $this->customerResourceFactory = $customerFactory; $this->accountConfig = $accountConfig; $this->orderService = $orderService; $this->eventManager = $eventManager; @@ -233,140 +227,150 @@ public function execute() $this->setPaymentOutOfTransit($this->payment); } - if (!method_exists($this->payment->getMethodInstance(), 'canProcessPostData')) { - return $this->handleProcessedResponse('/'); - } - - if (!$this->payment->getMethodInstance()->canProcessPostData($this->payment, $this->redirectRequest)) { + if($this->skipWaitingOnConsumerForProcessingOrder()) { return $this->handleProcessedResponse('/'); } $this->logger->addDebug(__METHOD__ . '|2|' . var_export($statusCode, true)); - if (($payment->getMethodInstance()->getCode() == 'buckaroo_magento2_paypal') + if (($this->payment->getMethodInstance()->getCode() == 'buckaroo_magento2_paypal') && ($statusCode == BuckarooStatusCode::PENDING_PROCESSING) ) { $statusCode = BuckarooStatusCode::CANCELLED_BY_USER; $this->logger->addDebug(__METHOD__ . '|22|' . var_export($statusCode, true)); } - switch ($statusCode) { - case BuckarooStatusCode::SUCCESS: - case BuckarooStatusCode::PENDING_PROCESSING: - $debugInfo = [ - $this->order->getStatus(), - $this->orderStatusFactory->get(BuckarooStatusCode::SUCCESS, $this->order), - ]; - $this->logger->addDebug(__METHOD__ . '|3|' . var_export($debugInfo, true)); - - if ($this->order->canInvoice()) { - $this->logger->addDebug(__METHOD__ . '|31|'); - if ($statusCode == BuckarooStatusCode::SUCCESS) { - //do nothing - push will change a status - $this->logger->addDebug(__METHOD__ . '|32|'); - } else { - $this->logger->addDebug(__METHOD__ . '|33|'); - // Set the 'Pending payment status' here - $pendingStatus = $this->orderStatusFactory->get( - BuckarooStatusCode::PENDING_PROCESSING, - $this->order - ); - if ($pendingStatus) { - $this->logger->addDebug(__METHOD__ . '|34|' . var_export($pendingStatus, true)); - $this->order->setStatus($pendingStatus); - $this->order->save(); - } - } - } - - $payment->getMethodInstance()->processCustomPostData($payment, $this->redirectRequest->getData()); - - /** @var \Magento\Payment\Model\MethodInterface $paymentMethod */ - $paymentMethod = $this->order->getPayment()->getMethodInstance(); - $store = $this->order->getStore(); - - // Send order confirmation mail if we're supposed to - /** - * @noinspection PhpUndefinedMethodInspection - */ - if (!$this->order->getEmailSent() - && ( - $this->accountConfig->getOrderConfirmationEmail($store) === "1" - || $paymentMethod->getConfigData('order_email', $store) === "1" - ) - ) { - $isKlarnaKpReserve = ($this->redirectRequest->hasPostData('primary_service', 'KlarnaKp') - && $this->redirectRequest->hasAdditionalInformation('service_action_from_magento', 'reserve') - && !empty($this->redirectRequest->getServiceKlarnakpReservationnumber())); - - if (!($this->redirectRequest->hasAdditionalInformation('initiated_by_magento', 1) - && $isKlarnaKpReserve) - ) { - if ($statusCode == BuckarooStatusCode::SUCCESS) { - $this->logger->addDebug(__METHOD__ . '|sendemail|'); - $this->orderRequestService->sendOrderEmail($this->order, true); - } - } - } + return $this->processRedirectByStatus($statusCode); + } - $pendingCode = BuckarooStatusCode::PENDING_PROCESSING; - if (($statusCode == $pendingCode) - && !$this->redirectRequest->hasPostData('payment_method', 'sofortueberweisung') - ) { - $this->addErrorMessage( - __( - 'Unfortunately an error occurred while processing your payment. Please try again. If this' . - ' error persists, please choose a different payment method.' - ) - ); - $this->logger->addDebug(__METHOD__ . '|5|'); - - $this->removeAmastyGiftcardOnFailed(); - - return $this->handleProcessedResponse('/'); - } + /** + * @throws NoSuchEntityException + * @throws LocalizedException + */ + private function processRedirectByStatus($statusCode) { - $this->logger->addDebug(__METHOD__ . '|51|' . var_export([ - $this->checkoutSession->getLastSuccessQuoteId(), - $this->checkoutSession->getLastQuoteId(), - $this->checkoutSession->getLastOrderId(), - $this->checkoutSession->getLastRealOrderId(), - $this->order->getQuoteId(), - $this->order->getId(), - $this->order->getIncrementId(), - ], true)); - - if (!$this->checkoutSession->getLastSuccessQuoteId() && $this->order->getQuoteId()) { - $this->logger->addDebug(__METHOD__ . '|52|'); - $this->checkoutSession->setLastSuccessQuoteId($this->order->getQuoteId()); - } - if (!$this->checkoutSession->getLastQuoteId() && $this->order->getQuoteId()) { - $this->logger->addDebug(__METHOD__ . '|53|'); - $this->checkoutSession->setLastQuoteId($this->order->getQuoteId()); - } - if (!$this->checkoutSession->getLastOrderId() && $this->order->getId()) { - $this->logger->addDebug(__METHOD__ . '|54|'); - $this->checkoutSession->setLastOrderId($this->order->getId()); - } - if (!$this->checkoutSession->getLastRealOrderId() && $this->order->getIncrementId()) { - $this->logger->addDebug(__METHOD__ . '|55|'); - $this->checkoutSession->setLastRealOrderId($this->order->getIncrementId()); - } - $this->logger->addDebug(__METHOD__ . '|6|'); - // Redirect to success page - return $this->redirectSuccess(); - case BuckarooStatusCode::ORDER_FAILED: - case BuckarooStatusCode::FAILED: - case BuckarooStatusCode::REJECTED: - case BuckarooStatusCode::CANCELLED_BY_USER: - return $this->handleFailed($statusCode); - //no default + if ($statusCode == BuckarooStatusCode::SUCCESS) { + return $this->processSucceededRedirect($statusCode); + } elseif ($statusCode == BuckarooStatusCode::PENDING_PROCESSING) { + return $this->processPendingRedirect($statusCode); + } elseif (in_array($statusCode, [ + BuckarooStatusCode::ORDER_FAILED, + BuckarooStatusCode::FAILED, + BuckarooStatusCode::REJECTED, + BuckarooStatusCode::CANCELLED_BY_USER + ])) { + return $this->handleFailed($statusCode); } - $this->logger->addDebug(__METHOD__ . '|9|'); return $this->_response; } + private function processSucceededRedirect($statusCode) + { + $this->sendKlarnaKpOrderConfirmation($statusCode); + + $this->setLastQuoteOrder(); + + return $this->redirectSuccess(); + } + + private function processPendingRedirect($statusCode) + { + if ($this->order->canInvoice()) { + $this->logger->addDebug(__METHOD__ . '|33|'); + // Set the 'Pending payment status' here + $pendingStatus = $this->orderStatusFactory->get( + BuckarooStatusCode::PENDING_PROCESSING, + $this->order + ); + if ($pendingStatus) { + $this->logger->addDebug(__METHOD__ . '|34|' . var_export($pendingStatus, true)); + $this->order->setStatus($pendingStatus); + $this->order->save(); + } + } + + $this->sendKlarnaKpOrderConfirmation($statusCode); + + if (!$this->redirectRequest->hasPostData('payment_method', 'sofortueberweisung')) { + $this->addErrorMessage( + __( + 'Unfortunately an error occurred while processing your payment. Please try again. If this' . + ' error persists, please choose a different payment method.' + ) + ); + $this->logger->addDebug(__METHOD__ . '|5|'); + + $this->removeAmastyGiftcardOnFailed(); + + return $this->handleProcessedResponse('/'); + } + + $this->setLastQuoteOrder(); + + return $this->redirectSuccess(); + } + + private function setLastQuoteOrder(): void + { + $this->logger->addDebug(__METHOD__ . '|51|' . var_export([ + $this->checkoutSession->getLastSuccessQuoteId(), + $this->checkoutSession->getLastQuoteId(), + $this->checkoutSession->getLastOrderId(), + $this->checkoutSession->getLastRealOrderId(), + $this->order->getQuoteId(), + $this->order->getId(), + $this->order->getIncrementId(), + ], true)); + + if (!$this->checkoutSession->getLastSuccessQuoteId() && $this->order->getQuoteId()) { + $this->logger->addDebug(__METHOD__ . '|52|'); + $this->checkoutSession->setLastSuccessQuoteId($this->order->getQuoteId()); + } + if (!$this->checkoutSession->getLastQuoteId() && $this->order->getQuoteId()) { + $this->logger->addDebug(__METHOD__ . '|53|'); + $this->checkoutSession->setLastQuoteId($this->order->getQuoteId()); + } + if (!$this->checkoutSession->getLastOrderId() && $this->order->getId()) { + $this->logger->addDebug(__METHOD__ . '|54|'); + $this->checkoutSession->setLastOrderId($this->order->getId()); + } + if (!$this->checkoutSession->getLastRealOrderId() && $this->order->getIncrementId()) { + $this->logger->addDebug(__METHOD__ . '|55|'); + $this->checkoutSession->setLastRealOrderId($this->order->getIncrementId()); + } + } + + private function sendKlarnaKpOrderConfirmation($statusCode) { + /** @var \Magento\Payment\Model\MethodInterface $paymentMethod */ + $paymentMethod = $this->order->getPayment()->getMethodInstance(); + $store = $this->order->getStore(); + + // Send order confirmation mail if we're supposed to + /** + * @noinspection PhpUndefinedMethodInspection + */ + if (!$this->order->getEmailSent() + && ( + $this->accountConfig->getOrderConfirmationEmail($store) === "1" + || $paymentMethod->getConfigData('order_email', $store) === "1" + ) + ) { + $isKlarnaKpReserve = ($this->redirectRequest->hasPostData('primary_service', 'KlarnaKp') + && $this->redirectRequest->hasAdditionalInformation('service_action_from_magento', 'reserve') + && !empty($this->redirectRequest->getServiceKlarnakpReservationnumber())); + + if (!($this->redirectRequest->hasAdditionalInformation('initiated_by_magento', 1) + && $isKlarnaKpReserve) + ) { + if ($statusCode == BuckarooStatusCode::SUCCESS) { + $this->logger->addDebug(__METHOD__ . '|sendemail|'); + $this->orderRequestService->sendOrderEmail($this->order, true); + } + } + } + } + /** * Handle final response * @@ -516,20 +520,7 @@ protected function redirectSuccess() $this->quote->setReservedOrderId(null); - if (!empty($this->redirectRequest->getPaymentMethod()) - && - ($this->redirectRequest->getPaymentMethod() == 'applepay') - && - !empty($this->redirectRequest->getStatusCode()) - && - ($this->redirectRequest->getStatusCode() == '190') - && - !empty($this->redirectRequest->getTest()) - && - ($this->redirectRequest->getTest() == 'true') - ) { - $this->redirectSuccessApplePay(); - } + $this->redirectSuccessApplePay(); $this->logger->addDebug(__METHOD__ . '|2|' . var_export($url, true)); @@ -543,14 +534,19 @@ protected function redirectSuccess() */ protected function redirectSuccessApplePay() { - $this->logger->addDebug(__METHOD__); - - $this->checkoutSession - ->setLastQuoteId($this->order->getQuoteId()) - ->setLastSuccessQuoteId($this->order->getQuoteId()) - ->setLastOrderId($this->order->getId()) - ->setLastRealOrderId($this->order->getIncrementId()) - ->setLastOrderStatus($this->order->getStatus()); + if ($this->redirectRequest->hasPostData('payment_method', 'applepay') + && $this->redirectRequest->hasPostData('status_code', '190') + && $this->redirectRequest->hasPostData('test', 'true') + ) { + $this->logger->addDebug(__METHOD__); + + $this->checkoutSession + ->setLastQuoteId($this->order->getQuoteId()) + ->setLastSuccessQuoteId($this->order->getQuoteId()) + ->setLastOrderId($this->order->getId()) + ->setLastRealOrderId($this->order->getIncrementId()) + ->setLastOrderStatus($this->order->getStatus()); + } } /** @@ -558,7 +554,7 @@ protected function redirectSuccessApplePay() * * @param int|null $statusCode * @return ResponseInterface - * @throws \Magento\Framework\Exception\NoSuchEntityException + * @throws \Magento\Framework\Exception\NoSuchEntityException|\Exception */ protected function handleFailed($statusCode) { @@ -697,4 +693,34 @@ public function getResponseParameters() { return $this->redirectRequest->getData(); } + + /** + * Skip process redirect for Processing Order when the status of the request is WaitingOnConsumer + * + * @return bool + */ + public function skipWaitingOnConsumerForProcessingOrder(): bool + { + if (in_array($this->payment->getMethod(), + [ + 'buckaroo_magento2_creditcards', + 'buckaroo_magento2_paylink', + 'buckaroo_magento2_payperemail', + 'buckaroo_magento2_transfer' + ])) { + + if ($this->payment->getAdditionalInformation(BuckarooAdapter::BUCKAROO_ORIGINAL_TRANSACTION_KEY_KEY) + != $this->redirectRequest->getTransactions()) { + return true; + } + + $orderState = $this->order->getState(); + if ($orderState == Order::STATE_PROCESSING + && $this->redirectRequest->getStatusCode() == BuckarooStatusCode::WAITING_ON_CONSUMER) { + return true; + } + } + + return false; + } } diff --git a/Model/Method/BuckarooAdapter.php b/Model/Method/BuckarooAdapter.php index d71877c9b..3d866d950 100644 --- a/Model/Method/BuckarooAdapter.php +++ b/Model/Method/BuckarooAdapter.php @@ -244,29 +244,6 @@ public function canProcessPostData($payment, PushRequestInterface $postData): bo return true; } - /** - * Process custom post data received on push or on redirect - * - * @param OrderPaymentInterface|InfoInterface $payment - * @param array $postData - * @throws \Exception - */ - public function processCustomPostData($payment, array $postData) - { - if ($payment->getMethod() == 'buckaroo_magento2_klarnakp') { - $order = $payment->getOrder(); - - if ($order->getBuckarooReservationNumber()) { - return; - } - - if (isset($postData['brq_service_klarnakp_reservationnumber'])) { - $order->setBuckarooReservationNumber($postData['brq_service_klarnakp_reservationnumber']); - $order->save(); - } - } - } - /** * Can create invoice on push * From e257ace8b68197183aff247e0b427258cdbae30d Mon Sep 17 00:00:00 2001 From: Lucian Turiac Date: Thu, 10 Aug 2023 23:21:06 +0300 Subject: [PATCH 20/29] BP-2133 - Refactor Redirect --- Controller/Redirect/IdinProcess.php | 84 ++++++++------- Controller/Redirect/Process.php | 157 +++++++++++++++------------- Model/Service/RedirectService.php | 84 --------------- 3 files changed, 132 insertions(+), 193 deletions(-) delete mode 100644 Model/Service/RedirectService.php diff --git a/Controller/Redirect/IdinProcess.php b/Controller/Redirect/IdinProcess.php index 5d4c6bf46..f606fc43d 100644 --- a/Controller/Redirect/IdinProcess.php +++ b/Controller/Redirect/IdinProcess.php @@ -1,8 +1,26 @@ order = $order; - $this->quote = $quote; - $this->logger = $logger; - $this->orderRequestService = $orderRequestService; - $this->orderStatusFactory = $orderStatusFactory; - $this->checkoutSession = $checkoutSession; - $this->customerSession = $customerSession; - $this->customerRepository = $customerRepository; - $this->customerModel = $customerModel; + parent::__construct($context, $logger, $quote, $accountConfig, $orderRequestService, + $orderStatusFactory, $checkoutSession, $customerSession, $customerRepository, + $orderService, $eventManager, $quoteRecreate, $requestPushFactory); + $this->customerResourceFactory = $customerFactory; - $this->accountConfig = $accountConfig; - $this->orderService = $orderService; - $this->eventManager = $eventManager; - $this->quoteRecreate = $quoteRecreate; // @codingStandardsIgnoreStart if (interface_exists("\Magento\Framework\App\CsrfAwareActionInterface")) { @@ -92,12 +95,12 @@ public function __construct( $request->getHeaders()->addHeaderLine('X_REQUESTED_WITH', 'XMLHttpRequest'); } } - $this->redirectRequest = $requestPushFactory->create(); // @codingStandardsIgnoreEnd + $this->redirectRequest = $requestPushFactory->create(); } /** - * @return \Magento\Framework\App\ResponseInterface|\Magento\Framework\Controller\ResultInterface|void + * @return ResponseInterface|\Magento\Framework\Controller\ResultInterface|void * @throws \Buckaroo\Magento2\Exception */ public function execute() @@ -122,7 +125,7 @@ public function execute() * * @return bool */ - private function setCustomerIDIN() + private function setCustomerIDIN(): bool { if (!empty($this->redirectRequest->getServiceIdinConsumerbin()) && !empty($this->redirectRequest->getServiceIdinIseighteenorolder()) @@ -130,12 +133,21 @@ private function setCustomerIDIN() ) { $this->checkoutSession->setCustomerIDIN($this->redirectRequest->getServiceIdinConsumerbin()); $this->checkoutSession->setCustomerIDINIsEighteenOrOlder(true); - if (!empty($this->redirectRequest->getAdditionalInformation('idin_cid'))) { - $customerNew = $this->customerModel->load((int)$this->redirectRequest->getAdditionalInformation('idin_cid')); + $idinCid = $this->redirectRequest->getAdditionalInformation('idin_cid'); + if (!empty($idinCid)) { + try { + /** @var Customer $customerNew */ + $customerNew = $this->customerRepository->getById((int)$idinCid); + } catch (\Exception $e) { + $this->addErrorMessage(__('Unfortunately customer was not find by IDIN id: "%1"!', $idinCid)); + $this->logger->addError(__METHOD__ . ' | ' . $e->getMessage()); + return false; + } $customerData = $customerNew->getDataModel(); $customerData->setCustomAttribute('buckaroo_idin', $this->redirectRequest->getServiceIdinConsumerbin()); $customerData->setCustomAttribute('buckaroo_idin_iseighteenorolder', 1); $customerNew->updateData($customerData); + $customerResource = $this->customerResourceFactory->create(); $customerResource->saveAttribute($customerNew, 'buckaroo_idin'); $customerResource->saveAttribute($customerNew, 'buckaroo_idin_iseighteenorolder'); diff --git a/Controller/Redirect/Process.php b/Controller/Redirect/Process.php index 7bfa35951..fd87e7765 100644 --- a/Controller/Redirect/Process.php +++ b/Controller/Redirect/Process.php @@ -17,11 +17,11 @@ * @copyright Copyright (c) Buckaroo B.V. * @license https://tldrlegal.com/license/mit-license */ +declare(strict_types=1); namespace Buckaroo\Magento2\Controller\Redirect; use Buckaroo\Magento2\Api\PushRequestInterface; -use Buckaroo\Magento2\Exception; use Buckaroo\Magento2\Logging\Log; use Buckaroo\Magento2\Model\BuckarooStatusCode; use Buckaroo\Magento2\Model\ConfigProvider\Account as AccountConfig; @@ -33,7 +33,6 @@ use Buckaroo\Magento2\Service\Sales\Quote\Recreate; use Magento\Checkout\Model\Session as CheckoutSession; use Magento\Customer\Api\CustomerRepositoryInterface; -use Magento\Customer\Model\Customer; use Magento\Customer\Model\ResourceModel\CustomerFactory; use Magento\Customer\Model\Session as CustomerSession; use Magento\Framework\App\Action\Action; @@ -43,15 +42,12 @@ use Magento\Framework\Event\ManagerInterface; use Magento\Framework\Exception\LocalizedException; use Magento\Framework\Exception\NoSuchEntityException; +use Magento\Framework\Phrase; use Magento\Quote\Model\Quote; use Magento\Sales\Api\Data\OrderInterface; use Magento\Sales\Api\Data\OrderPaymentInterface; use Magento\Sales\Model\Order; -/** - * @SuppressWarnings(PHPMD.CouplingBetweenObjects) - * @SuppressWarnings(PHPMD.TooManyFields) - */ class Process extends Action { /** @@ -87,7 +83,7 @@ class Process extends Action /** * @var Log */ - protected $logger; + protected Log $logger; /** * @var CheckoutSession @@ -97,34 +93,27 @@ class Process extends Action /** * @var CustomerSession */ - public CustomerSession $customerSession; + protected CustomerSession $customerSession; /** * @var CustomerRepositoryInterface */ - protected $customerRepository; - - /** - * @var Customer - */ - protected $customerModel; + protected CustomerRepositoryInterface $customerRepository; /** * @var OrderService */ - protected $orderService; + protected OrderService $orderService; /** * @var ManagerInterface */ - protected $eventManager; + protected ManagerInterface $eventManager; /** * @var Recreate */ - private $quoteRecreate; - - protected $quoteRepository; + protected Recreate $quoteRecreate; /** * @var PushRequestInterface @@ -183,8 +172,8 @@ public function __construct( $request->getHeaders()->addHeaderLine('X_REQUESTED_WITH', 'XMLHttpRequest'); } } - $this->redirectRequest = $requestPushFactory->create(); // @codingStandardsIgnoreEnd + $this->redirectRequest = $requestPushFactory->create(); } /** @@ -265,7 +254,11 @@ private function processRedirectByStatus($statusCode) { return $this->_response; } - private function processSucceededRedirect($statusCode) + /** + * @param $statusCode + * @return ResponseInterface + */ + private function processSucceededRedirect($statusCode): ResponseInterface { $this->sendKlarnaKpOrderConfirmation($statusCode); @@ -274,7 +267,12 @@ private function processSucceededRedirect($statusCode) return $this->redirectSuccess(); } - private function processPendingRedirect($statusCode) + /** + * @param $statusCode + * @return ResponseInterface + * @throws LocalizedException + */ + private function processPendingRedirect($statusCode): ResponseInterface { if ($this->order->canInvoice()) { $this->logger->addDebug(__METHOD__ . '|33|'); @@ -311,6 +309,9 @@ private function processPendingRedirect($statusCode) return $this->redirectSuccess(); } + /** + * @return void + */ private function setLastQuoteOrder(): void { $this->logger->addDebug(__METHOD__ . '|51|' . var_export([ @@ -379,7 +380,7 @@ private function sendKlarnaKpOrderConfirmation($statusCode) { * * @return ResponseInterface */ - public function handleProcessedResponse($path, $arguments = []) + public function handleProcessedResponse(string $path, array $arguments = []): ResponseInterface { $this->logger->addDebug(__METHOD__ . '|15|'); return $this->_redirect($path, $arguments); @@ -388,11 +389,11 @@ public function handleProcessedResponse($path, $arguments = []) /** * Add success message to be displayed to the user * - * @param string $message + * @param string|Phrase $message * * @return void */ - public function addSuccessMessage(string $message) + public function addSuccessMessage(string|Phrase $message): void { $this->messageManager->addSuccessMessage($message); } @@ -400,15 +401,40 @@ public function addSuccessMessage(string $message) /** * Add error message to be displayed to the user * - * @param string $message + * @param string|Phrase $message * * @return void */ - public function addErrorMessage(string $message) + public function addErrorMessage(string|Phrase $message): void { $this->messageManager->addErrorMessage($message); } + public function addErrorMessageByStatus($statusCode){ + + // StatusCode specified error messages + $statusCodeAddErrorMessage = []; + $statusCodeAddErrorMessage[BuckarooStatusCode::ORDER_FAILED] = + 'Unfortunately an error occurred while processing your payment. Please try again. If this' . + ' error persists, please choose a different payment method.'; + $statusCodeAddErrorMessage[BuckarooStatusCode::FAILED] = + 'Unfortunately an error occurred while processing your payment. Please try again. If this' . + ' error persists, please choose a different payment method.'; + $statusCodeAddErrorMessage[BuckarooStatusCode::REJECTED] = + 'Unfortunately an error occurred while processing your payment. Please try again. If this' . + ' error persists, please choose a different payment method.'; + $statusCodeAddErrorMessage[ + BuckarooStatusCode::CANCELLED_BY_USER + ] = 'According to our system, you have canceled the payment. If this' . + ' is not the case, please contact us.'; + + $this->addErrorMessage( + __( + $statusCodeAddErrorMessage[$statusCode] + ) + ); + } + /** * Create redirect response * @@ -532,7 +558,7 @@ protected function redirectSuccess() * * @return void */ - protected function redirectSuccessApplePay() + protected function redirectSuccessApplePay(): void { if ($this->redirectRequest->hasPostData('payment_method', 'applepay') && $this->redirectRequest->hasPostData('status_code', '190') @@ -575,28 +601,7 @@ protected function handleFailed($statusCode) * 2) cancel the order we had to create to even get here * 3) redirect back to the checkout page to offer the user feedback & the option to try again */ - - // StatusCode specified error messages - $statusCodeAddErrorMessage = []; - $statusCodeAddErrorMessage[BuckarooStatusCode::ORDER_FAILED] = - 'Unfortunately an error occurred while processing your payment. Please try again. If this' . - ' error persists, please choose a different payment method.'; - $statusCodeAddErrorMessage[BuckarooStatusCode::FAILED] = - 'Unfortunately an error occurred while processing your payment. Please try again. If this' . - ' error persists, please choose a different payment method.'; - $statusCodeAddErrorMessage[BuckarooStatusCode::REJECTED] = - 'Unfortunately an error occurred while processing your payment. Please try again. If this' . - ' error persists, please choose a different payment method.'; - $statusCodeAddErrorMessage[ - BuckarooStatusCode::CANCELLED_BY_USER - ] = 'According to our system, you have canceled the payment. If this' . - ' is not the case, please contact us.'; - - $this->addErrorMessage( - __( - $statusCodeAddErrorMessage[$statusCode] - ) - ); + $this->addErrorMessageByStatus($statusCode); //skip cancel order for PPE if (!empty($this->redirectRequest->getAdditionalInformation('frompayperemail'))) { @@ -606,6 +611,7 @@ protected function handleFailed($statusCode) if (!$this->cancelOrder($statusCode)) { $this->logger->addError('Could not cancel the order.'); } + $this->logger->addDebug(__METHOD__ . '|8|'); return $this->redirectFailure(); } @@ -630,29 +636,7 @@ protected function redirectFailure() $store = $this->order->getStore(); $this->logger->addDebug('start redirectFailure'); if ($this->accountConfig->getFailureRedirectToCheckout($store)) { - $this->logger->addDebug('getFailureRedirectToCheckout'); - if (!$this->customerSession->isLoggedIn() && ($this->order->getCustomerId() > 0)) { - $this->logger->addDebug('not isLoggedIn'); - $this->logger->addDebug('getCustomerId > 0'); - try { - $customer = $this->customerRepository->getById($this->order->getCustomerId()); - $this->customerSession->setCustomerDataAsLoggedIn($customer); - - if (!$this->checkoutSession->getLastRealOrderId() && $this->order->getIncrementId()) { - $this->checkoutSession->setLastRealOrderId($this->order->getIncrementId()); - $this->logger->addDebug(__METHOD__ . '|setLastRealOrderId|'); - if (!$this->getSkipHandleFailedRecreate()) { - $this->checkoutSession->restoreQuote(); - $this->logger->addDebug(__METHOD__ . '|restoreQuote|'); - } - } - $this->setSkipHandleFailedRecreate(); - } catch (\Exception $e) { - $this->logger->addError('Could not load customer'); - } - } - $this->logger->addDebug('ready for redirect'); - return $this->handleProcessedResponse('checkout', ['_fragment' => 'payment', '_query' => ['bk_e' => 1]]); + return $this->redirectOnCheckoutForFailedTransaction(); } /** @@ -663,6 +647,33 @@ protected function redirectFailure() return $this->handleProcessedResponse($url); } + private function redirectOnCheckoutForFailedTransaction() + { + $this->logger->addDebug('getFailureRedirectToCheckout'); + if (!$this->customerSession->isLoggedIn() && ($this->order->getCustomerId() > 0)) { + $this->logger->addDebug('not isLoggedIn'); + $this->logger->addDebug('getCustomerId > 0'); + try { + $customer = $this->customerRepository->getById($this->order->getCustomerId()); + $this->customerSession->setCustomerDataAsLoggedIn($customer); + + if (!$this->checkoutSession->getLastRealOrderId() && $this->order->getIncrementId()) { + $this->checkoutSession->setLastRealOrderId($this->order->getIncrementId()); + $this->logger->addDebug(__METHOD__ . '|setLastRealOrderId|'); + if (!$this->getSkipHandleFailedRecreate()) { + $this->checkoutSession->restoreQuote(); + $this->logger->addDebug(__METHOD__ . '|restoreQuote|'); + } + } + $this->setSkipHandleFailedRecreate(); + } catch (\Exception $e) { + $this->logger->addError('Could not load customer'); + } + } + $this->logger->addDebug('ready for redirect'); + return $this->handleProcessedResponse('checkout', ['_fragment' => 'payment', '_query' => ['bk_e' => 1]]); + } + /** * Set skip recreating quote on failed transaction * diff --git a/Model/Service/RedirectService.php b/Model/Service/RedirectService.php deleted file mode 100644 index e813924ac..000000000 --- a/Model/Service/RedirectService.php +++ /dev/null @@ -1,84 +0,0 @@ -logger->addDebug('start redirectToCheckout'); - if (!$this->customerSession->isLoggedIn()) { - $this->logger->addDebug('not isLoggedIn'); - if ($this->order->getCustomerId() > 0) { - $this->logger->addDebug('getCustomerId > 0'); - try { - $customer = $this->customerRepository->getById($this->order->getCustomerId()); - $this->customerSession->setCustomerDataAsLoggedIn($customer); - - if (!$this->checkoutSession->getLastRealOrderId() && $this->order->getIncrementId()) { - $this->checkoutSession->setLastRealOrderId($this->order->getIncrementId()); - $this->logger->addDebug(__METHOD__ . '|setLastRealOrderId|'); - $this->checkoutSession->restoreQuote(); - $this->logger->addDebug(__METHOD__ . '|restoreQuote|'); - } elseif ($this->redirectRequest->hasPostData('primary_service', 'IDIN')) { - $this->checkoutSession->restoreQuote(); - } - } catch (\Exception $e) { - $this->logger->addError('Could not load customer'); - } - } - } - $this->logger->addDebug('ready for redirect'); - return $this->handleProcessedResponse('checkout', ['_query' => ['bk_e' => 1]]); - } - - /** - * Redirect to Failure url, which means we've got a problem - * - * @return ResponseInterface - */ - protected function redirectFailure() - { - $store = $this->order->getStore(); - $this->logger->addDebug('start redirectFailure'); - if ($this->accountConfig->getFailureRedirectToCheckout($store)) { - $this->logger->addDebug('getFailureRedirectToCheckout'); - if (!$this->customerSession->isLoggedIn() && ($this->order->getCustomerId() > 0)) { - $this->logger->addDebug('not isLoggedIn'); - $this->logger->addDebug('getCustomerId > 0'); - try { - $customer = $this->customerRepository->getById($this->order->getCustomerId()); - $this->customerSession->setCustomerDataAsLoggedIn($customer); - - if (!$this->checkoutSession->getLastRealOrderId() && $this->order->getIncrementId()) { - $this->checkoutSession->setLastRealOrderId($this->order->getIncrementId()); - $this->logger->addDebug(__METHOD__ . '|setLastRealOrderId|'); - if (!$this->getSkipHandleFailedRecreate()) { - $this->checkoutSession->restoreQuote(); - $this->logger->addDebug(__METHOD__ . '|restoreQuote|'); - } - } - $this->setSkipHandleFailedRecreate(); - } catch (\Exception $e) { - $this->logger->addError('Could not load customer'); - } - } - $this->logger->addDebug('ready for redirect'); - return $this->handleProcessedResponse('checkout', ['_fragment' => 'payment', '_query' => ['bk_e' => 1]]); - } - - /** - * @noinspection PhpUndefinedMethodInspection - */ - $url = $this->accountConfig->getFailureRedirect($store); - - return $this->handleProcessedResponse($url); - } -} \ No newline at end of file From 9c1ce4df70be0d997ad4ac2752f571d33bc8fd81 Mon Sep 17 00:00:00 2001 From: Lucian Turiac Date: Fri, 11 Aug 2023 16:03:29 +0300 Subject: [PATCH 21/29] BP-2133 - Fix IDIN --- Controller/Redirect/IdinProcess.php | 33 +++++++++++++++++------------ Controller/Redirect/Process.php | 4 +--- Gateway/Request/IdinDataBuilder.php | 2 +- 3 files changed, 21 insertions(+), 18 deletions(-) diff --git a/Controller/Redirect/IdinProcess.php b/Controller/Redirect/IdinProcess.php index f606fc43d..e4863d971 100644 --- a/Controller/Redirect/IdinProcess.php +++ b/Controller/Redirect/IdinProcess.php @@ -34,11 +34,8 @@ use Magento\Customer\Model\ResourceModel\CustomerFactory; use Magento\Customer\Model\Session as CustomerSession; use Magento\Framework\App\Action\Context; -use Magento\Framework\App\Request\Http as Http; use Magento\Framework\App\ResponseInterface; use Magento\Framework\Event\ManagerInterface; -use Magento\Framework\Exception\LocalizedException; -use Magento\Framework\Exception\NoSuchEntityException; use Magento\Quote\Model\Quote; class IdinProcess extends Process @@ -86,17 +83,6 @@ public function __construct( $orderService, $eventManager, $quoteRecreate, $requestPushFactory); $this->customerResourceFactory = $customerFactory; - - // @codingStandardsIgnoreStart - if (interface_exists("\Magento\Framework\App\CsrfAwareActionInterface")) { - $request = $this->getRequest(); - if ($request instanceof Http && $request->isPost()) { - $request->setParam('isAjax', true); - $request->getHeaders()->addHeaderLine('X_REQUESTED_WITH', 'XMLHttpRequest'); - } - } - // @codingStandardsIgnoreEnd - $this->redirectRequest = $requestPushFactory->create(); } /** @@ -105,6 +91,7 @@ public function __construct( */ public function execute() { + // Initialize the order, quote, payment if ($this->redirectRequest->hasPostData('primary_service', 'IDIN')) { if ($this->setCustomerIDIN()) { $this->addSuccessMessage(__('Your iDIN verified succesfully!')); @@ -156,4 +143,22 @@ private function setCustomerIDIN(): bool } return false; } + + /** + * Create redirect response + * + * @return ResponseInterface + */ + protected function redirectToCheckout(): ResponseInterface + { + $this->logger->addDebug('start redirectToCheckout'); + try { + $this->checkoutSession->restoreQuote(); + + } catch (\Exception $e) { + $this->logger->addError('Could not restore the quote.'); + } + + return $this->handleProcessedResponse('checkout', ['_query' => ['bk_e' => 1]]); + } } \ No newline at end of file diff --git a/Controller/Redirect/Process.php b/Controller/Redirect/Process.php index fd87e7765..de05ea7a2 100644 --- a/Controller/Redirect/Process.php +++ b/Controller/Redirect/Process.php @@ -440,7 +440,7 @@ public function addErrorMessageByStatus($statusCode){ * * @return ResponseInterface */ - protected function redirectToCheckout() + protected function redirectToCheckout(): ResponseInterface { $this->logger->addDebug('start redirectToCheckout'); if (!$this->customerSession->isLoggedIn()) { @@ -456,8 +456,6 @@ protected function redirectToCheckout() $this->logger->addDebug(__METHOD__ . '|setLastRealOrderId|'); $this->checkoutSession->restoreQuote(); $this->logger->addDebug(__METHOD__ . '|restoreQuote|'); - } elseif ($this->redirectRequest->hasPostData('primary_service', 'IDIN')) { - $this->checkoutSession->restoreQuote(); } } catch (\Exception $e) { $this->logger->addError('Could not load customer'); diff --git a/Gateway/Request/IdinDataBuilder.php b/Gateway/Request/IdinDataBuilder.php index d1d8f2851..0c0f35ea5 100644 --- a/Gateway/Request/IdinDataBuilder.php +++ b/Gateway/Request/IdinDataBuilder.php @@ -120,7 +120,7 @@ public function getReturnUrl(): string { if ($this->returnUrl === null) { $url = $this->urlBuilder->setScope($this->store->getId()); - $url = $url->getRouteUrl('buckaroo/redirect/idin-process') . '?form_key=' . $this->getFormKey(); + $url = $url->getRouteUrl('buckaroo/redirect/idinProcess') . '?form_key=' . $this->getFormKey(); $this->setReturnUrl($url); } From 739dd7119f1f34961a4097a33c2af16cf80da6ee Mon Sep 17 00:00:00 2001 From: Lucian Turiac Date: Fri, 11 Aug 2023 16:57:55 +0300 Subject: [PATCH 22/29] BP-2133 - Add comments to functions, fix payconiq --- Controller/Payconiq/Process.php | 73 ++-- Controller/Redirect/IdinProcess.php | 5 +- Controller/Redirect/Process.php | 493 +++++++++++++++------------- 3 files changed, 288 insertions(+), 283 deletions(-) diff --git a/Controller/Payconiq/Process.php b/Controller/Payconiq/Process.php index 2d124bb0c..045705b0e 100644 --- a/Controller/Payconiq/Process.php +++ b/Controller/Payconiq/Process.php @@ -17,36 +17,31 @@ * @copyright Copyright (c) Buckaroo B.V. * @license https://tldrlegal.com/license/mit-license */ +declare(strict_types=1); namespace Buckaroo\Magento2\Controller\Payconiq; use Buckaroo\Magento2\Exception; -use Buckaroo\Magento2\Helper\Data; use Buckaroo\Magento2\Logging\Log; use Buckaroo\Magento2\Model\BuckarooStatusCode; -use Buckaroo\Magento2\Model\ConfigProvider\Factory; use Buckaroo\Magento2\Model\OrderStatusFactory; use Buckaroo\Magento2\Model\RequestPush\RequestPushFactory; use Buckaroo\Magento2\Model\Service\Order as OrderService; use Buckaroo\Magento2\Service\Push\OrderRequestService; use Buckaroo\Magento2\Service\Sales\Quote\Recreate; -use Magento\Checkout\Model\Cart; use Magento\Checkout\Model\Session as CheckoutSession; use Magento\Customer\Api\CustomerRepositoryInterface; -use Magento\Customer\Model\Customer; use Magento\Customer\Model\ResourceModel\CustomerFactory; use Magento\Customer\Model\Session as CustomerSession; use Magento\Framework\Api\SearchCriteriaBuilder; use Magento\Framework\App\Action\Context; use Magento\Framework\App\ResponseInterface; -use Magento\Framework\Controller\ResultInterface; use Magento\Framework\Event\ManagerInterface; use Magento\Framework\Exception\LocalizedException; use Magento\Quote\Model\Quote; use Magento\Sales\Api\Data\TransactionInterface; use Magento\Sales\Api\Data\TransactionSearchResultInterface; use Magento\Sales\Api\TransactionRepositoryInterface; -use Magento\Sales\Model\Order; use Magento\Sales\Model\Order\Payment\Transaction; /** @@ -57,79 +52,55 @@ class Process extends \Buckaroo\Magento2\Controller\Redirect\Process /** * @var null|Transaction */ - protected $transaction = null; + protected ?Transaction $transaction = null; /** * @var SearchCriteriaBuilder */ - protected $searchCriteriaBuilder; + protected SearchCriteriaBuilder $searchCriteriaBuilder; /** * @var TransactionRepositoryInterface */ - protected $transactionRepository; + protected TransactionRepositoryInterface $transactionRepository; /** * @param Context $context - * @param Order $order - * @param Quote $quote - * @param TransactionInterface $transaction * @param Log $logger + * @param Quote $quote + * @param AccountConfig $accountConfig * @param OrderRequestService $orderRequestService * @param OrderStatusFactory $orderStatusFactory * @param CheckoutSession $checkoutSession * @param CustomerSession $customerSession * @param CustomerRepositoryInterface $customerRepository - * @param Customer $customerModel - * @param CustomerFactory $customerFactory * @param OrderService $orderService - * @param SearchCriteriaBuilder $searchCriteriaBuilder - * @param TransactionRepositoryInterface $transactionRepository * @param ManagerInterface $eventManager * @param Recreate $quoteRecreate * @param RequestPushFactory $requestPushFactory - * @throws Exception - * - * @SuppressWarnings(PHPMD.ExcessiveParameterList) + * @param SearchCriteriaBuilder $searchCriteriaBuilder + * @param TransactionRepositoryInterface $transactionRepository */ public function __construct( Context $context, - Order $order, - Quote $quote, - TransactionInterface $transaction, Log $logger, + Quote $quote, + AccountConfig $accountConfig, OrderRequestService $orderRequestService, OrderStatusFactory $orderStatusFactory, CheckoutSession $checkoutSession, CustomerSession $customerSession, CustomerRepositoryInterface $customerRepository, - Customer $customerModel, - CustomerFactory $customerFactory, OrderService $orderService, - SearchCriteriaBuilder $searchCriteriaBuilder, - TransactionRepositoryInterface $transactionRepository, ManagerInterface $eventManager, Recreate $quoteRecreate, - RequestPushFactory $requestPushFactory + RequestPushFactory $requestPushFactory, + SearchCriteriaBuilder $searchCriteriaBuilder, + TransactionRepositoryInterface $transactionRepository, ) { - parent::__construct( - $context, - $order, - $quote, - $transaction, - $logger, - $orderRequestService, - $orderStatusFactory, - $checkoutSession, - $customerSession, - $customerRepository, - $customerModel, - $customerFactory, - $orderService, - $eventManager, - $quoteRecreate, - $requestPushFactory - ); + parent::__construct($context, $logger, $quote, $accountConfig, $orderRequestService, + $orderStatusFactory, $checkoutSession, $customerSession, $customerRepository, + $orderService, $eventManager, $quoteRecreate, $requestPushFactory); $this->searchCriteriaBuilder = $searchCriteriaBuilder; $this->transactionRepository = $transactionRepository; @@ -142,7 +113,7 @@ public function __construct( * @throws LocalizedException * @throws Exception */ - public function execute() + public function execute(): ResponseInterface { if (!$this->getTransactionKey()) { $this->_forward('defaultNoRoute'); @@ -150,7 +121,7 @@ public function execute() } $transaction = $this->getTransaction(); - $this->order = $transaction->getOrder(); + $this->order = $transaction->getOrder()->getOrder(); if ($this->customerSession->getCustomerId() == $this->order->getCustomerId()) { $this->logger->addError('Customer is different then the customer that start payconiq process request.'); @@ -161,7 +132,7 @@ public function execute() 'checkout', [ '_fragment' => 'payment', - '_query' => ['bk_e' => 1] + '_query' => ['bk_e' => 1] ] ); } @@ -198,10 +169,10 @@ protected function getTransactionKey() /** * Get transaction object * - * @return TransactionInterface|Transaction + * @return TransactionInterface|Transaction|null * @throws Exception */ - protected function getTransaction() + protected function getTransaction(): TransactionInterface|Transaction|null { if ($this->transaction != null) { return $this->transaction; @@ -225,7 +196,7 @@ protected function getTransaction() * @return TransactionSearchResultInterface * @throws Exception */ - protected function getList() + protected function getList(): TransactionSearchResultInterface { $transactionKey = $this->getTransactionKey(); diff --git a/Controller/Redirect/IdinProcess.php b/Controller/Redirect/IdinProcess.php index e4863d971..23a31a186 100644 --- a/Controller/Redirect/IdinProcess.php +++ b/Controller/Redirect/IdinProcess.php @@ -60,7 +60,6 @@ class IdinProcess extends Process * @param Recreate $quoteRecreate * @param RequestPushFactory $requestPushFactory * @param CustomerFactory $customerFactory - * @SuppressWarnings(PHPMD.ExcessiveParameterList) */ public function __construct( Context $context, @@ -86,10 +85,10 @@ public function __construct( } /** - * @return ResponseInterface|\Magento\Framework\Controller\ResultInterface|void + * @return ResponseInterface|void * @throws \Buckaroo\Magento2\Exception */ - public function execute() + public function execute(): ResponseInterface { // Initialize the order, quote, payment if ($this->redirectRequest->hasPostData('primary_service', 'IDIN')) { diff --git a/Controller/Redirect/Process.php b/Controller/Redirect/Process.php index de05ea7a2..73d18170c 100644 --- a/Controller/Redirect/Process.php +++ b/Controller/Redirect/Process.php @@ -50,6 +50,8 @@ class Process extends Action { + private const GENERAL_ERROR_MESSAGE = 'Unfortunately an error occurred while processing your payment. ' . + 'Please try again. If this error persists, please choose a different payment method.'; /** * @var Order $order */ @@ -181,24 +183,15 @@ public function __construct( * * @return ResponseInterface * @throws \Exception - * - * - * @SuppressWarnings(PHPMD.ExcessiveMethodLength) - * @SuppressWarnings(PHPMD.CyclomaticComplexity) - * @SuppressWarnings(PHPMD.NPathComplexity) */ - public function execute() + public function execute(): ResponseInterface { $this->logger->addDebug(__METHOD__ . '|' . var_export($this->redirectRequest->getOriginalRequest(), true)); - /** - * Check if there is a valid response. If not, redirect to home. - */ if (count($this->redirectRequest->getData()) === 0 || empty($this->redirectRequest->getStatusCode())) { return $this->handleProcessedResponse('/'); } - // Initialize the order, quote, payment $this->order = $this->orderRequestService->getOrderByRequest($this->redirectRequest); $statusCode = (int)$this->redirectRequest->getStatusCode(); @@ -209,14 +202,13 @@ public function execute() } $this->payment = $this->order->getPayment(); - - $this->checkoutSession->setRestoreQuoteLastOrder(false); - if ($this->payment) { $this->setPaymentOutOfTransit($this->payment); } - if($this->skipWaitingOnConsumerForProcessingOrder()) { + $this->checkoutSession->setRestoreQuoteLastOrder(false); + + if ($this->skipWaitingOnConsumerForProcessingOrder()) { return $this->handleProcessedResponse('/'); } @@ -233,11 +225,71 @@ public function execute() } /** - * @throws NoSuchEntityException - * @throws LocalizedException + * Handle final response + * + * @param string $path + * @param array $arguments + * + * @return ResponseInterface */ - private function processRedirectByStatus($statusCode) { + public function handleProcessedResponse(string $path, array $arguments = []): ResponseInterface + { + $this->logger->addDebug(__METHOD__ . '|15|'); + return $this->_redirect($path, $arguments); + } + + /** + * Set flag if user is on the payment provider page + * + * @param OrderPaymentInterface $payment + * @return void + * @throws \Exception + */ + protected function setPaymentOutOfTransit(OrderPaymentInterface $payment): void + { + $payment->setAdditionalInformation(BuckarooAdapter::BUCKAROO_PAYMENT_IN_TRANSIT, false)->save(); + } + + /** + * Skip process redirect for Processing Order when the status of the request is WaitingOnConsumer + * + * @return bool + */ + public function skipWaitingOnConsumerForProcessingOrder(): bool + { + if (in_array($this->payment->getMethod(), + [ + 'buckaroo_magento2_creditcards', + 'buckaroo_magento2_paylink', + 'buckaroo_magento2_payperemail', + 'buckaroo_magento2_transfer' + ])) { + + if ($this->payment->getAdditionalInformation(BuckarooAdapter::BUCKAROO_ORIGINAL_TRANSACTION_KEY_KEY) + != $this->redirectRequest->getTransactions()) { + return true; + } + $orderState = $this->order->getState(); + if ($orderState == Order::STATE_PROCESSING + && $this->redirectRequest->getStatusCode() == BuckarooStatusCode::WAITING_ON_CONSUMER) { + return true; + } + } + + return false; + } + + /** + * Processes a redirect based on the given status code. + * + * @param int $statusCode + * @return ResponseInterface + * @throws LocalizedException + * @throws NoSuchEntityException + */ + private function processRedirectByStatus(int $statusCode): ResponseInterface + { if ($statusCode == BuckarooStatusCode::SUCCESS) { return $this->processSucceededRedirect($statusCode); } elseif ($statusCode == BuckarooStatusCode::PENDING_PROCESSING) { @@ -255,61 +307,69 @@ private function processRedirectByStatus($statusCode) { } /** + * Processes a successful redirect based on the given status code. + * + * - Sends a Klarna KP order confirmation using the status code. + * - Sets the last quote and order. + * - Returns a successful redirect response. + * * @param $statusCode * @return ResponseInterface + * @throws \Exception */ private function processSucceededRedirect($statusCode): ResponseInterface { $this->sendKlarnaKpOrderConfirmation($statusCode); - $this->setLastQuoteOrder(); return $this->redirectSuccess(); } /** - * @param $statusCode - * @return ResponseInterface - * @throws LocalizedException + * Sends a Klarna KP order confirmation based on the given status code. + * + * - Retrieves the payment method and store from the order object. + * - Checks if the order confirmation email has not been sent and if the order confirmation email + * setting is enabled either globally or specifically for the payment method. + * - Validates if the redirect request contains specific post data and additional information related to Klarna KP + * - If all conditions are met, and the status code is SUCCESS, sends the order confirmation email. + * + * @param int $statusCode The status code representing the result of a payment or related process. + * @return void + * @throws \Exception If an exception occurs within the called methods. */ - private function processPendingRedirect($statusCode): ResponseInterface + private function sendKlarnaKpOrderConfirmation(int $statusCode): void { - if ($this->order->canInvoice()) { - $this->logger->addDebug(__METHOD__ . '|33|'); - // Set the 'Pending payment status' here - $pendingStatus = $this->orderStatusFactory->get( - BuckarooStatusCode::PENDING_PROCESSING, - $this->order - ); - if ($pendingStatus) { - $this->logger->addDebug(__METHOD__ . '|34|' . var_export($pendingStatus, true)); - $this->order->setStatus($pendingStatus); - $this->order->save(); - } - } - - $this->sendKlarnaKpOrderConfirmation($statusCode); - - if (!$this->redirectRequest->hasPostData('payment_method', 'sofortueberweisung')) { - $this->addErrorMessage( - __( - 'Unfortunately an error occurred while processing your payment. Please try again. If this' . - ' error persists, please choose a different payment method.' - ) - ); - $this->logger->addDebug(__METHOD__ . '|5|'); + $paymentMethod = $this->payment->getMethodInstance(); + $store = $this->order->getStore(); - $this->removeAmastyGiftcardOnFailed(); + if (!$this->order->getEmailSent() + && ( + $this->accountConfig->getOrderConfirmationEmail($store) === "1" + || $paymentMethod->getConfigData('order_email', $store) === "1" + ) + ) { + $isKlarnaKpReserve = ($this->redirectRequest->hasPostData('primary_service', 'KlarnaKp') + && $this->redirectRequest->hasAdditionalInformation('service_action_from_magento', 'reserve') + && !empty($this->redirectRequest->getServiceKlarnakpReservationnumber())); - return $this->handleProcessedResponse('/'); + if (!($this->redirectRequest->hasAdditionalInformation('initiated_by_magento', 1) + && $isKlarnaKpReserve + && $statusCode == BuckarooStatusCode::SUCCESS) + ) { + $this->logger->addDebug(__METHOD__ . '|sendemail|'); + $this->orderRequestService->sendOrderEmail($this->order, true); + } } - - $this->setLastQuoteOrder(); - - return $this->redirectSuccess(); } /** + * Sets the last quote and order information in the checkout session. + * + * - Logs the current status of the last successful quote ID, last quote ID, last order ID + * - If the last successful quote ID, last quote ID, last order ID, or last real order ID is not set + * in the checkout session, it updates them with the corresponding information from the order object. + * * @return void */ private function setLastQuoteOrder(): void @@ -342,48 +402,33 @@ private function setLastQuoteOrder(): void } } - private function sendKlarnaKpOrderConfirmation($statusCode) { - /** @var \Magento\Payment\Model\MethodInterface $paymentMethod */ - $paymentMethod = $this->order->getPayment()->getMethodInstance(); + /** + * Redirect to Success url, which means everything seems to be going fine + * + * @return ResponseInterface + */ + protected function redirectSuccess(): ResponseInterface + { + $this->logger->addDebug(__METHOD__ . '|1|'); + + $this->eventManager->dispatch('buckaroo_process_redirect_success_before'); + $store = $this->order->getStore(); - // Send order confirmation mail if we're supposed to /** * @noinspection PhpUndefinedMethodInspection */ - if (!$this->order->getEmailSent() - && ( - $this->accountConfig->getOrderConfirmationEmail($store) === "1" - || $paymentMethod->getConfigData('order_email', $store) === "1" - ) - ) { - $isKlarnaKpReserve = ($this->redirectRequest->hasPostData('primary_service', 'KlarnaKp') - && $this->redirectRequest->hasAdditionalInformation('service_action_from_magento', 'reserve') - && !empty($this->redirectRequest->getServiceKlarnakpReservationnumber())); + $url = $this->accountConfig->getSuccessRedirect($store); - if (!($this->redirectRequest->hasAdditionalInformation('initiated_by_magento', 1) - && $isKlarnaKpReserve) - ) { - if ($statusCode == BuckarooStatusCode::SUCCESS) { - $this->logger->addDebug(__METHOD__ . '|sendemail|'); - $this->orderRequestService->sendOrderEmail($this->order, true); - } - } - } - } + $this->addSuccessMessage(__('Your order has been placed successfully.')); - /** - * Handle final response - * - * @param string $path - * @param array $arguments - * - * @return ResponseInterface - */ - public function handleProcessedResponse(string $path, array $arguments = []): ResponseInterface - { - $this->logger->addDebug(__METHOD__ . '|15|'); - return $this->_redirect($path, $arguments); + $this->quote->setReservedOrderId(null); + + $this->redirectSuccessApplePay(); + + $this->logger->addDebug(__METHOD__ . '|2|' . var_export($url, true)); + + return $this->handleProcessedResponse($url); } /** @@ -399,93 +444,85 @@ public function addSuccessMessage(string|Phrase $message): void } /** - * Add error message to be displayed to the user - * - * @param string|Phrase $message + * Redirect if the transaction is of the success Apple Pay type * * @return void */ - public function addErrorMessage(string|Phrase $message): void + protected function redirectSuccessApplePay(): void { - $this->messageManager->addErrorMessage($message); - } - - public function addErrorMessageByStatus($statusCode){ - - // StatusCode specified error messages - $statusCodeAddErrorMessage = []; - $statusCodeAddErrorMessage[BuckarooStatusCode::ORDER_FAILED] = - 'Unfortunately an error occurred while processing your payment. Please try again. If this' . - ' error persists, please choose a different payment method.'; - $statusCodeAddErrorMessage[BuckarooStatusCode::FAILED] = - 'Unfortunately an error occurred while processing your payment. Please try again. If this' . - ' error persists, please choose a different payment method.'; - $statusCodeAddErrorMessage[BuckarooStatusCode::REJECTED] = - 'Unfortunately an error occurred while processing your payment. Please try again. If this' . - ' error persists, please choose a different payment method.'; - $statusCodeAddErrorMessage[ - BuckarooStatusCode::CANCELLED_BY_USER - ] = 'According to our system, you have canceled the payment. If this' . - ' is not the case, please contact us.'; + if ($this->redirectRequest->hasPostData('payment_method', 'applepay') + && $this->redirectRequest->hasPostData('status_code', '190') + && $this->redirectRequest->hasPostData('test', 'true') + ) { + $this->logger->addDebug(__METHOD__); - $this->addErrorMessage( - __( - $statusCodeAddErrorMessage[$statusCode] - ) - ); + $this->checkoutSession + ->setLastQuoteId($this->order->getQuoteId()) + ->setLastSuccessQuoteId($this->order->getQuoteId()) + ->setLastOrderId($this->order->getId()) + ->setLastRealOrderId($this->order->getIncrementId()) + ->setLastOrderStatus($this->order->getStatus()); + } } /** - * Create redirect response + * Processes a pending redirect based on the given status code. + * + * - If the order can be invoiced, it sets the 'Pending payment status' and saves the order. + * - Sends a Klarna KP order confirmation using the status code. + * - If the redirect request does not contain specific post data for the 'sofortueberweisung' payment method, + * it adds an error message, removes an Amasty gift card if failed, and redirect to home. + * - Sets the last quote and order. + * - Returns a successful redirect response. * + * @param $statusCode * @return ResponseInterface + * @throws LocalizedException + * @throws \Exception */ - protected function redirectToCheckout(): ResponseInterface + private function processPendingRedirect($statusCode): ResponseInterface { - $this->logger->addDebug('start redirectToCheckout'); - if (!$this->customerSession->isLoggedIn()) { - $this->logger->addDebug('not isLoggedIn'); - if ($this->order->getCustomerId() > 0) { - $this->logger->addDebug('getCustomerId > 0'); - try { - $customer = $this->customerRepository->getById($this->order->getCustomerId()); - $this->customerSession->setCustomerDataAsLoggedIn($customer); - - if (!$this->checkoutSession->getLastRealOrderId() && $this->order->getIncrementId()) { - $this->checkoutSession->setLastRealOrderId($this->order->getIncrementId()); - $this->logger->addDebug(__METHOD__ . '|setLastRealOrderId|'); - $this->checkoutSession->restoreQuote(); - $this->logger->addDebug(__METHOD__ . '|restoreQuote|'); - } - } catch (\Exception $e) { - $this->logger->addError('Could not load customer'); - } + if ($this->order->canInvoice()) { + $this->logger->addDebug(__METHOD__ . '|33|'); + $pendingStatus = $this->orderStatusFactory->get( + BuckarooStatusCode::PENDING_PROCESSING, + $this->order + ); + if ($pendingStatus) { + $this->logger->addDebug(__METHOD__ . '|34|' . var_export($pendingStatus, true)); + $this->order->setStatus($pendingStatus); + $this->order->save(); } } - $this->logger->addDebug('ready for redirect'); - return $this->handleProcessedResponse('checkout', ['_query' => ['bk_e' => 1]]); - } - /** - * Get order - * - * @return OrderInterface - */ - public function getOrder() - { - return $this->order; + $this->sendKlarnaKpOrderConfirmation($statusCode); + + if (!$this->redirectRequest->hasPostData('payment_method', 'sofortueberweisung')) { + $this->addErrorMessage( + __(self::GENERAL_ERROR_MESSAGE) + ); + $this->logger->addDebug(__METHOD__ . '|5|'); + + $this->removeAmastyGiftcardOnFailed(); + + return $this->handleProcessedResponse('/'); + } + + $this->setLastQuoteOrder(); + + return $this->redirectSuccess(); } /** - * Set flag if user is on the payment provider page + * Add error message to be displayed to the user + * + * @param string|Phrase $message * - * @param OrderPaymentInterface $payment * @return void - * @throws \Exception */ - protected function setPaymentOutOfTransit(OrderPaymentInterface $payment) + public function addErrorMessage(string|Phrase $message): void { - $payment->setAdditionalInformation(BuckarooAdapter::BUCKAROO_PAYMENT_IN_TRANSIT, false)->save(); + $this->messageManager->addErrorMessage($message); } /** @@ -493,7 +530,7 @@ protected function setPaymentOutOfTransit(OrderPaymentInterface $payment) * * @return void */ - protected function removeAmastyGiftcardOnFailed() + protected function removeAmastyGiftcardOnFailed(): void { if (class_exists(\Amasty\GiftCardAccount\Model\GiftCardAccount\Repository::class)) { $giftcardAccountRepository = $this->_objectManager->get( @@ -522,57 +559,6 @@ protected function removeAmastyGiftcardOnFailed() } } - /** - * Redirect to Success url, which means everything seems to be going fine - * - * @return ResponseInterface - */ - protected function redirectSuccess() - { - $this->logger->addDebug(__METHOD__ . '|1|'); - - $this->eventManager->dispatch('buckaroo_process_redirect_success_before'); - - $store = $this->order->getStore(); - - /** - * @noinspection PhpUndefinedMethodInspection - */ - $url = $this->accountConfig->getSuccessRedirect($store); - - $this->addSuccessMessage(__('Your order has been placed successfully.')); - - $this->quote->setReservedOrderId(null); - - $this->redirectSuccessApplePay(); - - $this->logger->addDebug(__METHOD__ . '|2|' . var_export($url, true)); - - return $this->handleProcessedResponse($url); - } - - /** - * Redirect if the transaction is of the success Apple Pay type - * - * @return void - */ - protected function redirectSuccessApplePay(): void - { - if ($this->redirectRequest->hasPostData('payment_method', 'applepay') - && $this->redirectRequest->hasPostData('status_code', '190') - && $this->redirectRequest->hasPostData('test', 'true') - ) { - $this->logger->addDebug(__METHOD__); - - $this->checkoutSession - ->setLastQuoteId($this->order->getQuoteId()) - ->setLastSuccessQuoteId($this->order->getQuoteId()) - ->setLastOrderId($this->order->getId()) - ->setLastRealOrderId($this->order->getIncrementId()) - ->setLastOrderStatus($this->order->getStatus()); - } - } - /** * Handle failed transactions * @@ -580,7 +566,7 @@ protected function redirectSuccessApplePay(): void * @return ResponseInterface * @throws \Magento\Framework\Exception\NoSuchEntityException|\Exception */ - protected function handleFailed($statusCode) + protected function handleFailed($statusCode): ResponseInterface { $this->logger->addDebug(__METHOD__ . '|7|'); @@ -624,12 +610,35 @@ public function getSkipHandleFailedRecreate() return false; } + /** + * Adds an error message to the session based on the given status code. + * + * @param int $statusCode + * @return void + */ + public function addErrorMessageByStatus(int $statusCode): void + { + $statusCodeAddErrorMessage = []; + $statusCodeAddErrorMessage[BuckarooStatusCode::ORDER_FAILED] = __(self::GENERAL_ERROR_MESSAGE); + $statusCodeAddErrorMessage[BuckarooStatusCode::FAILED] = __(self::GENERAL_ERROR_MESSAGE); + $statusCodeAddErrorMessage[BuckarooStatusCode::REJECTED] = __(self::GENERAL_ERROR_MESSAGE); + $statusCodeAddErrorMessage[BuckarooStatusCode::CANCELLED_BY_USER] + = __('According to our system, you have canceled the payment. If this is not the case, please contact us.'); + + $this->addErrorMessage( + __( + $statusCodeAddErrorMessage[$statusCode] + ) + ); + } + /** * Redirect to Failure url, which means we've got a problem * * @return ResponseInterface + * @throws \Exception */ - protected function redirectFailure() + protected function redirectFailure(): ResponseInterface { $store = $this->order->getStore(); $this->logger->addDebug('start redirectFailure'); @@ -645,7 +654,21 @@ protected function redirectFailure() return $this->handleProcessedResponse($url); } - private function redirectOnCheckoutForFailedTransaction() + /** + * Redirects to the checkout page for a failed transaction. + * + * - Logs the attempt to redirect to checkout for a failed transaction. + * - If the customer is not logged in, and there's an associated customer ID with the order, + * it attempts to retrieve the customer, log them in, and set necessary session data. + * - If the last real order ID is not set in the checkout session, and the order has an increment ID, + * it sets the last real order ID and may restore the quote. + * - Finally, it handles the processed response for a redirect to the checkout page, specifically + * to the payment section, with a query parameter indicating an error. + * + * @return ResponseInterface + * @throws \Exception + */ + private function redirectOnCheckoutForFailedTransaction(): ResponseInterface { $this->logger->addDebug('getFailureRedirectToCheckout'); if (!$this->customerSession->isLoggedIn() && ($this->order->getCustomerId() > 0)) { @@ -687,12 +710,23 @@ public function setSkipHandleFailedRecreate() * * @param int|null $statusCode * @return bool + * @throws LocalizedException */ - protected function cancelOrder($statusCode) + protected function cancelOrder(?int $statusCode): bool { return $this->orderService->cancel($this->order, $statusCode); } + /** + * Get order + * + * @return OrderInterface + */ + public function getOrder() + { + return $this->order; + } + /** * Get Response Parameters * @@ -704,32 +738,33 @@ public function getResponseParameters() } /** - * Skip process redirect for Processing Order when the status of the request is WaitingOnConsumer + * Create redirect response * - * @return bool + * @return ResponseInterface */ - public function skipWaitingOnConsumerForProcessingOrder(): bool + protected function redirectToCheckout(): ResponseInterface { - if (in_array($this->payment->getMethod(), - [ - 'buckaroo_magento2_creditcards', - 'buckaroo_magento2_paylink', - 'buckaroo_magento2_payperemail', - 'buckaroo_magento2_transfer' - ])) { - - if ($this->payment->getAdditionalInformation(BuckarooAdapter::BUCKAROO_ORIGINAL_TRANSACTION_KEY_KEY) - != $this->redirectRequest->getTransactions()) { - return true; - } + $this->logger->addDebug('start redirectToCheckout'); + if (!$this->customerSession->isLoggedIn()) { + $this->logger->addDebug('not isLoggedIn'); + if ($this->order->getCustomerId() > 0) { + $this->logger->addDebug('getCustomerId > 0'); + try { + $customer = $this->customerRepository->getById($this->order->getCustomerId()); + $this->customerSession->setCustomerDataAsLoggedIn($customer); - $orderState = $this->order->getState(); - if ($orderState == Order::STATE_PROCESSING - && $this->redirectRequest->getStatusCode() == BuckarooStatusCode::WAITING_ON_CONSUMER) { - return true; + if (!$this->checkoutSession->getLastRealOrderId() && $this->order->getIncrementId()) { + $this->checkoutSession->setLastRealOrderId($this->order->getIncrementId()); + $this->logger->addDebug(__METHOD__ . '|setLastRealOrderId|'); + $this->checkoutSession->restoreQuote(); + $this->logger->addDebug(__METHOD__ . '|restoreQuote|'); + } + } catch (\Exception $e) { + $this->logger->addError('Could not load customer'); + } } } - - return false; + $this->logger->addDebug('ready for redirect'); + return $this->handleProcessedResponse('checkout', ['_query' => ['bk_e' => 1]]); } } From d014797d5bb01d3cd0c00fadc9e0c4100601fdbe Mon Sep 17 00:00:00 2001 From: Lucian Turiac Date: Mon, 14 Aug 2023 09:45:19 +0300 Subject: [PATCH 23/29] BP-2813 - Refactor Push clean the old code --- Gateway/Response/RefundHandler.php | 5 +- Model/Push.php | 2272 +------------------------- Service/Push/OrderRequestService.php | 19 + 3 files changed, 33 insertions(+), 2263 deletions(-) diff --git a/Gateway/Response/RefundHandler.php b/Gateway/Response/RefundHandler.php index 0ca252e6f..a2c117e22 100644 --- a/Gateway/Response/RefundHandler.php +++ b/Gateway/Response/RefundHandler.php @@ -25,6 +25,7 @@ use Buckaroo\Magento2\Helper\Data; use Buckaroo\Magento2\Logging\Log as BuckarooLog; use Buckaroo\Magento2\Model\Push; +use Buckaroo\Magento2\Model\Push\DefaultProcessor; use Buckaroo\Transaction\Response\TransactionResponse; use Magento\Framework\App\ResourceConnection; use Magento\Framework\Message\ManagerInterface as MessageManager; @@ -102,13 +103,13 @@ public function refundTransactionSdk( ) { $this->buckarooLog->addDebug(__METHOD__ . '|10|'); $transactionKeysArray = $payment->getAdditionalInformation( - Push::BUCKAROO_RECEIVED_TRANSACTIONS_STATUSES + DefaultProcessor::BUCKAROO_RECEIVED_TRANSACTIONS_STATUSES ); foreach ($responseData->getRelatedTransactions() as $relatedTransaction) { $transactionKeysArray[$relatedTransaction['RelatedTransactionKey']] = $responseData->getStatusCode(); } $payment->setAdditionalInformation( - Push::BUCKAROO_RECEIVED_TRANSACTIONS_STATUSES, + DefaultProcessor::BUCKAROO_RECEIVED_TRANSACTIONS_STATUSES, $transactionKeysArray ); $connection = $this->resourceConnection->getConnection(); diff --git a/Model/Push.php b/Model/Push.php index c3d1f22f1..b78f941b4 100644 --- a/Model/Push.php +++ b/Model/Push.php @@ -17,195 +17,25 @@ * @copyright Copyright (c) Buckaroo B.V. * @license https://tldrlegal.com/license/mit-license */ +declare(strict_types=1); namespace Buckaroo\Magento2\Model; use Buckaroo\Magento2\Api\PushInterface; -use Buckaroo\Magento2\Api\PushProcessorInterface; use Buckaroo\Magento2\Api\PushRequestInterface; use Buckaroo\Magento2\Exception as BuckarooException; -use Buckaroo\Magento2\Helper\Data; -use Buckaroo\Magento2\Helper\PaymentGroupTransaction; use Buckaroo\Magento2\Logging\Log; -use Buckaroo\Magento2\Model\ConfigProvider\Account; -use Buckaroo\Magento2\Model\ConfigProvider\Method\Afterpay; -use Buckaroo\Magento2\Model\ConfigProvider\Method\Afterpay2; -use Buckaroo\Magento2\Model\ConfigProvider\Method\Afterpay20; -use Buckaroo\Magento2\Model\ConfigProvider\Method\Creditcard; -use Buckaroo\Magento2\Model\ConfigProvider\Method\Factory; -use Buckaroo\Magento2\Model\ConfigProvider\Method\Giftcards; -use Buckaroo\Magento2\Model\ConfigProvider\Method\Klarnakp; -use Buckaroo\Magento2\Model\ConfigProvider\Method\Paypal; -use Buckaroo\Magento2\Model\ConfigProvider\Method\PayPerEmail; -use Buckaroo\Magento2\Model\ConfigProvider\Method\SepaDirectDebit; -use Buckaroo\Magento2\Model\ConfigProvider\Method\Sofortbanking; -use Buckaroo\Magento2\Model\ConfigProvider\Method\Transfer; -use Buckaroo\Magento2\Model\ConfigProvider\Method\Voucher; -use Buckaroo\Magento2\Model\Method\BuckarooAdapter; use Buckaroo\Magento2\Model\Push\PushProcessorsFactory; use Buckaroo\Magento2\Model\Push\PushTransactionType; -use Buckaroo\Magento2\Model\Refund\Push as RefundPush; use Buckaroo\Magento2\Model\RequestPush\RequestPushFactory; -use Buckaroo\Magento2\Model\Validator\Push as ValidatorPush; use Buckaroo\Magento2\Service\Push\OrderRequestService; -use Magento\Framework\App\ResourceConnection; -use Magento\Framework\Exception\FileSystemException; -use Magento\Framework\Exception\LocalizedException; -use Magento\Framework\Filesystem\DirectoryList; -use Magento\Framework\Filesystem\Driver\File; -use Magento\Framework\Model\AbstractExtensibleModel; -use Magento\Framework\ObjectManagerInterface; -use Magento\Framework\Phrase; -use Magento\Framework\Webapi\Rest\Request; -use Magento\Payment\Model\InfoInterface; -use Magento\Quote\Model\Quote; -use Magento\Sales\Api\Data\OrderInterface; -use Magento\Sales\Api\Data\TransactionInterface; -use Magento\Sales\Model\Order; -use Magento\Sales\Model\Order\Email\Sender\InvoiceSender; -use Magento\Sales\Model\Order\Email\Sender\OrderSender; -use Magento\Sales\Model\Order\Payment; -use Magento\Sales\Model\Order\Payment\Transaction; -/** - * @SuppressWarnings(PHPMD.CouplingBetweenObjects) - * @SuppressWarnings(PHPMD.TooManyFields) - * @SuppressWarnings(PHPMD.ExcessiveClassComplexity) - */ class Push implements PushInterface { - public const BUCK_PUSH_CANCEL_AUTHORIZE_TYPE = 'I014'; - public const BUCK_PUSH_ACCEPT_AUTHORIZE_TYPE = 'I013'; - public const BUCK_PUSH_GROUPTRANSACTION_TYPE = 'I150'; - public const BUCK_PUSH_IDEAL_PAY = 'C021'; - - public const BUCK_PUSH_TYPE_TRANSACTION = 'transaction_push'; - public const BUCK_PUSH_TYPE_INVOICE = 'invoice_push'; - public const BUCK_PUSH_TYPE_INVOICE_INCOMPLETE = 'incomplete_invoice_push'; - public const BUCK_PUSH_TYPE_DATAREQUEST = 'datarequest_push'; - - public const BUCKAROO_RECEIVED_TRANSACTIONS = 'buckaroo_received_transactions'; - public const BUCKAROO_RECEIVED_TRANSACTIONS_STATUSES = 'buckaroo_received_transactions_statuses'; - - /** - * @var Request $request - */ - public $request; - - /** - * @var ValidatorPush $validator - */ - public $validator; - - /** - * @var Order $order - */ - public $order; - - /** - * @var Transaction - */ - private $transaction; - - /** - * @var OrderSender $orderSender - */ - public $orderSender; - - /** - * @var InvoiceSender $invoiceSender - */ - public $invoiceSender; - - /** - * @var array $postData - */ - public $postData; - - /** - * @var array originalPostData - */ - public $originalPostData; - - /** - * @var $refundPush - */ - public $refundPush; - - /** - * @var Data - */ - public $helper; - /** * @var Log $logging */ - public $logging; - - /** - * @var OrderStatusFactory OrderStatusFactory - */ - public $orderStatusFactory; - - /** - * @var Account - */ - public $configAccount; - - /** - * @var Factory - */ - public $configProviderMethodFactory; - - /** - * @var PaymentGroupTransaction - */ - protected $groupTransaction; - - /** - * @var bool - */ - protected $forceInvoice = false; - - /** - * @var ObjectManagerInterface - */ - protected $objectManager; - - /** - * @var bool - */ - private $dontSaveOrderUponSuccessPush = false; - - /** - * @var ResourceConnection - */ - protected $resourceConnection; - - /** - * @var bool - */ - private $isPayPerEmailB2BModePushInitial = false; - - /** - * @var DirectoryList - */ - protected $dirList; - - /** - * @var Klarnakp - */ - private $klarnakpConfig; - - /** - * @var Afterpay20 - */ - private $afterpayConfig; - - /** - * @var File - */ - private $fileSystemDriver; + public Log $logging; /** * @var PushRequestInterface @@ -217,11 +47,6 @@ class Push implements PushInterface */ private PushProcessorsFactory $pushProcessorsFactory; - /** - * @var PushProcessorInterface - */ - private PushProcessorInterface $pushProcessor; - /** * @var OrderRequestService */ @@ -233,76 +58,20 @@ class Push implements PushInterface private PushTransactionType $pushTransactionType; /** - * @param Order $order - * @param TransactionInterface $transaction - * @param Request $request - * @param ValidatorPush $validator - * @param OrderSender $orderSender - * @param InvoiceSender $invoiceSender - * @param Data $helper - * @param Account $configAccount - * @param RefundPush $refundPush * @param Log $logging - * @param Factory $configProviderMethodFactory - * @param OrderStatusFactory $orderStatusFactory - * @param PaymentGroupTransaction $groupTransaction - * @param ObjectManagerInterface $objectManager - * @param ResourceConnection $resourceConnection - * @param DirectoryList $dirList - * @param Klarnakp $klarnakpConfig - * @param Afterpay20 $afterpayConfig - * @param File $fileSystemDriver * @param RequestPushFactory $requestPushFactory * @param PushProcessorsFactory $pushProcessorsFactory * @param OrderRequestService $orderRequestService * @param PushTransactionType $pushTransactionType - * @SuppressWarnings(PHPMD.ExcessiveParameterList) */ public function __construct( - Order $order, - TransactionInterface $transaction, - Request $request, - ValidatorPush $validator, - OrderSender $orderSender, - InvoiceSender $invoiceSender, - Data $helper, - Account $configAccount, - RefundPush $refundPush, Log $logging, - Factory $configProviderMethodFactory, - OrderStatusFactory $orderStatusFactory, - PaymentGroupTransaction $groupTransaction, - ObjectManagerInterface $objectManager, - ResourceConnection $resourceConnection, - DirectoryList $dirList, - Klarnakp $klarnakpConfig, - Afterpay20 $afterpayConfig, - File $fileSystemDriver, RequestPushFactory $requestPushFactory, PushProcessorsFactory $pushProcessorsFactory, OrderRequestService $orderRequestService, PushTransactionType $pushTransactionType ) { - $this->order = $order; - $this->transaction = $transaction; - $this->request = $request; - $this->validator = $validator; - $this->orderSender = $orderSender; - $this->invoiceSender = $invoiceSender; - $this->helper = $helper; - $this->configAccount = $configAccount; - $this->refundPush = $refundPush; $this->logging = $logging; - $this->configProviderMethodFactory = $configProviderMethodFactory; - $this->orderStatusFactory = $orderStatusFactory; - - $this->groupTransaction = $groupTransaction; - $this->objectManager = $objectManager; - $this->resourceConnection = $resourceConnection; - $this->dirList = $dirList; - $this->klarnakpConfig = $klarnakpConfig; - $this->afterpayConfig = $afterpayConfig; - $this->fileSystemDriver = $fileSystemDriver; $this->pushRequst = $requestPushFactory->create(); $this->pushProcessorsFactory = $pushProcessorsFactory; $this->orderRequestService = $orderRequestService; @@ -312,2050 +81,31 @@ public function __construct( /** * @inheritdoc * + * @return bool * @throws BuckarooException - * @throws \Exception - * @todo Once Magento supports variable parameters, modify this method to no longer require a Request object - * - * @SuppressWarnings(PHPMD.CyclomaticComplexity) - * @SuppressWarnings(PHPMD.NPathComplexity) - * @SuppressWarnings(PHPMD.ExcessiveMethodLength) */ - public function receivePush() + public function receivePush(): bool { // Log the push request $this->logging->addDebug(__METHOD__ . '|1|' . var_export($this->pushRequst->getOriginalRequest(), true)); // Load Order - $this->order = $this->orderRequestService->getOrderByRequest($this->pushRequst); - - // Validate Signature - $store = $this->order->getStore(); - $validSignature = $this->pushRequst->validate($store); - - if (!$validSignature) { - $this->logging->addDebug('Invalid push signature'); - throw new BuckarooException(__('Signature from push is incorrect')); - } - -// Get Push Transaction Type - $pushTransactionType = $this->pushTransactionType->getPushTransactionType($this->pushRequst, $this->order); - -// Process Push - $this->pushProcessor = $this->pushProcessorsFactory->get($pushTransactionType); - return $this->pushProcessor->processPush($this->pushRequst); - - // Lock Push Processing - $this->logging->addDebug(__METHOD__ . '|1_2|'); - $lockHandler = $this->lockPushProcessing(); - $this->logging->addDebug(__METHOD__ . '|1_3|'); - - // Check if is Failed group transaction execute specific handler - // criteria.handle - if ($this->isFailedGroupTransaction()) { - $this->handleGroupTransactionFailed(); - return true; - } - - // Check if is group transaction info - if ($this->isGroupTransactionInfo()) { - if($this->isCanceledGroupTransaction()) { - $this->cancelGroupTransactionOrder(); - return true; - } - if ($this->isGroupTransactionFailed()) { - $this->savePartGroupTransaction(); - } else { - return true; - } - } - - // Load order by transaction id - $this->loadOrder(); - - // Skip Handle group transaction - if ($this->skipHandlingForFailedGroupTransactions()) { - return true; - } - - // skip Push based on specific condition - if (!$this->isPushNeeded()) { - return true; - } + $order = $this->orderRequestService->getOrderByRequest($this->pushRequst); // Validate Signature - $store = $this->order ? $this->order->getStore() : null; - //Check if the push can be processed and if the order can be updated IMPORTANT => use the original post data. + $store = $order->getStore(); $validSignature = $this->pushRequst->validate($store); - $transactionType = $this->getTransactionType(); - //Validate status code and return response - $postDataStatusCode = $this->getStatusCode(); - $this->logging->addDebug(__METHOD__ . '|1_5|' . var_export($postDataStatusCode, true)); - - $this->logging->addDebug(__METHOD__ . '|1_10|' . var_export($transactionType, true)); - - $response = $this->validator->validateStatusCode($postDataStatusCode); - - //Check if the push have PayLink - $this->receivePushCheckPayLink($response, $validSignature); - - $payment = $this->order->getPayment(); - - if ($this->pushCheckPayPerEmailCancel($response, $validSignature, $payment)) { - return true; - } - - //Check second push for PayPerEmail - $receivePushCheckPayPerEmailResult = $this->receivePushCheckPayPerEmail($response, $validSignature, $payment); - - $skipFirstPush = $payment->getAdditionalInformation('skip_push'); - - $this->logging->addDebug(__METHOD__ . '|1_20|' . var_export($skipFirstPush, true)); - - /** - * Buckaroo Push is send before Response, for correct flow we skip the first push - * for some payment methods - * - * @todo when buckaroo changes the push / response order this can be removed - */ - if ($skipFirstPush > 0) { - $payment->setAdditionalInformation('skip_push', (int)$skipFirstPush - 1); - $payment->save(); - throw new BuckarooException( - __('Skipped handling this push, first handle response, action will be taken on the next push.') - ); - } - - if ($this->receivePushCheckDuplicates()) { - $this->unlockPushProcessing($lockHandler); - throw new BuckarooException(__('Skipped handling this push, duplicate')); - } - - $this->logging->addDebug(__METHOD__ . '|2|' . var_export($response, true)); - - $canUpdateOrder = $this->canUpdateOrderStatus($response); - - $this->logging->addDebug(__METHOD__ . '|3|' . var_export($canUpdateOrder, true)); - - //Check if the push is a refund request or cancel authorize - if (!empty($this->pushRequst->getAmountCredit())) { - if ($response['status'] !== 'BUCKAROO_MAGENTO2_STATUSCODE_SUCCESS' - && $this->order->isCanceled() - && $this->pushRequst->getTransactionType() == self::BUCK_PUSH_CANCEL_AUTHORIZE_TYPE - && $validSignature - ) { - return $this->processCancelAuthorize(); - } elseif ($response['status'] !== 'BUCKAROO_MAGENTO2_STATUSCODE_SUCCESS' - && !$this->order->hasInvoices() - ) { - throw new BuckarooException( - __('Refund failed ! Status : %1 and the order does not contain an invoice', $response['status']) - ); - } elseif ($response['status'] !== 'BUCKAROO_MAGENTO2_STATUSCODE_SUCCESS' - && $this->order->hasInvoices() - ) { - //don't proceed failed refund push - $this->logging->addDebug(__METHOD__ . '|10|'); - $this->setOrderNotificationNote(__('push notification for refund has no success status, ignoring.')); - return true; - } - return $this->refundPush->receiveRefundPush($this->pushRequst, $validSignature, $this->order); - } - - //Last validation before push can be completed if (!$validSignature) { $this->logging->addDebug('Invalid push signature'); throw new BuckarooException(__('Signature from push is incorrect')); - //If the signature is valid but the order cant be updated, try to add a notification to the order comments. - } elseif ($validSignature && !$canUpdateOrder) { - $this->logging->addDebug('Order can not receive updates'); - if ($receivePushCheckPayPerEmailResult) { - $config = $this->configProviderMethodFactory->get(PayPerEmail::CODE); - if ($config->isEnabledB2B()) { - $this->logging->addDebug(__METHOD__ . '|$this->order->getState()|' . $this->order->getState()); - if ($this->order->getState() === Order::STATE_COMPLETE) { - $this->order->setState(Order::STATE_PROCESSING); - $this->order->save(); - } - return true; - } - } - $this->setOrderNotificationNote(__('The order has already been processed.')); - throw new BuckarooException( - __('Signature from push is correct but the order can not receive updates') - ); - } - - if (!$this->isGroupTransactionInfo()) { - $this->setTransactionKey(); - } - - $statusCodeSuccess = $this->helper->getStatusCode('BUCKAROO_MAGENTO2_STATUSCODE_SUCCESS'); - if (!empty($this->pushRequst->getStatusmessage())) { - if ($this->order->getState() === Order::STATE_NEW - && empty($this->pushRequst->getAdditionalInformation('frompayperemail')) - && !$this->pushRequst->hasPostData('transaction_method', 'transfer') - && empty($this->pushRequst->getRelatedtransactionPartialpayment()) - && $this->pushRequst->hasPostData('statuscode', $statusCodeSuccess) - ) { - $this->order->setState(Order::STATE_PROCESSING); - $this->order->addStatusHistoryComment( - $this->pushRequst->getStatusmessage(), - $this->helper->getOrderStatusByState($this->order, Order::STATE_PROCESSING) - ); - } else { - $this->order->addStatusHistoryComment($this->pushRequst->getStatusmessage()); - } - } - - if (!in_array($payment->getMethod(), [Giftcards::CODE, Voucher::CODE]) - && $this->isGroupTransactionPart()) { - $this->savePartGroupTransaction(); - return true; - } - - - switch ($transactionType) { - case self::BUCK_PUSH_TYPE_INVOICE: - $this->processCm3Push(); - break; - case self::BUCK_PUSH_TYPE_INVOICE_INCOMPLETE: - throw new BuckarooException( - __('Skipped handling this invoice push because it is too soon.') - ); - case self::BUCK_PUSH_TYPE_TRANSACTION: - case self::BUCK_PUSH_TYPE_DATAREQUEST: - default: - $this->processPush($response); - break; } - $this->logging->addDebug(__METHOD__ . '|5|'); - if (!$this->dontSaveOrderUponSuccessPush) { - $this->logging->addDebug(__METHOD__ . '|5-1|'); - $this->order->save(); - } - - $this->unlockPushProcessing($lockHandler); - - $this->logging->addDebug(__METHOD__ . '|6|'); - - return true; - } - - /** - * Check for duplicate transaction pushes from Buckaroo and update the payment transaction statuses accordingly. - * - * @param int|null $receivedStatusCode - * @param string|null $trxId - * @return bool - * @throws \Exception - * - * @SuppressWarnings(PHPMD.CyclomaticComplexity) - * @SuppressWarnings(PHPMD.NPathComplexity) - */ - private function receivePushCheckDuplicates(int $receivedStatusCode = null, string $trxId = null): bool - { - $this->logging->addDebug(__METHOD__ . '|1|' . var_export($this->order->getPayment()->getMethod(), true)); - - $save = false; - if (!$receivedStatusCode) { - $save = true; - if (empty($this->pushRequst->getStatusCode())) { - return false; - } - $receivedStatusCode = $this->pushRequst->getStatusCode(); - } - - if (!$trxId) { - if (empty($this->pushRequst->getTransactions())) { - return false; - } - $trxId = $this->pushRequst->getTransactions(); - } - - $payment = $this->order->getPayment(); - $ignoredPaymentMethods = [ - Giftcards::CODE, - Transfer::CODE - ]; - - if ($payment - && $payment->getMethod() - && $receivedStatusCode - && ($this->getTransactionType() == self::BUCK_PUSH_TYPE_TRANSACTION) - && (!in_array($payment->getMethod(), $ignoredPaymentMethods)) - ) { - $this->logging->addDebug(__METHOD__ . '|5|'); - - $receivedTrxStatuses = $payment->getAdditionalInformation( - self::BUCKAROO_RECEIVED_TRANSACTIONS_STATUSES - ); - $this->logging->addDebug(__METHOD__ . '|10|' . - var_export([$receivedTrxStatuses, $receivedStatusCode], true)); - if ($receivedTrxStatuses - && is_array($receivedTrxStatuses) - && !empty($trxId) - && isset($receivedTrxStatuses[$trxId]) - && ($receivedTrxStatuses[$trxId] == $receivedStatusCode) - ) { - $orderStatus = $this->helper->getOrderStatusByState($this->order, Order::STATE_NEW); - $statusCode = $this->helper->getStatusCode('BUCKAROO_MAGENTO2_STATUSCODE_SUCCESS'); - if (($this->order->getState() == Order::STATE_NEW) - && ($this->order->getStatus() == $orderStatus) - && ($receivedStatusCode == $statusCode) - ) { - //allow duplicated pushes for 190 statuses in case if order stills to be new/pending - $this->logging->addDebug(__METHOD__ . '|13|'); - return false; - } - - $this->logging->addDebug(__METHOD__ . '|15|'); - return true; - } - if ($save) { - $this->logging->addDebug(__METHOD__ . '|17|'); - $this->setReceivedTransactionStatuses(); - $payment->save(); - } - } - $this->logging->addDebug(__METHOD__ . '|20|'); - - return false; - } - - /** - * Check if it is needed to handle the push message based on postdata - * - * @return bool - * @throws \Exception - * - * @SuppressWarnings(PHPMD.CyclomaticComplexity) - */ - private function isPushNeeded(): bool - { - $this->logging->addDebug(__METHOD__ . '|1|'); - if ($this->pushRequst->hasAdditionalInformation('initiated_by_magento', 1) - && $this->pushRequst->hasAdditionalInformation('service_action_from_magento', ['refund']) - ) { - $statusCodeSuccess = BuckarooStatusCode::SUCCESS; - if ($this->pushRequst->hasPostData('statuscode', $statusCodeSuccess) - && !empty($this->pushRequst->getRelatedtransactionRefund()) - ) { - if ($this->receivePushCheckDuplicates( - BuckarooStatusCode::PENDING_APPROVAL, - $this->pushRequst->getRelatedtransactionRefund() - ) - ) { - $this->logging->addDebug(__METHOD__ . '|4|'); - return true; - } - } - $this->logging->addDebug(__METHOD__ . '|5|'); - return false; - } - - $types = ['capture', 'cancelauthorize', 'cancelreservation']; - if ($this->pushRequst->hasAdditionalInformation('initiated_by_magento', 1) - && $this->pushRequst->hasAdditionalInformation('service_action_from_magento', $types) - && empty($this->pushRequst->getRelatedtransactionRefund()) - ) { - return false; - } - - if ($this->pushRequst->hasAdditionalInformation('initiated_by_magento', 1) - && $this->pushRequst->hasPostData('transaction_method', ['klarnakp', 'KlarnaKp']) - && $this->pushRequst->hasAdditionalInformation('service_action_from_magento', 'pay') - && !empty($this->pushRequst->getServiceKlarnakpCaptureid()) - ) { - return false; - } - - return true; - } - - /** - * Load the order from the Push Data based on the Order Increment ID or transaction key. - * - * @return void - */ - private function loadOrder() - { - $brqOrderId = $this->getOrderIncrementId(); - - //Check if the order can receive further status updates - $this->order->loadByIncrementId((string)$brqOrderId); - - if (!$this->order->getId()) { - $this->logging->addDebug('Order could not be loaded by Invoice Number or Order Number'); - // try to get order by transaction id on payment. - $this->order = $this->getOrderByTransactionKey(); - } - } - - /** - * Save the current order and reload it from the database. - * - * @return void - * @throws \Exception - */ - private function saveAndReloadOrder() - { - $this->order->save(); - $this->loadOrder(); - } - - /** - * Retrieve the status code from the push request based on the transaction type. - * - * @return int|string - * - * @SuppressWarnings(PHPMD.CyclomaticComplexity) - */ - private function getStatusCode() - { - $transactionType = $this->getTransactionType(); - $statusCode = 0; - switch ($transactionType) { - case self::BUCK_PUSH_TYPE_TRANSACTION: - case self::BUCK_PUSH_TYPE_DATAREQUEST: - if ($this->pushRequst->getStatusCode() !== null) { - $statusCode = $this->pushRequst->getStatusCode(); - } - break; - case self::BUCK_PUSH_TYPE_INVOICE: - case self::BUCK_PUSH_TYPE_INVOICE_INCOMPLETE: - if (!empty($this->pushRequst->getEventparametersStatuscode())) { - $statusCode = $this->pushRequst->getEventparametersStatuscode(); - } - - if (!empty($this->pushRequst->getEventparametersTransactionstatuscode())) { - $statusCode = $this->pushRequst->getEventparametersTransactionstatuscode(); - } - break; - } - - $statusCodeSuccess = $this->helper->getStatusCode('BUCKAROO_MAGENTO2_STATUSCODE_SUCCESS'); - if ($this->pushRequst->getStatusCode() !== null - && ($this->pushRequst->getStatusCode() == $statusCodeSuccess) - && !$statusCode - ) { - $statusCode = $statusCodeSuccess; - } - - return $statusCode; - } - - /** - * Determine the transaction type based on push request data and the saved invoice key. - * - * @return bool|string - * - * @SuppressWarnings(PHPMD.CyclomaticComplexity) - */ - public function getTransactionType() - { - //If an order has an invoice key, then it should only be processed by invoice pushes - $savedInvoiceKey = (string)$this->order->getPayment()->getAdditionalInformation('buckaroo_cm3_invoice_key'); - - if (!empty($this->pushRequst->getInvoicekey()) - && !empty($this->pushRequst->getSchemekey()) - && strlen($savedInvoiceKey) > 0 - ) { - return self::BUCK_PUSH_TYPE_INVOICE; - } - - if (!empty($this->pushRequst->getInvoicekey()) - && !empty($this->pushRequst->getSchemekey()) - && strlen($savedInvoiceKey) == 0 - ) { - return self::BUCK_PUSH_TYPE_INVOICE_INCOMPLETE; - } - - if (!empty($this->pushRequst->getDatarequest())) { - return self::BUCK_PUSH_TYPE_DATAREQUEST; - } - - if (empty($this->pushRequst->getInvoicekey()) - && empty($this->pushRequst->getServiceCreditmanagement3Invoicekey()) - && empty($this->pushRequst->getDatarequest()) - && strlen($savedInvoiceKey) <= 0 - ) { - return self::BUCK_PUSH_TYPE_TRANSACTION; - } - - return false; - } - - /** - * Handle cancelled order authorization and update payment transactions. - * - * @return bool - */ - public function processCancelAuthorize(): bool - { - try { - $this->setTransactionKey(); - } catch (\Exception $e) { - $this->logging->addDebug($e->getLogMessage()); - } - - $this->logging->addDebug('Order autorize has been canceld, trying to update payment transactions'); - - return true; - } - - /** - * Process the push according the response status - * - * @param array $response - * @return void - * @throws BuckarooException - * @throws LocalizedException - * - * @SuppressWarnings(PHPMD.CyclomaticComplexity) - */ - public function processPush(array $response) - { - $this->logging->addDebug(__METHOD__ . '|1|' . var_export($response['status'], true)); - $payment = $this->order->getPayment(); - - if (!$payment->getMethodInstance()->canProcessPostData($payment, $this->pushRequst)) { - return; - } - - if ($this->giftcardPartialPayment()) { - return; - } - - $newStatus = $this->orderStatusFactory->get($this->pushRequst->getStatusCode(), $this->order); - - $this->logging->addDebug(__METHOD__ . '|5|' . var_export($newStatus, true)); - - if ($this->isPayPerEmailB2BModePushInitial($response)) { - $response['status'] = 'BUCKAROO_MAGENTO2_STATUSCODE_SUCCESS'; - $newStatus = $this->configAccount->getOrderStatusSuccess(); - $this->logging->addDebug(__METHOD__ . '|15|' . var_export([$response['status'], $newStatus], true)); - $this->isPayPerEmailB2BModePushInitial = true; - } - - switch ($response['status']) { - case 'BUCKAROO_MAGENTO2_STATUSCODE_TECHNICAL_ERROR': - case 'BUCKAROO_MAGENTO2_STATUSCODE_VALIDATION_FAILURE': - case 'BUCKAROO_MAGENTO2_STATUSCODE_CANCELLED_BY_MERCHANT': - case 'BUCKAROO_MAGENTO2_STATUSCODE_CANCELLED_BY_USER': - case 'BUCKAROO_MAGENTO2_STATUSCODE_FAILED': - case 'BUCKAROO_MAGENTO2_STATUSCODE_REJECTED': - $this->processFailedPush($newStatus, $response['message']); - break; - case 'BUCKAROO_MAGENTO2_STATUSCODE_SUCCESS': - if ($this->order->getPayment()->getMethod() == Paypal::CODE) { - $paypalConfig = $this->configProviderMethodFactory->get(Paypal::CODE); - - /** - * @var Paypal $paypalConfig - */ - $newSellersProtectionStatus = $paypalConfig->getSellersProtectionIneligible(); - if ($paypalConfig->getSellersProtection() && !empty($newSellersProtectionStatus)) { - $newStatus = $newSellersProtectionStatus; - } - } - $this->processSucceededPush($newStatus, $response['message']); - break; - case 'BUCKAROO_MAGENTO2_STATUSCODE_NEUTRAL': - $this->setOrderNotificationNote($response['message']); - break; - case 'BUCKAROO_MAGENTO2_STATUSCODE_PAYMENT_ON_HOLD': - case 'BUCKAROO_MAGENTO2_STATUSCODE_WAITING_ON_CONSUMER': - case 'BUCKAROO_MAGENTO2_STATUSCODE_PENDING_PROCESSING': - case 'BUCKAROO_MAGENTO2_STATUSCODE_WAITING_ON_USER_INPUT': - $this->processPendingPaymentPush(); - break; - } - } - - /** - * Process the Credit Management push, update invoice status and send confirmation mail if required. - * - * @return void - * @throws LocalizedException - */ - public function processCm3Push() - { - $invoiceKey = $this->pushRequst->getInvoicekey(); - $savedInvoiceKey = $this->order->getPayment()->getAdditionalInformation('buckaroo_cm3_invoice_key'); - - if ($invoiceKey != $savedInvoiceKey) { - return; - } - - if ($this->updateCm3InvoiceStatus()) { - $this->sendCm3ConfirmationMail(); - } - } - - /** - * Update the Credit Management invoice status based on push request data and save invoice if required. - * - * @return bool - * @throws LocalizedException - */ - private function updateCm3InvoiceStatus(): bool - { - $isPaid = filter_var(strtolower($this->pushRequst->getIspaid()), FILTER_VALIDATE_BOOLEAN); - $canInvoice = ($this->order->canInvoice() && !$this->order->hasInvoices()); - - $amount = floatval($this->pushRequst->getAmountDebit()); - $amount = $this->order->getBaseCurrency()->formatTxt($amount); - $statusMessage = 'Payment push status : Creditmanagement invoice with a total amount of ' - . $amount . ' has been paid'; - - if (!$isPaid && !$canInvoice) { - $statusMessage = 'Payment push status : Creditmanagement invoice has been (partially) refunded'; - } + // Get Push Transaction Type + $pushTransactionType = $this->pushTransactionType->getPushTransactionType($this->pushRequst, $order); - if (!$isPaid && $canInvoice) { - $statusMessage = 'Payment push status : Waiting for consumer'; - } - - if ($isPaid && $canInvoice) { - $originalKey = BuckarooAdapter::BUCKAROO_ORIGINAL_TRANSACTION_KEY_KEY; - $this->pushRequst->setTransactions($this->order->getPayment()->getAdditionalInformation($originalKey)); - $this->pushRequst->setAmount($this->pushRequst->getAmountDebit()); - - if (!$this->saveInvoice()) { - return false; - } - } - - $this->updateOrderStatus($this->order->getState(), $this->order->getStatus(), $statusMessage); - - return true; - } - - /** - * Sends the CM3 confirmation email if the CM3 status code is 10 and the order email has not been sent. - * - * @return void - * @throws LocalizedException - */ - private function sendCm3ConfirmationMail() - { - $store = $this->order->getStore(); - $cm3StatusCode = 0; - - if (!empty($this->pushRequst->getInvoicestatuscode())) { - $cm3StatusCode = $this->pushRequst->getInvoicestatuscode(); - } - - $paymentMethod = $this->order->getPayment()->getMethodInstance(); - $configOrderMail = $this->configAccount->getOrderConfirmationEmail($store) - || $paymentMethod->getConfigData('order_email', $store); - - if (!$this->order->getEmailSent() && $cm3StatusCode == 10 && $configOrderMail) { - $this->orderSender->send($this->order); - } - } - - /** - * Checks if the payment is a partial payment using a gift card. - * - * @return bool - */ - private function giftcardPartialPayment(): bool - { - $payment = $this->order->getPayment(); - - if ($payment->getMethod() != Giftcards::CODE - || (!empty($this->pushRequst->getAmount()) - && $this->pushRequst->getAmount() >= $this->order->getGrandTotal()) - || empty($this->pushRequst->getRelatedtransactionPartialpayment()) - ) { - return false; - } - - if ($this->groupTransaction->isGroupTransaction($this->pushRequst->getInvoiceNumber())) { - return false; - } - - if (!$this->isGroupTransactionInfoType()) { - $payment->setAdditionalInformation( - BuckarooAdapter::BUCKAROO_ORIGINAL_TRANSACTION_KEY_KEY, - $this->pushRequst->getRelatedtransactionPartialpayment() - ); - - $this->addGiftcardPartialPaymentToPaymentInformation(); - } - - return true; - } - - /** - * Adds the gift card partial payment information to the payment's additional information. - * - * @return void - */ - protected function addGiftcardPartialPaymentToPaymentInformation() - { - $payment = $this->order->getPayment(); - - $transactionAmount = $this->pushRequst->getAmount(); - $transactionKey = $this->pushRequst->getTransactions(); - $transactionMethod = $this->pushRequst->getTransactionMethod(); - - $transactionData = $payment->getAdditionalInformation(BuckarooAdapter::BUCKAROO_ALL_TRANSACTIONS); - - $transactionArray = []; - if (is_array($transactionData) && count($transactionData) > 0) { - $transactionArray = $transactionData; - } - - if (!empty($transactionKey) && $transactionAmount > 0) { - $transactionArray[$transactionKey] = [$transactionMethod, $transactionAmount]; - - $payment->setAdditionalInformation( - BuckarooAdapter::BUCKAROO_ALL_TRANSACTIONS, - $transactionArray - ); - } - } - - /** - * Sets the transaction key in the payment's additional information if it's not already set. - * - * @return void - */ - protected function setTransactionKey() - { - $payment = $this->order->getPayment(); - $originalKey = BuckarooAdapter::BUCKAROO_ORIGINAL_TRANSACTION_KEY_KEY; - $transactionKey = $this->getTransactionKey(); - - if (!$payment->getAdditionalInformation($originalKey) && strlen($transactionKey) > 0) { - $payment->setAdditionalInformation($originalKey, $transactionKey); - } - } - - /** - * Store additional transaction information to track multiple payments manually - * Multiple Buckaroo pushes can resolve into incorrect - * - * @return void - */ - protected function setReceivedPaymentFromBuckaroo() - { - if (empty($this->pushRequst->getTransactions())) { - return; - } - - $payment = $this->order->getPayment(); - - if (!$payment->getAdditionalInformation(self::BUCKAROO_RECEIVED_TRANSACTIONS)) { - $payment->setAdditionalInformation( - self::BUCKAROO_RECEIVED_TRANSACTIONS, - [$this->pushRequst->getTransactions() => floatval($this->pushRequst->getAmount())] - ); - } else { - $buckarooTransactionKeysArray = $payment->getAdditionalInformation(self::BUCKAROO_RECEIVED_TRANSACTIONS); - - $buckarooTransactionKeysArray[$this->pushRequst->getTransactions()] = - floatval($this->pushRequst->getAmount()); - - $payment->setAdditionalInformation(self::BUCKAROO_RECEIVED_TRANSACTIONS, $buckarooTransactionKeysArray); - } - } - - /** - * It updates the BUCKAROO_RECEIVED_TRANSACTIONS_STATUSES payment additional information - * with the current received tx status. - * - * @return void - */ - protected function setReceivedTransactionStatuses(): void - { - $txId = $this->pushRequst->getTransactions(); - $statusCode = $this->pushRequst->getStatusCode(); - - if (empty($txId) || empty($statusCode)) { - return; - } - - $payment = $this->order->getPayment(); - - $receivedTxStatuses = $payment->getAdditionalInformation(self::BUCKAROO_RECEIVED_TRANSACTIONS_STATUSES) ?? []; - $receivedTxStatuses[$txId] = $statusCode; - - $payment->setAdditionalInformation(self::BUCKAROO_RECEIVED_TRANSACTIONS_STATUSES, $receivedTxStatuses); - } - - /** - * Retrieves the transaction key from the push request. - * - * @return string - */ - private function getTransactionKey(): string - { - $trxId = ''; - - if (!empty($this->pushRequst->getTransactions())) { - $trxId = $this->pushRequst->getTransactions(); - } - - if (!empty($this->pushRequst->getDatarequest())) { - $trxId = $this->pushRequst->getDatarequest(); - } - - if (!empty($this->pushRequst->getServiceKlarnaAutopaytransactionkey()) - ) { - $trxId = $this->pushRequst->getServiceKlarnaAutopaytransactionkey(); - } - - if (!empty($this->pushRequst->getServiceKlarnakpAutopaytransactionkey()) - ) { - $trxId = $this->pushRequst->getServiceKlarnakpAutopaytransactionkey(); - } - - if (!empty($this->pushRequst->getRelatedtransactionRefund())) { - $trxId = $this->pushRequst->getRelatedtransactionRefund(); - } - - return $trxId; - } - - /** - * Sometimes the push does not contain the order id, when that's the case try to get the order by his payment, - * by using its own transaction key. - * - * @return Payment - * @throws BuckarooException - */ - protected function getOrderByTransactionKey(): Payment - { - $trxId = $this->getTransactionKey(); - - $this->transaction->load($trxId, 'txn_id'); - $order = $this->transaction->getOrder(); - - if (!$order) { - throw new BuckarooException(__('There was no order found by transaction Id')); - } - - return $order; - } - - /** - * Checks if the order can be updated by checking its state and status. - * - * @param array $response - * @return bool - * - * @SuppressWarnings(PHPMD.CyclomaticComplexity) - */ - protected function canUpdateOrderStatus(array $response): bool - { - /** - * Types of statusses - */ - $completedStateAndStatus = [Order::STATE_COMPLETE, Order::STATE_COMPLETE]; - $cancelledStateAndStatus = [Order::STATE_CANCELED, Order::STATE_CANCELED]; - $holdedStateAndStatus = [Order::STATE_HOLDED, Order::STATE_HOLDED]; - $closedStateAndStatus = [Order::STATE_CLOSED, Order::STATE_CLOSED]; - /** - * Get current state and status of order - */ - $currentStateAndStatus = [$this->order->getState(), $this->order->getStatus()]; - $this->logging->addDebug(__METHOD__ . '|1|' . var_export($currentStateAndStatus, true)); - - /** - * If the types are not the same and the order can receive an invoice the order can be udpated by BPE. - */ - if ($completedStateAndStatus != $currentStateAndStatus - && $cancelledStateAndStatus != $currentStateAndStatus - && $holdedStateAndStatus != $currentStateAndStatus - && $closedStateAndStatus != $currentStateAndStatus - ) { - return true; - } - - if (($this->order->getState() === Order::STATE_CANCELED) - && ($this->order->getStatus() === Order::STATE_CANCELED) - && ($response['status'] === 'BUCKAROO_MAGENTO2_STATUSCODE_SUCCESS') - && !isset($this->postData['brq_relatedtransaction_partialpayment']) - ) { - $this->logging->addDebug(__METHOD__ . '|2|'); - - $this->order->setState(Order::STATE_NEW); - $this->order->setStatus('pending'); - - foreach ($this->order->getAllItems() as $item) { - $item->setQtyCanceled(0); - } - - $this->forceInvoice = true; - return true; - } - - return false; - } - - /** - * Process the failed push response from Buckaroo and update the order accordingly. - * - * @param string $newStatus - * @param string $message - * @return bool - * @throws LocalizedException - * - * @SuppressWarnings(PHPMD.CyclomaticComplexity) - */ - public function processFailedPush(string $newStatus, string $message): bool - { - $this->logging->addDebug(__METHOD__ . '|1|' . var_export($newStatus, true)); - - if (($this->order->getState() === Order::STATE_PROCESSING) - && ($this->order->getStatus() === Order::STATE_PROCESSING) - ) { - //do not update to failed if we had a success already - $this->logging->addDebug(__METHOD__ . '|2|'); - return false; - } - - $description = 'Payment status : ' . $message; - - if (!empty($this->pushRequst->getServiceAntifraudAction())) { - $description .= $this->pushRequst->getServiceAntifraudAction() . - ' ' . - $this->pushRequst->getServiceAntifraudCheck() . - ' ' . - $this->pushRequst->getServiceAntifraudDetails(); - } - - $store = $this->order->getStore(); - - $buckarooCancelOnFailed = $this->configAccount->getCancelOnFailed($store); - - $payment = $this->order->getPayment(); - - if ($buckarooCancelOnFailed && $this->order->canCancel()) { - $this->logging->addDebug(__METHOD__ . '|' . 'Buckaroo push failed : ' . $message . ' : Cancel order.'); - - // BUCKM2-78: Never automatically cancelauthorize via push for afterpay - // setting parameter which will cause to stop the cancel process on - // Buckaroo/Model/Method/BuckarooAdapter.php:880 - $methods = [ - 'buckaroo_magento2_afterpay', - 'buckaroo_magento2_afterpay2', - 'buckaroo_magento2_klarna', - 'buckaroo_magento2_klarnakp' - ]; - if (in_array($payment->getMethodInstance()->getCode(), $methods)) { - $payment->setAdditionalInformation('buckaroo_failed_authorize', 1); - $payment->save(); - } - - $this->updateOrderStatus(Order::STATE_CANCELED, $newStatus, $description); - - try { - $this->order->cancel()->save(); - } catch (\Throwable $t) { - $this->logging->addDebug(__METHOD__ . '|3|'); - // SignifydGateway/Gateway error on line 208" - } - return true; - } - - $this->logging->addDebug(__METHOD__ . '|4|'); - $force = false; - if (($payment->getMethodInstance()->getCode() == 'buckaroo_magento2_mrcash') - && ($this->order->getState() === Order::STATE_NEW) - && ($this->order->getStatus() === 'pending') - ) { - $force = true; - } - $this->updateOrderStatus(Order::STATE_CANCELED, $newStatus, $description, $force); - - return true; - } - - /** - * Process the successful push response from Buckaroo and update the order accordingly. - * - * @param string $newStatus - * @param string $message - * @return bool - * @throws LocalizedException - * - * @SuppressWarnings(PHPMD.CyclomaticComplexity) - * @SuppressWarnings(PHPMD.NPathComplexity) - * @SuppressWarnings(PHPMD.ExcessiveMethodLength) - */ - public function processSucceededPush(string $newStatus, string $message): bool - { - $this->logging->addDebug(__METHOD__ . '|1|' . var_export($newStatus, true)); - - $amount = $this->order->getTotalDue(); - - if (!empty($this->pushRequst->getAmount())) { - $this->logging->addDebug(__METHOD__ . '|11|'); - $amount = floatval($this->pushRequst->getAmount()); - } - - if (!empty($this->pushRequst->getServiceKlarnaReservationnumber())) { - $this->order->setBuckarooReservationNumber($this->pushRequst->getServiceKlarnaReservationnumber()); - $this->order->save(); - } - - if (!empty($this->pushRequst->getServiceKlarnakpReservationnumber())) { - $this->order->setBuckarooReservationNumber($this->pushRequst->getServiceKlarnakpReservationnumber()); - $this->order->save(); - } - - $store = $this->order->getStore(); - $payment = $this->order->getPayment(); - - /** - * @var \Magento\Payment\Model\MethodInterface $paymentMethod - */ - $paymentMethod = $payment->getMethodInstance(); - - if (!$this->order->getEmailSent() - && ($this->configAccount->getOrderConfirmationEmail($store) - || $paymentMethod->getConfigData('order_email', $store) - ) - ) { - $this->logging->addDebug(__METHOD__ . '|sendemail|' . - var_export($this->configAccount->getOrderConfirmationEmailSync($store), true)); - $this->orderSender->send($this->order, $this->configAccount->getOrderConfirmationEmailSync($store)); - } - - /** force state eventhough this can lead to a transition of the order - * like new -> processing - */ - $forceState = false; - $state = Order::STATE_PROCESSING; - - $this->logging->addDebug(__METHOD__ . '|2|'); - - if ($paymentMethod->canPushInvoice($this->pushRequst)) { - $this->logging->addDebug(__METHOD__ . '|3|'); - $description = 'Payment status : ' . $message . "
"; - if ($this->pushRequst->hasPostData('transaction_method', 'transfer')) { - //keep amount fetched from brq_amount - $description .= 'Amount of ' . $this->order->getBaseCurrency()->formatTxt($amount) . ' has been paid'; - } else { - $amount = $this->order->getBaseTotalDue(); - $description .= 'Total amount of ' . - $this->order->getBaseCurrency()->formatTxt($amount) . ' has been paid'; - } - } else { - $description = 'Authorization status : ' . $message . "
"; - $description .= 'Total amount of ' . $this->order->getBaseCurrency()->formatTxt($this->order->getTotalDue()) - . ' has been authorized. Please create an invoice to capture the authorized amount.'; - $forceState = true; - } - - if ($this->isPayPerEmailB2BModePushInitial) { - $description = ''; - } - - $this->dontSaveOrderUponSuccessPush = false; - if ($paymentMethod->canPushInvoice($this->pushRequst)) { - $this->logging->addDebug(__METHOD__ . '|4|'); - - if (!$this->isPayPerEmailB2BModePushInitial && $this->isPayPerEmailB2BModePushPaid()) { - $this->logging->addDebug(__METHOD__ . '|4_1|'); - //Fix for suspected fraud when the order currency does not match with the payment's currency - $amount = ($payment->isSameCurrency() && $payment->isCaptureFinal($this->order->getGrandTotal())) ? - $this->order->getGrandTotal() : $this->order->getBaseTotalDue(); - $payment->registerCaptureNotification($amount); - $payment->save(); - $this->order->setState('complete'); - $this->order->addStatusHistoryComment($description, 'complete'); - $this->order->save(); - - if ($transactionKey = $this->getTransactionKey()) { - foreach ($this->order->getInvoiceCollection() as $invoice) { - $invoice->setTransactionId($transactionKey)->save(); - } - } - return true; - } - - if ($this->pushRequst->hasAdditionalInformation('initiated_by_magento', 1) && - ( - $this->pushRequst->hasPostData('transaction_method', 'KlarnaKp') && - $this->pushRequst->hasAdditionalInformation('service_action_from_magento', 'pay') && - empty($this->pushRequst->getServiceKlarnakpReservationnumber()) && - $this->klarnakpConfig->isInvoiceCreatedAfterShipment() - ) || - ( - $this->pushRequst->hasPostData('transaction_method', 'afterpay') && - $this->pushRequst->hasAdditionalInformation('service_action_from_magento', 'capture') && - $this->afterpayConfig->isInvoiceCreatedAfterShipment() - ) - ) { - $this->logging->addDebug(__METHOD__ . '|5_1|'); - $this->dontSaveOrderUponSuccessPush = true; - return true; - } else { - $this->logging->addDebug(__METHOD__ . '|6|'); - - if ($this->pushRequst->hasPostData('transaction_method', 'transfer')) { - //invoice only in case of full or last remained amount - $this->logging->addDebug(__METHOD__ . '|61|' . var_export([ - $this->order->getId(), - $amount, - $this->order->getTotalDue(), - $this->order->getTotalPaid(), - ], true)); - - $saveInvoice = true; - if (($amount < $this->order->getTotalDue()) - || (($amount == $this->order->getTotalDue()) && ($this->order->getTotalPaid() > 0)) - ) { - $this->logging->addDebug(__METHOD__ . '|64|'); - - $forceState = true; - if ($amount < $this->order->getTotalDue()) { - $this->logging->addDebug(__METHOD__ . '|65|'); - $state = Order::STATE_NEW; - $newStatus = $this->orderStatusFactory->get( - $this->helper->getStatusCode('BUCKAROO_MAGENTO2_STATUSCODE_PENDING_PROCESSING'), - $this->order - ); - $saveInvoice = false; - } - - $this->saveAndReloadOrder(); - - $this->order->setTotalDue($this->order->getTotalDue() - $amount); - $this->order->setBaseTotalDue($this->order->getTotalDue() - $amount); - - $totalPaid = $this->order->getTotalPaid() + $amount; - $this->order->setTotalPaid( - $totalPaid > $this->order->getGrandTotal() ? $this->order->getGrandTotal() : $totalPaid - ); - - $baseTotalPaid = $this->order->getBaseTotalPaid() + $amount; - $this->order->setBaseTotalPaid( - $baseTotalPaid > $this->order->getBaseGrandTotal() ? - $this->order->getBaseGrandTotal() : $baseTotalPaid - ); - - $this->saveAndReloadOrder(); - - $connection = $this->resourceConnection->getConnection(); - $connection->update( - $connection->getTableName('sales_order'), - [ - 'total_due' => $this->order->getTotalDue(), - 'base_total_due' => $this->order->getTotalDue(), - 'total_paid' => $this->order->getTotalPaid(), - 'base_total_paid' => $this->order->getBaseTotalPaid(), - ], - $connection->quoteInto('entity_id = ?', $this->order->getId()) - ); - } - - if ($saveInvoice) { - if (!$this->saveInvoice()) { - return false; - } - } - } else { - if (!$this->saveInvoice()) { - return false; - } - } - } - } - - if (!empty($this->pushRequst->getServiceKlarnaAutopaytransactionkey()) - && ($this->pushRequst->getStatusCode() == 190) - ) { - $this->saveInvoice(); - } - - if (!empty($this->pushRequst->getServiceKlarnakpAutopaytransactionkey()) - && ($this->pushRequst->getStatusCode() == 190) - ) { - $this->saveInvoice(); - } - - if ($this->groupTransaction->isGroupTransaction($this->pushRequst->getInvoiceNumber())) { - $forceState = true; - } - - $this->logging->addDebug(__METHOD__ . '|8|'); - - $this->processSucceededPushAuth($payment); - - $this->updateOrderStatus($state, $newStatus, $description, $forceState); - - $this->logging->addDebug(__METHOD__ . '|9|'); - - return true; - } - - // Create a function that process push request for Paypal - - /** - * Process the pending payment push response from Buckaroo and update the order accordingly. - * - * @return bool - * @throws LocalizedException - */ - public function processPendingPaymentPush(): bool - { - $this->logging->addDebug(__METHOD__ . '|1|'); - - $store = $this->order->getStore(); - $payment = $this->order->getPayment(); - - $paymentMethod = $payment->getMethodInstance(); - - // Transfer has a slightly different flow where a successful order has a 792 status code instead of an 190 one - if (!$this->order->getEmailSent() - && in_array( - $payment->getMethod(), - [ - Transfer::CODE, - SepaDirectDebit::CODE, - Sofortbanking::CODE, - PayPerEmail::CODE, - ] - ) - && ($this->configAccount->getOrderConfirmationEmail($store) - || $paymentMethod->getConfigData('order_email', $store) - ) - ) { - $this->logging->addDebug(__METHOD__ . '|sendemail|'); - $this->orderSender->send($this->order); - } - - return true; - } - - /** - * Try to add a notification note to the order comments. - * - * @param string|Phrase $message - * @throws \Exception - */ - protected function setOrderNotificationNote(Phrase|string $message) - { - $note = 'Buckaroo attempted to update this order, but failed: ' . $message; - try { - $this->order->addStatusToHistory($note); - $this->order->save(); - } catch (\Exception $e) { - $this->logging->addDebug($e->getLogMessage()); - } - } - - /** - * Updates the order state and add a comment. - * - * @param string $orderState - * @param string $newStatus - * @param string $description - * @param bool $force - * @throws \Exception - */ - protected function updateOrderStatus( - string $orderState, - string $newStatus, - string $description, - bool $force = false - ) { - $this->logging->addDebug(__METHOD__ . '|0|' . var_export([$orderState, $newStatus, $description], true)); - if ($this->order->getState() == $orderState || $force) { - $this->logging->addDebug(__METHOD__ . '|1|'); - $this->logging->addDebug('||| $orderState: ' . '|1|' . $orderState); - if ($this->dontSaveOrderUponSuccessPush) { - $this->order->addCommentToStatusHistory($description) - ->setIsCustomerNotified(false) - ->setEntityName('invoice') - ->setStatus($newStatus) - ->save(); - } else { - $this->order->addCommentToStatusHistory($description, $newStatus); - } - } else { - $this->logging->addDebug(__METHOD__ . '|2|'); - $this->logging->addDebug('||| $orderState: ' . '|2|' . $orderState); - if ($this->dontSaveOrderUponSuccessPush) { - $this->order->addCommentToStatusHistory($description) - ->setIsCustomerNotified(false) - ->setEntityName('invoice') - ->save(); - } else { - $this->order->addCommentToStatusHistory($description); - } - } - } - - /** - * Creates and saves the invoice and adds for each invoice the buckaroo transaction keys - * Only when the order can be invoiced and has not been invoiced before. - * - * @return bool - * @throws BuckarooException - * @throws LocalizedException - * - * @SuppressWarnings(PHPMD.CyclomaticComplexity) - * @SuppressWarnings(PHPMD.NPathComplexity) - */ - protected function saveInvoice(): bool - { - $this->logging->addDebug(__METHOD__ . '|1|'); - if (!$this->forceInvoice - && (!$this->order->canInvoice() || $this->order->hasInvoices())) { - $this->logging->addDebug('Order can not be invoiced'); - //throw new BuckarooException(__('Order can not be invoiced')); - return false; - - } - - $this->logging->addDebug(__METHOD__ . '|5|'); - - /** - * Only when the order can be invoiced and has not been invoiced before. - */ - if (!$this->isGroupTransactionInfoType()) { - $this->addTransactionData(); - } - - /** - * @var Payment $payment - */ - $payment = $this->order->getPayment(); - - $invoiceAmount = 0; - if (!empty($this->pushRequst->getAmount())) { - $invoiceAmount = floatval($this->pushRequst->getAmount()); - } - if (($payment->getMethod() == Giftcards::CODE) - && $invoiceAmount != $this->order->getGrandTotal() - ) { - $this->setReceivedPaymentFromBuckaroo(); - - $payment->registerCaptureNotification($invoiceAmount, true); - $payment->save(); - - $receivedPaymentsArray = $payment->getAdditionalInformation(self::BUCKAROO_RECEIVED_TRANSACTIONS); - - if (!is_array($receivedPaymentsArray)) { - return false; - } - - $payment->capture(); //creates invoice - $payment->save(); - } elseif ($this->isPayPerEmailB2BModePushInitial) { - $this->logging->addDebug(__METHOD__ . '|10|'); - $invoice = $this->order->prepareInvoice()->register(); - $invoice->setOrder($this->order); - $this->order->addRelatedObject($invoice); - $payment->setCreatedInvoice($invoice); - $payment->setShouldCloseParentTransaction(true); - } else { - $this->logging->addDebug(__METHOD__ . '|15|'); - //Fix for suspected fraud when the order currency does not match with the payment's currency - $amount = ($payment->isSameCurrency() - && $payment->isCaptureFinal($this->order->getGrandTotal())) ? - $this->order->getGrandTotal() : $this->order->getBaseTotalDue(); - $payment->registerCaptureNotification($amount); - $payment->save(); - } - - $this->logging->addDebug(__METHOD__ . '|20|'); - - $transactionKey = $this->getTransactionKey(); - - if (strlen($transactionKey) <= 0) { - return true; - } - - $this->logging->addDebug(__METHOD__ . '|25|'); - - /** @var \Magento\Sales\Model\Order\Invoice $invoice */ - foreach ($this->order->getInvoiceCollection() as $invoice) { - $invoice->setTransactionId($transactionKey)->save(); - - if (!empty($this->pushRequst->getInvoiceNumber()) - && $this->groupTransaction->isGroupTransaction($this->pushRequst->getInvoiceNumber())) { - $this->logging->addDebug(__METHOD__ . '|27|'); - $invoice->setState(2); - } - - if (!$invoice->getEmailSent() && $this->configAccount->getInvoiceEmail($this->order->getStore())) { - $this->logging->addDebug(__METHOD__ . '|30|sendinvoiceemail'); - $this->invoiceSender->send($invoice, true); - } - } - - $this->logging->addDebug(__METHOD__ . '|35|'); - - $this->order->setIsInProcess(true); - $this->order->save(); - - $this->dontSaveOrderUponSuccessPush = true; - - return true; - } - - /** - * Adds transaction data to the order payment with the given transaction key and data. - * - * @param bool $transactionKey - * @param bool $data - * @return Payment - * @throws LocalizedException - * @throws \Exception - */ - public function addTransactionData(bool $transactionKey = false, bool $data = false): Payment - { - /** - * @var Payment $payment - */ - $payment = $this->order->getPayment(); - - $transactionKey = $transactionKey ?: $this->getTransactionKey(); - - if (strlen($transactionKey) <= 0) { - throw new \Exception(__('There was no transaction ID found')); - } - - /** - * Save the transaction's response as additional info for the transaction. - */ - $postData = $data ?: $this->pushRequst->getData(); - $rawInfo = $this->helper->getTransactionAdditionalInfo($postData); - - /** - * @noinspection PhpUndefinedMethodInspection - */ - $payment->setTransactionAdditionalInfo( - Transaction::RAW_DETAILS, - $rawInfo - ); - - /** - * Save the payment's transaction key. - */ - /** - * @noinspection PhpUndefinedMethodInspection - */ - if ($this->pushRequst->hasPostData('transaction_method', 'KlarnaKp')) { - $payment->setTransactionId($transactionKey); - } else { - $payment->setTransactionId($transactionKey . '-capture'); - } - /** - * @noinspection PhpUndefinedMethodInspection - */ - $payment->setParentTransactionId($transactionKey); - $payment->setAdditionalInformation( - \Buckaroo\Magento2\Model\Method\BuckarooAdapter::BUCKAROO_ORIGINAL_TRANSACTION_KEY_KEY, - $transactionKey - ); - - return $payment; - } - - private function isGroupTransactionInfoType() - { - if (!empty($this->pushRequst->getTransactionType()) - && ($this->pushRequst->getTransactionType() == self::BUCK_PUSH_GROUPTRANSACTION_TYPE) - ) { - return true; - } - return false; - } - - /** - * Checks if the transaction type is a group transaction. - * - * @return bool - */ - private function isGroupTransactionInfo() - { - $this->logging->addDebug(__METHOD__ . '|1|'); - if ($this->isGroupTransactionInfoType()) { - if ($this->pushRequst->getStatusCode() != - $this->helper->getStatusCode('BUCKAROO_MAGENTO2_STATUSCODE_SUCCESS') - ) { - return true; - } - } - return false; - } - - /** - * Checks if the push request is a group transaction with a non-success status code. - * - * @return false|mixed - */ - private function isGroupTransactionPart() - { - if (!is_null($this->pushRequst->getTransactions())) { - return $this->groupTransaction->getGroupTransactionByTrxId($this->pushRequst->getTransactions()); - } - return false; - } - - /** - * Check if the group transaction has failed. same as: isFailedGroupTransaction - * - * @return bool - */ - private function isGroupTransactionFailed() - { - if ($this->isGroupTransactionInfoType() - && $this->pushRequst->getStatusCode() == - $this->helper->getStatusCode('BUCKAROO_MAGENTO2_STATUSCODE_FAILED') - ) { - return true; - } - - return false; - } - - /** - * Save the part group transaction. - * - * @return void - * @throws \Exception - */ - private function savePartGroupTransaction() - { - $items = $this->groupTransaction->getGroupTransactionByTrxId($this->pushRequst->getTransactions()); - if (is_array($items) && count($items) > 0) { - foreach ($items as $item) { - $item2['status'] = $this->pushRequst->getStatusCode(); - $item2['entity_id'] = $item['entity_id']; - $this->groupTransaction->updateGroupTransaction($item2); - } - } - } - - /** - * Check if the PayLink payment was successful. - * - * @param array $response - * @param bool $validSignature - * @return bool - * @throws \Exception - */ - private function receivePushCheckPayLink(array $response, bool $validSignature): bool - { - if (!empty($this->pushRequst->getAdditionalInformation('frompaylink')) - && $response['status'] == 'BUCKAROO_MAGENTO2_STATUSCODE_SUCCESS' - && $validSignature - ) { - $payment = $this->order->getPayment(); - $payment->setMethod('buckaroo_magento2_payperemail'); - $payment->save(); - $this->order->save(); - return true; - } - return false; - } - - /** - * Check if the Pay Per Email payment was cancelled. - * - * @param array $response - * @param bool $validSignature - * @param InfoInterface $payment - * @return bool - * @throws BuckarooException - */ - private function pushCheckPayPerEmailCancel(array $response, bool $validSignature, InfoInterface $payment): bool - { - $failedStatuses = [ - 'BUCKAROO_MAGENTO2_STATUSCODE_TECHNICAL_ERROR', - 'BUCKAROO_MAGENTO2_STATUSCODE_VALIDATION_FAILURE', - 'BUCKAROO_MAGENTO2_STATUSCODE_CANCELLED_BY_MERCHANT', - 'BUCKAROO_MAGENTO2_STATUSCODE_CANCELLED_BY_USER', - 'BUCKAROO_MAGENTO2_STATUSCODE_FAILED', - 'BUCKAROO_MAGENTO2_STATUSCODE_REJECTED' - ]; - $status = $this->helper->getStatusByValue($this->pushRequst->getStatusCode() ?? ''); - if ((!empty($this->pushRequst->getAdditionalInformation('frompayperemail')) - || ($payment->getMethod() == 'buckaroo_magento2_payperemail')) - && !empty($this->pushRequst->getTransactionMethod()) - && ((in_array($response['status'], $failedStatuses)) - || (in_array($status, $failedStatuses)) - ) && $validSignature - ) { - $config = $this->configProviderMethodFactory->get(PayPerEmail::CODE); - if ($config->getEnabledCronCancelPPE()) { - return true; - } - } - return false; - } - - /** - * Check if the Pay Per Email payment was successful. - * - * @param array $response - * @param bool $validSignature - * @param InfoInterface $payment - * @return bool - * @throws \Exception - * - * @SuppressWarnings(PHPMD.CyclomaticComplexity) - */ - private function receivePushCheckPayPerEmail(array $response, bool $validSignature, InfoInterface $payment) - { - $status = $this->helper->getStatusByValue($this->pushRequst->getStatusCode() ?? ''); - if ((!empty($this->pushRequst->getAdditionalInformation('frompayperemail')) - || ($payment->getMethod() == 'buckaroo_magento2_payperemail')) - && !empty($this->pushRequst->getTransactionMethod()) - && (($response['status'] == 'BUCKAROO_MAGENTO2_STATUSCODE_SUCCESS') - || ($status == 'BUCKAROO_MAGENTO2_STATUSCODE_SUCCESS') - ) && $validSignature - && $this->pushRequst->getTransactionMethod() != 'payperemail') { - $brq_transaction_method = strtolower($this->pushRequst->getTransactionMethod()); - $payment = $this->order->getPayment(); - $payment->setAdditionalInformation('isPayPerEmail', $brq_transaction_method); - - $options = new \Buckaroo\Magento2\Model\Config\Source\PaymentMethods\PayPerEmail(); - foreach ($options->toOptionArray() as $item) { - if (($item['value'] == $brq_transaction_method) && isset($item['code'])) { - $payment->setMethod($item['code']); - $payment->setAdditionalInformation( - BuckarooAdapter::BUCKAROO_ORIGINAL_TRANSACTION_KEY_KEY, - $this->getTransactionKey() - ); - if ($item['code'] == 'buckaroo_magento2_creditcards') { - $payment->setAdditionalInformation('card_type', $brq_transaction_method); - } - } - } - $payment->save(); - $this->order->save(); - return true; - } - - return false; - } - - /** - * Check if the Pay Per Email payment is in B2B mode. - * - * @return bool - * @throws BuckarooException - */ - public function isPayPerEmailB2BModePush(): bool - { - if (!empty($this->pushRequst->getAdditionalInformation('frompayperemail')) - && !empty($this->pushRequst->getTransactionMethod()) - && ($this->pushRequst->getTransactionMethod() == 'payperemail') - ) { - $this->logging->addDebug(__METHOD__ . '|1|'); - $config = $this->configProviderMethodFactory->get(PayPerEmail::CODE); - if ($config->isEnabledB2B()) { - $this->logging->addDebug(__METHOD__ . '|5|'); - return true; - } - } - return false; - } - - /** - * Check if the Pay Per Email payment is in B2C mode. - * - * @return bool - * @throws BuckarooException - */ - public function isPayPerEmailB2CModePush(): bool - { - if (!empty($this->pushRequst->getAdditionalInformation('frompayperemail')) - && !empty($this->pushRequst->getTransactionMethod()) - && ($this->pushRequst->getTransactionMethod() == 'payperemail') - ) { - $this->logging->addDebug(__METHOD__ . '|1|'); - $config = $this->configProviderMethodFactory->get(PayPerEmail::CODE); - if (!$config->isEnabledB2B()) { - $this->logging->addDebug(__METHOD__ . '|5|'); - return true; - } - } - return false; - } - - /** - * Check if the Pay Per Email payment is in B2B mode and in the initial push. - * - * @param array $response - * @return bool - * @throws BuckarooException - */ - public function isPayPerEmailB2BModePushInitial(array $response): bool - { - $this->logging->addDebug(__METHOD__ . '|1|'); - return $this->isPayPerEmailB2BModePush() - && ($response['status'] == 'BUCKAROO_MAGENTO2_STATUSCODE_WAITING_ON_CONSUMER'); - } - - /** - * Check if the Pay Per Email payment is in B2C mode and in the initial push. - * - * @param array $response - * @return bool - * @throws BuckarooException - */ - public function isPayPerEmailB2CModePushInitial(array $response): bool - { - $this->logging->addDebug(__METHOD__ . '|1|'); - return $this->isPayPerEmailB2CModePush() - && ($response['status'] == 'BUCKAROO_MAGENTO2_STATUSCODE_WAITING_ON_CONSUMER'); - } - - /** - * Check if the Pay Per Email payment is in B2B mode and has been paid. - * - * @return bool - * @throws BuckarooException - */ - public function isPayPerEmailB2BModePushPaid(): bool - { - $this->logging->addDebug(__METHOD__ . '|1|'); - return $this->isPayPerEmailB2BModePush(); - } - - /** - * Get the order increment ID based on the invoice number or order number. - * - * @return string|false - */ - private function getOrderIncrementId() - { - $brqOrderId = false; - - if (!empty($this->pushRequst->getInvoiceNumber()) && strlen($this->pushRequst->getInvoiceNumber()) > 0) { - $brqOrderId = $this->pushRequst->getInvoiceNumber(); - } - - if (!empty($this->pushRequst->getOrderNumber()) && strlen($this->pushRequst->getOrderNumber()) > 0) { - $brqOrderId = $this->pushRequst->getOrderNumber(); - } - - return $brqOrderId; - } - - /** - * Get the file path for the lock push processing file. - * - * @return string|false - * @throws FileSystemException - */ - private function getLockPushProcessingFilePath() - { - if ($brqOrderId = $this->getOrderIncrementId()) { - return $this->dirList->getPath('tmp') . DIRECTORY_SEPARATOR . 'bk_push_ppe_' . sha1($brqOrderId); - } else { - return false; - } - } - - /** - * Determine if the lock push processing criteria are met. - * - * @return bool - */ - private function lockPushProcessingCriteria(): bool - { - $statusCodeSuccess = $this->helper->getStatusCode('BUCKAROO_MAGENTO2_STATUSCODE_SUCCESS'); - if (!empty($this->pushRequst->getAdditionalInformation('frompayperemail')) - || ( - ($this->pushRequst->hasPostData('statuscode', $statusCodeSuccess)) - && $this->pushRequst->hasPostData('transaction_method', 'ideal') - && $this->pushRequst->hasPostData('transaction_type', self::BUCK_PUSH_IDEAL_PAY) - ) - ) { - return true; - } else { - return false; - } - } - - /** - * Lock the push processing if criteria are met. - * - * @return resource|void - * @throws FileSystemException - */ - private function lockPushProcessing() - { - if ($this->lockPushProcessingCriteria()) { - $this->logging->addDebug(__METHOD__ . '|1|'); - if ($path = $this->getLockPushProcessingFilePath()) { - if ($fp = $this->fileSystemDriver->fileOpen($path, "w+")) { - $this->fileSystemDriver->fileLock($fp, LOCK_EX); - $this->logging->addDebug(__METHOD__ . '|5|'); - return $fp; - } - } - } - } - - /** - * Unlock the push processing. - * - * @param resource $lockHandler - * @return void - * @throws FileSystemException - */ - private function unlockPushProcessing($lockHandler) - { - if ($this->lockPushProcessingCriteria()) { - $this->logging->addDebug(__METHOD__ . '|1|'); - $this->fileSystemDriver->fileClose($lockHandler); - if (($path = $this->getLockPushProcessingFilePath()) && $this->fileSystemDriver->isExists($path)) { - $this->fileSystemDriver->deleteFile($path); - $this->logging->addDebug(__METHOD__ . '|5|'); - } - } - } - - /** - * Process succeeded push authorization. - * - * @param InfoInterface $payment - * @return void - * @throws \Exception - */ - private function processSucceededPushAuth(InfoInterface $payment) - { - $authPpaymentMethods = [ - Afterpay::CODE, - Afterpay2::CODE, - Afterpay20::CODE, - Creditcard::CODE, - Klarnakp::CODE - ]; - - if (in_array($payment->getMethod(), $authPpaymentMethods)) { - if ((($payment->getMethod() == Klarnakp::CODE) - || ( - !empty($this->pushRequst->getTransactionType()) - && in_array($this->pushRequst->getTransactionType(), ['I038', 'I880']) - ) - ) && !empty($this->pushRequst->getStatusCode()) - && ($this->pushRequst->getStatusCode() == 190) - ) { - $this->logging->addDebug(__METHOD__ . '|88|' . var_export($payment->getMethod(), true)); - $this->order->setState(Order::STATE_PROCESSING); - $this->order->save(); - } - } - } - - /** - * Handle push from main group transaction fail - * - * @return void - */ - protected function handleGroupTransactionFailed() - { - try { - $this->cancelOrder( - $this->postData['brq_invoicenumber'] - ); - $this->groupTransaction->setGroupTransactionsStatus( - $this->postData['brq_transactions'], - $this->postData['brq_statuscode'] - ); - } catch (\Throwable $th) { - $this->logging->addDebug(__METHOD__ . '|' . (string)$th); - } - } - - /** - * Check if is a failed transaction - * - * @return boolean - */ - protected function isFailedGroupTransaction(): bool - { - return $this->pushRequst->hasPostData( - 'transaction_type', - self::BUCK_PUSH_GROUPTRANSACTION_TYPE - ) && $this->pushRequst->hasPostData( - 'statuscode', - $this->helper->getStatusCode('BUCKAROO_MAGENTO2_STATUSCODE_FAILED') - ); - } - - /** - * Ship push handling for a failed transaction - * - * @return bool - */ - protected function skipHandlingForFailedGroupTransactions(): bool - { - return - $this->order !== null && - $this->order->getId() !== null && - $this->order->getState() == Order::STATE_CANCELED && - ( - $this->pushRequst->hasPostData( - 'brq_transaction_type', - 'V202' - ) || - - $this->pushRequst->hasPostData( - 'brq_transaction_type', - 'V203' - ) || - $this->pushRequst->hasPostData( - 'brq_transaction_type', - 'V204' - ) - ); - } - - /** - * Get quote by increment/reserved order id - * - * @param string $reservedOrderId - * @return Quote|null - */ - protected function getQuoteByReservedOrderId(string $reservedOrderId): ?Quote - { - /** @var \Magento\Quote\Model\QuoteFactory $quoteFactory */ - $quoteFactory = $this->objectManager->get('Magento\Quote\Model\QuoteFactory'); - /** @var \Magento\Quote\Model\ResourceModel\Quote $quoteResourceModel */ - $quoteResourceModel = $this->objectManager->get('Magento\Quote\Model\ResourceModel\Quote'); - - $quote = $quoteFactory->create(); - - $quoteResourceModel->load($quote, $reservedOrderId, 'reserved_order_id'); - if (!$quote->isEmpty()) { - return $quote; - } - - return null; - } - - /** - * Create order from found quote by reserved order id - * - * @param Quote $quote - * @return AbstractExtensibleModel|OrderInterface|object|null - * @throws \Exception - * @throws LocalizedException - */ - protected function createOrder(Quote $quote) - { - /** @var \Magento\Quote\Model\QuoteManagement $quoteManagement */ - $quoteManagement = $this->objectManager->get('Magento\Quote\Model\QuoteManagement'); - - return $quoteManagement->submit($quote); - } - - /** - * Cancel order for failed group transaction - * - * @param string $reservedOrderId - * @return void - * @throws LocalizedException - */ - protected function cancelOrder(string $reservedOrderId, $historyComment = 'Giftcard has expired') - { - $order = $this->order->loadByIncrementId($reservedOrderId); - - if ($order->getEntityId() === null) { - $order = $this->createOrderFromQuote($reservedOrderId); - } - - /** @var \Magento\Sales\Api\OrderManagementInterface */ - $orderManagement = $this->objectManager->get('Magento\Sales\Api\OrderManagementInterface'); - - if ($order instanceof OrderInterface && - $order->getEntityId() !== null && - $order->getState() !== Order::STATE_CANCELED - ) { - $orderManagement->cancel($order->getEntityId()); - - $order->addCommentToStatusHistory( - __($historyComment) - ) - ->setIsCustomerNotified(false) - ->setEntityName('invoice') - ->save(); - } - } - - /** - * Create order from quote - * - * @param string $reservedOrderId - * @return AbstractExtensibleModel|OrderInterface|object|null - * @throws \Exception - * @throws LocalizedException - */ - protected function createOrderFromQuote(string $reservedOrderId) - { - $quote = $this->getQuoteByReservedOrderId($reservedOrderId); - if (!$quote instanceof Quote) { - return null; - } - - //fix missing email validation - if ($quote->getCustomerEmail() == null) { - $quote->setCustomerEmail( - $quote->getBillingAddress()->getEmail() - ); - } - - $order = $this->createOrder($quote); - - //keep the quote active but remove the canceled order from it - $quote->setIsActive(true); - $quote->setOrigOrderId(0); - $quote->setReservedOrderId(null); - $quote->save(); - return $order; - } - - /** - * Cancel order when group transaction is canceled - * - * @return void - * @throws LocalizedException - */ - public function cancelGroupTransactionOrder() - { - if( - isset($this->postData['brq_invoicenumber']) && - is_string($this->postData['brq_invoicenumber']) - ) { - $this->cancelOrder( - $this->postData['brq_invoicenumber'], - 'Inline giftcard order was canceled' - ); - } - } - - /** - * Check if the request is a canceled group transaction - * - * @return boolean - */ - public function isCanceledGroupTransaction() - { - return $this->pushRequst->hasPostData( - 'brq_transaction_type', - self::BUCK_PUSH_GROUPTRANSACTION_TYPE - ) && - $this->pushRequst->hasPostData( - 'brq_statuscode', - $this->helper->getStatusCode('BUCKAROO_MAGENTO2_STATUSCODE_CANCELLED_BY_USER') - ); + // Process Push + $pushProcessor = $this->pushProcessorsFactory->get($pushTransactionType); + return $pushProcessor->processPush($this->pushRequst); } } diff --git a/Service/Push/OrderRequestService.php b/Service/Push/OrderRequestService.php index 6743e2e14..253e8aebb 100644 --- a/Service/Push/OrderRequestService.php +++ b/Service/Push/OrderRequestService.php @@ -1,4 +1,23 @@ Date: Mon, 14 Aug 2023 09:47:20 +0300 Subject: [PATCH 24/29] BP-2813 - Remove testing code --- Gateway/Request/BasicParameter/InvoiceDataBuilder.php | 4 ++-- Service/Push/OrderRequestService.php | 5 ++--- 2 files changed, 4 insertions(+), 5 deletions(-) diff --git a/Gateway/Request/BasicParameter/InvoiceDataBuilder.php b/Gateway/Request/BasicParameter/InvoiceDataBuilder.php index 3e033a3af..b93727a69 100644 --- a/Gateway/Request/BasicParameter/InvoiceDataBuilder.php +++ b/Gateway/Request/BasicParameter/InvoiceDataBuilder.php @@ -51,8 +51,8 @@ public function build(array $buildSubject): array $this->setOrder($paymentDO->getOrder()->getOrder()); return [ - 'invoice' => 'LT' . $this->getInvoiceId(), - 'order' => 'LT' . $this->getOrder()->getIncrementId() + 'invoice' => $this->getInvoiceId(), + 'order' => $this->getOrder()->getIncrementId() ]; } diff --git a/Service/Push/OrderRequestService.php b/Service/Push/OrderRequestService.php index 253e8aebb..c09bd8137 100644 --- a/Service/Push/OrderRequestService.php +++ b/Service/Push/OrderRequestService.php @@ -21,6 +21,7 @@ namespace Buckaroo\Magento2\Service\Push; +use Buckaroo\Exceptions\BuckarooException; use Buckaroo\Magento2\Api\PushRequestInterface; use Buckaroo\Magento2\Logging\Log; use Magento\Framework\App\ResourceConnection; @@ -133,8 +134,6 @@ protected function getOrderIncrementIdFromRequest($pushRequest): ?string $brqOrderId = $pushRequest->getOrderNumber(); } - $brqOrderId = str_replace('LT', '', $brqOrderId); - return $brqOrderId; } @@ -154,7 +153,7 @@ protected function getOrderByTransactionKey($pushRequest): OrderPayment $order = $this->transaction->getOrder(); if (!$order) { - throw new \Exception(__('There was no order found by transaction Id')); + throw new BuckarooException(__('There was no order found by transaction Id')); } return $order; From 5802014df4f57f484b39b1127a2bf3e4a380a42c Mon Sep 17 00:00:00 2001 From: Lucian Turiac Date: Tue, 15 Aug 2023 16:03:41 +0300 Subject: [PATCH 25/29] BP-2132 - BP-2813 - code review --- Model/Push/DefaultProcessor.php | 15 ++++++---- Model/Push/PartialPaymentProcessor.php | 24 ---------------- Model/Push/PushProcessorsFactory.php | 40 +++++++++++++++++++++----- Model/Push/PushTransactionType.php | 13 ++------- Model/Push/RefundProcessor.php | 1 + 5 files changed, 47 insertions(+), 46 deletions(-) delete mode 100644 Model/Push/PartialPaymentProcessor.php diff --git a/Model/Push/DefaultProcessor.php b/Model/Push/DefaultProcessor.php index acaa28a34..0e3413404 100644 --- a/Model/Push/DefaultProcessor.php +++ b/Model/Push/DefaultProcessor.php @@ -626,14 +626,19 @@ protected function processPushByStatus(): bool if ($statusKey == 'BUCKAROO_MAGENTO2_STATUSCODE_SUCCESS') { return $this->processSucceededPush($newStatus, $statusMessage); - } elseif (in_array($statusKey, $this->buckarooStatusCode->getFailedStatuses())) { + } + + if (in_array($statusKey, $this->buckarooStatusCode->getFailedStatuses())) { return $this->processFailedPush($newStatus, $statusMessage); - } elseif (in_array($statusKey, $this->buckarooStatusCode->getPendingStatuses())) { + } + + if (in_array($statusKey, $this->buckarooStatusCode->getPendingStatuses())) { return $this->processPendingPaymentPush(); - } else { - $this->orderRequestService->setOrderNotificationNote($statusMessage); - return true; } + + $this->orderRequestService->setOrderNotificationNote($statusMessage); + return true; + } /** diff --git a/Model/Push/PartialPaymentProcessor.php b/Model/Push/PartialPaymentProcessor.php deleted file mode 100644 index fb221ce0b..000000000 --- a/Model/Push/PartialPaymentProcessor.php +++ /dev/null @@ -1,24 +0,0 @@ -pushRequest = $pushRequest; - $this->order = $this->orderRequestService->getOrderByRequest(); - $this->payment = $this->order->getPayment(); - - // Check Push Dublicates - if ($this->receivePushCheckDuplicates()) { - throw new BuckarooException(__('Skipped handling this push, duplicate')); - } - // TODO: Implement processPush() method. - } -} \ No newline at end of file diff --git a/Model/Push/PushProcessorsFactory.php b/Model/Push/PushProcessorsFactory.php index aab09a15f..cb3f0778c 100644 --- a/Model/Push/PushProcessorsFactory.php +++ b/Model/Push/PushProcessorsFactory.php @@ -1,4 +1,23 @@ getPaymentMethod(); $pushProcessorClass = $this->pushProcessors[$paymentMethod] ?? $pushProcessorClass; if ($pushTransactionType->isFromPayPerEmail()) { - $this->pushProcessors['group_transaction']; + return $this->pushProcessors['group_transaction']; } // Check if is Group Transaction Push if ($pushTransactionType->isGroupTransaction()) { - $pushProcessorClass = $this->pushProcessors['group_transaction']; + return $this->pushProcessors['group_transaction']; } // Check if is Credit Management Push $pushType = $pushTransactionType->getPushType(); if ($pushType == PushTransactionType::BUCK_PUSH_TYPE_INVOICE) { - $pushProcessorClass = $this->pushProcessors['credit_managment']; + return $this->pushProcessors['credit_managment']; } elseif ($pushType == PushTransactionType::BUCK_PUSH_TYPE_INVOICE_INCOMPLETE) { throw new BuckarooException( __('Skipped handling this invoice push because it is too soon.') @@ -105,9 +129,11 @@ private function getPushProcessorClass(?PushTransactionType $pushTransactionType // Check if is Refund or Cancel Authorize Push if ($pushTransactionType->getServiceAction() == 'refund') { - $pushProcessorClass = $this->pushProcessors['refund']; - } elseif ($pushTransactionType->getServiceAction() == 'cancel_authorize') { - $pushProcessorClass = $this->pushProcessors['cancel_authorize']; + return $this->pushProcessors['refund']; + } + + if ($pushTransactionType->getServiceAction() == 'cancel_authorize') { + return $this->pushProcessors['cancel_authorize']; } return $pushProcessorClass; diff --git a/Model/Push/PushTransactionType.php b/Model/Push/PushTransactionType.php index fcd956e93..26ca51dae 100644 --- a/Model/Push/PushTransactionType.php +++ b/Model/Push/PushTransactionType.php @@ -214,19 +214,12 @@ private function getStatusCodeByTransactionType(string $transactionType): int switch ($transactionType) { case self::BUCK_PUSH_TYPE_TRANSACTION: case self::BUCK_PUSH_TYPE_DATAREQUEST: - if ($this->pushRequest->getStatusCode() !== null) { - $statusCode = $this->pushRequest->getStatusCode(); - } + $statusCode = $this->pushRequest->getStatusCode() ?: $statusCode; break; case self::BUCK_PUSH_TYPE_INVOICE: case self::BUCK_PUSH_TYPE_INVOICE_INCOMPLETE: - if (!empty($this->pushRequest->getEventparametersStatuscode())) { - $statusCode = $this->pushRequest->getEventparametersStatuscode(); - } - - if (!empty($this->pushRequest->getEventparametersTransactionstatuscode())) { - $statusCode = $this->pushRequest->getEventparametersTransactionstatuscode(); - } + $statusCode = $this->pushRequest->getEventparametersStatuscode() ?: $statusCode; + $statusCode = $this->pushRequest->getEventparametersTransactionstatuscode() ?: $statusCode; break; } diff --git a/Model/Push/RefundProcessor.php b/Model/Push/RefundProcessor.php index 176db1253..68088b9da 100644 --- a/Model/Push/RefundProcessor.php +++ b/Model/Push/RefundProcessor.php @@ -82,6 +82,7 @@ public function processPush(PushRequestInterface $pushRequest): bool * * @param PushRequestInterface $pushRequest * @return bool + * @throws \Exception */ private function skipPendingRefundPush(PushRequestInterface $pushRequest): bool { From 8b7b1a869b650dde6fb6b32baf6d2d165d30c4d0 Mon Sep 17 00:00:00 2001 From: Lucian Turiac Date: Tue, 15 Aug 2023 18:29:52 +0300 Subject: [PATCH 26/29] BP-2132 - BP-2813 - fix PHP_MD and PHP_CS --- Controller/Payconiq/Process.php | 7 ++-- Controller/Redirect/IdinProcess.php | 5 +++ Controller/Redirect/Process.php | 6 +-- Model/ConfigProvider/Method/Applepay.php | 2 +- Model/Push/AfterpayProcessor.php | 33 +++++++++++++++ Model/Push/DefaultProcessor.php | 6 +++ Model/Push/GroupTransactionPushProcessor.php | 2 +- Model/Push/IdealProcessor.php | 2 +- Model/Push/KlarnaKpProcessor.php | 33 +++++++++++++++ Model/Push/PayPerEmailProcessor.php | 40 +++++++++++++++++++ Model/Push/PaypalProcessor.php | 14 +++++++ Model/Push/PushTransactionType.php | 4 ++ Model/Push/RefundProcessor.php | 37 ++++++++++++++++- Service/LockerProcess.php | 42 ++++++++++---------- Service/Push/OrderRequestService.php | 2 +- 15 files changed, 201 insertions(+), 34 deletions(-) diff --git a/Controller/Payconiq/Process.php b/Controller/Payconiq/Process.php index 045705b0e..4bd03aaab 100644 --- a/Controller/Payconiq/Process.php +++ b/Controller/Payconiq/Process.php @@ -24,6 +24,7 @@ use Buckaroo\Magento2\Exception; use Buckaroo\Magento2\Logging\Log; use Buckaroo\Magento2\Model\BuckarooStatusCode; +use Buckaroo\Magento2\Model\ConfigProvider\Account as AccountConfig; use Buckaroo\Magento2\Model\OrderStatusFactory; use Buckaroo\Magento2\Model\RequestPush\RequestPushFactory; use Buckaroo\Magento2\Model\Service\Order as OrderService; @@ -37,7 +38,6 @@ use Magento\Framework\App\Action\Context; use Magento\Framework\App\ResponseInterface; use Magento\Framework\Event\ManagerInterface; -use Magento\Framework\Exception\LocalizedException; use Magento\Quote\Model\Quote; use Magento\Sales\Api\Data\TransactionInterface; use Magento\Sales\Api\Data\TransactionSearchResultInterface; @@ -96,7 +96,7 @@ public function __construct( Recreate $quoteRecreate, RequestPushFactory $requestPushFactory, SearchCriteriaBuilder $searchCriteriaBuilder, - TransactionRepositoryInterface $transactionRepository, + TransactionRepositoryInterface $transactionRepository ) { parent::__construct($context, $logger, $quote, $accountConfig, $orderRequestService, $orderStatusFactory, $checkoutSession, $customerSession, $customerRepository, @@ -110,10 +110,9 @@ public function __construct( * Redirect Process Payconiq * * @return ResponseInterface|void - * @throws LocalizedException * @throws Exception */ - public function execute(): ResponseInterface + public function execute() { if (!$this->getTransactionKey()) { $this->_forward('defaultNoRoute'); diff --git a/Controller/Redirect/IdinProcess.php b/Controller/Redirect/IdinProcess.php index 23a31a186..e329e6dc4 100644 --- a/Controller/Redirect/IdinProcess.php +++ b/Controller/Redirect/IdinProcess.php @@ -38,6 +38,9 @@ use Magento\Framework\Event\ManagerInterface; use Magento\Quote\Model\Quote; +/** + * @SuppressWarnings(PHPMD.CouplingBetweenObjects) + */ class IdinProcess extends Process { /** @@ -60,6 +63,8 @@ class IdinProcess extends Process * @param Recreate $quoteRecreate * @param RequestPushFactory $requestPushFactory * @param CustomerFactory $customerFactory + * + * @SuppressWarnings(PHPMD.ExcessiveParameterList) */ public function __construct( Context $context, diff --git a/Controller/Redirect/Process.php b/Controller/Redirect/Process.php index 73d18170c..b8453bdde 100644 --- a/Controller/Redirect/Process.php +++ b/Controller/Redirect/Process.php @@ -181,10 +181,10 @@ public function __construct( /** * Process action * - * @return ResponseInterface + * @return ResponseInterface|void * @throws \Exception */ - public function execute(): ResponseInterface + public function execute() { $this->logger->addDebug(__METHOD__ . '|' . var_export($this->redirectRequest->getOriginalRequest(), true)); @@ -438,7 +438,7 @@ protected function redirectSuccess(): ResponseInterface * * @return void */ - public function addSuccessMessage(string|Phrase $message): void + public function addSuccessMessage($message): void { $this->messageManager->addSuccessMessage($message); } diff --git a/Model/ConfigProvider/Method/Applepay.php b/Model/ConfigProvider/Method/Applepay.php index d6e380fe9..492593014 100644 --- a/Model/ConfigProvider/Method/Applepay.php +++ b/Model/ConfigProvider/Method/Applepay.php @@ -71,7 +71,7 @@ public function __construct( AllowedCurrencies $allowedCurrencies, PaymentFee $paymentFeeHelper, StoreManagerInterface $storeManager, - Resolver $localeResolver, + Resolver $localeResolver ) { parent::__construct($assetRepo, $scopeConfig, $allowedCurrencies, $paymentFeeHelper); diff --git a/Model/Push/AfterpayProcessor.php b/Model/Push/AfterpayProcessor.php index 996330a4b..f03576c30 100644 --- a/Model/Push/AfterpayProcessor.php +++ b/Model/Push/AfterpayProcessor.php @@ -1,4 +1,23 @@ dirList->getPath('tmp') . DIRECTORY_SEPARATOR . 'bk_push_ppe_' . sha1($lockName); } - - /** - * Determine if the lock push processing criteria are met. - * - * @return bool - */ - private function lockPushProcessingCriteria(): bool - { - $statusCodeSuccess = $this->helper->getStatusCode('BUCKAROO_MAGENTO2_STATUSCODE_SUCCESS'); - if (!empty($this->pushRequst->getAdditionalInformation('frompayperemail')) - || ( - ($this->pushRequst->hasPostData('statuscode', $statusCodeSuccess)) - && $this->pushRequst->hasPostData('transaction_method', 'ideal') - && $this->pushRequst->hasPostData('transaction_type', self::BUCK_PUSH_IDEAL_PAY) - ) - ) { - return true; - } else { - return false; - } - } } \ No newline at end of file diff --git a/Service/Push/OrderRequestService.php b/Service/Push/OrderRequestService.php index c09bd8137..5cf177f0a 100644 --- a/Service/Push/OrderRequestService.php +++ b/Service/Push/OrderRequestService.php @@ -97,7 +97,7 @@ public function __construct( * @return Order|OrderPayment * @throws \Exception */ - public function getOrderByRequest(?PushRequestInterface $pushRequest = null): Order|OrderPayment + public function getOrderByRequest(?PushRequestInterface $pushRequest = null) { if ($this->order->getId()) { return $this->order; From b70fae14ca1838d93777fb4f0e526a8d89386908 Mon Sep 17 00:00:00 2001 From: Lucian Turiac Date: Tue, 15 Aug 2023 18:54:44 +0300 Subject: [PATCH 27/29] BP-2132 - BP-2813 - fix PHP_MD --- Controller/Payconiq/Process.php | 2 +- Controller/Redirect/Process.php | 2 +- Gateway/Request/SaveIssuerDataBuilder.php | 2 +- Model/Push/DefaultProcessor.php | 2 +- Model/Push/GroupTransactionPushProcessor.php | 22 ++++++++++++++++++++ Model/Push/IdealProcessor.php | 17 +++++++++++++++ Service/Push/OrderRequestService.php | 2 +- 7 files changed, 44 insertions(+), 5 deletions(-) diff --git a/Controller/Payconiq/Process.php b/Controller/Payconiq/Process.php index 4bd03aaab..7f30f77d7 100644 --- a/Controller/Payconiq/Process.php +++ b/Controller/Payconiq/Process.php @@ -171,7 +171,7 @@ protected function getTransactionKey() * @return TransactionInterface|Transaction|null * @throws Exception */ - protected function getTransaction(): TransactionInterface|Transaction|null + protected function getTransaction() { if ($this->transaction != null) { return $this->transaction; diff --git a/Controller/Redirect/Process.php b/Controller/Redirect/Process.php index 40131df4c..44a12fe04 100644 --- a/Controller/Redirect/Process.php +++ b/Controller/Redirect/Process.php @@ -521,7 +521,7 @@ private function processPendingRedirect($statusCode): ResponseInterface * * @return void */ - public function addErrorMessage(string|Phrase $message): void + public function addErrorMessage(string $message): void { $this->messageManager->addErrorMessage($message); } diff --git a/Gateway/Request/SaveIssuerDataBuilder.php b/Gateway/Request/SaveIssuerDataBuilder.php index 738e903ad..9d2544776 100644 --- a/Gateway/Request/SaveIssuerDataBuilder.php +++ b/Gateway/Request/SaveIssuerDataBuilder.php @@ -63,7 +63,7 @@ public function build(array $buildSubject): array * * @return void */ - public function saveLastUsedIssuer(OrderPaymentInterface|InfoInterface $payment): void + public function saveLastUsedIssuer($payment): void { /** @var Order $order */ $order = $payment->getOrder(); diff --git a/Model/Push/DefaultProcessor.php b/Model/Push/DefaultProcessor.php index ab4b0d877..50f242a71 100644 --- a/Model/Push/DefaultProcessor.php +++ b/Model/Push/DefaultProcessor.php @@ -51,7 +51,7 @@ /** * @SuppressWarnings(PHPMD.CouplingBetweenObjects) - * @SuppressWarnings(PHPMD.CyclomaticComplexity) + * @SuppressWarnings(PHPMD.ExcessiveClassComplexity) */ class DefaultProcessor implements PushProcessorInterface { diff --git a/Model/Push/GroupTransactionPushProcessor.php b/Model/Push/GroupTransactionPushProcessor.php index 6d86bd81f..5661a9779 100644 --- a/Model/Push/GroupTransactionPushProcessor.php +++ b/Model/Push/GroupTransactionPushProcessor.php @@ -1,4 +1,23 @@ Date: Tue, 15 Aug 2023 18:58:42 +0300 Subject: [PATCH 28/29] BP-2132 - BP-2813 - fix PHP_MD --- Controller/Payconiq/Process.php | 2 ++ Controller/Redirect/Process.php | 5 ++++- 2 files changed, 6 insertions(+), 1 deletion(-) diff --git a/Controller/Payconiq/Process.php b/Controller/Payconiq/Process.php index 7f30f77d7..9fcc965d5 100644 --- a/Controller/Payconiq/Process.php +++ b/Controller/Payconiq/Process.php @@ -80,6 +80,8 @@ class Process extends \Buckaroo\Magento2\Controller\Redirect\Process * @param RequestPushFactory $requestPushFactory * @param SearchCriteriaBuilder $searchCriteriaBuilder * @param TransactionRepositoryInterface $transactionRepository + * + * @SuppressWarnings(PHPMD.ExcessiveParameterList) */ public function __construct( Context $context, diff --git a/Controller/Redirect/Process.php b/Controller/Redirect/Process.php index 44a12fe04..f5e4f8f4c 100644 --- a/Controller/Redirect/Process.php +++ b/Controller/Redirect/Process.php @@ -48,6 +48,9 @@ use Magento\Sales\Api\Data\OrderPaymentInterface; use Magento\Sales\Model\Order; +/** + * @SuppressWarnings(PHPMD.CouplingBetweenObjects) + */ class Process extends Action { private const GENERAL_ERROR_MESSAGE = 'Unfortunately an error occurred while processing your payment. ' . @@ -521,7 +524,7 @@ private function processPendingRedirect($statusCode): ResponseInterface * * @return void */ - public function addErrorMessage(string $message): void + public function addErrorMessage($message): void { $this->messageManager->addErrorMessage($message); } From f73ec9e6ccc94e6c7f4086323d3b1df95e0349c6 Mon Sep 17 00:00:00 2001 From: Lucian Turiac Date: Wed, 16 Aug 2023 13:36:12 +0300 Subject: [PATCH 29/29] BP-2132 - BP-2813 - code review --- Model/Push/PushProcessorsFactory.php | 7 +++- Model/Push/RefundProcessor.php | 61 +++++++++++++--------------- 2 files changed, 34 insertions(+), 34 deletions(-) diff --git a/Model/Push/PushProcessorsFactory.php b/Model/Push/PushProcessorsFactory.php index cb3f0778c..c5f03b23b 100644 --- a/Model/Push/PushProcessorsFactory.php +++ b/Model/Push/PushProcessorsFactory.php @@ -108,8 +108,9 @@ private function getPushProcessorClass(?PushTransactionType $pushTransactionType // Set Push Processor by Payment Method $paymentMethod = $pushTransactionType->getPaymentMethod(); $pushProcessorClass = $this->pushProcessors[$paymentMethod] ?? $pushProcessorClass; + if ($pushTransactionType->isFromPayPerEmail()) { - return $this->pushProcessors['group_transaction']; + return $this->pushProcessors['payperemail']; } // Check if is Group Transaction Push @@ -121,7 +122,9 @@ private function getPushProcessorClass(?PushTransactionType $pushTransactionType $pushType = $pushTransactionType->getPushType(); if ($pushType == PushTransactionType::BUCK_PUSH_TYPE_INVOICE) { return $this->pushProcessors['credit_managment']; - } elseif ($pushType == PushTransactionType::BUCK_PUSH_TYPE_INVOICE_INCOMPLETE) { + } + + if ($pushType == PushTransactionType::BUCK_PUSH_TYPE_INVOICE_INCOMPLETE) { throw new BuckarooException( __('Skipped handling this invoice push because it is too soon.') ); diff --git a/Model/Push/RefundProcessor.php b/Model/Push/RefundProcessor.php index 73292f1f8..ccf34a2a6 100644 --- a/Model/Push/RefundProcessor.php +++ b/Model/Push/RefundProcessor.php @@ -21,7 +21,6 @@ namespace Buckaroo\Magento2\Model\Push; -use Buckaroo\Magento2\Api\PushProcessorInterface; use Buckaroo\Magento2\Api\PushRequestInterface; use Buckaroo\Magento2\Exception as BuckarooException; use Buckaroo\Magento2\Helper\Data; @@ -31,7 +30,6 @@ use Buckaroo\Magento2\Model\ConfigProvider\Account; use Buckaroo\Magento2\Model\OrderStatusFactory; use Buckaroo\Magento2\Model\Refund\Push as RefundPush; -use Buckaroo\Magento2\Model\Validator\Push as ValidatorPush; use Buckaroo\Magento2\Service\Push\OrderRequestService; use Magento\Sales\Api\Data\TransactionInterface; @@ -74,7 +72,6 @@ public function __construct( parent::__construct($orderRequestService, $pushTransactionType, $logging, $helper, $transaction, $groupTransaction, $buckarooStatusCode,$orderStatusFactory, $configAccount); $this->refundPush = $refundPush; - } /** @@ -91,22 +88,20 @@ public function processPush(PushRequestInterface $pushRequest): bool return true; } - if ($this->pushTransactionType->getStatusKey() !== 'BUCKAROO_MAGENTO2_STATUSCODE_SUCCESS' - && !$this->order->hasInvoices() - ) { - throw new BuckarooException( - __('Refund failed ! Status : %1 and the order does not contain an invoice', - $this->pushTransactionType->getStatusKey()) - ); - } elseif ($this->pushTransactionType->getStatusKey() !== 'BUCKAROO_MAGENTO2_STATUSCODE_SUCCESS' - && $this->order->hasInvoices() - ) { - //don't proceed failed refund push - $this->logging->addDebug(__METHOD__ . '|10|'); - $this->orderRequestService->setOrderNotificationNote( - __('Push notification for refund has no success status, ignoring.') - ); - return true; + if ($this->pushTransactionType->getStatusKey() !== 'BUCKAROO_MAGENTO2_STATUSCODE_SUCCESS') { + if ($this->order->hasInvoices()) { + //don't proceed failed refund push + $this->logging->addDebug(__METHOD__ . '|10|'); + $this->orderRequestService->setOrderNotificationNote( + __('Push notification for refund has no success status, ignoring.') + ); + return true; + } else { + throw new BuckarooException( + __('Refund failed ! Status : %1 and the order does not contain an invoice', + $this->pushTransactionType->getStatusKey()) + ); + } } return $this->refundPush->receiveRefundPush($this->pushRequest, true, $this->order); @@ -121,22 +116,24 @@ public function processPush(PushRequestInterface $pushRequest): bool */ private function skipPendingRefundPush(PushRequestInterface $pushRequest): bool { - if ($pushRequest->hasAdditionalInformation('initiated_by_magento', 1) - && $pushRequest->hasAdditionalInformation('service_action_from_magento', ['refund']) + if (!$pushRequest->hasAdditionalInformation('initiated_by_magento', 1) + || !$pushRequest->hasAdditionalInformation('service_action_from_magento', ['refund']) ) { - if ($pushRequest->hasPostData('statuscode', BuckarooStatusCode::SUCCESS) - && !empty($pushRequest->getRelatedtransactionRefund()) - && $this->receivePushCheckDuplicates( - BuckarooStatusCode::PENDING_APPROVAL, - $pushRequest->getRelatedtransactionRefund() - )) { - $this->logging->addDebug(__METHOD__ . '|4|'); - return false; - } $this->logging->addDebug(__METHOD__ . '|5|'); - return true; + return false; } - return false; + if ($pushRequest->hasPostData('statuscode', BuckarooStatusCode::SUCCESS) + && !empty($pushRequest->getRelatedtransactionRefund()) + && $this->receivePushCheckDuplicates( + BuckarooStatusCode::PENDING_APPROVAL, + $pushRequest->getRelatedtransactionRefund() + )) { + $this->logging->addDebug(__METHOD__ . '|4|'); + return false; + } + + + return true; } } \ No newline at end of file