diff --git a/.version b/.version
index eca07e4..ac2cdeb 100644
--- a/.version
+++ b/.version
@@ -1 +1 @@
-2.1.2
+2.1.3
diff --git a/CHANGELOG.MD b/CHANGELOG.MD
index 074a4f6..a45b9e0 100644
--- a/CHANGELOG.MD
+++ b/CHANGELOG.MD
@@ -5,6 +5,17 @@ All notable changes to this project will be documented in this file.
The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/),
and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html).
+## [2.1.3]
+
+
+### Added
+
+- Adding minimum amount validation
+
+### Fixed
+
+- Performance improvements
+
## [2.1.1]
### Fixed
diff --git a/Service/TpayService.php b/Service/TpayService.php
index b8501fc..6afc64e 100644
--- a/Service/TpayService.php
+++ b/Service/TpayService.php
@@ -6,9 +6,11 @@
use Exception;
use Magento\Framework\Event\ManagerInterface as EventManagerInterface;
+use Magento\Sales\Api\Data\InvoiceInterface;
use Magento\Sales\Api\Data\OrderInterface;
use Magento\Sales\Api\Data\OrderPaymentInterface;
use Magento\Sales\Api\Data\TransactionInterface;
+use Magento\Sales\Api\InvoiceRepositoryInterface;
use Magento\Sales\Api\OrderPaymentRepositoryInterface;
use Magento\Sales\Model\Order;
use Magento\Sales\Model\Order\Invoice;
@@ -30,6 +32,9 @@ class TpayService extends RegisterCaptureNotificationOperation
/** @var OrderPaymentRepositoryInterface */
protected $orderPaymentRepository;
+ /** @var InvoiceRepositoryInterface */
+ protected $invoiceRepository;
+
/** @var BuilderInterface */
protected $builder;
@@ -39,6 +44,7 @@ class TpayService extends RegisterCaptureNotificationOperation
public function __construct(
OrderRepositoryInterface $orderRepository,
OrderPaymentRepositoryInterface $orderPaymentRepository,
+ InvoiceRepositoryInterface $invoiceRepository,
BuilderInterface $builder,
CommandInterface $stateCommand,
BuilderInterface $transactionBuilder,
@@ -48,6 +54,7 @@ public function __construct(
) {
$this->orderRepository = $orderRepository;
$this->orderPaymentRepository = $orderPaymentRepository;
+ $this->invoiceRepository = $invoiceRepository;
$this->builder = $builder;
$this->invoiceService = $invoiceService;
parent::__construct(
@@ -91,6 +98,16 @@ public function getPayment(string $orderId): OrderPaymentInterface
return $order->getPayment();
}
+ public function getOrderById(string $orderId): OrderInterface
+ {
+ return $this->orderRepository->getByIncrementId($orderId);
+ }
+
+ public function saveOrderPayment(OrderPaymentInterface $payment): OrderPaymentInterface
+ {
+ return $this->orderPaymentRepository->save($payment);
+ }
+
/**
* @throws Exception
*
@@ -99,57 +116,24 @@ public function getPayment(string $orderId): OrderPaymentInterface
public function setOrderStatus(string $orderId, array $validParams, TpayConfigInterface $tpayConfig)
{
$order = $this->getOrderById($orderId);
+ $emailNotify = false;
if (!$order->getId()) {
return false;
}
- $sendNewInvoiceMail = (bool) $tpayConfig->getInvoiceSendMail();
- $orderAmount = (float) number_format((float) $order->getBaseGrandTotal(), 2, '.', '');
- $trStatus = $validParams['tr_status'];
- $emailNotify = false;
-
- if ('TRUE' === $trStatus && ((float) number_format($validParams['tr_paid'], 2, '.', '') === $orderAmount)) {
- if (Order::STATE_PROCESSING !== $order->getState()) {
- $emailNotify = true;
- }
- $status = Order::STATE_PROCESSING;
- $this->registerCaptureNotificationTpay($order->getPayment(), $order->getBaseGrandTotal(), $validParams);
- } elseif ('CHARGEBACK' === $trStatus) {
- $order->addCommentToStatusHistory($this->getTransactionDesc($validParams));
- $this->orderRepository->save($order);
+ $status = $this->determineOrderStatus($order, $validParams, $emailNotify);
+ if (!$status) {
return $order;
- } else {
- if (Order::STATE_HOLDED !== $order->getState()) {
- $emailNotify = true;
- }
- $comment = __('The order has been holded: ').''.$this->getTransactionDesc($validParams);
- $status = Order::STATE_HOLDED;
- $order->addStatusToHistory($status, $comment, true);
}
- if ($emailNotify) {
- $order->setSendEmail(true);
- }
-
- $order->setStatus($status)->setState($status);
- $this->orderRepository->save($order);
- if ($sendNewInvoiceMail) {
- foreach ($order->getInvoiceCollection() as $invoice) {
- $invoiceId = $invoice->getId();
- $this->invoiceService->notify($invoiceId);
- }
- }
+ $order = $this->updateOrderStatus($order, $status, $emailNotify);
+ $this->sendInvoiceEmailsIfNeeded($order, $tpayConfig);
return $order;
}
- public function getOrderById(string $orderId): OrderInterface
- {
- return $this->orderRepository->getByIncrementId($orderId);
- }
-
public function setCardOrderStatus($orderId, array $validParams, TpayConfigInterface $tpayConfig)
{
/** @var Order $order */
@@ -159,45 +143,18 @@ public function setCardOrderStatus($orderId, array $validParams, TpayConfigInter
return false;
}
- $sendNewInvoiceMail = (bool) $tpayConfig->getInvoiceSendMail();
- $transactionDesc = $this->getCardTransactionDesc($validParams);
- $orderAmount = (float) number_format((float) $order->getBaseGrandTotal(), 2, '.', '');
- $emailNotify = false;
-
- $order = $this->updateTransactionId($order, $validParams);
- $amountCheck = (float) number_format((float) $validParams['amount'], 2, '.', '') !== $orderAmount;
-
- if (!isset($validParams['status']) || 'correct' !== $validParams['status'] || $amountCheck) {
- $comment = __('Payment has been declined. ').''.$transactionDesc;
- $this->addCommentToHistory($orderId, $comment);
- } else {
- if (Order::STATE_PROCESSING != $order->getState()) {
- $emailNotify = true;
- }
- $this->registerCardCaptureNotificationTpay($order->getPayment(), $order->getBaseGrandTotal(), $validParams);
- }
+ $emailNotify = $this->commentCardOrder($order, $validParams, $orderId);
if ($emailNotify) {
$order->setSendEmail(true);
}
+ $this->sendInvoiceEmailsIfNeeded($order, $tpayConfig);
$this->orderRepository->save($order);
- if ($sendNewInvoiceMail) {
- foreach ($order->getInvoiceCollection() as $invoice) {
- $invoiceId = $invoice->getId();
- $this->invoiceService->notify($invoiceId);
- }
- }
-
return $order;
}
- public function saveOrderPayment(OrderPaymentInterface $payment): OrderPaymentInterface
- {
- return $this->orderPaymentRepository->save($payment);
- }
-
/** @return bool|string */
protected function getTransactionDesc(array $validParams)
{
@@ -227,18 +184,19 @@ protected function getCardTransactionDesc($validParams)
if (empty($validParams)) {
return false;
}
+
if (isset($validParams['err_desc'])) {
return 'Payment error: '.$validParams['err_desc'].', error code: '.$validParams['err_code'];
}
+
$error = null;
+
if ('declined' === $validParams['status']) {
$error = $validParams['reason'];
}
$transactionDesc = (is_null($error)) ? ' ' : ' Reason: '.$error.'';
- $transactionDesc .= (isset($validParams['test_mode'])) && 1 === (int) $validParams['test_mode']
- ? ' TEST '
- : ' ';
+ $transactionDesc .= (isset($validParams['test_mode'])) && 1 === (int) $validParams['test_mode'] ? ' TEST ' : ' ';
return $transactionDesc;
}
@@ -247,13 +205,26 @@ protected function getCardTransactionDesc($validParams)
* @param float|string $amount
* @param bool|int $skipFraudDetection
*/
- private function registerCaptureNotificationTpay(
- OrderPaymentInterface $payment,
- $amount,
- array $validParams,
- $skipFraudDetection = false
- ) {
- // @var $payment Payment
+ private function registerCaptureNotificationTpay(OrderPaymentInterface $payment, $amount, array $validParams, bool $skipFraudDetection = false)
+ {
+ $this->setTransactionIdForPayment($payment);
+
+ $order = $payment->getOrder();
+ $amount = (float) $amount;
+ $invoice = $this->getInvoiceForTransactionId($order, $payment->getTransactionId());
+
+ if (!$invoice && $payment->isCaptureFinal($amount)) {
+ $invoice = $this->createAndRegisterInvoice($order, $payment);
+ } else {
+ $this->handlePotentialFraud($payment, $amount, $skipFraudDetection);
+ }
+
+ $this->finalizePayment($payment, $invoice, $amount, $order);
+ $this->createTransactionAndAddComments($payment, $invoice, $validParams, $amount, $order);
+ }
+
+ private function setTransactionIdForPayment(OrderPaymentInterface $payment): void
+ {
$payment->setTransactionId(
$this->transactionManager->generateTransactionId(
$payment,
@@ -262,52 +233,82 @@ private function registerCaptureNotificationTpay(
)
);
- $order = $payment->getOrder();
- $amount = (float) $amount;
- $invoice = $this->getInvoiceForTransactionId($order, $payment->getTransactionId());
+ $this->orderPaymentRepository->save($payment);
+ }
- if (!$invoice && $payment->isCaptureFinal($amount)) {
- $invoice = $order->prepareInvoice()->register();
- $invoice->setOrder($order);
- $order->addRelatedObject($invoice);
- $payment->setCreatedInvoice($invoice);
- $payment->setShouldCloseParentTransaction(true);
- } else {
- $payment->setIsFraudDetected(!$skipFraudDetection);
- $this->updateTotals($payment, ['base_amount_paid_online' => $amount]);
+ private function createAndRegisterInvoice(OrderInterface $order, OrderPaymentInterface $payment, ?string $state = null): InvoiceInterface
+ {
+ $invoice = $order->prepareInvoice()->register();
+ $invoice->setOrder($order);
+ $order->addRelatedObject($invoice);
+ $payment->setCreatedInvoice($invoice);
+ $payment->setShouldCloseParentTransaction(true);
+
+ if ($state) {
+ $order->setState($state);
}
+ $this->invoiceRepository->save($invoice);
+ $this->orderRepository->save($order);
+ $this->orderPaymentRepository->save($payment);
+
+ return $invoice;
+ }
+
+ private function handlePotentialFraud(OrderPaymentInterface $payment, float $amount, bool $skipFraudDetection): void
+ {
+ $payment->setIsFraudDetected(!$skipFraudDetection);
+ $this->updateTotals($payment, ['base_amount_paid_online' => $amount]);
+
+ $this->orderPaymentRepository->save($payment);
+ }
+
+ private function finalizePayment(OrderPaymentInterface $payment, ?InvoiceInterface $invoice, float $amount, OrderInterface $order): void
+ {
if (!$payment->getIsTransactionPending() && $invoice && Invoice::STATE_OPEN === $invoice->getState()) {
$invoice->setOrder($order);
$invoice->pay();
$this->updateTotals($payment, ['base_amount_paid_online' => $amount]);
$order->addRelatedObject($invoice);
+
+ $this->invoiceRepository->save($invoice);
+ $this->orderRepository->save($order);
+ $this->orderPaymentRepository->save($payment);
}
+ }
+ private function createTransactionAndAddComments(OrderPaymentInterface $payment, ?InvoiceInterface $invoice, array $validParams, float $amount, OrderInterface $order): void
+ {
$message = $this->stateCommand->execute($payment, $amount, $order);
- $payment
- ->setTransactionId($validParams['tr_id'])
+ $payment->setTransactionId($validParams['tr_id'])
->setTransactionAdditionalInfo(Transaction::RAW_DETAILS, $validParams);
$transaction = $payment->addTransaction(Transaction::TYPE_ORDER, $invoice, true);
$message = $payment->prependMessage($message);
$payment->addTransactionCommentsToOrder($transaction, $message);
+
+ $this->orderPaymentRepository->save($payment);
+ $this->orderRepository->save($order);
}
- private function registerCardCaptureNotificationTpay(
- OrderPaymentInterface $payment,
- $amount,
- $validParams,
- $skipFraudDetection = false
- ) {
- // @var $payment Payment
- $payment->setTransactionId(
- $this->transactionManager->generateTransactionId(
- $payment,
- Transaction::TYPE_CAPTURE,
- $payment->getAuthorizationTransaction()
- )
- );
+ private function createCardTransactionAndAddComments(OrderPaymentInterface $payment, ?InvoiceInterface $invoice, array $validParams, float $amount, OrderInterface $order): void
+ {
+ $payment
+ ->setTransactionId($validParams['sale_auth'])
+ ->setTransactionAdditionalInfo(Transaction::RAW_DETAILS, $validParams);
+
+ $transaction = $payment->addTransaction(TransactionInterface::TYPE_CAPTURE, $invoice, true);
+ $message = $this->stateCommand->execute($payment, $amount, $order);
+ $message = $payment->prependMessage($message);
+ $payment->addTransactionCommentsToOrder($transaction, $message);
+
+ $this->orderPaymentRepository->save($payment);
+ $this->orderRepository->save($order);
+ }
+
+ private function registerCardCaptureNotificationTpay(OrderPaymentInterface $payment, $amount, $validParams, $skipFraudDetection = false)
+ {
+ $this->setTransactionIdForPayment($payment);
$order = $payment->getOrder();
$amount = (float) $amount;
@@ -317,40 +318,17 @@ private function registerCardCaptureNotificationTpay(
if (!in_array($orderCurrencyCode, CurrencyCodesDictionary::CODES)) {
throw new Exception(sprintf('Order currency %s does not exist in Tpay dictionary!', $orderCurrencyCode));
}
+
$orderCurrency = array_search($orderCurrencyCode, CurrencyCodesDictionary::CODES);
- // register new capture
- if (
- !$invoice
- && $payment->isCaptureFinal($amount)
- && ($orderCurrency === (int) $validParams['currency'] || $orderCurrencyCode === $validParams['currency'])
- ) {
- $invoice = $order->prepareInvoice()->register();
- $invoice->setOrder($order);
- $order->addRelatedObject($invoice);
- $payment->setCreatedInvoice($invoice);
- $payment->setShouldCloseParentTransaction(true);
- $order->setState(Order::STATE_PROCESSING);
- $this->orderRepository->save($order);
- } else {
- $payment->setIsFraudDetected(!$skipFraudDetection);
- $this->updateTotals($payment, ['base_amount_paid_online' => $amount]);
- }
- if (!$payment->getIsTransactionPending() && $invoice && Invoice::STATE_OPEN === $invoice->getState()) {
- $invoice->setOrder($order);
- $invoice->pay();
- $this->updateTotals($payment, ['base_amount_paid_online' => $amount]);
- $order->addRelatedObject($invoice);
+ if (!$invoice && $payment->isCaptureFinal($amount) && ($orderCurrency === (int) $validParams['currency'] || $orderCurrencyCode === $validParams['currency'])) {
+ $invoice = $this->createAndRegisterInvoice($order, $payment, Order::STATE_PROCESSING);
+ } else {
+ $this->handlePotentialFraud($payment, $amount, $skipFraudDetection);
}
- $payment
- ->setTransactionId($validParams['sale_auth'])
- ->setTransactionAdditionalInfo(Transaction::RAW_DETAILS, $validParams);
-
- $transaction = $payment->addTransaction(TransactionInterface::TYPE_CAPTURE, $invoice, true);
- $message = $this->stateCommand->execute($payment, $amount, $order);
- $message = $payment->prependMessage($message);
- $payment->addTransactionCommentsToOrder($transaction, $message);
+ $this->finalizePayment($payment, $invoice, $amount, $order);
+ $this->createCardTransactionAndAddComments($payment, $invoice, $validParams, $amount, $order);
}
private function updateTransactionId(Order $order, array $validParams): Order
@@ -363,4 +341,81 @@ private function updateTransactionId(Order $order, array $validParams): Order
return $order;
}
+
+ private function determineOrderStatus(OrderInterface $order, array $validParams, bool &$emailNotify): ?string
+ {
+ $orderAmount = (float) number_format((float) $order->getBaseGrandTotal(), 2, '.', '');
+ $trStatus = $validParams['tr_status'];
+
+ if ('TRUE' === $trStatus && ((float) number_format($validParams['tr_paid'], 2, '.', '') === $orderAmount)) {
+ if (Order::STATE_PROCESSING !== $order->getState()) {
+ $emailNotify = true;
+ }
+
+ $this->registerCaptureNotificationTpay($order->getPayment(), $order->getBaseGrandTotal(), $validParams);
+
+ return Order::STATE_PROCESSING;
+ }
+ if ('CHARGEBACK' === $trStatus) {
+ $order->addCommentToStatusHistory($this->getTransactionDesc($validParams));
+ $this->orderRepository->save($order);
+
+ return null;
+ }
+
+ if (Order::STATE_HOLDED !== $order->getState()) {
+ $emailNotify = true;
+ }
+
+ $comment = __('The order has been holded: ').''.$this->getTransactionDesc($validParams);
+ $status = Order::STATE_HOLDED;
+ $order->addStatusToHistory($status, $comment, true);
+
+ return $status;
+ }
+
+ private function commentCardOrder(OrderInterface &$order, array $validParams, string $orderId): bool
+ {
+ $transactionDesc = $this->getCardTransactionDesc($validParams);
+ $orderAmount = (float) number_format((float) $order->getBaseGrandTotal(), 2, '.', '');
+ $emailNotify = false;
+
+ $order = $this->updateTransactionId($order, $validParams);
+ $amountCheck = (float) number_format((float) $validParams['amount'], 2, '.', '') !== $orderAmount;
+
+ if (!isset($validParams['status']) || 'correct' !== $validParams['status'] || $amountCheck) {
+ $comment = __('Payment has been declined. ').''.$transactionDesc;
+ $this->addCommentToHistory($orderId, $comment);
+ } else {
+ if (Order::STATE_PROCESSING != $order->getState()) {
+ $emailNotify = true;
+ }
+
+ $this->registerCardCaptureNotificationTpay($order->getPayment(), $order->getBaseGrandTotal(), $validParams);
+ }
+
+ return $emailNotify;
+ }
+
+ private function updateOrderStatus(OrderInterface $order, string $status, bool $emailNotify): OrderInterface
+ {
+ if ($emailNotify) {
+ $order->setSendEmail(true);
+ }
+
+ $order->setStatus($status)->setState($status);
+ $this->orderRepository->save($order);
+
+ return $order;
+ }
+
+ private function sendInvoiceEmailsIfNeeded(OrderInterface $order, TpayConfigInterface $tpayConfig): void
+ {
+ if ($tpayConfig->getInvoiceSendMail()) {
+ foreach ($order->getInvoiceCollection() as $invoice) {
+ $invoiceId = $invoice->getId();
+ $this->invoiceService->notify($invoiceId);
+ }
+ }
+ }
}