diff --git a/CHANGELOG.md b/CHANGELOG.md index 8e50606..14efd13 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,5 +1,10 @@ # CHANGELOG +## 9.0.1 (2022-12-16) +Features: +- Implement Xendit metric +- Fix get payment_method from URL query + ## 9.0.0 (2022-10-26) Features: - Add new IDR payment: Atome diff --git a/Controller/Checkout/AbstractAction.php b/Controller/Checkout/AbstractAction.php index a512b4a..530f0cc 100644 --- a/Controller/Checkout/AbstractAction.php +++ b/Controller/Checkout/AbstractAction.php @@ -27,6 +27,7 @@ use Xendit\M2Invoice\Helper\Crypto; use Xendit\M2Invoice\Helper\Data; use Xendit\M2Invoice\Helper\ErrorHandler; +use Xendit\M2Invoice\Helper\Metric; /** * Class AbstractAction @@ -146,8 +147,14 @@ abstract class AbstractAction extends Action */ private $multishipping; + /** + * @var Metric + */ + protected $metricHelper; + /** * AbstractAction constructor. + * * @param Session $checkoutSession * @param Context $context * @param CategoryFactory $categoryFactory @@ -168,6 +175,7 @@ abstract class AbstractAction extends Action * @param ErrorHandler $errorHandler * @param State $state * @param Multishipping $multishipping + * @param Metric $metricHelper */ public function __construct( Session $checkoutSession, @@ -189,7 +197,8 @@ public function __construct( CustomerSession $customerSession, ErrorHandler $errorHandler, State $state, - Multishipping $multishipping + Multishipping $multishipping, + Metric $metricHelper ) { parent::__construct($context); @@ -215,6 +224,7 @@ public function __construct( $this->errorHandler = $errorHandler; $this->state = $state; $this->multishipping = $multishipping; + $this->metricHelper = $metricHelper; } /** @@ -233,22 +243,6 @@ protected function getCheckoutSession() return $this->checkoutSession; } - /** - * @return CategoryFactory - */ - protected function getCategoryFactory() - { - return $this->categoryFactory; - } - - /** - * @return OrderFactory - */ - protected function getOrderFactory() - { - return $this->orderFactory; - } - /** * @return LoggerInterface */ @@ -479,14 +473,6 @@ protected function getXenditCallbackUrl() return $baseUrl . 'xendit/checkout/notification'; } - /** - * @return CookieManagerInterface - */ - protected function getCookieManager() - { - return $this->cookieManager; - } - protected function getStateMultishipping() { return $this->state; @@ -518,19 +504,26 @@ protected function orderValidToCreateXenditInvoice(Order $order): bool } /** - * @return mixed|string - */ - protected function getPreferredMethod() - { - $preferredMethod = $this->getRequest()->getParam('preferred_method'); - if ($preferredMethod == 'cc') { - $preferredMethod = 'CREDIT_CARD'; - } - - if ($preferredMethod == 'shopeepayph') { - $preferredMethod = 'SHOPEEPAY'; + * Get preferred payment from order + * + * @param Order $order + * @return false|string + */ + protected function getPreferredMethod(Order $order) + { + $payment = $order->getPayment(); + $preferredMethod = $this->getDataHelper()->xenditPaymentMethod( + $payment->getMethod() + ); + + switch ($preferredMethod) { + case 'cc': + return 'CREDIT_CARD'; + case 'shopeepayph': + return 'SHOPEEPAY'; + default: + return $preferredMethod; } - return $preferredMethod; } /** diff --git a/Controller/Checkout/Invoice.php b/Controller/Checkout/Invoice.php index 50d95e0..6b0d485 100644 --- a/Controller/Checkout/Invoice.php +++ b/Controller/Checkout/Invoice.php @@ -20,8 +20,8 @@ class Invoice extends AbstractAction */ public function execute() { + $order = $this->getOrder(); try { - $order = $this->getOrder(); $apiData = $this->getApiRequestData($order); if ($order->getState() === Order::STATE_NEW) { @@ -39,13 +39,24 @@ public function execute() $this->getLogger()->debug('Order in unrecognized state: ' . $order->getState()); $this->_redirect('checkout/cart'); } - } catch (\Exception $e) { + } catch (\Throwable $e) { $message = 'Exception caught on xendit/checkout/invoice: ' . $e->getMessage(); $this->getLogger()->debug('Exception caught on xendit/checkout/invoice: ' . $message); $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() + ] + ); + return $this->redirectToCart($message); } } @@ -54,6 +65,7 @@ public function execute() * @param $order * @return array|void * @throws \Magento\Framework\Exception\NoSuchEntityException + * @throws LocalizedException */ private function getApiRequestData($order) { @@ -65,9 +77,7 @@ private function getApiRequestData($order) } $orderId = $order->getRealOrderId(); - $preferredMethod = $this->getRequest()->getParam('preferred_method'); - - $shippingAddress = $order->getShippingAddress(); + $preferredMethod = $this->getPreferredMethod($order); $orderItems = $order->getAllItems(); $items = []; foreach ($orderItems as $orderItem) { @@ -115,7 +125,7 @@ private function getApiRequestData($order) */ private function createInvoice($requestData) { - $invoiceUrl = $this->getDataHelper()->getCheckoutUrl() . "/payment/xendit/invoice"; + $invoiceUrl = $this->getDataHelper()->getXenditApiUrl() . "/payment/xendit/invoice"; $invoiceMethod = Request::METHOD_POST; $invoice = ''; diff --git a/Controller/Checkout/InvoiceMultishipping.php b/Controller/Checkout/InvoiceMultishipping.php index 34970ea..849bf3c 100644 --- a/Controller/Checkout/InvoiceMultishipping.php +++ b/Controller/Checkout/InvoiceMultishipping.php @@ -15,10 +15,22 @@ class InvoiceMultishipping extends AbstractAction { /** - * @return \Magento\Framework\App\ResponseInterface|\Magento\Framework\Controller\Result\Redirect|\Magento\Framework\Controller\ResultInterface + * @return \Magento\Framework\App\ResponseInterface|\Magento\Framework\Controller\Result\Redirect|\Magento\Framework\Controller\ResultInterface|null + * @throws LocalizedException */ public function execute() { + $transactionAmount = 0; + $orderProcessed = false; + $orders = []; + $items = []; + $currency = ''; + $billingEmail = ''; + $customerObject = []; + + $orderIncrementIds = []; + $preferredMethod = ''; + try { $orderIds = $this->getMultiShippingOrderIds(); if (empty($orderIds)) { @@ -27,17 +39,6 @@ public function execute() return $this->redirectToCart($message); } - $transactionAmount = 0; - $orderProcessed = false; - $orders = []; - $items = []; - $currency = ''; - $billingEmail = ''; - $customerObject = []; - - $orderIncrementIds = []; - $preferredMethod = $this->getPreferredMethod(); - foreach ($orderIds as $orderId) { $order = $this->getOrderRepo()->get($orderId); if (!$this->orderValidToCreateXenditInvoice($order)) { @@ -46,6 +47,9 @@ public function execute() return $this->redirectToCart($message); } + if (empty($preferredMethod)) { + $preferredMethod = $this->getPreferredMethod($order); + } $orderIncrementIds[] = $order->getRealOrderId(); $orderState = $order->getState(); @@ -122,9 +126,20 @@ public function execute() $resultRedirect = $this->getRedirectFactory()->create(); $resultRedirect->setUrl($redirectUrl); return $resultRedirect; - } catch (\Exception $e) { + } catch (\Throwable $e) { $message = 'Exception caught on xendit/checkout/redirect: ' . $e->getMessage(); $this->getLogger()->info($message); + + // log metric error + $this->metricHelper->sendMetric( + 'magento2_checkout', + [ + 'type' => 'error', + 'payment_method' => $preferredMethod, + 'error_message' => $e->getMessage() + ] + ); + return $this->redirectToCart($message); } } @@ -136,7 +151,7 @@ public function execute() */ private function createInvoice($requestData) { - $invoiceUrl = $this->getDataHelper()->getCheckoutUrl() . "/payment/xendit/invoice"; + $invoiceUrl = $this->getDataHelper()->getXenditApiUrl() . "/payment/xendit/invoice"; $invoiceMethod = Request::METHOD_POST; try { diff --git a/Controller/Checkout/Notification.php b/Controller/Checkout/Notification.php index 6af0c41..f37357d 100644 --- a/Controller/Checkout/Notification.php +++ b/Controller/Checkout/Notification.php @@ -336,7 +336,7 @@ private function checkOrder(Order $order, $callbackPayload, $invoice, $callbackD */ private function getXenditInvoice($invoiceId) { - $invoiceUrl = $this->dataHelper->getCheckoutUrl() . "/payment/xendit/invoice/$invoiceId"; + $invoiceUrl = $this->dataHelper->getXenditApiUrl() . "/payment/xendit/invoice/$invoiceId"; $this->logger->info("getXenditInvoice"); $this->logger->info($invoiceUrl); diff --git a/Controller/Payment/OverviewPost.php b/Controller/Payment/OverviewPost.php index 68c08ea..81692df 100755 --- a/Controller/Payment/OverviewPost.php +++ b/Controller/Payment/OverviewPost.php @@ -142,7 +142,7 @@ public function execute() ); $this->_redirect('*/*/billing'); } - $redirect = $baseUrl . '/xendit/checkout/invoicemultishipping?preferred_method=' . $xenditPaymentMethod; + $redirect = $baseUrl . '/xendit/checkout/invoicemultishipping'; $this->_redirect($redirect); } else { //OTHERS diff --git a/Helper/ApiRequest.php b/Helper/ApiRequest.php index 97fd467..d583640 100644 --- a/Helper/ApiRequest.php +++ b/Helper/ApiRequest.php @@ -110,7 +110,7 @@ private function getHeaders($isPublicRequest, $preferredMethod = null, $customHe 'Content-Type' => 'application/json', 'x-plugin-name' => 'MAGENTO2', 'user-agent' => 'Magento 2 Module', - 'x-plugin-version' => '9.0.0' + 'x-plugin-version' => \Xendit\M2Invoice\Helper\Data::XENDIT_M2INVOICE_VERSION ]; if ($preferredMethod !== null) { diff --git a/Helper/Data.php b/Helper/Data.php index 9f46ad5..8264b84 100644 --- a/Helper/Data.php +++ b/Helper/Data.php @@ -30,6 +30,8 @@ */ class Data extends AbstractHelper { + const XENDIT_M2INVOICE_VERSION = '9.0.1'; + /** * @var StoreManagerInterface */ @@ -173,7 +175,7 @@ protected function getStoreManager() /** * @return mixed */ - public function getCheckoutUrl() + public function getXenditApiUrl() { return $this->xendit->getConfigData('xendit_url'); } diff --git a/Helper/Metric.php b/Helper/Metric.php new file mode 100644 index 0000000..b23669e --- /dev/null +++ b/Helper/Metric.php @@ -0,0 +1,87 @@ +xenditPayment = $xenditPayment; + $this->apiRequestHelper = $apiRequestHelper; + $this->dataHelper = $dataHelper; + } + + /** + * @param string $name + * @param array $tags + * @param string $error_code + * @return null + * @throws \Exception + */ + public function sendMetric(string $name, array $tags, string $error_code = '') + { + $metrics = [ + 'name' => $name, + 'additional_tags' => array_merge( + [ + 'version' => \Xendit\M2Invoice\Helper\Data::XENDIT_M2INVOICE_VERSION, + 'is_live' => $this->xenditPayment->isLive() + ], + $tags + ) + ]; + if ($error_code) { + $metrics['additional_tags']['error_code'] = $error_code; + } + return $this->trackMetricCount($metrics); + } + + /** + * Log metrics to Datadog for monitoring + * + * @param array $requestData + * @return void + * @throws \Exception + */ + public function trackMetricCount(array $requestData) + { + try { + $this->apiRequestHelper->request( + $this->dataHelper->getXenditApiUrl() . "/log/metrics/count", + \Zend\Http\Request::METHOD_POST, + $requestData + ); + } catch (LocalizedException $e) { + } + } +} diff --git a/Model/Payment/AbstractInvoice.php b/Model/Payment/AbstractInvoice.php index 14afd45..f1e5007 100755 --- a/Model/Payment/AbstractInvoice.php +++ b/Model/Payment/AbstractInvoice.php @@ -19,6 +19,7 @@ use Xendit\M2Invoice\External\Serialize\Serializer\Json as XenditSerializerJson; use Magento\Quote\Api\Data\CartInterface; use Magento\Customer\Model\Session as CustomerSession; +use Xendit\M2Invoice\Helper\Metric; /** * Class AbstractInvoice @@ -91,6 +92,8 @@ class AbstractInvoice extends AbstractMethod */ protected $customerSession; + protected $metricHelper; + /** * AbstractInvoice constructor. * @param Context $context @@ -124,7 +127,8 @@ public function __construct( CartRepositoryInterface $quoteRepository, MagentoSerializerJson $magentoSerializerJson, XenditSerializerJson $xenditSerializerJson, - CustomerSession $customerSession + CustomerSession $customerSession, + Metric $metricHelper ) { parent::__construct( $context, @@ -145,6 +149,7 @@ public function __construct( $this->magentoSerializerJson = $magentoSerializerJson; $this->xenditSerializerJson = $xenditSerializerJson; $this->customerSession = $customerSession; + $this->metricHelper = $metricHelper; if (interface_exists("Magento\Framework\Serialize\Serializer\Json")) { $this->serializer = $this->magentoSerializerJson; diff --git a/Model/Payment/CC.php b/Model/Payment/CC.php index b5fe4d3..1b59dc3 100644 --- a/Model/Payment/CC.php +++ b/Model/Payment/CC.php @@ -29,29 +29,37 @@ class CC extends AbstractInvoice /** * @param \Magento\Payment\Model\InfoInterface $payment * @param $amount - * @return $this|CC + * @return $this|void|CC * @throws \Magento\Framework\Exception\LocalizedException - * @throws \Magento\Framework\Exception\NoSuchEntityException - * @throws \Magento\Payment\Gateway\Http\ClientException */ public function refund(\Magento\Payment\Model\InfoInterface $payment, $amount) { $chargeId = $payment->getAdditionalInformation('xendit_charge_id'); - if ($chargeId) { - $order = $payment->getOrder(); - $orderId = $order->getRealOrderId(); - $canRefundMore = $payment->getCreditmemo()->getInvoice()->canRefund(); - - $refundData = [ - 'amount' => $this->getCurrency() == 'IDR' ? $this->dataHelper->truncateDecimal($amount) : $amount, - 'external_id' => $this->dataHelper->getExternalId($orderId, true) - ]; - $refund = $this->requestRefund($chargeId, $refundData); + try { + $order = $payment->getOrder(); + $orderId = $order->getRealOrderId(); + $canRefundMore = $payment->getCreditmemo()->getInvoice()->canRefund(); - $this->handleRefundResult($payment, $refund, $canRefundMore); + $refundData = [ + 'amount' => $this->getCurrency() == 'IDR' ? $this->dataHelper->truncateDecimal($amount) : $amount, + 'external_id' => $this->dataHelper->getExternalId($orderId, true) + ]; + $refund = $this->requestRefund($chargeId, $refundData); - return $this; + $this->handleRefundResult($payment, $refund, $canRefundMore); + return $this; + } catch (\Throwable $e) { + // log metric error + $this->metricHelper->sendMetric( + 'magento2_refund', + [ + 'type' => 'error', + 'payment_method' => $this->methodCode, + 'error_message' => $e->getMessage() + ] + ); + } } else { throw new \Magento\Framework\Exception\LocalizedException( __("Refund not available because there is no capture") @@ -98,7 +106,7 @@ private function handleRefundResult($payment, $refund, $canRefundMore) */ private function requestRefund($chargeId, $requestData) { - $refundUrl = $this->dataHelper->getCheckoutUrl() . "/payment/xendit/credit-card/charges/$chargeId/refund"; + $refundUrl = $this->dataHelper->getXenditApiUrl() . "/payment/xendit/credit-card/charges/$chargeId/refund"; $refundMethod = \Zend\Http\Request::METHOD_POST; try { diff --git a/composer.json b/composer.json index d488581..dc275c8 100644 --- a/composer.json +++ b/composer.json @@ -2,7 +2,7 @@ "name": "xendit/m2invoice", "description": "Xendit Payment Gateway Module", "type": "magento2-module", - "version": "9.0.0", + "version": "9.0.1", "license": [ "GPL-3.0" ], diff --git a/etc/module.xml b/etc/module.xml index 5f88b5a..fe9b2de 100644 --- a/etc/module.xml +++ b/etc/module.xml @@ -1,4 +1,4 @@ - +