diff --git a/Api/PushProcessorInterface.php b/Api/PushProcessorInterface.php
new file mode 100644
index 000000000..5b7b0fcdc
--- /dev/null
+++ b/Api/PushProcessorInterface.php
@@ -0,0 +1,12 @@
+searchCriteriaBuilder = $searchCriteriaBuilder;
$this->transactionRepository = $transactionRepository;
@@ -151,7 +112,6 @@ public function __construct(
* Redirect Process Payconiq
*
* @return ResponseInterface|void
- * @throws LocalizedException
* @throws Exception
*/
public function execute()
@@ -162,7 +122,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.');
@@ -173,7 +133,7 @@ public function execute()
'checkout',
[
'_fragment' => 'payment',
- '_query' => ['bk_e' => 1]
+ '_query' => ['bk_e' => 1]
]
);
}
@@ -181,9 +141,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
}
@@ -212,7 +170,7 @@ protected function getTransactionKey()
/**
* Get transaction object
*
- * @return TransactionInterface|Transaction
+ * @return TransactionInterface|Transaction|null
* @throws Exception
*/
protected function getTransaction()
@@ -239,7 +197,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
new file mode 100644
index 000000000..e329e6dc4
--- /dev/null
+++ b/Controller/Redirect/IdinProcess.php
@@ -0,0 +1,168 @@
+customerResourceFactory = $customerFactory;
+ }
+
+ /**
+ * @return ResponseInterface|void
+ * @throws \Buckaroo\Magento2\Exception
+ */
+ public function execute(): ResponseInterface
+ {
+ // Initialize the order, quote, payment
+ 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(): bool
+ {
+ if (!empty($this->redirectRequest->getServiceIdinConsumerbin())
+ && !empty($this->redirectRequest->getServiceIdinIseighteenorolder())
+ && $this->redirectRequest->getServiceIdinIseighteenorolder() == 'True'
+ ) {
+ $this->checkoutSession->setCustomerIDIN($this->redirectRequest->getServiceIdinConsumerbin());
+ $this->checkoutSession->setCustomerIDINIsEighteenOrOlder(true);
+ $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');
+ }
+ return true;
+ }
+ 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 e901554e8..f5e4f8f4c 100644
--- a/Controller/Redirect/Process.php
+++ b/Controller/Redirect/Process.php
@@ -17,209 +17,157 @@
* @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\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\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\Api\Data\TransactionInterface;
use Magento\Sales\Model\Order;
-use Magento\Sales\Model\Order\Email\Sender\OrderSender;
/**
* @SuppressWarnings(PHPMD.CouplingBetweenObjects)
- * @SuppressWarnings(PHPMD.TooManyFields)
*/
class Process extends Action
{
- /**
- * @var CustomerSession
- */
- public $customerSession;
-
- /**
- * @var array
- */
- protected $response;
-
+ 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
*/
- protected $order;
+ protected Order $order;
/**
* @var Quote $quote
*/
- protected $quote;
-
- /**
- * @var Data $helper
- */
- protected $helper;
+ protected Quote $quote;
/**
- * @var Cart
+ * @var OrderPaymentInterface|null
*/
- protected $cart;
+ protected ?OrderPaymentInterface $payment;
/**
- * @var ConfigProviderInterface
+ * @var AccountConfig
*/
- protected $accountConfig;
+ protected AccountConfig $accountConfig;
/**
- * @var OrderSender
+ * @var OrderRequestService
*/
- protected $orderSender;
+ protected OrderRequestService $orderRequestService;
/**
* @var OrderStatusFactory
*/
- protected $orderStatusFactory;
+ protected OrderStatusFactory $orderStatusFactory;
/**
* @var Log
*/
- protected $logger;
+ protected Log $logger;
/**
* @var CheckoutSession
*/
- protected $checkoutSession;
-
- /**
- * @var CustomerRepositoryInterface
- */
- protected $customerRepository;
+ protected CheckoutSession $checkoutSession;
/**
- * @var SessionFactory
- */
- protected $_sessionFactory;
-
- /**
- * @var Customer
+ * @var CustomerSession
*/
- protected $customerModel;
+ protected CustomerSession $customerSession;
/**
- * @var CustomerFactory
+ * @var CustomerRepositoryInterface
*/
- protected $customerResourceFactory;
+ protected CustomerRepositoryInterface $customerRepository;
/**
* @var OrderService
*/
- protected $orderService;
-
- /**
- * @var TransactionInterface
- */
- private $transaction;
+ protected OrderService $orderService;
/**
* @var ManagerInterface
*/
- protected $eventManager;
+ protected ManagerInterface $eventManager;
/**
* @var Recreate
*/
- private $quoteRecreate;
+ protected Recreate $quoteRecreate;
/**
* @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,
Recreate $quoteRecreate,
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,199 +177,54 @@ public function __construct(
$request->getHeaders()->addHeaderLine('X_REQUESTED_WITH', 'XMLHttpRequest');
}
}
- $this->pushRequst = $requestPushFactory->create();
// @codingStandardsIgnoreEnd
+ $this->redirectRequest = $requestPushFactory->create();
}
/**
* Process action
*
- * @return ResponseInterface
+ * @return ResponseInterface|void
* @throws \Exception
- *
- *
- * @SuppressWarnings(PHPMD.ExcessiveMethodLength)
- * @SuppressWarnings(PHPMD.CyclomaticComplexity)
- * @SuppressWarnings(PHPMD.NPathComplexity)
*/
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);
+ $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();
-
- if ($payment) {
- $this->setPaymentOutOfTransit($payment);
+ $this->payment = $this->order->getPayment();
+ if ($this->payment) {
+ $this->setPaymentOutOfTransit($this->payment);
}
- if (!method_exists($payment->getMethodInstance(), 'canProcessPostData')) {
- return $this->handleProcessedResponse('/');
- }
+ $this->checkoutSession->setRestoreQuoteLastOrder(false);
- if (!$payment->getMethodInstance()->canProcessPostData($payment, $this->pushRequst)) {
+ if ($this->skipWaitingOnConsumerForProcessingOrder()) {
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'))
+ if (($this->payment->getMethodInstance()->getCode() == 'buckaroo_magento2_paypal')
+ && ($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'):
- $debugInfo = [
- $this->order->getStatus(),
- $this->orderStatusFactory->get(
- $this->helper->getStatusCode('BUCKAROO_MAGENTO2_STATUSCODE_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')) {
- //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'),
- $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->pushRequst->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->pushRequst->hasPostData('primary_service', 'KlarnaKp')
- && $this->pushRequst->hasAdditionalInformation('service_action_from_magento', 'reserve')
- && !empty($this->pushRequst->getServiceKlarnakpReservationnumber()));
-
- if (!($this->pushRequst->hasAdditionalInformation('initiated_by_magento', 1)
- && $isKlarnaKpReserve)
- ) {
- if ($statusCode == $this->helper->getStatusCode('BUCKAROO_MAGENTO2_STATUSCODE_SUCCESS')) {
- $this->logger->addDebug(__METHOD__ . '|sendemail|');
- $this->orderSender->send($this->order, true);
- }
- }
- }
-
- $pendingCode = $this->helper->getStatusCode('BUCKAROO_MAGENTO2_STATUSCODE_PENDING_PROCESSING');
- if (($statusCode == $pendingCode)
- && !$this->pushRequst->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->removeCoupon();
- $this->removeAmastyGiftcardOnFailed();
-
- return $this->handleProcessedResponse('/');
- }
-
- $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 $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'):
- return $this->handleFailed($statusCode);
- //no default
- }
-
- $this->logger->addDebug(__METHOD__ . '|9|');
- return $this->_response;
+ return $this->processRedirectByStatus($statusCode);
}
/**
@@ -432,170 +235,298 @@ public function execute()
*
* @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);
}
/**
- * Set consumer bin IDIN on customer
+ * 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
*/
- private function setCustomerIDIN()
+ public function skipWaitingOnConsumerForProcessingOrder(): bool
{
- 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');
+ 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 true;
}
+
return false;
}
/**
- * Add success message to be displayed to the user
- *
- * @param string $message
+ * Processes a redirect based on the given status code.
*
- * @return void
+ * @param int $statusCode
+ * @return ResponseInterface
+ * @throws LocalizedException
+ * @throws NoSuchEntityException
*/
- public function addSuccessMessage(string $message)
+ private function processRedirectByStatus(int $statusCode): ResponseInterface
{
- $this->messageManager->addSuccessMessage($message);
+ 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);
+ }
+
+ return $this->_response;
}
/**
- * Add error message to be displayed to the user
+ * Processes a successful redirect based on the given status code.
*
- * @param string $message
+ * - Sends a Klarna KP order confirmation using the status code.
+ * - Sets the last quote and order.
+ * - Returns a successful redirect response.
*
- * @return void
+ * @param $statusCode
+ * @return ResponseInterface
+ * @throws \Exception
*/
- public function addErrorMessage(string $message)
+ private function processSucceededRedirect($statusCode): ResponseInterface
{
- $this->messageManager->addErrorMessage($message);
+ $this->sendKlarnaKpOrderConfirmation($statusCode);
+ $this->setLastQuoteOrder();
+
+ return $this->redirectSuccess();
}
/**
- * Create redirect response
+ * Sends a Klarna KP order confirmation based on the given status code.
*
- * @return ResponseInterface
+ * - 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.
*/
- protected function redirectToCheckout()
+ private function sendKlarnaKpOrderConfirmation(int $statusCode): void
{
- $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);
+ $paymentMethod = $this->payment->getMethodInstance();
+ $store = $this->order->getStore();
- 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->pushRequst->hasPostData('primary_service', 'IDIN')) {
- $this->checkoutSession->restoreQuote();
- }
- } catch (\Exception $e) {
- $this->logger->addError('Could not load customer');
- }
+ 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
+ && $statusCode == BuckarooStatusCode::SUCCESS)
+ ) {
+ $this->logger->addDebug(__METHOD__ . '|sendemail|');
+ $this->orderRequestService->sendOrderEmail($this->order, true);
}
}
- $this->logger->addDebug('ready for redirect');
- return $this->handleProcessedResponse('checkout', ['_query' => ['bk_e' => 1]]);
}
/**
- * Load order by invoice number, order number or by transaction key
+ * 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.
*
- * @throws Exception
+ * @return void
*/
- private function loadOrder()
+ private function setLastQuoteOrder(): void
{
- $brqOrderId = false;
-
- if (!empty($this->pushRequst->getInvoiceNumber())) {
- $brqOrderId = $this->pushRequst->getInvoiceNumber();
+ $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 (!empty($this->pushRequst->getOrderNumber())) {
- $brqOrderId = $this->pushRequst->getOrderNumber();
+ if (!$this->checkoutSession->getLastQuoteId() && $this->order->getQuoteId()) {
+ $this->logger->addDebug(__METHOD__ . '|53|');
+ $this->checkoutSession->setLastQuoteId($this->order->getQuoteId());
}
-
- $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();
+ 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());
}
}
/**
- * Get order by transaction key
+ * Redirect to Success url, which means everything seems to be going fine
*
- * @return \Magento\Sales\Model\Order\Payment
- * @throws Exception
+ * @return ResponseInterface
*/
- private function getOrderByTransactionKey()
+ protected function redirectSuccess(): ResponseInterface
{
- $trxId = '';
+ $this->logger->addDebug(__METHOD__ . '|1|');
- if (!empty($this->pushRequst->getTransactions())) {
- $trxId = $this->pushRequst->getTransactions();
- }
+ $this->eventManager->dispatch('buckaroo_process_redirect_success_before');
- if (!empty($this->pushRequst->getDatarequest())) {
- $trxId = $this->pushRequst->getDatarequest();
- }
+ $store = $this->order->getStore();
+
+ /**
+ * @noinspection PhpUndefinedMethodInspection
+ */
+ $url = $this->accountConfig->getSuccessRedirect($store);
- $this->transaction->load($trxId, 'txn_id');
- $order = $this->transaction->getOrder();
+ $this->addSuccessMessage(__('Your order has been placed successfully.'));
- if (!$order) {
- throw new Exception(__('There was no order found by transaction Id'));
- }
+ $this->quote->setReservedOrderId(null);
+
+ $this->redirectSuccessApplePay();
- return $order;
+ $this->logger->addDebug(__METHOD__ . '|2|' . var_export($url, true));
+
+ return $this->handleProcessedResponse($url);
}
/**
- * Get order
+ * Add success message to be displayed to the user
*
- * @return \Magento\Sales\Api\Data\OrderInterface
+ * @param string|Phrase $message
+ *
+ * @return void
*/
- public function getOrder()
+ public function addSuccessMessage($message): void
{
- return $this->order;
+ $this->messageManager->addSuccessMessage($message);
}
/**
- * Set flag if user is on the payment provider page
+ * Redirect if the transaction is of the success Apple Pay type
*
- * @param OrderPaymentInterface $payment
* @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());
+ }
+ }
+
+ /**
+ * 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 setPaymentOutOfTransit(OrderPaymentInterface $payment)
+ private function processPendingRedirect($statusCode): ResponseInterface
{
- $payment->setAdditionalInformation(BuckarooAdapter::BUCKAROO_PAYMENT_IN_TRANSIT, false)->save();
+ 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->sendKlarnaKpOrderConfirmation($statusCode);
+
+ if (!$this->redirectRequest->hasPostData('payment_method', 'sofortueberweisung')) {
+ $this->addErrorMessage(
+ __(self::GENERAL_ERROR_MESSAGE)
+ );
+ $this->logger->addDebug(__METHOD__ . '|5|');
+
+ $this->removeCoupon();
+ $this->removeAmastyGiftcardOnFailed();
+
+ return $this->handleProcessedResponse('/');
+ }
+
+ $this->setLastQuoteOrder();
+
+ return $this->redirectSuccess();
+ }
+
+ /**
+ * Add error message to be displayed to the user
+ *
+ * @param string|Phrase $message
+ *
+ * @return void
+ */
+ public function addErrorMessage($message): void
+ {
+ $this->messageManager->addErrorMessage($message);
}
/**
@@ -603,7 +534,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(
@@ -632,79 +563,19 @@ 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);
-
- if (!empty($this->pushRequst->getPaymentMethod())
- &&
- ($this->pushRequst->getPaymentMethod() == 'applepay')
- &&
- !empty($this->pushRequst->getStatusCode())
- &&
- ($this->pushRequst->getStatusCode() == '190')
- &&
- !empty($this->pushRequst->getTest())
- &&
- ($this->pushRequst->getTest() == 'true')
- ) {
- $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()
- {
- $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
*
* @param int|null $statusCode
* @return ResponseInterface
- * @throws \Magento\Framework\Exception\NoSuchEntityException
+ * @throws \Magento\Framework\Exception\NoSuchEntityException|\Exception
*/
- protected function handleFailed($statusCode)
+ protected function handleFailed($statusCode): ResponseInterface
{
$this->logger->addDebug(__METHOD__ . '|7|');
$this->eventManager->dispatch('buckaroo_process_handle_failed_before');
- $this->removeCoupon();
$this->removeAmastyGiftcardOnFailed();
if (!$this->getSkipHandleFailedRecreate()
@@ -718,37 +589,17 @@ 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[$this->helper->getStatusCode('BUCKAROO_MAGENTO2_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')] =
- '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')] =
- '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')
- ] = '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->pushRequst->getAdditionalInformation('frompayperemail'))) {
+ if (!empty($this->redirectRequest->getAdditionalInformation('frompayperemail'))) {
return $this->redirectFailure();
}
if (!$this->cancelOrder($statusCode)) {
$this->logger->addError('Could not cancel the order.');
}
+
$this->logger->addDebug(__METHOD__ . '|8|');
return $this->redirectFailure();
}
@@ -763,39 +614,40 @@ 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');
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();
}
/**
@@ -806,6 +658,47 @@ protected function redirectFailure()
return $this->handleProcessedResponse($url);
}
+ /**
+ * 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)) {
+ $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
*
@@ -821,12 +714,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;
+ }
+
/**
* Remove coupon from failed order if magento enterprise
*
@@ -860,6 +764,37 @@ protected function removeCoupon()
*/
public function getResponseParameters()
{
- return $this->pushRequst->getData();
+ return $this->redirectRequest->getData();
+ }
+
+ /**
+ * Create redirect response
+ *
+ * @return ResponseInterface
+ */
+ protected function redirectToCheckout(): 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');
+ }
+ }
+ }
+ $this->logger->addDebug('ready for redirect');
+ return $this->handleProcessedResponse('checkout', ['_query' => ['bk_e' => 1]]);
}
}
diff --git a/Gateway/Request/IdinDataBuilder.php b/Gateway/Request/IdinDataBuilder.php
index 3fb085f15..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/process') . '?form_key=' . $this->getFormKey();
+ $url = $url->getRouteUrl('buckaroo/redirect/idinProcess') . '?form_key=' . $this->getFormKey();
$this->setReturnUrl($url);
}
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/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/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/BuckarooStatusCode.php b/Model/BuckarooStatusCode.php
new file mode 100644
index 000000000..91d04fa14
--- /dev/null
+++ b/Model/BuckarooStatusCode.php
@@ -0,0 +1,133 @@
+ '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
+ {
+ $statusKey = array_search($responseCode, $this->statusCodes);
+ return $statusKey ?: '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/ConfigProvider/Method/Applepay.php b/Model/ConfigProvider/Method/Applepay.php
index 717da9770..a3f1fe773 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/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/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
*
diff --git a/Model/OrderStatusFactory.php b/Model/OrderStatusFactory.php
index 7c9c0e9f2..f4e484205 100644
--- a/Model/OrderStatusFactory.php
+++ b/Model/OrderStatusFactory.php
@@ -81,12 +81,7 @@ public function get($statusCode, Order $order)
* @var BuckarooAdapter $paymentMethodInstance
*/
$paymentMethodInstance = $order->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 a3d494557..b78f941b4 100644
--- a/Model/Push.php
+++ b/Model/Push.php
@@ -17,2292 +17,95 @@
* @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\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\Refund\Push as RefundPush;
+use Buckaroo\Magento2\Model\Push\PushProcessorsFactory;
+use Buckaroo\Magento2\Model\Push\PushTransactionType;
use Buckaroo\Magento2\Model\RequestPush\RequestPushFactory;
-use Buckaroo\Magento2\Model\Validator\Push as ValidatorPush;
-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;
+use Buckaroo\Magento2\Service\Push\OrderRequestService;
-/**
- * @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;
+ public Log $logging;
/**
- * @var Klarnakp
+ * @var PushRequestInterface
*/
- private $klarnakpConfig;
+ public PushRequestInterface $pushRequst;
/**
- * @var Afterpay20
+ * @var PushProcessorsFactory
*/
- private $afterpayConfig;
+ private PushProcessorsFactory $pushProcessorsFactory;
/**
- * @var File
+ * @var OrderRequestService
*/
- private $fileSystemDriver;
+ private OrderRequestService $orderRequestService;
/**
- * @var PushRequestInterface
+ * @var PushTransactionType
*/
- public PushRequestInterface $pushRequst;
+ 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
- * @SuppressWarnings(PHPMD.ExcessiveParameterList)
+ * @param PushProcessorsFactory $pushProcessorsFactory
+ * @param OrderRequestService $orderRequestService
+ * @param PushTransactionType $pushTransactionType
*/
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
+ 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;
+ $this->pushTransactionType = $pushTransactionType;
}
/**
* @inheritdoc
*
- * @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)
+ * @return bool
+ * @throws BuckarooException
*/
- public function receivePush()
+ public function receivePush(): bool
{
- //Start debug mailing/logging with the postdata.
+ // Log the push request
$this->logging->addDebug(__METHOD__ . '|1|' . var_export($this->pushRequst->getOriginalRequest(), true));
- $this->logging->addDebug(__METHOD__ . '|1_2|');
- $lockHandler = $this->lockPushProcessing();
- $this->logging->addDebug(__METHOD__ . '|1_3|');
-
- if ($this->isFailedGroupTransaction()) {
- $this->handleGroupTransactionFailed();
- return true;
- }
-
- if ($this->isGroupTransactionInfo()) {
- if($this->isCanceledGroupTransaction()) {
- $this->cancelGroupTransactionOrder();
- return true;
- }
- if ($this->isGroupTransactionFailed()) {
- $this->savePartGroupTransaction();
- } else {
- return true;
- }
- }
-
- $this->loadOrder();
-
- $this->logging->addDebug(__METHOD__ . '|6668| ' . var_export([
- 'orderState' => $this->order->getState(),
- 'orderStatus' => $this->order->getStatus(),
- 'orderId' => $this->order->getIncrementId()
- ], true));
-
- if ($this->skipHandlingForFailedGroupTransactions()) {
- return true;
- }
-
- if (!$this->isPushNeeded()) {
- return true;
- }
+ // Load Order
+ $order = $this->orderRequestService->getOrderByRequest($this->pushRequst);
- $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.
+ // Validate Signature
+ $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())) {
- $this->logging->addDebug(__METHOD__ . '|665| STATE_PROCESSING');
- $this->logging->addDebug(__METHOD__ . '|666| ' . var_export([
- 'orderState' => $this->order->getState(),
- 'orderStatus' => $this->order->getStatus(),
- 'orderId' => $this->order->getIncrementId(),
- 'frompayperemail' => $this->pushRequst->getAdditionalInformation('frompayperemail'),
- 'getPartialpayment' => $this->pushRequst->getRelatedtransactionPartialpayment(),
- 'statuscode' => $this->pushRequst->getStatusCode()
- ], true));
- if ($this->order->getState() === Order::STATE_NEW
- && empty($this->pushRequst->getAdditionalInformation('frompayperemail'))
- && !$this->pushRequst->hasPostData('brq_transaction_method', 'transfer')
- && empty($this->pushRequst->getRelatedtransactionPartialpayment())
- && $this->pushRequst->hasPostData('statuscode', $statusCodeSuccess)
- ) {
- $this->logging->addDebug(__METHOD__ . '|666| STATE_PROCESSING');
-
- $this->order->setState(Order::STATE_PROCESSING);
- $this->order->addStatusHistoryComment(
- $this->pushRequst->getStatusmessage(),
- $this->helper->getOrderStatusByState($this->order, Order::STATE_PROCESSING)
- );
- } else {
- $this->logging->addDebug(__METHOD__ . '|667| STATE_PROCESSING');
- $this->order->addStatusHistoryComment($this->pushRequst->getStatusmessage());
- }
- $this->logging->addDebug(__METHOD__ . '|668| STATE_PROCESSING');
- }
-
- 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 = $this->helper->getStatusCode('BUCKAROO_MAGENTO2_STATUSCODE_SUCCESS');
- if ($this->pushRequst->hasPostData('statuscode', $statusCodeSuccess)
- && !empty($this->pushRequst->getRelatedtransactionRefund())
- ) {
- if ($this->receivePushCheckDuplicates(
- $this->helper->getStatusCode('BUCKAROO_MAGENTO2_STATUSCODE_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 \Buckaroo\Magento2\Model\ConfigProvider\Method\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
- */
- 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';
- }
-
- 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);
+ // Get Push Transaction Type
+ $pushTransactionType = $this->pushTransactionType->getPushTransactionType($this->pushRequst, $order);
- 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;
- }
-
- /**
- * 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 Phrase|string $message
- * @throws \Exception
- */
- protected function setOrderNotificationNote(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.
- *
- * @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
- */
- 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
- */
- 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->hasPostData(
- 'brq_transaction_type',
- self::BUCK_PUSH_GROUPTRANSACTION_TYPE
- ) &&
- $this->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/Model/Push/AfterpayProcessor.php b/Model/Push/AfterpayProcessor.php
new file mode 100644
index 000000000..f03576c30
--- /dev/null
+++ b/Model/Push/AfterpayProcessor.php
@@ -0,0 +1,90 @@
+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->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/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/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
new file mode 100644
index 000000000..50f242a71
--- /dev/null
+++ b/Model/Push/DefaultProcessor.php
@@ -0,0 +1,1052 @@
+pushTransactionType = $pushTransactionType;
+ $this->orderRequestService = $orderRequestService;
+ $this->logging = $logging;
+ $this->helper = $helper;
+ $this->transaction = $transaction;
+ $this->groupTransaction = $groupTransaction;
+ $this->buckarooStatusCode = $buckarooStatusCode;
+ $this->orderStatusFactory = $orderStatusFactory;
+ $this->configAccount = $configAccount;
+ }
+
+ /**
+ * @throws BuckarooException
+ * @throws FileSystemException
+ * @throws \Exception
+ */
+ public function processPush(PushRequestInterface $pushRequest): bool
+ {
+ $this->initializeFields($pushRequest);
+
+ // Skip Push
+ if ($this->skipPush()) {
+ return true;
+ }
+
+ // Check Push Dublicates
+ if ($this->receivePushCheckDuplicates()) {
+ throw new BuckarooException(__('Skipped handling this push, duplicate'));
+ }
+
+ // 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->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;
+ }
+
+ /**
+ * @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();
+ }
+
+ /**
+ * Skip the push if the conditions are met.
+ *
+ * @return bool
+ * @throws \Exception
+ */
+ protected function skipPush(): bool
+ {
+ // 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;
+ }
+
+ /**
+ * @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;
+ }
+
+ /**
+ * Check if it is needed to handle the push message based on postdata
+ *
+ * @return bool
+ * @throws \Exception
+ *
+ * @SuppressWarnings(PHPMD.CyclomaticComplexity)
+ */
+ protected 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;
+ }
+
+ /**
+ * 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;
+ }
+
+ 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)
+ */
+ protected function receivePushCheckDuplicates(int $receivedStatusCode = null, string $trxId = null): bool
+ {
+ $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();
+ }
+
+ $ignoredPaymentMethods = [
+ Giftcards::CODE,
+ Transfer::CODE
+ ];
+ if ($this->payment
+ && $this->payment->getMethod()
+ && $receivedStatusCode
+ && ($this->pushTransactionType->getPushType() == PushTransactionType::BUCK_PUSH_TYPE_TRANSACTION)
+ && (!in_array($this->payment->getMethod(), $ignoredPaymentMethods))
+ ) {
+ $this->logging->addDebug(__METHOD__ . '|5|');
+
+ $receivedTrxStatuses = $this->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);
+ if (($this->order->getState() == Order::STATE_NEW)
+ && ($this->order->getStatus() == $orderStatus)
+ && ($receivedStatusCode == BuckarooStatusCode::SUCCESS)
+ ) {
+ //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();
+ $this->payment->save();
+ }
+ }
+ $this->logging->addDebug(__METHOD__ . '|20|');
+
+ return false;
+ }
+
+ /**
+ * It updates the BUCKAROO_RECEIVED_TRANSACTIONS_STATUSES payment additional information
+ * with the current received tx status.
+ *
+ * @return void
+ * @throws LocalizedException
+ */
+ protected function setReceivedTransactionStatuses(): void
+ {
+ $txId = $this->pushRequest->getTransactions();
+ $statusCode = $this->pushRequest->getStatusCode();
+
+ if (empty($txId) || empty($statusCode)) {
+ return;
+ }
+
+ $receivedTxStatuses = $this->payment->getAdditionalInformation(
+ self::BUCKAROO_RECEIVED_TRANSACTIONS_STATUSES) ?? [];
+ $receivedTxStatuses[$txId] = $statusCode;
+
+ $this->payment->setAdditionalInformation(self::BUCKAROO_RECEIVED_TRANSACTIONS_STATUSES, $receivedTxStatuses);
+ }
+
+ /**
+ * Checks if the order can be updated by checking its state and status.
+ *
+ * @return bool
+ *
+ * @SuppressWarnings(PHPMD.CyclomaticComplexity)
+ */
+ protected function canUpdateOrderStatus(): 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)
+ && ($this->pushTransactionType->getStatusKey() === 'BUCKAROO_MAGENTO2_STATUSCODE_SUCCESS')
+ && $this->pushRequest->getRelatedtransactionPartialpayment() == null
+ ) {
+ $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;
+ }
+
+ /**
+ * 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
+ */
+ 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());
+ }
+ }
+ }
+
+ /**
+ * 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);
+ }
+ }
+ }
+
+ /**
+ *
+ * @return true
+ */
+ protected function canProcessPostData()
+ {
+ return true;
+ }
+
+ /**
+ * Checks if the payment is a partial payment using a gift card.
+ *
+ * @return bool
+ * @throws LocalizedException
+ */
+ protected function giftcardPartialPayment(): bool
+ {
+ if ($this->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) {
+ $this->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
+ );
+ }
+ }
+
+ /**
+ * 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);
+ }
+
+ if (in_array($statusKey, $this->buckarooStatusCode->getFailedStatuses())) {
+ return $this->processFailedPush($newStatus, $statusMessage);
+ }
+
+ if (in_array($statusKey, $this->buckarooStatusCode->getPendingStatuses())) {
+ return $this->processPendingPaymentPush();
+ }
+
+ $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;
+ }
+ }
+
+ if ($this->groupTransaction->isGroupTransaction($this->pushRequest->getInvoiceNumber())) {
+ $paymentDetails['forceState'] = true;
+ }
+
+ $this->logging->addDebug(__METHOD__ . '|8|');
+
+ $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(
+ $this->order,
+ (bool)$this->configAccount->getOrderConfirmationEmailSync($store)
+ );
+ }
+ }
+
+ /**
+ * 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;
+ }
+
+ 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;
+ }
+
+ $this->addTransactionData();
+
+ $this->logging->addDebug(__METHOD__ . '|15|');
+ //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();
+
+ $transactionKey = $this->getTransactionKey();
+
+ if (strlen($transactionKey) <= 0) {
+ return true;
+ }
+
+ $this->logging->addDebug(__METHOD__ . '|25|');
+
+ /** @var Invoice $invoice */
+ foreach ($this->order->getInvoiceCollection() as $invoice) {
+ $invoice->setTransactionId($transactionKey)->save();
+
+ if (!empty($this->pushRequest->getInvoiceNumber())
+ && $this->groupTransaction->isGroupTransaction($this->pushRequest->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->orderRequestService->sendInvoiceEmail($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
+ {
+ $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.
+ *
+ * @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->pushRequest->getServiceAntifraudAction())) {
+ $description .= $this->pushRequest->getServiceAntifraudAction() .
+ ' ' .
+ $this->pushRequest->getServiceAntifraudCheck() .
+ ' ' .
+ $this->pushRequest->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->orderRequestService->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->orderRequestService->updateOrderStatus(Order::STATE_CANCELED, $newStatus, $description, $force);
+
+ return true;
+ }
+
+ protected function processPendingPaymentPush(): bool
+ {
+ return true;
+ }
+
+ /**
+ * 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;
+ }
+
+ 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;
+ }
+
+ return [
+ 'amount' => $amount,
+ 'description' => $description,
+ 'forceState' => $forceState
+ ];
+ }
+
+ /**
+ * @param array $paymentDetails
+ * @return bool
+ *
+ * @SuppressWarnings(PHPMD.UnusedFormalParameter)
+ */
+ protected function invoiceShouldBeSaved(array &$paymentDetails): bool
+ {
+ return true;
+ }
+}
\ No newline at end of file
diff --git a/Model/Push/GroupTransactionPushProcessor.php b/Model/Push/GroupTransactionPushProcessor.php
new file mode 100644
index 000000000..5661a9779
--- /dev/null
+++ b/Model/Push/GroupTransactionPushProcessor.php
@@ -0,0 +1,335 @@
+groupTransaction = $groupTransaction;
+ $this->logging = $logging;
+ $this->orderRequestService = $orderRequestService;
+ $this->orderManagement = $orderManagement;
+ $this->quoteManagement = $quoteManagement;
+ $this->quoteFactory = $quoteFactory;
+ $this->quoteResource = $quoteResource;
+ $this->defaultProcessor = $defaultProcessor;
+ }
+
+ /**
+ * @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 $this->defaultProcessor->processPush($pushRequest);
+ }
+
+ /**
+ * 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/IdealProcessor.php b/Model/Push/IdealProcessor.php
new file mode 100644
index 000000000..53a0d48d7
--- /dev/null
+++ b/Model/Push/IdealProcessor.php
@@ -0,0 +1,110 @@
+lockerProcess = $lockerProcess;
+
+ }
+
+ /**
+ * @throws FileSystemException
+ * @throws BuckarooException
+ */
+ public function processPush(PushRequestInterface $pushRequest): bool
+ {
+ $this->pushRequest = $pushRequest;
+
+ if ($this->lockPushProcessingCriteria()) {
+ $this->lockerProcess->lockProcess($this->getOrderIncrementId());
+ }
+
+ parent::processPush($pushRequest);
+
+ $this->lockerProcess->unlockProcess();
+
+ return true;
+ }
+
+ /**
+ * Determine if the lock push processing criteria are met.
+ *
+ * @return bool
+ */
+ protected function lockPushProcessingCriteria(): bool
+ {
+ return $this->pushRequest->hasPostData('statuscode', BuckarooStatusCode::SUCCESS)
+ && $this->pushRequest->hasPostData('transaction_type', self::BUCK_PUSH_IDEAL_PAY);
+ }
+}
\ No newline at end of file
diff --git a/Model/Push/KlarnaKpProcessor.php b/Model/Push/KlarnaKpProcessor.php
new file mode 100644
index 000000000..d46401776
--- /dev/null
+++ b/Model/Push/KlarnaKpProcessor.php
@@ -0,0 +1,145 @@
+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.
+ *
+ * @return string
+ */
+ protected function getTransactionKey(): string
+ {
+ $trxId = parent::getTransactionKey();
+
+ if (!empty($this->pushRequest->getServiceKlarnakpAutopaytransactionkey())
+ ) {
+ $trxId = $this->pushRequest->getServiceKlarnakpAutopaytransactionkey();
+ }
+
+ 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
new file mode 100644
index 000000000..e0a5f7072
--- /dev/null
+++ b/Model/Push/KlarnaProcessor.php
@@ -0,0 +1,59 @@
+pushRequest->getServiceKlarnaAutopaytransactionkey())
+ ) {
+ $trxId = $this->pushRequest->getServiceKlarnaAutopaytransactionkey();
+ }
+
+ 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
new file mode 100644
index 000000000..54479bee2
--- /dev/null
+++ b/Model/Push/PayPerEmailProcessor.php
@@ -0,0 +1,431 @@
+lockerProcess = $lockerProcess;
+ $this->configPayPerEmail = $configPayPerEmail;
+
+ }
+
+ /**
+ * @throws FileSystemException
+ * @throws \Exception
+ *
+ * @SuppressWarnings(PHPMD.CyclomaticComplexity)
+ * @SuppressWarnings(PHPMD.NPathComplexity)
+ */
+ public function processPush(PushRequestInterface $pushRequest): bool
+ {
+ $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;
+ }
+
+ /**
+ * Determine if the lock push processing criteria are met.
+ *
+ * @return bool
+ */
+ 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());
+ }
+ }
+ }
+
+ /**
+ * 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..916b5e4f0
--- /dev/null
+++ b/Model/Push/PaypalProcessor.php
@@ -0,0 +1,92 @@
+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/PushProcessorsFactory.php b/Model/Push/PushProcessorsFactory.php
new file mode 100644
index 000000000..c5f03b23b
--- /dev/null
+++ b/Model/Push/PushProcessorsFactory.php
@@ -0,0 +1,144 @@
+objectManager = $objectManager;
+ $this->pushProcessors = $pushProcessors;
+ $this->orderRequestService = $orderRequestService;
+ }
+
+ /**
+ * Retrieve the appropriate push processor for a given transaction type.
+ *
+ * @param PushTransactionType|null $pushTransactionType
+ * @return ?PushProcessorInterface
+ * @throws BuckarooException
+ */
+ public function get(?PushTransactionType $pushTransactionType): ?PushProcessorInterface
+ {
+ if (!$this->pushProcessor instanceof PushProcessorInterface) {
+ if (empty($this->pushProcessors)) {
+ throw new \LogicException('Push processors is not set.');
+ }
+
+ $pushProcessorClass = $this->getPushProcessorClass($pushTransactionType);
+ if (empty($pushProcessorClass)) {
+ throw new BuckarooException(new Phrase('Unknown Push Processor type'));
+ }
+
+ $this->pushProcessor = $this->objectManager->get($pushProcessorClass);
+
+ }
+ return $this->pushProcessor;
+ }
+
+ /**
+ * Determine the class of the push processor based on the provided transaction type.
+ *
+ * @param PushTransactionType|null $pushTransactionType
+ * @return mixed
+ * @throws BuckarooException
+ */
+ private function getPushProcessorClass(?PushTransactionType $pushTransactionType)
+ {
+ // Set Default Push Processor
+ $pushProcessorClass = $this->pushProcessors['default'];
+
+ // Set Push Processor by Payment Method
+ $paymentMethod = $pushTransactionType->getPaymentMethod();
+ $pushProcessorClass = $this->pushProcessors[$paymentMethod] ?? $pushProcessorClass;
+
+ if ($pushTransactionType->isFromPayPerEmail()) {
+ return $this->pushProcessors['payperemail'];
+ }
+
+ // Check if is Group Transaction Push
+ if ($pushTransactionType->isGroupTransaction()) {
+ return $this->pushProcessors['group_transaction'];
+ }
+
+ // Check if is Credit Management Push
+ $pushType = $pushTransactionType->getPushType();
+ if ($pushType == PushTransactionType::BUCK_PUSH_TYPE_INVOICE) {
+ return $this->pushProcessors['credit_managment'];
+ }
+
+ if ($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') {
+ return $this->pushProcessors['refund'];
+ }
+
+ if ($pushTransactionType->getServiceAction() == 'cancel_authorize') {
+ return $this->pushProcessors['cancel_authorize'];
+ }
+
+ return $pushProcessorClass;
+ }
+}
\ No newline at end of file
diff --git a/Model/Push/PushTransactionType.php b/Model/Push/PushTransactionType.php
new file mode 100644
index 000000000..0d7986b9a
--- /dev/null
+++ b/Model/Push/PushTransactionType.php
@@ -0,0 +1,462 @@
+buckarooStatusCode = $buckarooStatusCode;
+ }
+
+ /**
+ * @param PushRequestInterface|null $pushRequest
+ * @param Order|null $order
+ * @return PushTransactionType
+ */
+ public function getPushTransactionType(?PushRequestInterface $pushRequest, ?Order $order): PushTransactionType
+ {
+ if (!$this->isSet) {
+ $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 = $this->pushRequest->getTransactionType();
+ $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();
+ $this->isFromPayPerEmail = (bool)$this->pushRequest->getAdditionalInformation('frompayperemail')
+ ?? (bool)$this->pushRequest->getAdditionalInformation('frompayperemail')
+ ?? false;
+
+ $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(): string
+ {
+ //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 '';
+ }
+
+ /**
+ * Retrieve the status code from the push request based on the transaction type.
+ *
+ * @param string $transactionType
+ * @return int
+ *
+ * @SuppressWarnings(PHPMD.CyclomaticComplexity)
+ */
+ private function getStatusCodeByTransactionType(string $transactionType): int
+ {
+ $statusCode = 0;
+ switch ($transactionType) {
+ case self::BUCK_PUSH_TYPE_TRANSACTION:
+ case self::BUCK_PUSH_TYPE_DATAREQUEST:
+ $statusCode = $this->pushRequest->getStatusCode() ?: $statusCode;
+ break;
+ case self::BUCK_PUSH_TYPE_INVOICE:
+ case self::BUCK_PUSH_TYPE_INVOICE_INCOMPLETE:
+ $statusCode = $this->pushRequest->getEventparametersStatuscode() ?: $statusCode;
+ $statusCode = $this->pushRequest->getEventparametersTransactionstatuscode() ?: $statusCode;
+ break;
+ }
+
+ if ($this->pushRequest->getStatusCode() !== null
+ && ($this->pushRequest->getStatusCode() == BuckarooStatusCode::SUCCESS)
+ && !$statusCode
+ ) {
+ $statusCode = BuckarooStatusCode::SUCCESS;
+ }
+
+ 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 getStatusKey(): string
+ {
+ return $this->statusKey;
+ }
+
+ /**
+ * @param string $statusKey
+ */
+ public function setStatusKey(string $statusKey): void
+ {
+ $this->statusKey = $statusKey;
+ }
+
+ /**
+ * @return string|null
+ */
+ public function getTransactionType(): ?string
+ {
+ return $this->transactionType;
+ }
+
+ /**
+ * @param string|null $transactionType
+ */
+ public function setTransactionType(?string $transactionType): void
+ {
+ $this->transactionType = $transactionType;
+ }
+
+ /**
+ * @return string|null
+ */
+ public function getServiceAction(): ?string
+ {
+ 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';
+ }
+ }
+ }
+
+ return $this->serviceAction;
+ }
+
+ /**
+ * @param string $serviceAction
+ */
+ public function setServiceAction(string $serviceAction): void
+ {
+ $this->serviceAction = $serviceAction;
+ }
+
+ /**
+ * @return string
+ */
+ public function getPushType(): string
+ {
+ return $this->pushType;
+ }
+
+ /**
+ * @param string $pushType
+ */
+ public function setPushType(string $pushType): void
+ {
+ $this->pushType = $pushType;
+ }
+
+ /**
+ * @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 getMagentoServiceAction(): string
+ {
+ return $this->magentoServiceAction;
+ }
+
+ /**
+ * @param string $magentoServiceAction
+ */
+ public function setMagentoServiceAction(string $magentoServiceAction): void
+ {
+ $this->magentoServiceAction = $magentoServiceAction;
+ }
+
+ /**
+ * @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->creditManagement;
+ }
+
+ /**
+ * @param bool $creditManagement
+ */
+ public function setCreditManagment(bool $creditManagement): void
+ {
+ $this->creditManagement = $creditManagement;
+ }
+
+ /**
+ * @return Order
+ */
+ public function getOrder(): Order
+ {
+ return $this->order;
+ }
+
+ /**
+ * @param Order $order
+ */
+ 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
new file mode 100644
index 000000000..ccf34a2a6
--- /dev/null
+++ b/Model/Push/RefundProcessor.php
@@ -0,0 +1,139 @@
+refundPush = $refundPush;
+ }
+
+ /**
+ * @throws BuckarooException
+ * @throws \Exception
+ */
+ public function processPush(PushRequestInterface $pushRequest): bool
+ {
+ $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') {
+ 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);
+ }
+
+ /**
+ * Skip Pending Refund Push
+ *
+ * @param PushRequestInterface $pushRequest
+ * @return bool
+ * @throws \Exception
+ */
+ private function skipPendingRefundPush(PushRequestInterface $pushRequest): bool
+ {
+ if (!$pushRequest->hasAdditionalInformation('initiated_by_magento', 1)
+ || !$pushRequest->hasAdditionalInformation('service_action_from_magento', ['refund'])
+ ) {
+ $this->logging->addDebug(__METHOD__ . '|5|');
+ 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
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/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 4ff6f7d3b..f17c48d88 100644
--- a/Model/RequestPush/HttppostPushRequest.php
+++ b/Model/RequestPush/HttppostPushRequest.php
@@ -32,6 +32,10 @@
* @method getSchemekey()
* @method getServiceCreditmanagement3Invoicekey()
* @method getEventparametersStatuscode()
+ * @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 ff82a3693..4f0851f37 100644
--- a/Model/RequestPush/JsonPushRequest.php
+++ b/Model/RequestPush/JsonPushRequest.php
@@ -33,6 +33,10 @@
* @method getSchemekey()
* @method getServiceCreditmanagement3Invoicekey()
* @method getEventparametersStatuscode()
+ * @method getEventparametersTransactionstatuscode()
+ * @method getIspaid()
+ * @method getInvoicestatuscode()
+ * @method getRelatedtransactionPartialpayment()
*/
class JsonPushRequest extends AbstractPushRequest implements PushRequestInterface
{
diff --git a/Service/LockerProcess.php b/Service/LockerProcess.php
new file mode 100644
index 000000000..766b32860
--- /dev/null
+++ b/Service/LockerProcess.php
@@ -0,0 +1,91 @@
+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);
+ }
+}
\ No newline at end of file
diff --git a/Service/Push/OrderRequestService.php b/Service/Push/OrderRequestService.php
new file mode 100644
index 000000000..6373e72f6
--- /dev/null
+++ b/Service/Push/OrderRequestService.php
@@ -0,0 +1,327 @@
+order = $order;
+ $this->logging = $logging;
+ $this->transaction = $transaction;
+ $this->orderSender = $orderSender;
+ $this->invoiceSender = $invoiceSender;
+ $this->resourceConnection = $resourceConnection;
+ }
+
+ /**
+ * Load the order from the Push Data based on the Order Increment ID or transaction key.
+ *
+ * @param PushRequestInterface|null $pushRequest
+ * @return Order|OrderPayment
+ * @throws \Exception
+ */
+ public function getOrderByRequest(?PushRequestInterface $pushRequest = null)
+ {
+ if ($this->order->getId()) {
+ 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 BuckarooException(__('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;
+ }
+
+ /**
+ * Try to add a notification note to the order comments.
+ *
+ * @param Phrase|string $message
+ */
+ public function setOrderNotificationNote($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());
+ }
+ }
+
+ /**
+ * 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.
+ *
+ * @param Order $order
+ * @param bool $forceSyncMode
+ * @return bool
+ */
+ public function sendOrderEmail(Order $order, bool $forceSyncMode = false): bool
+ {
+ return $this->orderSender->send($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);
+ }
+
+ 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
+ */
+ public 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/config.xml b/etc/config.xml
index 6277b6470..c01132a96 100644
--- a/etc/config.xml
+++ b/etc/config.xml
@@ -502,7 +502,7 @@
0
- PayPerEmailFacade
+ PayLinkFacade
pending
Buckaroo PayLink
0
diff --git a/etc/di.xml b/etc/di.xml
index 362b5a73d..8ec1b9098 100644
--- a/etc/di.xml
+++ b/etc/di.xml
@@ -465,6 +465,26 @@
+
+
+
+
+ - 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\AfterpayProcessor
+ - Buckaroo\Magento2\Model\Push\KlarnaProcessor
+ - Buckaroo\Magento2\Model\Push\KlarnaKpProcessor
+ - Buckaroo\Magento2\Model\Push\PayPerEmailProcessor
+ - Buckaroo\Magento2\Model\Push\TransferProcessor
+
+
+
+
@@ -3074,6 +3094,30 @@
+
+
+
+ Buckaroo\Magento2\Model\ConfigProvider\Method\PayLink::CODE
+ PayLinkValueHandlerPool
+
+
+
+
+
+
+ - PayLinkConfigValueHandler
+
+
+
+
+
+
+ Buckaroo\Magento2\Model\ConfigProvider\Method\PayLink
+
+
+
+
+