From f5ff5df30e6aa1828020d69ead0a951e1a4649c5 Mon Sep 17 00:00:00 2001 From: Andy Kim Date: Mon, 15 May 2023 15:10:32 +0700 Subject: [PATCH] Add debug log for checkout flow (#163) * enable debug logging for checkout flow * Fix load order by increment_id * Fix sonar tests --------- Co-authored-by: andy --- CHANGELOG.md | 4 + Controller/Checkout/AbstractAction.php | 39 +++-- Controller/Checkout/Invoice.php | 100 +++++++++---- Controller/Checkout/InvoiceMultishipping.php | 121 +++++++++++----- Controller/Checkout/Notification.php | 143 ++++++++++++++----- Helper/Checkout.php | 6 +- Helper/Data.php | 6 +- Helper/Metric.php | 4 +- Logger/Handler.php | 36 ++++- Model/Payment/Xendit.php | 20 +++ Plugin/ConfigElementGroupPlugin.php | 12 +- composer.json | 2 +- etc/adminhtml/system.xml | 9 ++ etc/config.xml | 1 + etc/module.xml | 2 +- 15 files changed, 378 insertions(+), 127 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index ff2fd367..f89566ee 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,5 +1,9 @@ # CHANGELOG +## 10.0.3 (2023-05-11) +Improvements: +- Implementation debug logging + ## 10.0.2 (2023-03-21) Improvements: - Update min/max total of Akulaku diff --git a/Controller/Checkout/AbstractAction.php b/Controller/Checkout/AbstractAction.php index 2a2780ff..07035401 100644 --- a/Controller/Checkout/AbstractAction.php +++ b/Controller/Checkout/AbstractAction.php @@ -10,6 +10,7 @@ use Magento\Framework\Controller\Result\JsonFactory; use Magento\Framework\DB\Transaction as DbTransaction; use Magento\Framework\Exception\LocalizedException; +use Magento\Framework\Phrase; use Magento\Framework\Stdlib\CookieManagerInterface; use Magento\Framework\UrlInterface; use Magento\Multishipping\Model\Checkout\Type\Multishipping; @@ -28,6 +29,7 @@ use Xendit\M2Invoice\Helper\Data; use Xendit\M2Invoice\Helper\ErrorHandler; use Xendit\M2Invoice\Helper\Metric; +use Xendit\M2Invoice\Logger\Logger as XenditLogger; /** * Class AbstractAction @@ -35,8 +37,6 @@ */ abstract class AbstractAction extends Action { - const LOG_FILE = 'xendit.log'; - /** * @var Session */ @@ -182,7 +182,7 @@ public function __construct( Context $context, CategoryFactory $categoryFactory, OrderFactory $orderFactory, - LoggerInterface $logger, + XenditLogger $logger, Data $dataHelper, Crypto $cryptoHelper, Checkout $checkoutHelper, @@ -433,25 +433,34 @@ protected function getRedirectFactory() } /** - * @param $order + * @param Order $order * @param $failureReason + * @return Order * @throws LocalizedException */ - protected function cancelOrder($order, $failureReason) + protected function cancelOrder(Order $order, $failureReason) { $orderState = Order::STATE_CANCELED; - if ($order->getStatus() != $orderState) { - $order->setState($orderState) + try { + $message = "Order #" . $order->getIncrementId() . " was cancelled by Xendit because " . $failureReason; + $order->setState($orderState) ->setStatus($orderState) - ->addStatusHistoryComment("Order #" . $order->getIncrementId() . " was cancelled by Xendit because " . $failureReason); - $order->save(); - - $this->getCheckoutHelper()->cancelOrderById($order->getId(), "Order #" . ($order->getId()) . " was rejected by Xendit"); - $this->getCheckoutHelper()->restoreQuote(); //restore cart + ->addStatusHistoryComment($message); + $this->orderRepo->save($order); + + $this->getCheckoutHelper()->cancelOrderById($order->getId(), "Order #" . ($order->getId()) . " was rejected by Xendit"); + $this->getCheckoutHelper()->restoreQuote(); //restore cart + + $this->logger->info($message); + } catch (\Exception $ex) { + $this->logger->error('Cancel order failed:' . $ex->getMessage(), ['order_id' => $order->getIncrementId()]); + throw new LocalizedException( + new Phrase($ex->getMessage()) + ); + } } - - return; + return $order; } /** @@ -497,7 +506,7 @@ protected function getMultiShippingOrderIds() */ protected function orderValidToCreateXenditInvoice(Order $order): bool { - if (!empty($order) && empty($order->getXenditTransactionId())) { + if (empty($order->getXenditTransactionId())) { return true; } return false; diff --git a/Controller/Checkout/Invoice.php b/Controller/Checkout/Invoice.php index fa262e8d..dc452362 100644 --- a/Controller/Checkout/Invoice.php +++ b/Controller/Checkout/Invoice.php @@ -27,34 +27,46 @@ public function execute() if ($order->getState() === Order::STATE_NEW) { $this->changePendingPaymentStatus($order); + $invoice = $this->createInvoice($apiData); $this->addInvoiceData($order, $invoice); - $redirectUrl = $this->getXenditRedirectUrl($invoice, $apiData['preferred_method']); + $redirectUrl = $this->getXenditRedirectUrl($invoice, $apiData['preferred_method']); + $this->getLogger()->info( + 'Redirect customer to Xendit', + ['order_id' => $order->getIncrementId(), 'redirect_url' => $redirectUrl] + ); $resultRedirect = $this->getRedirectFactory()->create(); $resultRedirect->setUrl($redirectUrl); return $resultRedirect; } elseif ($order->getState() === Order::STATE_CANCELED) { + $this->getLogger()->info('Order is already canceled', ['order_id' => $order->getIncrementId()]); + $this->_redirect('checkout/cart'); } else { - $this->getLogger()->debug('Order in unrecognized state: ' . $order->getState()); + $this->getLogger()->info('Order in unrecognized state', ['state' => $order->getState(), 'order_id' => $order->getIncrementId()]); $this->_redirect('checkout/cart'); } } catch (\Throwable $e) { + $errorMessage = sprintf('xendit/checkout/invoice failed: Order #%s - %s', $order->getIncrementId(), $e->getMessage()); + + $this->getLogger()->error($errorMessage, ['order_id' => $order->getIncrementId()]); $this->getLogger()->debug('Exception caught on xendit/checkout/invoice: ' . $e->getMessage()); $this->getLogger()->debug($e->getTraceAsString()); - $this->cancelOrder($order, $e->getMessage()); - - // log metric error - $this->metricHelper->sendMetric( - 'magento2_checkout', - [ - 'type' => 'error', - 'payment_method' => $this->getPreferredMethod($order), - 'error_message' => $e->getMessage() - ] - ); + // cancel order + try { + $this->cancelOrder($order, $e->getMessage()); + $this->metricHelper->sendMetric( + 'magento2_checkout', + [ + 'type' => 'error', + 'payment_method' => $this->getPreferredMethod($order), + 'error_message' => $errorMessage + ] + ); + } catch (\Exception $e) { + } return $this->redirectToCart($e->getMessage()); } @@ -124,6 +136,8 @@ private function createInvoice($requestData) try { if (isset($requestData['preferred_method'])) { + $this->getLogger()->info('createInvoice start', ['data' => $requestData]); + $invoice = $this->getApiHelper()->request( $invoiceUrl, $invoiceMethod, @@ -147,6 +161,7 @@ private function createInvoice($requestData) ); } + $this->getLogger()->info('createInvoice success', ['xendit_invoice' => $invoice]); return $invoice; } @@ -163,32 +178,65 @@ private function getXenditRedirectUrl($invoice, $preferredMethod) /** * @param Order $order * @return void + * @throws LocalizedException */ private function changePendingPaymentStatus(Order $order) { - $order->setState(Order::STATE_PENDING_PAYMENT)->setStatus(Order::STATE_PENDING_PAYMENT); - $order->addCommentToStatusHistory("Pending Xendit payment."); - $this->getOrderRepo()->save($order); + try { + $order->setState(Order::STATE_PENDING_PAYMENT)->setStatus(Order::STATE_PENDING_PAYMENT); + $order->addCommentToStatusHistory("Pending Xendit payment."); + $this->getOrderRepo()->save($order); + + $this->getLogger()->info( + 'changePendingPaymentStatus success', + ['order_id' => $order->getIncrementId()] + ); + } catch (\Exception $e) { + $this->getLogger()->error( + sprintf('changePendingPaymentStatus failed: %s', $e->getMessage()), + ['order_id' => $order->getIncrementId()] + ); + + throw new LocalizedException( + new Phrase($e->getMessage()) + ); + } } /** * @param Order $order * @param array $invoice * @return void + * @throws \Exception */ private function addInvoiceData(Order $order, array $invoice) { - $payment = $order->getPayment(); - $payment->setAdditionalInformation('payment_gateway', 'xendit'); - if (isset($invoice['id'])) { - $payment->setAdditionalInformation('xendit_invoice_id', $invoice['id']); - $order->setXenditTransactionId($invoice['id']); - } - if (isset($invoice['expiry_date'])) { - $payment->setAdditionalInformation('xendit_invoice_exp_date', $invoice['expiry_date']); - } + try { + $payment = $order->getPayment(); + $payment->setAdditionalInformation('payment_gateway', 'xendit'); + if (isset($invoice['id'])) { + $payment->setAdditionalInformation('xendit_invoice_id', $invoice['id']); + $order->setXenditTransactionId($invoice['id']); + } + if (isset($invoice['expiry_date'])) { + $payment->setAdditionalInformation('xendit_invoice_exp_date', $invoice['expiry_date']); + } + + $this->getOrderRepo()->save($order); + $this->getLogger()->info( + 'addInvoiceData success', + ['order_id' => $order->getIncrementId(), 'xendit_transaction_id' => $invoice['id']] + ); + } catch (\Exception $e) { + $this->getLogger()->error( + sprintf('addInvoiceData failed: %s', $e->getMessage()), + ['order_id' => $order->getIncrementId(), 'xendit_transaction_id' => $invoice['id']] + ); - $this->getOrderRepo()->save($order); + throw new LocalizedException( + new Phrase($e->getMessage()) + ); + } } /** diff --git a/Controller/Checkout/InvoiceMultishipping.php b/Controller/Checkout/InvoiceMultishipping.php index 58fa6288..630f8c08 100644 --- a/Controller/Checkout/InvoiceMultishipping.php +++ b/Controller/Checkout/InvoiceMultishipping.php @@ -31,12 +31,13 @@ public function execute() $orderIncrementIds = []; $preferredMethod = ''; + $orderIds = $this->getMultiShippingOrderIds(); + $rawOrderIds = implode('-', $orderIds); try { - $orderIds = $this->getMultiShippingOrderIds(); if (empty($orderIds)) { $message = __('The order not exist'); - $this->getLogger()->info($message); + $this->getLogger()->info($message, ['order_ids' => $orderIds]); return $this->redirectToCart($message); } @@ -44,7 +45,7 @@ public function execute() $order = $this->getOrderRepo()->get($orderId); if (!$this->orderValidToCreateXenditInvoice($order)) { $message = __('Order processed'); - $this->getLogger()->info($message); + $this->getLogger()->info($message, ['order_id' => $orderId]); return $this->redirectToCart($message); } @@ -96,7 +97,6 @@ public function execute() return $this->_redirect('multishipping/checkout/success'); } - $rawOrderIds = implode('-', $orderIds); $requestData = [ 'external_id' => $this->getDataHelper()->getExternalId($rawOrderIds), 'payer_email' => $billingEmail, @@ -116,34 +116,41 @@ public function execute() } $invoice = $this->createInvoice($requestData); - - if (!empty($invoice) && isset($invoice['error_code'])) { - $message = $this->getErrorHandler()->mapInvoiceErrorCode( - $invoice['error_code'], - str_replace('{{currency}}', $currency, $invoice['message'] ?? '') - ); - // cancel order and redirect to cart - return $this->processFailedPayment($orderIds, $message); - } - $this->addInvoiceData($orders, $invoice); $redirectUrl = $this->getXenditRedirectUrl($invoice, $preferredMethod); + $this->getLogger()->info( + 'Redirect customer to Xendit', + array_merge($this->getLogContext($orders, $invoice), ['redirect_url' => $redirectUrl]) + ); + $resultRedirect = $this->getRedirectFactory()->create(); $resultRedirect->setUrl($redirectUrl); return $resultRedirect; } catch (\Throwable $e) { - $this->getLogger()->info('Exception caught on xendit/checkout/redirect: ' . $e->getMessage()); - - // log metric error - $this->metricHelper->sendMetric( - 'magento2_checkout', - [ - 'type' => 'error', - 'payment_method' => $preferredMethod, - 'error_message' => $e->getMessage() - ] + $logContext = $this->getLogContext($orders); + $message = sprintf( + 'Exception caught on xendit/checkout/invoicemultishipping: Order_ids %s - %s', + implode(', ', $logContext['order_ids'] ?? []), + $e->getMessage() ); + $this->getLogger()->error($message, $logContext); + + try { + // cancel orders + $this->processFailedPayment($orderIds, $message); + + // log metric error + $this->metricHelper->sendMetric( + 'magento2_checkout', + [ + 'type' => 'error', + 'payment_method' => $preferredMethod, + 'error_message' => $message + ] + ); + } catch (\Exception $ex) { + } return $this->redirectToCart($e->getMessage()); } @@ -161,13 +168,27 @@ private function createInvoice($requestData) try { if (isset($requestData['preferred_method'])) { - return $this->getApiHelper()->request( + $this->getLogger()->info('createInvoice start', ['data' => $requestData]); + + $invoice = $this->getApiHelper()->request( $invoiceUrl, $invoiceMethod, $requestData, false, $requestData['preferred_method'] ); + if (isset($invoice['error_code'])) { + $message = $this->getErrorHandler()->mapInvoiceErrorCode( + $invoice['error_code'], + str_replace('{{currency}}', $requestData['currency'], $invoice['message'] ?? '') + ); + throw new LocalizedException( + new Phrase($message) + ); + } + + $this->getLogger()->info('createInvoice success', ['xendit_invoice' => $invoice]); + return $invoice; } } catch (LocalizedException $e) { throw new LocalizedException( @@ -190,20 +211,34 @@ private function getXenditRedirectUrl($invoice, $preferredMethod) * @param array $orders * @param array $invoice * @return void + * @throws LocalizedException */ private function addInvoiceData(array $orders, array $invoice) { - foreach ($orders as $order) { - $payment = $order->getPayment(); - $payment->setAdditionalInformation('payment_gateway', 'xendit'); - if (isset($invoice['id'])) { - $payment->setAdditionalInformation('xendit_invoice_id', $invoice['id']); - $order->setXenditTransactionId($invoice['id']); - } - if (isset($invoice['expiry_date'])) { - $payment->setAdditionalInformation('xendit_invoice_exp_date', $invoice['expiry_date']); + try { + foreach ($orders as $order) { + $payment = $order->getPayment(); + $payment->setAdditionalInformation('payment_gateway', 'xendit'); + if (isset($invoice['id'])) { + $payment->setAdditionalInformation('xendit_invoice_id', $invoice['id']); + $order->setXenditTransactionId($invoice['id']); + } + if (isset($invoice['expiry_date'])) { + $payment->setAdditionalInformation('xendit_invoice_exp_date', $invoice['expiry_date']); + } + $this->getOrderRepo()->save($order); } - $this->getOrderRepo()->save($order); + + $this->getLogger()->info('addInvoiceData success', $this->getLogContext($orders, $invoice)); + } catch (\Exception $e) { + $this->getLogger()->error( + sprintf('addInvoiceData failed: %s', $e->getMessage()), + $this->getLogContext($orders, $invoice) + ); + + throw new LocalizedException( + new Phrase($e->getMessage()) + ); } } @@ -238,4 +273,20 @@ private function processFailedPayment(array $orderIds, string $failureReason = ' )); $this->_redirect('checkout/cart', ['_secure' => false]); } + + /** + * @param array $orders + * @param array $invoice + * @return array + */ + protected function getLogContext(array $orders, array $invoice = []): array + { + $context['order_ids'] = array_map(function (Order $order) { + return $order->getIncrementId(); + }, $orders); + if (!empty($invoice) && !empty($invoice['id'])) { + $context['xendit_transaction_id'] = $invoice['id']; + } + return $context; + } } diff --git a/Controller/Checkout/Notification.php b/Controller/Checkout/Notification.php index f37357d7..0736ca49 100644 --- a/Controller/Checkout/Notification.php +++ b/Controller/Checkout/Notification.php @@ -12,6 +12,7 @@ use Magento\Framework\Exception\LocalizedException; use Magento\Framework\Phrase; use Magento\Framework\Webapi\Exception; +use Magento\Sales\Api\Data\TransactionInterface; use Magento\Sales\Model\Order; use Magento\Sales\Model\Order\Payment\Transaction; use Magento\Sales\Model\OrderFactory; @@ -143,18 +144,16 @@ public function validateForCsrf(RequestInterface $request): ?bool */ public function execute() { - try { - $post = $this->getRequest()->getContent(); - $callbackPayload = json_decode($post, true); - - $this->logger->info("callbackPayload"); - $this->logger->info($post); + $post = $this->getRequest()->getContent(); + $callbackPayload = json_decode($post, true); + $this->logger->info("callbackPayload", $callbackPayload); + try { // Invoice: Regular CC, Ewallet, Retail Outlet, PayLater return $this->handleInvoiceCallback($callbackPayload); } catch (\Exception $e) { $message = "Error invoice callback: " . $e->getMessage(); - $this->logger->info($message); + $this->logger->error($message, $callbackPayload); $result = $this->jsonResultFactory->create(); /** You may introduce your own constants for this custom REST API */ @@ -179,11 +178,12 @@ protected function isXenditInvoicePaid(string $status): bool /** * @param string $message - * @return void + * @param array $context + * @return \Magento\Framework\Controller\Result\Json */ - protected function responseSuccess(string $message) + protected function responseSuccess(string $message, array $context = []) { - $this->logger->info($message); + $this->logger->info($message, $context); $result = $this->jsonResultFactory->create(); $result->setData([ 'status' => __('SUCCESS'), @@ -195,11 +195,12 @@ protected function responseSuccess(string $message) /** * @param string $message * @param string $status + * @param array $context * @return \Magento\Framework\Controller\Result\Json */ - protected function responseError(string $message, string $status = 'ERROR') + protected function responseError(string $message, string $status = 'ERROR', array $context = []) { - $this->logger->error($message); + $this->logger->error($message, $context); $result = $this->jsonResultFactory->create(); /** You may introduce your own constants for this custom REST API */ $result->setHttpResponseCode(Exception::HTTP_BAD_REQUEST); @@ -211,13 +212,69 @@ protected function responseError(string $message, string $status = 'ERROR') return $result; } + /** + * @param string $incrementId + * @return int|null + * @throws \Exception + */ + protected function getOrderByIncrementId(string $incrementId) + { + try { + $order = $this->xenditModel->getOrderByIncrementId($incrementId); + $this->logger->info('getOrderByIncrementId', ['increment_id' => $incrementId, 'order_id' => $order->getEntityId()]); + + return $order->getEntityId(); + } catch (\Exception $ex) { + $this->logger->error($ex->getMessage(), ['order_id' => $incrementId]); + throw new \Exception(__('#%1: %2', $incrementId, $ex->getMessage())); + } + } + + /** + * @param string $successUrl + * @return bool + */ + protected function isMultiShippingOrder(string $successUrl): bool + { + $parseUrl = parse_url($successUrl); + if (empty($parseUrl['query'])) { + return false; + } + parse_str($parseUrl['query'], $params); + return !empty($params['type']) && $params['type'] === 'multishipping'; + } + + /** + * @param array $invoice + * @return array + * @throws \Exception + */ + protected function extractOrderIdsFromXenditInvoice(array $invoice): array + { + $orderIds = $this->xenditModel->getOrderIdsByTransactionId($invoice['id']); + if (empty($orderIds)) { + // Give the second chance to get order from callback description (order_id) + if (!empty($invoice['success_redirect_url']) && + $this->isMultiShippingOrder($invoice['success_redirect_url'])) { + $orderIds = array_map('trim', explode('-', $invoice['description'])); + + $this->logger->info('multiShippingOrder', ['order_ids' => $orderIds]); + } else { + $orderIds[] = $this->getOrderByIncrementId($invoice['description']); + } + } + return $orderIds; + } + /** * @param $callbackPayload * @return \Magento\Framework\Controller\Result\Json|null * @throws LocalizedException + * @throws \Magento\Framework\Exception\AlreadyExistsException * @throws \Magento\Framework\Exception\InputException * @throws \Magento\Framework\Exception\NoSuchEntityException * @throws \Magento\Payment\Gateway\Http\ClientException + * @throws \Exception */ public function handleInvoiceCallback($callbackPayload) { @@ -227,10 +284,6 @@ public function handleInvoiceCallback($callbackPayload) $description = $callbackPayload['description']; $transactionId = $callbackPayload['id']; - $orderIds = $this->xenditModel->getOrderIdsByTransactionId($transactionId); - if (empty($orderIds)) { - return $this->responseError(__('No order(s) found for transaction id %1', $transactionId)); - } // Check if Xendit invoice exists on Xendit $invoice = $this->getXenditInvoice($transactionId); @@ -238,6 +291,11 @@ public function handleInvoiceCallback($callbackPayload) return $this->responseError(__('The transaction id does not exist')); } + $orderIds = $this->extractOrderIdsFromXenditInvoice($invoice); + if (empty($orderIds)) { + return $this->responseError(__('No order(s) found for transaction id %1', $transactionId)); + } + $result = null; foreach ($orderIds as $orderId) { $order = $this->orderRepository->get($orderId); @@ -259,15 +317,13 @@ public function handleInvoiceCallback($callbackPayload) */ private function checkOrder(Order $order, $callbackPayload, $invoice, $callbackDescription) { - // Check if order exists in Magento - if (empty($order)) { - return $this->responseError(__('Order not found')); - } - // Start check order - $this->logger->info("checkOrder"); $transactionId = $callbackPayload['id']; $paymentStatus = $invoice['status']; + $this->logger->info( + "checkOrder", + ['order_id' => $order->getIncrementId(), 'xendit_transaction_id' => $transactionId, 'status' => $paymentStatus] + ); // Check if order is canceled try { @@ -281,24 +337,32 @@ private function checkOrder(Order $order, $callbackPayload, $invoice, $callbackD // Check if order already created invoice if (!$order->canInvoice()) { - return $this->responseSuccess(__('Order is already processed')); + return $this->responseSuccess( + __('Order is already processed'), + ['order_id' => $order->getIncrementId()] + ); } // Check if the Xendit invoice not belong to the order if (isset($invoice['description']) && $invoice['description'] !== $callbackDescription) { - return $this->responseError(__('Invoice is not for this order')); + return $this->responseError( + __('Invoice is not for this order'), + __('ERROR'), + ['callback_description' => $callbackDescription, 'invoice_description' => $invoice['description']] + ); } // Start update the order status $this->logger->info($paymentStatus); if ($this->isXenditInvoicePaid($paymentStatus)) { + // Change order status $order->setState(Order::STATE_PROCESSING) ->setStatus(Order::STATE_PROCESSING) ->addCommentToStatusHistory("Xendit payment completed. Transaction ID: $transactionId"); $payment = $order->getPayment(); $payment->setTransactionId($transactionId); - $payment->addTransaction(Transaction::TYPE_CAPTURE, null, true); + $payment->addTransaction(TransactionInterface::TYPE_CAPTURE, null, true); if (!empty($invoice['credit_card_charge_id'])) { $payment->setAdditionalInformation('xendit_charge_id', $invoice['credit_card_charge_id']); @@ -309,11 +373,20 @@ private function checkOrder(Order $order, $callbackPayload, $invoice, $callbackD $payment->setAdditionalInformation('xendit_installment', $callbackPayload['installment']); $payment->save(); } + + // insert xendit_transaction_id if order missing this + if (empty($order->getXenditTransactionId())) { + $order->setXenditTransactionId($transactionId); + } + $this->orderRepository->save($order); // Create invoice for order $this->invoiceOrder($order, $transactionId); - return $this->responseSuccess(__('Transaction paid')); + return $this->responseSuccess( + __('Transaction paid'), + ['order_id' => $order->getIncrementId(), 'xendit_transaction_id' => $transactionId] + ); } else { //FAILED or EXPIRED if ($order->getStatus() != Order::STATE_CANCELED) { $this->getCheckoutHelper() @@ -325,7 +398,11 @@ private function checkOrder(Order $order, $callbackPayload, $invoice, $callbackD "Xendit payment " . strtolower($paymentStatus) . ". Transaction ID: $transactionId" ); $this->orderRepository->save($order); - return $this->responseError(__('Transaction not paid'), __('FAILED')); + return $this->responseError( + __('Transaction not paid'), + __('FAILED'), + ['order_id' => $order->getIncrementId(), 'xendit_transaction_id' => $transactionId] + ); } } @@ -338,8 +415,7 @@ private function getXenditInvoice($invoiceId) { $invoiceUrl = $this->dataHelper->getXenditApiUrl() . "/payment/xendit/invoice/$invoiceId"; - $this->logger->info("getXenditInvoice"); - $this->logger->info($invoiceUrl); + $this->logger->info("getXenditInvoice", ['get_invoice_url' => $invoiceUrl]); $invoiceMethod = Request::METHOD_GET; try { @@ -354,13 +430,14 @@ private function getXenditInvoice($invoiceId) } /** - * @param $order - * @param $transactionId + * @param Order $order + * @param string $transactionId + * @return void * @throws LocalizedException */ - private function invoiceOrder($order, $transactionId) + private function invoiceOrder(Order $order, string $transactionId) { - $this->logger->info("invoiceOrder"); + $this->logger->info("invoiceOrder", ['order_id' => $order->getIncrementId(), 'xendit_transaction_id' => $transactionId]); if (!$order->canInvoice()) { throw new LocalizedException( __('Cannot create an invoice.') diff --git a/Helper/Checkout.php b/Helper/Checkout.php index d96df19c..d686fb7a 100644 --- a/Helper/Checkout.php +++ b/Helper/Checkout.php @@ -169,12 +169,12 @@ public function cancelOrder(Order $order, string $comment = "") */ public function processOrdersFailedPayment(array $orderIds, string $failureReason = 'Unexpected Error with empty charge') { - foreach ($orderIds as $key => $value) { - $order = $this->orderRepository->get($value); + foreach ($orderIds as $orderId) { + $order = $this->orderRepository->get($orderId); $orderState = Order::STATE_CANCELED; $order->setState($orderState) ->setStatus($orderState) - ->addCommentToStatusHistory("Order #" . $value . " was rejected by Xendit because " . $failureReason); + ->addCommentToStatusHistory("Order #" . $orderId . " was rejected by Xendit because " . $failureReason); $order = $this->orderRepository->save($order); $quoteId = $order->getQuoteId(); diff --git a/Helper/Data.php b/Helper/Data.php index eac6b609..b1267820 100644 --- a/Helper/Data.php +++ b/Helper/Data.php @@ -30,7 +30,7 @@ */ class Data extends AbstractHelper { - const XENDIT_M2INVOICE_VERSION = '10.0.2'; + const XENDIT_M2INVOICE_VERSION = '10.0.3'; /** * @var StoreManagerInterface @@ -449,7 +449,7 @@ public function xenditPaymentMethod($payment) // method name => frontend routing $listPayment = $this->getXenditPaymentList(); $response = false; - if (!!array_key_exists($payment, $listPayment)) { + if (array_key_exists($payment, $listPayment)) { $response = $listPayment[$payment]; } @@ -557,7 +557,7 @@ public function getCreditCardImages(string $code) } }, explode(",", $cardImages) ?? []), function ($item) { - return !!$item; + return $item; } ); } diff --git a/Helper/Metric.php b/Helper/Metric.php index b23669e0..ccd96d95 100644 --- a/Helper/Metric.php +++ b/Helper/Metric.php @@ -70,13 +70,13 @@ public function sendMetric(string $name, array $tags, string $error_code = '') * Log metrics to Datadog for monitoring * * @param array $requestData - * @return void + * @return mixed|void * @throws \Exception */ public function trackMetricCount(array $requestData) { try { - $this->apiRequestHelper->request( + return $this->apiRequestHelper->request( $this->dataHelper->getXenditApiUrl() . "/log/metrics/count", \Zend\Http\Request::METHOD_POST, $requestData diff --git a/Logger/Handler.php b/Logger/Handler.php index 4f966825..cb244821 100644 --- a/Logger/Handler.php +++ b/Logger/Handler.php @@ -1,9 +1,11 @@ scopeConfig = $scopeConfig; + parent::__construct($filesystem, null, null); + } + + /** + * @param array $record + * @return bool + */ + public function isHandling(array $record): bool + { + $isDebugEnabled = (bool)$this->scopeConfig->getValue("payment/xendit/debug", ScopeInterface::SCOPE_STORE); + if ($isDebugEnabled) { + return true; + } + + return $record['level'] >= \Monolog\Logger::WARNING; + } } diff --git a/Model/Payment/Xendit.php b/Model/Payment/Xendit.php index 78cfd397..c3d1ecf4 100644 --- a/Model/Payment/Xendit.php +++ b/Model/Payment/Xendit.php @@ -4,6 +4,7 @@ use Magento\Directory\Helper\Data as DirectoryHelper; use Magento\Framework\Api\SearchCriteriaBuilder; +use Magento\Framework\Exception\NoSuchEntityException; use Magento\Sales\Api\Data\OrderInterface; use Magento\Sales\Model\OrderRepository; use Xendit\M2Invoice\Logger\Logger as XenditLogger; @@ -230,4 +231,23 @@ public function getOrderIdsByTransactionId(string $transactionId): array return $order->getId(); }, $orders->getItems()); } + + /** + * @param string $incrementId + * @return OrderInterface + * @throws NoSuchEntityException + */ + public function getOrderByIncrementId(string $incrementId): OrderInterface + { + $searchCriteria = $this->searchCriteriaBuilder->addFilter( + 'main_table.' . OrderInterface::INCREMENT_ID, + $incrementId + )->create(); + + if (!($orderItems = $this->orderRepository->getList($searchCriteria)->getItems())) { + throw new NoSuchEntityException(__('Requested order doesn\'t exist')); + } + + return reset($orderItems); + } } diff --git a/Plugin/ConfigElementGroupPlugin.php b/Plugin/ConfigElementGroupPlugin.php index 11158a3c..cab7f931 100644 --- a/Plugin/ConfigElementGroupPlugin.php +++ b/Plugin/ConfigElementGroupPlugin.php @@ -76,12 +76,14 @@ public function getCurrentCurrency() */ public function afterIsVisible(Group $group, $result) { - if (in_array($group->getId(), self::PAYMENT_GROUP) && !$group->hasChildren()) { - return false; - } + if (strpos($group->getPath(), 'xendit')) { + if (in_array($group->getId(), self::PAYMENT_GROUP) && !$group->hasChildren()) { + return false; + } - if ($this->helper->xenditPaymentMethod($group->getId())) { - return $this->helper->isAvailableOnCurrency($group->getId(), $this->getCurrentCurrency()); + if ($this->helper->xenditPaymentMethod($group->getId())) { + return $this->helper->isAvailableOnCurrency($group->getId(), $this->getCurrentCurrency()); + } } return $result; } diff --git a/composer.json b/composer.json index 3d13b701..cb99a6cb 100644 --- a/composer.json +++ b/composer.json @@ -2,7 +2,7 @@ "name": "xendit/m2invoice", "description": "Xendit Payment Gateway Module", "type": "magento2-module", - "version": "10.0.2", + "version": "10.0.3", "license": [ "GPL-3.0" ], diff --git a/etc/adminhtml/system.xml b/etc/adminhtml/system.xml index 9a9bbea1..c1f23c2d 100644 --- a/etc/adminhtml/system.xml +++ b/etc/adminhtml/system.xml @@ -154,6 +154,15 @@ required-entry + + + Magento\Config\Model\Config\Source\Yesno + + + Log path: /var/log/xendit_payment.log]]> + + + diff --git a/etc/config.xml b/etc/config.xml index b124df23..fc0f82bf 100644 --- a/etc/config.xml +++ b/etc/config.xml @@ -20,6 +20,7 @@ all magento-xendit + 0 1 diff --git a/etc/module.xml b/etc/module.xml index ac3b754c..56e6531a 100644 --- a/etc/module.xml +++ b/etc/module.xml @@ -1,4 +1,4 @@ - +