Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
3 changes: 3 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
@@ -1,3 +1,6 @@
### 1.8.0
- Monri Components GooglePay integration

### 1.7.0
- Improved Monri WebPay tokenization by using API for transaction creation.
- Added "Instant Purchase" on the product page for customers with saved Monri WebPay tokens.
Expand Down
130 changes: 130 additions & 0 deletions Controller/GooglePay/Cancel.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,130 @@
<?php
/**
* This file is part of the Monri Payments module
*
* (c) Monri Payments d.o.o.
*
* @author Favicode <contact@favicode.net>
*/

namespace Monri\Payments\Controller\GooglePay;

use Exception;
use Magento\Checkout\Model\Session;
use Magento\Framework\App\Action\Context;
use Magento\Framework\Controller\Result\Redirect;
use Magento\Framework\Controller\ResultFactory;
use Magento\Framework\Exception\InputException;
use Magento\Framework\Exception\NoSuchEntityException;
use Magento\Framework\Exception\NotFoundException;
use Magento\Payment\Gateway\Command\CommandManagerInterface;
use Magento\Payment\Model\InfoInterface;
use Magento\Payment\Model\Method\Logger;
use Magento\Sales\Model\OrderRepository;
use Monri\Payments\Controller\AbstractGatewayResponse;
use Monri\Payments\Model\GetOrderIdByIncrement;

/**
* @SuppressWarnings(PHPMD.AllPurposeAction)
*/
class Cancel extends AbstractGatewayResponse
{
/**
* @var Session
*/
private $checkoutSession;
/**
* @var Logger
*/
private $logger;

/**
* Cancel constructor.
*
* @param Context $context
* @param OrderRepository $orderRepository
* @param CommandManagerInterface $commandManager
* @param GetOrderIdByIncrement $getOrderIdByIncrement
* @param Session $checkoutSession
* @param Logger $logger
*/
public function __construct(
Context $context,
OrderRepository $orderRepository,
CommandManagerInterface $commandManager,
GetOrderIdByIncrement $getOrderIdByIncrement,
Session $checkoutSession,
Logger $logger
) {
parent::__construct($context, $orderRepository, $commandManager, $getOrderIdByIncrement);

$this->checkoutSession = $checkoutSession;
$this->logger = $logger;
}

/**
* Cancels an order.
*
* @return Redirect|void
*/
public function execute()
{
$log = [
'location' => __METHOD__,
'errors' => [],
'success' => true,
];

/** @var Redirect $resultRedirect */
$resultRedirect = $this->resultFactory->create(ResultFactory::TYPE_REDIRECT);

try {
$order = $this->getOrderById(
$this->checkoutSession->getData('last_order_id')
);

/** @var InfoInterface $payment */
$payment = $order->getPayment();

$gatewayResponse = $this->buildCancelGatewayResponse($payment);
$log['payload'] = $gatewayResponse;

$result = $this->processGatewayResponse($gatewayResponse, $payment, ['disabled' => true]);

if (isset($result['message'])) {
$log['errors'][] = 'Error processing payment: ' . $result['message'];
$this->messageManager->addNoticeMessage(__('The payment has been denied: %1', $result['message']));
} else {
$log['errors'][] = 'Error processing payment.';
$this->messageManager->addNoticeMessage(__('The payment has been denied.'));
}
} catch (InputException | NoSuchEntityException | NotFoundException $e) {
$log['errors'][] = 'Caught exception: ' . $e->getMessage();
$log['success'] = false;
$this->messageManager->addNoticeMessage(__('Order not found.'));
} catch (Exception $e) {
$log['errors'][] = 'Caught unexpected exception: ' . $e->getMessage();
$log['success'] = false;
$this->messageManager->addNoticeMessage(__('Error processing payment, please try again later.'));
} finally {
$this->checkoutSession->restoreQuote();
$this->logger->debug($log);
}

return $resultRedirect->setPath('checkout/cart');
}

/**
* Build minimal cancel response for Google Pay gateway_response command.
*
* @param InfoInterface $payment
* @return array
*/
private function buildCancelGatewayResponse(InfoInterface $payment): array
{
return [
'status' => 'declined',
'order_number' => $payment->getAdditionalInformation('monri_order_number'),
];
}
}
139 changes: 139 additions & 0 deletions Controller/GooglePay/OrderStatus.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,139 @@
<?php
/**
* This file is part of the Monri Payments module
*
* (c) Monri Payments d.o.o.
*
* @author Favicode <contact@favicode.net>
*/

namespace Monri\Payments\Controller\GooglePay;

use Exception;
use Magento\Checkout\Model\Session;
use Magento\Framework\App\Action\Action;
use Magento\Framework\App\Action\Context;
use Magento\Framework\Controller\Result\Json;
use Magento\Framework\Controller\ResultFactory;
use Magento\Framework\Exception\InputException;
use Magento\Framework\Exception\NoSuchEntityException;
use Magento\Payment\Gateway\Command\CommandManagerInterface;
use Magento\Payment\Model\Method\Logger;
use Magento\Sales\Model\OrderRepository;
use Monri\Payments\Model\GetOrderIdByIncrement;

/**
* AJAX endpoint for polling Google Pay order payment status.
*
* @SuppressWarnings(PHPMD.AllPurposeAction)
*/
class OrderStatus extends Action
{
/**
* @var Session
*/
private $checkoutSession;

/**
* @var OrderRepository
*/
private $orderRepository;

/**
* @var CommandManagerInterface
*/
private $commandManager;

/**
* @var Logger
*/
private $logger;

/**
* @var GetOrderIdByIncrement
*/
private $getOrderIdByIncrement;

/**
* OrderStatus constructor.
*
* @param Context $context
* @param Session $checkoutSession
* @param OrderRepository $orderRepository
* @param CommandManagerInterface $commandManager
* @param GetOrderIdByIncrement $getOrderIdByIncrement
* @param Logger $logger
*/
public function __construct(
Context $context,
Session $checkoutSession,
OrderRepository $orderRepository,
CommandManagerInterface $commandManager,
GetOrderIdByIncrement $getOrderIdByIncrement,
Logger $logger
) {
parent::__construct($context);

$this->checkoutSession = $checkoutSession;
$this->orderRepository = $orderRepository;
$this->commandManager = $commandManager;
$this->getOrderIdByIncrement = $getOrderIdByIncrement;
$this->logger = $logger;
}

/**
* Poll order payment status and return JSON.
*
* Returns:
* {"status": "approved"} – payment was approved
* {"status": "pending"} – payment not yet finalised
* {"status": "error", "message": "..."} – unrecoverable error
*
* @return Json
*/
public function execute()
{
$log = [
'location' => __METHOD__,
'errors' => [],
];

/** @var Json $result */
$result = $this->resultFactory->create(ResultFactory::TYPE_JSON);

try {
$orderId = $this->checkoutSession->getData('last_order_id');

if (!$orderId) {
$result->setData(['status' => 'error', 'message' => 'Order not found.']);
return $result;
}

$order = $this->orderRepository->get($orderId);
$payment = $order->getPayment();

// Run check_status which fetches the latest status from Monri API
// and stores it in payment additional information.
$this->commandManager->executeByCode('check_status', $payment);

$gatewayStatus = $payment->getAdditionalInformation('gateway_status');
$log['gateway_status'] = $gatewayStatus;

if ($gatewayStatus === 'approved') {
$result->setData(['status' => 'approved']);
} else {
$result->setData(['status' => 'pending']);
}
} catch (InputException | NoSuchEntityException $e) {
$log['errors'][] = 'Order not found: ' . $e->getMessage();
$result->setData(['status' => 'error', 'message' => 'Order not found.']);
} catch (Exception $e) {
$log['errors'][] = 'Exception: ' . $e->getMessage();
$result->setData(['status' => 'error', 'message' => 'Error checking order status.']);
} finally {
$this->logger->debug($log);
}

return $result;
}
}
26 changes: 26 additions & 0 deletions Controller/GooglePay/Payment.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,26 @@
<?php
namespace Monri\Payments\Controller\GooglePay;

use Magento\Framework\App\Action\HttpGetActionInterface;
use Magento\Framework\View\Result\PageFactory;

class Payment implements HttpGetActionInterface
{
/**
* Payment constructor.
*
* @param PageFactory $resultPageFactory
*/
public function __construct(
private PageFactory $resultPageFactory
) {
}

/**
* @inheritDoc
*/
public function execute()
{
return $this->resultPageFactory->create();
}
}
Loading