diff --git a/Block/Adminhtml/System/Config/Form/Field/UpaWebhookSetting.php b/Block/Adminhtml/System/Config/Form/Field/UpaWebhookSetting.php
new file mode 100644
index 00000000..cfae33f0
--- /dev/null
+++ b/Block/Adminhtml/System/Config/Form/Field/UpaWebhookSetting.php
@@ -0,0 +1,65 @@
+scopeConfig = $scopeConfig;
+ parent::__construct($context, $data);
+ }
+
+ /**
+ * @param AbstractElement $element
+ * @return string
+ */
+ protected function _getElementHtml(AbstractElement $element)
+ {
+ $request = $this->getRequest();
+ $website = $request->getParam('website');
+ $store = $request->getParam('store');
+
+ if ($store) {
+ $scope = ScopeInterface::SCOPE_STORE;
+ $scopeId = $store;
+ } elseif ($website) {
+ $scope = ScopeInterface::SCOPE_WEBSITE;
+ $scopeId = $website;
+ } else {
+ $scope = ScopeConfigInterface::SCOPE_TYPE_DEFAULT;
+ $scopeId = null;
+ }
+
+ if ($this->scopeConfig->isSetFlag('payment/omise/is_upa_feature_flag_enabled', $scope, $scopeId)) {
+ $element->setValue('1');
+ $element->setDisabled(true);
+ $html = parent::_getElementHtml($element)
+ . '';
+ } else {
+ $html = parent::_getElementHtml($element);
+ }
+
+ return '
'
+ . $html . '
';
+ }
+}
diff --git a/Controller/Callback/UPACallback.php b/Controller/Callback/UPACallback.php
index beffef73..122eb8eb 100644
--- a/Controller/Callback/UPACallback.php
+++ b/Controller/Callback/UPACallback.php
@@ -1,21 +1,11 @@
session = $session;
$this->omise = $omise;
- $this->charge = $charge;
- $this->helper = $helper;
- $this->emailHelper = $emailHelper;
- $this->config = $config;
- $this->checkoutSession = $checkoutSession;
- $this->request = $request;
- $this->omiseCheckoutSession = $omiseCheckoutSession;
$this->omise->defineUserAgent();
$this->omise->defineApiVersion();
$this->omise->defineApiKeys();
@@ -114,7 +48,6 @@ public function __construct(
*/
public function execute()
{
- $finalPayment = [];
$order = $this->session->getLastRealOrder();
if (!$this->isValid($order)) {
@@ -126,139 +59,6 @@ public function execute()
return $this->redirect(self::PATH_SUCCESS);
}
- try {
- $payment = $order->getPayment();
- $checkoutSession = $this->getCheckoutSession($payment);
- $sessionPayments = $checkoutSession->payments;
-
- if ($checkoutSession && !is_array($sessionPayments) || empty($sessionPayments)) {
- $errorMessage = __('The payment session is invalid or no payment information was found. Please contact our support if you have any questions.');
- return $this->redirectBackToCart($order, $errorMessage);
- }
-
- $sessionStatus = $checkoutSession->status;
- $finalPayment = $this->getFinalPayment($sessionPayments, $sessionStatus);
-
- if (!empty($finalPayment) && !empty($finalPayment['charge_id'])) {
- $chargeId = $finalPayment['charge_id'];
- $charge = $this->charge->find($chargeId);
- } else {
- $errorMessage = __('The payment session is invalid or no payment information was found. Please contact our support if you have any questions.');
- return $this->redirectBackToCart($order, $errorMessage);
- }
-
- if (!$charge instanceof \Omise\Payment\Model\Api\BaseObject) {
- throw new LocalizedException(
- __('Couldn\'t retrieve charge transaction. Please contact administrator.')
- );
- }
- if ($charge instanceof \Omise\Payment\Model\Api\Error) {
- // restoring the cart
- $this->checkoutSession->restoreQuote();
- throw new LocalizedException(__($charge->getMessage()));
- }
- if ($charge->isFailed()) {
- $this->handleFailure($charge);
- return;
- }
-
- // Do not proceed if webhook is enabled
- if ($this->config->isWebhookEnabled()) {
- return $this->redirect(self::PATH_SUCCESS);
- }
-
- $payment->setTransactionId($charge->id);
- $payment->setLastTransId($charge->id);
- $payment->setAdditionalInformation('charge_id', $charge->id);
-
- if ($charge->isSuccessful()) {
- return $this->handleSuccess($order, $charge, $payment);
- }
-
- return $this->handlePending($order, $payment);
- } catch (Exception $e) {
- $this->cancel($order, $e->getMessage());
- return $this->redirect(self::PATH_CART);
- }
- }
-
- /**
- * Mark order as failed
- *
- * @param object $charge
- */
- private function handleFailure($charge)
- {
- // restoring the cart
- $this->checkoutSession->restoreQuote();
- $failureMessage = $charge->failure_message ?
- ucfirst($charge->failure_message) :
- __('Payment cancelled');
- $errorMessage = __(
- 'Payment failed. %1, please contact our support if you have any questions.',
- $failureMessage
- );
-
- // This cancels the order, logs error and displays message in cart page
- throw new \Magento\Framework\Exception\LocalizedException($errorMessage);
- }
-
- /**
- * Mark order as success
- *
- * @param object $order
- * @param object $charge
- * @param object $payment
- */
- private function handleSuccess($order, $charge, $payment)
- {
- // Update order state and status.
- $order->setState(Order::STATE_PROCESSING);
- $order->setStatus($order->getConfig()->getStateDefaultStatus(Order::STATE_PROCESSING));
-
- $invoice = $this->helper->createInvoiceAndMarkAsPaid($order, $charge->id, $charge->capture);
- $this->emailHelper->sendInvoiceAndConfirmationEmails($order);
-
- if ($charge->capture) {
- // Add transaction.
- $payment->addTransactionCommentsToOrder(
- $payment->addTransaction(Transaction::TYPE_PAYMENT, $invoice),
- __(
- $comment = __('Amount of %1 has been paid via Omise Gateway.'),
- $order->getBaseCurrency()->formatTxt($invoice->getBaseGrandTotal())
- )
- );
- }
- $order->save();
- return $this->redirect(self::PATH_SUCCESS);
- }
-
- /**
- * Mark order as pending
- *
- * @param object $order
- * @param object $payment
- */
- private function handlePending($order, $payment)
- {
- // Update order state and status.
- $order->setState(Order::STATE_PAYMENT_REVIEW);
- $order->setStatus($order->getConfig()->getStateDefaultStatus(Order::STATE_PAYMENT_REVIEW));
-
- // Add transaction.
- $transaction = $payment->addTransaction(Transaction::TYPE_PAYMENT);
- $transaction->setIsClosed(false);
- $payment->addTransactionCommentsToOrder(
- $transaction,
- __('The payment is under processing.
Due to bank processing, this might take up to an hour to
- complete. The payment status will be updated once the processing result is available (you can
- check the latest status on the Omise Dashboard).')
- );
-
- $order->save();
-
- // TODO: Should redirect users to a page that tell users that
- // their payment is in review instead of success page.
return $this->redirect(self::PATH_SUCCESS);
}
@@ -299,16 +99,6 @@ private function isValid($order)
return true;
}
- /**
- * @param \Magento\Sales\Model\Order $order
- *
- * @return \Magento\Sales\Api\Data\InvoiceInterface
- */
- protected function invoice(Order $order)
- {
- return $order->getInvoiceCollection()->getLastItem();
- }
-
/**
* @param string $path
*
@@ -330,74 +120,4 @@ protected function invalid(Order $order, $message)
$this->messageManager->addErrorMessage($message);
}
-
- /**
- * @param \Magento\Sales\Model\Order $order
- * @param \Magento\Framework\Phrase|string $message
- */
- protected function cancel(Order $order, $message)
- {
- if ($order->hasInvoices()) {
- $invoice = $this->invoice($order);
- $invoice->cancel();
- $order->addRelatedObject($invoice);
- }
-
- $order->registerCancellation($message)->save();
- $this->messageManager->addErrorMessage($message);
- }
-
- private function redirectBackToCart($order, $errorMessage)
- {
- $this->invalid($order, $errorMessage);
- $this->checkoutSession->restoreQuote();
- return $this->redirect(self::PATH_CART);
- }
-
- /**
- * @param Magento\Sales\Model\Order\Payment $payment
- * @return \Omise\Payment\Model\Api\CheckoutSession|null
- */
- private function getCheckoutSession($payment)
- {
- $sessionId = $payment->getAdditionalInformation('session_id');
- if (empty($sessionId)) {
- $this->checkoutSession->restoreQuote();
- throw new LocalizedException(
- __('Cannot retrieve a session reference id. Please contact our support to confirm your payment.')
- );
- }
-
- $checkoutSession = $this->omiseCheckoutSession->getSessionInfo($sessionId);
- return $checkoutSession;
- }
-
- /**
- * @param array $payments
- * @param string $sessionStatus
- * @return array|null
- */
- private function getFinalPayment($payments, $sessionStatus)
- {
- if (!is_array($payments) || empty($payments)) {
- return null;
- }
-
- $paymentsWithChargeId = array_filter($payments, function ($payment) {
- return !empty($payment['charge_id']);
- });
-
- if (empty($paymentsWithChargeId)) {
- return null;
- }
-
- foreach ($paymentsWithChargeId as $payment) {
- $paymentStatus = strtolower(isset($payment['status']) ? (string) $payment['status'] : '');
- if ($paymentStatus === strtolower((string) $sessionStatus)) {
- return $payment;
- }
- }
-
- return end($paymentsWithChargeId);
- }
}
diff --git a/Gateway/Request/UPAPaymentDataBuilder.php b/Gateway/Request/UPAPaymentDataBuilder.php
index af9a909e..425fe3dc 100644
--- a/Gateway/Request/UPAPaymentDataBuilder.php
+++ b/Gateway/Request/UPAPaymentDataBuilder.php
@@ -12,6 +12,11 @@
class UPAPaymentDataBuilder implements BuilderInterface
{
+ /**
+ * URL for omise upa dynamic webhook.
+ */
+ const WEBHOOK_URI = 'omise/callback/webhook';
+
/**
* @var Resolver
*/
@@ -74,6 +79,8 @@ public function build(array $buildSubject)
$upaThemeColor = $this->omiseHelper->getConfig('upa_theme_color', $order->getStoreId());
$upaTextColor = $this->omiseHelper->getConfig('upa_text_color', $order->getStoreId());
+ $dynamicWebhookFlag = $this->omiseHelper->getConfig('dynamic_webhooks', $order->getStoreId());
+ $webhookStatus = $this->omiseHelper->getConfig('webhook_status', $order->getStoreId());
$locale = $this->localeResolver->getLocale();
@@ -111,6 +118,9 @@ public function build(array $buildSubject)
"is_upa" => true
];
+ $webhookUrl = $store->getBaseUrl() . self::WEBHOOK_URI;
+ $payload['webhooks'] = [$webhookUrl];
+
$locale = substr(strtolower($locale), 0, 2);
if (!empty($locale)) {
$payload['locale'] = $locale;
diff --git a/Helper/OmiseHelper.php b/Helper/OmiseHelper.php
index d47b12e1..56daccee 100644
--- a/Helper/OmiseHelper.php
+++ b/Helper/OmiseHelper.php
@@ -35,6 +35,7 @@
use Omise\Payment\Model\Config\Conveniencestore;
use Omise\Payment\Model\Config\WeChatPay;
use Magento\Framework\App\Config\ScopeConfigInterface;
+use Omise\Payment\Model\Api\CheckoutSession as OmiseCheckoutSession;
class OmiseHelper extends AbstractHelper
{
@@ -219,18 +220,26 @@ class OmiseHelper extends AbstractHelper
* @var ScopeConfigInterface
*/
protected $scopeConfig;
+
+ /**
+ * @var OmiseCheckoutSession
+ */
+ protected $omiseCheckoutSession;
/**
* @param Header $header
* @param Config $config
* @param ScopeConfigInterface $scopeConfig
+ * @param OmiseCheckoutSession $omiseCheckoutSession
*/
public function __construct(
Config $config,
- ScopeConfigInterface $scopeConfig
+ ScopeConfigInterface $scopeConfig,
+ OmiseCheckoutSession $omiseCheckoutSession
) {
$this->config = $config;
$this->scopeConfig = $scopeConfig;
+ $this->omiseCheckoutSession = $omiseCheckoutSession;
$this->omisePaymentMethods = array_merge(
$this->offsitePaymentMethods,
$this->offlinePaymentMethods,
@@ -272,7 +281,7 @@ public function isAllowUpa($methodCode)
*/
public function checkoutSessionEndpoint()
{
- return "https://checkout-page.omise.co/";
+ return $this->config->checkoutSessionEndpoint();
}
/**
@@ -400,7 +409,7 @@ public function isOrderOmisePayment($order)
$payment = $order->getPayment();
$method = $payment->getMethodInstance();
$methodCode = $method->getCode();
- return strpos($methodCode, "omise") > -1;
+ return strpos($methodCode, 'omise') !== false;
}
/**
@@ -420,7 +429,26 @@ public function canOrderStatusAutoSync($order)
public function getOrderChargeId($order)
{
if ($this->isOrderOmisePayment($order)) {
- return $order->getPayment()->getAdditionalInformation('charge_id');
+ if($order->getPayment()->getAdditionalInformation('charge_id')) {
+ return $order->getPayment()->getAdditionalInformation('charge_id');
+ }
+ if ($order->getPayment()->getAdditionalInformation('session_id')){
+ $payment = $order->getPayment();
+ $sessionId = $payment->getAdditionalInformation('session_id');
+ $this->config->setStoreId($order->getStoreId());
+ $checkoutSession = $this->omiseCheckoutSession->getSessionInfo($sessionId);
+
+ if($checkoutSession) {
+ $sessionPayments = $checkoutSession->payments;
+ $sessionStatus = $checkoutSession->status;
+ if (is_array($sessionPayments) && !empty($sessionPayments)) {
+ $finalPayment = $this->getFinalPayment($sessionPayments, $sessionStatus);
+ if (!empty($finalPayment) && !empty($finalPayment['charge_id'])) {
+ return $finalPayment['charge_id'];
+ }
+ }
+ }
+ }
}
}
@@ -522,4 +550,32 @@ public function hasShopeepayFailed($paymentMethod, $isChargeSuccess)
{
return $paymentMethod === 'omise_offsite_shopeepay' && !$isChargeSuccess;
}
+
+ /**
+ * @param array $payments
+ * @param string $sessionStatus
+ * @return array|null
+ */
+ private function getFinalPayment($payments, $sessionStatus)
+ {
+ if (!is_array($payments) || empty($payments)) {
+ return null;
+ }
+
+ $paymentsWithChargeId = array_filter($payments, function ($payment) {
+ return !empty($payment['charge_id']);
+ });
+
+ if (empty($paymentsWithChargeId)) {
+ return null;
+ }
+
+ foreach ($paymentsWithChargeId as $payment) {
+ $paymentStatus = strtolower(isset($payment['status']) ? (string) $payment['status'] : '');
+ if ($paymentStatus === strtolower((string) $sessionStatus)) {
+ return $payment;
+ }
+ }
+ return end($paymentsWithChargeId);
+ }
}
diff --git a/Model/Api/CheckoutSession.php b/Model/Api/CheckoutSession.php
index 1d0e29ba..b3cd061a 100644
--- a/Model/Api/CheckoutSession.php
+++ b/Model/Api/CheckoutSession.php
@@ -5,7 +5,6 @@
use Exception;
use OmiseApiResource;
use Omise\Payment\Model\Config\Config;
-use Omise\Payment\Helper\OmiseHelper;
use Omise\Payment\Helper\RequestHelper;
use Magento\Framework\Exception\LocalizedException;
@@ -18,26 +17,18 @@ class CheckoutSession extends BaseObject
*/
private $requestHelper;
- /**
- * @var OmiseHelper
- */
- private $omiseHelper;
-
/**
* Injecting dependencies
*
* @param Config $config
* @param RequestHelper $requestHelper
- * @param OmiseHelper $omiseHelper
*/
public function __construct(
Config $config,
- RequestHelper $requestHelper,
- OmiseHelper $omiseHelper
+ RequestHelper $requestHelper
) {
$this->requestHelper = $requestHelper;
$this->config = $config;
- $this->omiseHelper = $omiseHelper;
}
/**
@@ -49,7 +40,7 @@ public function __construct(
public function createSession($params)
{
try {
- $endpoint = $this->omiseHelper->checkoutSessionEndpoint();
+ $endpoint = $this->config->checkoutSessionEndpoint();
$session = $this->requestHelper->sendUpaSessionRequest(
$endpoint."api/sessions",
OmiseApiResource::REQUEST_POST,
@@ -73,7 +64,7 @@ public function createSession($params)
public function getSessionInfo($sessionId)
{
try {
- $endpoint = $this->omiseHelper->checkoutSessionEndpoint();
+ $endpoint = $this->config->checkoutSessionEndpoint();
$session = $this->requestHelper->sendUpaSessionRequest(
$endpoint."api/sessions/".$sessionId,
OmiseApiResource::REQUEST_GET,
diff --git a/Model/Config/Config.php b/Model/Config/Config.php
index fdc9e279..1c19e4eb 100644
--- a/Model/Config/Config.php
+++ b/Model/Config/Config.php
@@ -64,6 +64,14 @@ public function canInitialize()
return $this->canInitialize;
}
+ /**
+ * @return string
+ */
+ public function checkoutSessionEndpoint()
+ {
+ return 'https://checkout-page.omise.co/';
+ }
+
/**
* Change the store ID from the default store to fetch store specific values
*
diff --git a/Model/SyncStatus.php b/Model/SyncStatus.php
index d4504672..0038be43 100644
--- a/Model/SyncStatus.php
+++ b/Model/SyncStatus.php
@@ -123,6 +123,11 @@ private function markPaymentSuccessful($order, $charge)
$this->helper->createInvoiceAndMarkAsPaid($order, $charge['id']);
$this->emailHelper->sendInvoiceAndConfirmationEmails($order);
+ $payment = $order->getPayment();
+ $payment->setTransactionId($charge['id']);
+ $payment->setLastTransId($charge['id']);
+ $payment->setAdditionalInformation('charge_id', $charge['id']);
+
$order->addStatusHistoryComment(
__(
'Omise: Payment successful.
An amount %1 %2 has been paid (manual sync).',
diff --git a/Observer/WebhookObserver/WebhookCompleteObserver.php b/Observer/WebhookObserver/WebhookCompleteObserver.php
index 256b7554..d04014c2 100644
--- a/Observer/WebhookObserver/WebhookCompleteObserver.php
+++ b/Observer/WebhookObserver/WebhookCompleteObserver.php
@@ -102,6 +102,13 @@ private function processOrder($isCaptured = true)
$isCaptured
);
+ // Set the charge transaction IDs for UPA payments created through a checkout session.
+ if ($this->payment->getAdditionalInformation('session_id')) {
+ $this->payment->setTransactionId($this->charge->id);
+ $this->payment->setLastTransId($this->charge->id);
+ $this->payment->setAdditionalInformation('charge_id', $this->charge->id);
+ }
+
$this->emailHelper->sendInvoiceAndConfirmationEmails($this->orderData);
// addTransactionCommentsToOrder with message for authorise or capture
diff --git a/Plugin/ConfigSectionPaymentPlugin.php b/Plugin/ConfigSectionPaymentPlugin.php
index 0282955a..10499036 100644
--- a/Plugin/ConfigSectionPaymentPlugin.php
+++ b/Plugin/ConfigSectionPaymentPlugin.php
@@ -84,6 +84,14 @@ public function beforeSave(CoreConfig $coreConfig)
//on the admin setting page the setting value will inherit from website scope
$this->parentScopeType = $this->retrieveParentScope($coreConfig);
$omiseConfigData = $coreConfig->toArray()['groups']['omise'];
+ if (!empty($omiseConfigData['fields']['is_upa_feature_flag_enabled']['value'])) {
+ $groups = $coreConfig->getGroups();
+ $groups['omise']['fields']['webhook_status'] = ['value' => 1];
+ $groups['omise']['fields']['dynamic_webhooks'] = ['value' => 1];
+ $coreConfig->setData('groups', $groups);
+ $omiseConfigData['fields']['webhook_status'] = ['value' => 1];
+ $omiseConfigData['fields']['dynamic_webhooks'] = ['value' => 1];
+ }
$keys = $this->getKeys($omiseConfigData);
// if both keys are empty then we ignore the check.
diff --git a/Test/Unit/Controller/Callback/UPACallbackTest.php b/Test/Unit/Controller/Callback/UPACallbackTest.php
index 239d2a5f..0ad9ad82 100644
--- a/Test/Unit/Controller/Callback/UPACallbackTest.php
+++ b/Test/Unit/Controller/Callback/UPACallbackTest.php
@@ -4,18 +4,11 @@
use Magento\Checkout\Model\Session;
use Magento\Framework\App\Action\Context;
-use Magento\Framework\App\Request\Http;
use Magento\Framework\Controller\Result\Redirect;
use Magento\Framework\Message\ManagerInterface;
use Magento\Sales\Model\Order;
use Magento\Sales\Model\Order\Payment;
-use Magento\Sales\Model\Order\Payment\Transaction;
use Omise\Payment\Controller\Callback\UPACallback;
-use Omise\Payment\Helper\OmiseEmailHelper;
-use Omise\Payment\Helper\OmiseHelper;
-use Omise\Payment\Model\Api\Charge;
-use Omise\Payment\Model\Api\CheckoutSession;
-use Omise\Payment\Model\Config\Cc;
use Omise\Payment\Model\Omise;
use PHPUnit\Framework\TestCase;
@@ -27,1050 +20,126 @@ class UPACallbackTest extends TestCase
private $context;
private $session;
private $omise;
- private $charge;
- private $helper;
- private $emailHelper;
- private $config;
- private $checkoutSession;
- private $request;
- private $omiseCheckoutSession;
private $messageManager;
- private const ORDER_ID = 1;
- private const SESSION_ID = 'session_123';
- private const CHARGE_ID = 'chrg_test_123';
protected function setUp(): void
{
$this->context = $this->createMock(Context::class);
-
$this->session = $this->createMock(Session::class);
$this->omise = $this->createMock(Omise::class);
- $this->charge = $this->createMock(Charge::class);
- $this->helper = $this->createMock(OmiseHelper::class);
- $this->emailHelper = $this->createMock(OmiseEmailHelper::class);
- $this->config = $this->createMock(Cc::class);
- $this->request = $this->createMock(Http::class);
-
- $this->checkoutSession = $this->createMock(
- \Magento\Checkout\Model\Session::class
- );
-
- $this->omiseCheckoutSession = $this->createMock(
- \Omise\Payment\Model\Api\CheckoutSession::class
- );
-
$this->messageManager = $this->createMock(ManagerInterface::class);
$this->context->method('getMessageManager')
->willReturn($this->messageManager);
-
- $this->omise->method('defineUserAgent');
- $this->omise->method('defineApiVersion');
- $this->omise->method('defineApiKeys');
}
private function getController()
{
- $controller = $this->getMockBuilder(UPACallback::class)
- ->setConstructorArgs(
- [
- $this->context,
- $this->session,
- $this->omise,
- $this->charge,
- $this->helper,
- $this->emailHelper,
- $this->config,
- $this->checkoutSession,
- $this->request,
- $this->omiseCheckoutSession
- ]
- )
- ->onlyMethods(['_redirect', 'getRequest'])
- ->getMock();
-
- $controller->method('getRequest')
- ->willReturn($this->request);
-
- return $controller;
- }
-
- /**
- * @param Payment|null $payment
- * @param int|null $id
- * @param string $state
- * @return Order
- */
- private function createOrder(
- ?Payment $payment = null,
- ?int $id = null,
- bool $allowstatus = false,
- string $state = Order::STATE_PENDING_PAYMENT
- ): Order {
- if ($allowstatus) {
- return $this->createConfiguredMock(Order::class, [
- 'getId' => $id,
- 'getPayment' => $payment,
- 'getState' => $state,
- ]);
- }
- return $this->createConfiguredMock(Order::class, [
- 'getId' => $id,
- 'getPayment' => $payment
- ]);
- }
-
- /**
- * @param string $sessionId
- * @param string $method
- * @return Payment
- */
- private function createPayment(
- string $sessionId = '',
- bool $allowMethod = false,
- string $method = 'omise_promptpay'
- ): Payment {
- if ($allowMethod) {
- return $this->createConfiguredMock(Payment::class, [
- 'getAdditionalInformation' => $sessionId,
- 'getMethod' => $method
- ]);
- }
- return $this->createConfiguredMock(Payment::class, [
- 'getAdditionalInformation' => $sessionId,
- ]);
- }
-
- /**
- * @param array $payments
- * @return \stdClass
- */
- private function createSessionInfo(
- array $payments,
- string $status = ''
- ): \stdClass {
- $sessionInfo = new \stdClass();
- $sessionInfo->payments = $payments;
- $sessionInfo->status = $status;
-
- return $sessionInfo;
- }
-
- /**
- * Invoke the private payment selection method.
- *
- * @param array $payments
- * @param string $sessionStatus
- * @return array|null
- */
- private function getFinalPayment(array $payments, string $sessionStatus = '')
- {
- $controller = $this->getController();
- $method = new \ReflectionMethod(UPACallback::class, 'getFinalPayment');
- $method->setAccessible(true);
-
- return $method->invoke($controller, $payments, $sessionStatus);
- }
-
- /**
- * @covers \Omise\Payment\Controller\Callback\UPACallback::getFinalPayment
- * @uses \Omise\Payment\Controller\Callback\UPACallback::__construct
- */
- public function testGetFinalPaymentReturnsNullWhenAllPaymentsLackChargeId()
- {
- $payments = [
- ['status' => 'pending'],
- ['status' => 'failed'],
- ];
-
- $this->assertNull(
- $this->getFinalPayment($payments, 'failed')
- );
- }
-
- /**
- * @covers \Omise\Payment\Controller\Callback\UPACallback::getFinalPayment
- * @uses \Omise\Payment\Controller\Callback\UPACallback::__construct
- */
- public function testGetFinalPaymentReturnsPaymentMatchingSessionStatus()
- {
- $payments = [
- ['status' => 'pending', 'charge_id' => 'chrg_pending'],
- ['status' => 'SUCCESSFUL', 'charge_id' => self::CHARGE_ID],
- ['status' => 'successful'],
- ];
-
- $this->assertSame(
- $payments[1],
- $this->getFinalPayment($payments, 'successful')
- );
- }
-
- /**
- * @covers \Omise\Payment\Controller\Callback\UPACallback::getFinalPayment
- * @uses \Omise\Payment\Controller\Callback\UPACallback::__construct
- */
- public function testGetFinalPaymentReturnsLastPaymentWithChargeIdAsFallback()
- {
- $payments = [
- ['status' => 'pending', 'charge_id' => 'chrg_pending'],
- ['status' => 'failed'],
- ['status' => 'processing', 'charge_id' => self::CHARGE_ID],
- ];
-
- $this->assertSame(
- $payments[2],
- $this->getFinalPayment($payments, 'successful')
- );
- }
-
- /**
- * @covers \Omise\Payment\Controller\Callback\UPACallback
- */
- public function testExecuteWithSuccessfulCharge()
- {
- $payment = $this->createPayment(self::SESSION_ID, true, 'omise_promptpay');
- $order = $this->createOrder($payment, self::ORDER_ID, true, Order::STATE_PENDING_PAYMENT);
-
- $invoice = $this->getMockBuilder(
- \Magento\Sales\Model\Order\Invoice::class
- )
- ->disableOriginalConstructor()
- ->getMock();
-
- $transaction = $this->createMock(Transaction::class);
-
- $orderConfig = $this->createMock(
- \Magento\Sales\Model\Order\Config::class
- );
-
- $currency = $this->createMock(
- \Magento\Directory\Model\Currency::class
- );
-
- $this->session->method('getLastRealOrder')
- ->willReturn($order);
-
- $this->request->method('getParam')
- ->with('chargeId')
- ->willReturn(self::CHARGE_ID);
-
- $sessionInfo = $this->createSessionInfo([
- [
- 'charge_id' => self::CHARGE_ID,
- 'status' => 'successful'
- ]
- ], 'successful');
-
- $this->omiseCheckoutSession
- ->expects($this->once())
- ->method('getSessionInfo')
- ->with(self::SESSION_ID)
- ->willReturn($sessionInfo);
-
- $charge = $this->getMockBuilder(
- \Omise\Payment\Model\Api\BaseObject::class
- )
- ->disableOriginalConstructor()
- ->addMethods(['isFailed', 'isSuccessful'])
- ->getMock();
-
- $charge->id = self::CHARGE_ID;
-
- $charge->method('isFailed')
- ->willReturn(false);
-
- $charge->method('isSuccessful')
- ->willReturn(true);
-
- $charge->capture = true;
-
- $this->charge->expects($this->once())
- ->method('find')
- ->with(self::CHARGE_ID)
- ->willReturn($charge);
-
- $payment->expects($this->once())
- ->method('setTransactionId')
- ->with(self::CHARGE_ID)
- ->willReturnSelf();
-
- $payment->expects($this->once())
- ->method('setLastTransId')
- ->with(self::CHARGE_ID)
- ->willReturnSelf();
-
- $this->config->method('isWebhookEnabled')
- ->willReturn(false);
-
- $order->expects($this->once())
- ->method('setState')
- ->with(Order::STATE_PROCESSING)
- ->willReturnSelf();
-
- $order->method('getConfig')
- ->willReturn($orderConfig);
-
- $orderConfig->method('getStateDefaultStatus')
- ->with(Order::STATE_PROCESSING)
- ->willReturn('processing');
-
- $order->expects($this->once())
- ->method('setStatus')
- ->with('processing')
- ->willReturnSelf();
-
- $this->helper->expects($this->once())
- ->method('createInvoiceAndMarkAsPaid')
- ->with($order, self::CHARGE_ID)
- ->willReturn($invoice);
-
- $this->emailHelper->expects($this->once())
- ->method('sendInvoiceAndConfirmationEmails')
- ->with($order);
-
- $invoice->method('getBaseGrandTotal')
- ->willReturn(100);
-
- $order->method('getBaseCurrency')
- ->willReturn($currency);
-
- $currency->method('formatTxt')
- ->with(100)
- ->willReturn('100.00');
-
- $payment->expects($this->once())
- ->method('addTransaction')
- ->with(Transaction::TYPE_PAYMENT, $invoice)
- ->willReturn($transaction);
-
- $expectedMessage = __('Amount of %1 has been paid via Omise Gateway.', '100.00');
- $payment->expects($this->once())
- ->method('addTransactionCommentsToOrder')
- ->with(
- $transaction,
- $expectedMessage
- )
- ->willReturnSelf();
-
- $order->expects($this->once())
- ->method('save')
- ->willReturnSelf();
-
- $controller = $this->getController();
-
- $redirectResult = $this->createMock(Redirect::class);
-
- $controller->expects($this->once())
- ->method('_redirect')
- ->with(
- 'checkout/onepage/success',
- ['_secure' => true]
- )
- ->willReturn($redirectResult);
-
- $result = $controller->execute();
- $this->assertSame($redirectResult, $result);
- }
-
- /**
- * @covers \Omise\Payment\Controller\Callback\UPACallback
- */
- public function testExecuteWithSuccessfulAuthorizedCharge()
- {
- $payment = $this->createPayment(
- self::SESSION_ID,
- true,
- 'omise_creditcard'
- );
-
- $order = $this->createOrder(
- $payment,
- self::ORDER_ID,
- true,
- Order::STATE_PENDING_PAYMENT
- );
-
- $orderConfig = $this->createMock(
- \Magento\Sales\Model\Order\Config::class
- );
-
- $this->session->method('getLastRealOrder')
- ->willReturn($order);
-
- $this->request->method('getParam')
- ->with('chargeId')
- ->willReturn(self::CHARGE_ID);
-
- $sessionInfo = $this->createSessionInfo([
- [
- 'charge_id' => self::CHARGE_ID,
- 'status' => 'successful'
- ]
- ], 'successful');
-
- $this->omiseCheckoutSession
- ->expects($this->once())
- ->method('getSessionInfo')
- ->with(self::SESSION_ID)
- ->willReturn($sessionInfo);
-
- $charge = $this->getMockBuilder(
- \Omise\Payment\Model\Api\BaseObject::class
- )
- ->disableOriginalConstructor()
- ->addMethods(['isFailed', 'isSuccessful'])
+ return $this->getMockBuilder(UPACallback::class)
+ ->setConstructorArgs([$this->context, $this->session, $this->omise])
+ ->onlyMethods(['_redirect'])
->getMock();
-
- $charge->id = self::CHARGE_ID;
- $charge->capture = false;
-
- $charge->method('isFailed')
- ->willReturn(false);
-
- $charge->method('isSuccessful')
- ->willReturn(true);
-
- $this->charge->method('find')
- ->willReturn($charge);
-
- $payment->expects($this->once())
- ->method('setTransactionId')
- ->with(self::CHARGE_ID)
- ->willReturnSelf();
-
- $payment->expects($this->once())
- ->method('setLastTransId')
- ->with(self::CHARGE_ID)
- ->willReturnSelf();
-
- $this->config->method('isWebhookEnabled')
- ->willReturn(false);
-
- $order->expects($this->once())
- ->method('setState')
- ->with(Order::STATE_PROCESSING)
- ->willReturnSelf();
-
- $order->method('getConfig')
- ->willReturn($orderConfig);
-
- $orderConfig->method('getStateDefaultStatus')
- ->with(Order::STATE_PROCESSING)
- ->willReturn('processing');
-
- $order->expects($this->once())
- ->method('setStatus')
- ->with('processing')
- ->willReturnSelf();
-
- $this->helper->expects($this->once())
- ->method('createInvoiceAndMarkAsPaid')
- ->with($order, self::CHARGE_ID, false);
-
- $this->emailHelper->expects($this->once())
- ->method('sendInvoiceAndConfirmationEmails')
- ->with($order);
-
- // No transaction/message is created for authorized charge.
- $payment->expects($this->never())
- ->method('prependMessage');
-
- $payment->expects($this->never())
- ->method('addTransaction');
-
- $payment->expects($this->never())
- ->method('addTransactionCommentsToOrder');
-
- $order->expects($this->once())
- ->method('save')
- ->willReturnSelf();
-
- $controller = $this->getController();
-
- $redirectResult = $this->createMock(Redirect::class);
-
- $controller->expects($this->once())
- ->method('_redirect')
- ->with(
- 'checkout/onepage/success',
- ['_secure' => true]
- )
- ->willReturn($redirectResult);
-
- $this->assertSame(
- $redirectResult,
- $controller->execute()
- );
}
/**
- * @covers \Omise\Payment\Controller\Callback\UPACallback
+ * @covers ::execute
+ * @uses ::__construct
+ * @uses ::isValid
+ * @uses ::redirect
*/
- public function testExecuteWithPendingCharge()
+ public function testExecuteRedirectsValidPendingOrderToSuccess(): void
{
- $payment = $this->createPayment(self::SESSION_ID);
- $order = $this->createOrder($payment, self::ORDER_ID, true, Order::STATE_PENDING_PAYMENT);
- $transaction = $this->createMock(Transaction::class);
-
- $orderConfig = $this->createMock(\Magento\Sales\Model\Order\Config::class);
-
- $this->session->method('getLastRealOrder')
- ->willReturn($order);
-
- $this->request->method('getParam')
- ->with('chargeId')
- ->willReturn(self::CHARGE_ID);
-
- $sessionInfo = $this->createSessionInfo([
- ['charge_id' => self::CHARGE_ID]
+ $payment = $this->createMock(Payment::class);
+ $order = $this->createConfiguredMock(Order::class, [
+ 'getId' => 10,
+ 'getPayment' => $payment,
+ 'getState' => Order::STATE_PENDING_PAYMENT,
]);
-
- $this->omiseCheckoutSession
- ->expects($this->once())
- ->method('getSessionInfo')
- ->with(self::SESSION_ID)
- ->willReturn($sessionInfo);
-
- $charge = $this->getMockBuilder(
- \Omise\Payment\Model\Api\BaseObject::class
- )
- ->disableOriginalConstructor()
- ->addMethods(['isFailed', 'isSuccessful'])
- ->getMock();
-
- $charge->id = self::CHARGE_ID;
-
- $charge->method('isFailed')
- ->willReturn(false);
-
- $charge->method('isSuccessful')
- ->willReturn(false);
-
- $this->charge->expects($this->once())
- ->method('find')
- ->with(self::CHARGE_ID)
- ->willReturn($charge);
-
- $payment->expects($this->once())
- ->method('setTransactionId')
- ->with(self::CHARGE_ID)
- ->willReturnSelf();
-
- $payment->expects($this->once())
- ->method('setLastTransId')
- ->with(self::CHARGE_ID)
- ->willReturnSelf();
-
- $this->config->method('isWebhookEnabled')
- ->willReturn(false);
-
- // handlePending assertions
- $order->expects($this->once())
- ->method('setState')
- ->with(Order::STATE_PAYMENT_REVIEW)
- ->willReturnSelf();
-
- $order->method('getConfig')
- ->willReturn($orderConfig);
-
- $orderConfig->expects($this->once())
- ->method('getStateDefaultStatus')
- ->with(Order::STATE_PAYMENT_REVIEW)
- ->willReturn('payment_review');
-
- $order->expects($this->once())
- ->method('setStatus')
- ->with('payment_review')
- ->willReturnSelf();
-
- $payment->expects($this->once())
- ->method('addTransaction')
- ->with(Transaction::TYPE_PAYMENT)
- ->willReturn($transaction);
-
- $transaction->expects($this->once())
- ->method('setIsClosed')
- ->with(false)
- ->willReturnSelf();
-
- $payment->expects($this->once())
- ->method('addTransactionCommentsToOrder')
- ->with(
- $transaction,
- $this->anything()
- )
- ->willReturnSelf();
-
- $order->expects($this->once())
- ->method('save')
- ->willReturnSelf();
-
- $controller = $this->getController();
-
- $redirectResult = $this->createMock(Redirect::class);
-
- $controller->expects($this->once())
- ->method('_redirect')
- ->with(
- 'checkout/onepage/success',
- ['_secure' => true]
- )
- ->willReturn($redirectResult);
-
- $result = $controller->execute();
- $this->assertSame($redirectResult, $result);
- }
-
- /**
- * @covers \Omise\Payment\Controller\Callback\UPACallback
- */
- public function testExecuteWithChargeFailure()
- {
- $payment = $this->createPayment(self::SESSION_ID);
- $order = $this->createOrder($payment, self::ORDER_ID, true, Order::STATE_PENDING_PAYMENT);
-
- $this->session->method('getLastRealOrder')
- ->willReturn($order);
-
- $this->request->method('getParam')
- ->with('chargeId')
- ->willReturn(self::CHARGE_ID);
-
- $sessionInfo = $this->createSessionInfo([
- [
- 'charge_id' => self::CHARGE_ID,
- 'status' => 'pending'
- ]
- ], 'pending');
-
- $this->omiseCheckoutSession
- ->expects($this->once())
- ->method('getSessionInfo')
- ->with(self::SESSION_ID)
- ->willReturn($sessionInfo);
-
- $charge = $this->getMockBuilder(
- \Omise\Payment\Model\Api\BaseObject::class
- )
- ->disableOriginalConstructor()
- ->addMethods(['isFailed', 'isSuccessful'])
- ->getMock();
-
- $charge->id = self::CHARGE_ID;
- $charge->failure_message = 'bank rejected';
-
- $charge->method('isFailed')
- ->willReturn(true);
-
- $this->charge->expects($this->once())
- ->method('find')
- ->with(self::CHARGE_ID)
- ->willReturn($charge);
-
- $this->checkoutSession->expects($this->once())
- ->method('restoreQuote');
-
- $order->expects($this->once())
- ->method('hasInvoices')
- ->willReturn(false);
-
- $order->expects($this->once())
- ->method('registerCancellation')
- ->willReturnSelf();
-
- $order->expects($this->once())
- ->method('save')
- ->willReturnSelf();
-
- $this->messageManager->expects($this->once())
- ->method('addErrorMessage');
+ $this->session->method('getLastRealOrder')->willReturn($order);
+ $redirect = $this->createMock(Redirect::class);
$controller = $this->getController();
-
- $controller->expects($this->once())
- ->method('_redirect')
- ->with('checkout/cart', ['_secure' => true]);
-
- $controller->execute();
- }
-
- /**
- * @covers \Omise\Payment\Controller\Callback\UPACallback
- */
- public function testExecuteWithWebhookEnabledBuildsTransactionAndRedirectsToSuccess()
- {
- $payment = $this->createPayment(self::SESSION_ID);
- $order = $this->createOrder($payment, self::ORDER_ID, true, Order::STATE_PENDING_PAYMENT);
-
- $this->session->method('getLastRealOrder')
- ->willReturn($order);
-
- $this->request->method('getParam')
- ->with('chargeId')
- ->willReturn(self::CHARGE_ID);
-
- $sessionInfo = $this->createSessionInfo([
- [
- 'charge_id' => self::CHARGE_ID,
- 'status' => 'failed'
- ]
- ], 'failed');
-
- $this->omiseCheckoutSession
- ->expects($this->once())
- ->method('getSessionInfo')
- ->with(self::SESSION_ID)
- ->willReturn($sessionInfo);
-
- $charge = $this->getMockBuilder(
- \Omise\Payment\Model\Api\BaseObject::class
- )
- ->disableOriginalConstructor()
- ->addMethods(['isFailed', 'isSuccessful'])
- ->getMock();
-
- $charge->id = self::CHARGE_ID;
- $charge->status = 'pending';
-
- $charge->method('isFailed')
- ->willReturn(false);
-
- $charge->method('isSuccessful')
- ->willReturn(false);
-
- $this->charge->method('find')
- ->with(self::CHARGE_ID)
- ->willReturn($charge);
-
- $this->config->method('isWebhookEnabled')
- ->willReturn(true);
-
- $controller = $this->getController();
-
- $redirectResult = $this->createMock(Redirect::class);
-
$controller->expects($this->once())
->method('_redirect')
->with('checkout/onepage/success', ['_secure' => true])
- ->willReturn($redirectResult);
-
- $result = $controller->execute();
-
- $this->assertInstanceOf(Redirect::class, $result);
- $this->assertSame($redirectResult, $result);
- }
-
- /**
- * @covers \Omise\Payment\Controller\Callback\UPACallback
- */
- public function testExecuteProcessingOrderRedirectsToSuccess()
- {
- $payment = $this->createPayment(self::SESSION_ID);
- $order = $this->createOrder($payment, self::ORDER_ID);
-
- $this->session->method('getLastRealOrder')
- ->willReturn($order);
-
- $this->request->method('getParam')
- ->willReturn(self::CHARGE_ID);
-
- $order->method('getState')
- ->willReturn(Order::STATE_PROCESSING);
-
- $controller = $this->getController();
-
- $controller->expects($this->once())
- ->method('_redirect')
- ->with(
- 'checkout/onepage/success',
- ['_secure' => true]
- )
- ->willReturn($this->createMock(Redirect::class));
-
- $controller->execute();
- }
-
- /**
- * @covers \Omise\Payment\Controller\Callback\UPACallback
- */
- public function testExecuteWithMissingPayment()
- {
- $order = $this->createOrder(null, self::ORDER_ID);
-
- $this->session->method('getLastRealOrder')
- ->willReturn($order);
-
- $controller = $this->getController();
-
- $controller->expects($this->once())
- ->method('_redirect')
- ->with('checkout/cart', ['_secure' => true]);
-
- $controller->execute();
- }
-
- /**
- * @covers \Omise\Payment\Controller\Callback\UPACallback
- */
- public function testExecuteWithInvalidOrderState()
- {
- $payment = $this->createPayment(self::SESSION_ID);
- $order = $this->createOrder($payment, self::ORDER_ID, true, Order::STATE_COMPLETE);
-
- $this->session->method('getLastRealOrder')
- ->willReturn($order);
-
- $this->request->method('getParam')
- ->willReturn(self::CHARGE_ID);
-
- $controller = $this->getController();
-
- $controller->expects($this->once())
- ->method('_redirect');
+ ->willReturn($redirect);
- $controller->execute();
+ $this->assertSame($redirect, $controller->execute());
}
/**
- * @covers \Omise\Payment\Controller\Callback\UPACallback
+ * @covers ::execute
+ * @uses ::__construct
+ * @uses ::isValid
+ * @uses ::redirect
*/
- public function testExecuteWithoutSessionId()
+ public function testExecuteRedirectsProcessingOrderToSuccess(): void
{
- $payment = $this->createPayment();
- $order = $this->createOrder($payment, self::ORDER_ID, true, Order::STATE_PENDING_PAYMENT);
-
- $this->session->method('getLastRealOrder')
- ->willReturn($order);
-
- $this->checkoutSession->expects($this->once())
- ->method('restoreQuote');
-
- $order->expects($this->once())
- ->method('hasInvoices')
- ->willReturn(false);
-
- $order->expects($this->once())
- ->method('registerCancellation')
- ->willReturnSelf();
-
- $order->expects($this->once())
- ->method('save')
- ->willReturnSelf();
-
- $this->messageManager->expects($this->once())
- ->method('addErrorMessage');
+ $payment = $this->createMock(Payment::class);
+ $order = $this->createConfiguredMock(Order::class, [
+ 'getId' => 10,
+ 'getPayment' => $payment,
+ 'getState' => Order::STATE_PROCESSING,
+ ]);
+ $this->session->method('getLastRealOrder')->willReturn($order);
+ $redirect = $this->createMock(Redirect::class);
$controller = $this->getController();
-
$controller->expects($this->once())
->method('_redirect')
- ->with('checkout/cart', ['_secure' => true]);
- $this->assertSame('', $payment->getAdditionalInformation('session_id'));
- $controller->execute();
- }
-
- /**
- * @covers \Omise\Payment\Controller\Callback\UPACallback
- */
- public function testExecuteWithInvalidPaymentsArray()
- {
- $payment = $this->createPayment(self::SESSION_ID);
- $order = $this->createOrder($payment, self::ORDER_ID, true, Order::STATE_PENDING_PAYMENT);
-
- $this->session->method('getLastRealOrder')
- ->willReturn($order);
-
- $sessionInfo = new \stdClass();
- $sessionInfo->payments = null;
- $sessionInfo->status = '';
-
- $this->omiseCheckoutSession
- ->expects($this->once())
- ->method('getSessionInfo')
- ->with(self::SESSION_ID)
- ->willReturn($sessionInfo);
-
- $controller = $this->getController();
-
- $controller->expects($this->once())
- ->method('_redirect');
-
- $controller->execute();
- }
-
- /**
- * @covers \Omise\Payment\Controller\Callback\UPACallback
- */
- public function testExecuteWithInvalidPaymentsData()
- {
- $payment = $this->createPayment(self::SESSION_ID);
-
- $order = $this->createOrder($payment, self::ORDER_ID, true, Order::STATE_PENDING_PAYMENT);
-
- $this->session->method('getLastRealOrder')
- ->willReturn($order);
-
- $sessionInfo = $this->createSessionInfo([
- [
- 'status' => 'pending'
- ]
- ], 'pending');
-
- $this->omiseCheckoutSession
- ->expects($this->once())
- ->method('getSessionInfo')
- ->with(self::SESSION_ID)
- ->willReturn($sessionInfo);
-
- $controller = $this->getController();
-
- $controller->expects($this->once())
- ->method('_redirect');
+ ->with('checkout/onepage/success', ['_secure' => true])
+ ->willReturn($redirect);
- $controller->execute();
+ $this->assertSame($redirect, $controller->execute());
}
-
- /**
- * @covers \Omise\Payment\Controller\Callback\UPACallback
- */
- public function testExecuteInvalidOrderRedirectsToCart()
- {
- $order = $this->createOrder();
-
- $this->session->method('getLastRealOrder')
- ->willReturn($order);
-
- $this->request->method('getParam')
- ->with('chargeId')
- ->willReturn(self::CHARGE_ID);
-
- $controller = $this->getController();
- $controller->expects($this->once())
- ->method('_redirect')
- ->with('checkout/cart', ['_secure' => true])
- ->willReturn($this->createMock(Redirect::class));
-
- $controller->execute();
- }
-
/**
- * @covers \Omise\Payment\Controller\Callback\UPACallback
+ * @covers ::execute
+ * @uses ::__construct
+ * @uses ::isValid
+ * @uses ::redirect
*/
- public function testExecuteChargeFindThrowsException()
+ public function testExecuteRedirectsToCartWhenOrderIsMissing(): void
{
- $payment = $this->createPayment(self::SESSION_ID);
- $order = $this->createOrder($payment, self::ORDER_ID, true, Order::STATE_PENDING_PAYMENT);
-
- $this->session->method('getLastRealOrder')
- ->willReturn($order);
-
- $this->request->method('getParam')
- ->willReturn(self::CHARGE_ID);
-
- $sessionInfo = $this->createSessionInfo([
- [
- 'charge_id' => self::CHARGE_ID,
- 'status' => 'successful'
- ]
- ], 'successful');
-
- $this->omiseCheckoutSession
- ->expects($this->once())
- ->method('getSessionInfo')
- ->with(self::SESSION_ID)
- ->willReturn($sessionInfo);
-
- $this->charge->expects($this->once())
- ->method('find')
- ->willThrowException(new \Exception('API Error'));
-
- $order->expects($this->once())
- ->method('hasInvoices')
- ->willReturn(false);
-
- $order->expects($this->once())
- ->method('registerCancellation')
- ->with('API Error')
- ->willReturnSelf();
-
- $order->expects($this->once())
- ->method('save')
- ->willReturnSelf();
-
- $this->messageManager->expects($this->once())
- ->method('addErrorMessage');
+ $order = $this->createConfiguredMock(Order::class, ['getId' => null]);
+ $this->session->method('getLastRealOrder')->willReturn($order);
+ $redirect = $this->createMock(Redirect::class);
+ $this->messageManager->expects($this->once())->method('addErrorMessage');
$controller = $this->getController();
-
$controller->expects($this->once())
->method('_redirect')
->with('checkout/cart', ['_secure' => true])
- ->willReturn($this->createMock(Redirect::class));
+ ->willReturn($redirect);
- $controller->execute();
+ $this->assertSame($redirect, $controller->execute());
}
/**
- * @covers \Omise\Payment\Controller\Callback\UPACallback
- * @uses \Omise\Payment\Model\Api\Error
+ * @covers ::execute
+ * @uses ::__construct
+ * @uses ::invalid
+ * @uses ::isValid
+ * @uses ::redirect
*/
- public function testExecuteChargeErrorRestoresQuoteAndRedirectsToCart()
+ public function testExecuteRedirectsToCartWhenPaymentIsMissing(): void
{
- $payment = $this->createPayment(self::SESSION_ID);
- $order = $this->createOrder($payment, self::ORDER_ID, true, Order::STATE_PENDING_PAYMENT);
-
- $this->session->method('getLastRealOrder')
- ->willReturn($order);
-
- $this->request->method('getParam')
- ->with('chargeId')
- ->willReturn(self::CHARGE_ID);
-
- $sessionInfo = $this->createSessionInfo([
- [
- 'charge_id' => self::CHARGE_ID,
- 'status' => 'successful'
- ]
- ], 'successful');
-
- $this->omiseCheckoutSession
- ->expects($this->once())
- ->method('getSessionInfo')
- ->with(self::SESSION_ID)
- ->willReturn($sessionInfo);
-
- $this->checkoutSession->expects($this->once())
- ->method('restoreQuote');
-
- $this->charge->method('find')
- ->with(self::CHARGE_ID)
- ->willReturn(new \Omise\Payment\Model\Api\Error(['message' => 'Failed message']));
-
- $order->expects($this->once())
- ->method('hasInvoices')
- ->willReturn(false);
-
- $order->expects($this->once())
- ->method('registerCancellation')
- ->with('Failed message')
- ->willReturnSelf();
-
- $order->expects($this->once())
- ->method('save')
- ->willReturnSelf();
-
- $this->messageManager->expects($this->once())
- ->method('addErrorMessage');
+ $order = $this->createConfiguredMock(Order::class, [
+ 'getId' => 10,
+ 'getPayment' => null,
+ ]);
+ $this->session->method('getLastRealOrder')->willReturn($order);
+ $redirect = $this->createMock(Redirect::class);
+ $order->expects($this->once())->method('addStatusHistoryComment');
+ $order->expects($this->once())->method('save');
+ $this->messageManager->expects($this->once())->method('addErrorMessage');
$controller = $this->getController();
-
$controller->expects($this->once())
->method('_redirect')
->with('checkout/cart', ['_secure' => true])
- ->willReturn($this->createMock(Redirect::class));
+ ->willReturn($redirect);
- $controller->execute();
+ $this->assertSame($redirect, $controller->execute());
}
}
diff --git a/Test/Unit/Gateway/Request/UPAPaymentDataBuilderTest.php b/Test/Unit/Gateway/Request/UPAPaymentDataBuilderTest.php
index 4ff9b43d..d76ce512 100644
--- a/Test/Unit/Gateway/Request/UPAPaymentDataBuilderTest.php
+++ b/Test/Unit/Gateway/Request/UPAPaymentDataBuilderTest.php
@@ -5,7 +5,7 @@
use Magento\Framework\Locale\Resolver;
use Magento\Framework\UrlInterface;
use Magento\Payment\Gateway\Data\OrderAdapterInterface;
-use Magento\Store\Api\Data\StoreInterface;
+use Magento\Store\Model\Store;
use Magento\Store\Model\StoreManagerInterface;
use Omise\Payment\Gateway\Request\UPAPaymentDataBuilder;
use Omise\Payment\Helper\OmiseHelper;
@@ -47,7 +47,7 @@ public function testBuildReturnsPayload(): void
{
$paymentDO = $this->createMock(PaymentDataObject::class);
$payment = $this->getMockBuilder(InfoMock::class)->getMock();
- $store = $this->createMock(StoreInterface::class);
+ $store = $this->createMock(Store::class);
$order = $this->createConfiguredMock(
OrderAdapterInterface::class,
[
@@ -68,6 +68,8 @@ public function testBuildReturnsPayload(): void
$store->method('getName')
->willReturn('Default Store');
+ $store->method('getBaseUrl')
+ ->willReturn('https://example.com/');
$this->storeManager->expects($this->once())
->method('getStore')
@@ -99,11 +101,13 @@ public function testBuildReturnsPayload(): void
'https://example.com/cancel'
);
- $this->omiseHelper->expects($this->exactly(2))
+ $this->omiseHelper->expects($this->exactly(4))
->method('getConfig')
->willReturnMap([
['upa_theme_color', 1, '#000000'],
['upa_text_color', 1, '#FFFFFF'],
+ ['dynamic_webhooks', 1, '1'],
+ ['webhook_status', 1, '1'],
]);
$result = $this->builder->build([
@@ -129,6 +133,7 @@ public function testBuildReturnsPayload(): void
'theme_color' => '#000000',
'text_color' => '#FFFFFF'
],
+ 'webhooks' => ['https://example.com/omise/callback/webhook'],
'is_upa' => true,
'locale' => 'en'
], $result);
@@ -141,7 +146,7 @@ public function testBuildWithoutLocale(): void
{
$paymentDO = $this->createMock(PaymentDataObject::class);
$payment = $this->createMock(InfoMock::class);
- $store = $this->createMock(StoreInterface::class);
+ $store = $this->createMock(Store::class);
$order = $this->createConfiguredMock(
OrderAdapterInterface::class,
[
@@ -162,6 +167,8 @@ public function testBuildWithoutLocale(): void
$store->method('getName')
->willReturn('Default Store');
+ $store->method('getBaseUrl')
+ ->willReturn('https://example.com/');
$this->storeManager->method('getStore')
->willReturn($store);
@@ -173,6 +180,8 @@ public function testBuildWithoutLocale(): void
->willReturnMap([
['upa_theme_color', 1, '#000000'],
['upa_text_color', 1, '#FFFFFF'],
+ ['dynamic_webhooks', 1, '1'],
+ ['webhook_status', 1, '1'],
]);
$this->localeResolver->method('getLocale')
@@ -213,7 +222,7 @@ public function testBuildReturnsEmptyArrayWhenMethodIdIsEmpty(): void
$this->storeManager->method('getStore')
->willReturn(
- $this->createMock(StoreInterface::class)
+ $this->createMock(Store::class)
);
$this->omiseHelper->expects($this->once())
diff --git a/Test/Unit/Helper/OmiseHelperTest.php b/Test/Unit/Helper/OmiseHelperTest.php
index 0da6ee7a..fceba8e4 100644
--- a/Test/Unit/Helper/OmiseHelperTest.php
+++ b/Test/Unit/Helper/OmiseHelperTest.php
@@ -7,6 +7,7 @@
use Omise\Payment\Model\Config\Paynow;
use Omise\Payment\Model\Config\CcGooglePay;
use Omise\Payment\Model\Config\Conveniencestore;
+use Omise\Payment\Model\Api\CheckoutSession;
class OmiseHelperTest extends \PHPUnit\Framework\TestCase
{
@@ -16,6 +17,8 @@ class OmiseHelperTest extends \PHPUnit\Framework\TestCase
protected $scopeConfig;
+ protected $checkoutSession;
+
protected $model;
private $authorizeUri = 'https://somefakeuri.com/redirect';
@@ -29,7 +32,8 @@ public function setUp(): void
{
$this->configMock = $this->createMock('Omise\Payment\Model\Config\Config');
$this->scopeConfig = $this->createMock('Magento\Framework\App\Config\ScopeConfigInterface');
- $this->model = new OmiseHelper($this->configMock, $this->scopeConfig);
+ $this->checkoutSession = $this->createMock(CheckoutSession::class);
+ $this->model = new OmiseHelper($this->configMock, $this->scopeConfig, $this->checkoutSession);
}
/**
@@ -268,6 +272,10 @@ public function isAllowUpaReturnsFalseForUnsupportedMethod()
*/
public function checkoutSessionEndpointReturnsCorrectUrl()
{
+ $this->configMock->expects($this->once())
+ ->method('checkoutSessionEndpoint')
+ ->willReturn('https://checkout-page.omise.co/');
+
$this->assertEquals(
'https://checkout-page.omise.co/',
$this->model->checkoutSessionEndpoint()
diff --git a/Test/Unit/Model/Api/CheckoutSessionTest.php b/Test/Unit/Model/Api/CheckoutSessionTest.php
index ae9dca14..c365da36 100644
--- a/Test/Unit/Model/Api/CheckoutSessionTest.php
+++ b/Test/Unit/Model/Api/CheckoutSessionTest.php
@@ -8,7 +8,6 @@
use Omise\Payment\Model\Api\CheckoutSession;
use Omise\Payment\Model\Config\Config;
use Omise\Payment\Helper\RequestHelper;
-use Omise\Payment\Helper\OmiseHelper;
use OmiseApiResource;
class CheckoutSessionTest extends TestCase
@@ -23,16 +22,10 @@ class CheckoutSessionTest extends TestCase
*/
private $requestHelper;
- /**
- * @var OmiseHelper|\PHPUnit\Framework\MockObject\MockObject
- */
- private $omiseHelper;
-
protected function setUp(): void
{
$this->config = $this->createMock(Config::class);
$this->requestHelper = $this->createMock(RequestHelper::class);
- $this->omiseHelper = $this->createMock(OmiseHelper::class);
}
/**
@@ -42,8 +35,7 @@ public function testConstruct()
{
$model = new CheckoutSession(
$this->config,
- $this->requestHelper,
- $this->omiseHelper
+ $this->requestHelper
);
$this->assertInstanceOf(
@@ -70,13 +62,12 @@ public function testCreateSessionSuccess()
$model = new CheckoutSession(
$this->config,
- $this->requestHelper,
- $this->omiseHelper
+ $this->requestHelper
);
- $this->omiseHelper->expects($this->once())
+ $this->config->expects($this->once())
->method('checkoutSessionEndpoint')
- ->willReturn('https://api.omise.co/');
+ ->willReturn('https://checkout-page.omise.co/');
$this->config->expects($this->once())
->method('getSecretKey')
@@ -85,7 +76,7 @@ public function testCreateSessionSuccess()
$this->requestHelper->expects($this->once())
->method('sendUpaSessionRequest')
->with(
- 'https://api.omise.co/api/sessions',
+ 'https://checkout-page.omise.co/api/sessions',
OmiseApiResource::REQUEST_POST,
'sk_test',
$params,
@@ -115,13 +106,12 @@ public function testGetSessionInfoSuccess()
$model = new CheckoutSession(
$this->config,
- $this->requestHelper,
- $this->omiseHelper
+ $this->requestHelper
);
- $this->omiseHelper->expects($this->once())
+ $this->config->expects($this->once())
->method('checkoutSessionEndpoint')
- ->willReturn('https://api.omise.co/');
+ ->willReturn('https://checkout-page.omise.co/');
$this->config->expects($this->once())
->method('getSecretKey')
@@ -130,7 +120,7 @@ public function testGetSessionInfoSuccess()
$this->requestHelper->expects($this->once())
->method('sendUpaSessionRequest')
->with(
- 'https://api.omise.co/api/sessions/' . $sessionId,
+ 'https://checkout-page.omise.co/api/sessions/' . $sessionId,
OmiseApiResource::REQUEST_GET,
'sk_test'
)
@@ -154,13 +144,12 @@ public function testCreateSessionThrowsLocalizedException()
$model = new CheckoutSession(
$this->config,
- $this->requestHelper,
- $this->omiseHelper
+ $this->requestHelper
);
- $this->omiseHelper->expects($this->once())
+ $this->config->expects($this->once())
->method('checkoutSessionEndpoint')
- ->willReturn('https://api.omise.co/');
+ ->willReturn('https://checkout-page.omise.co/');
$this->requestHelper->expects($this->once())
->method('sendUpaSessionRequest')
@@ -182,13 +171,12 @@ public function testGetSessionInfoThrowsLocalizedException()
$model = new CheckoutSession(
$this->config,
- $this->requestHelper,
- $this->omiseHelper
+ $this->requestHelper
);
- $this->omiseHelper->expects($this->once())
+ $this->config->expects($this->once())
->method('checkoutSessionEndpoint')
- ->willReturn('https://api.omise.co/');
+ ->willReturn('https://checkout-page.omise.co/');
$this->requestHelper->expects($this->once())
->method('sendUpaSessionRequest')
diff --git a/etc/adminhtml/system.xml b/etc/adminhtml/system.xml
index a2435603..ce508c6f 100644
--- a/etc/adminhtml/system.xml
+++ b/etc/adminhtml/system.xml
@@ -51,6 +51,7 @@
Magento\Config\Model\Config\Source\Yesno
+ Omise\Payment\Block\Adminhtml\System\Config\Form\Field\UpaWebhookSetting
our webhooks documentation.
Unless dynamic webhooks are enabled, you must add the URL below as a new endpoint on your Omise Payments dashboard (HTTPS only).
@@ -60,6 +61,7 @@
Magento\Config\Model\Config\Source\Yesno
+ Omise\Payment\Block\Adminhtml\System\Config\Form\Field\UpaWebhookSetting
1
diff --git a/view/adminhtml/web/js/upa-webhook-setting.js b/view/adminhtml/web/js/upa-webhook-setting.js
new file mode 100644
index 00000000..5a5ba7bf
--- /dev/null
+++ b/view/adminhtml/web/js/upa-webhook-setting.js
@@ -0,0 +1,49 @@
+define([], function () {
+ 'use strict';
+
+ return function () {
+ var upaFlag = document.querySelector('[name="groups[omise][fields][is_upa_feature_flag_enabled][value]"]');
+ if (!upaFlag || upaFlag.dataset.webhookToggleBound) {
+ return;
+ }
+
+ upaFlag.dataset.webhookToggleBound = '1';
+
+ var webhookFieldNames = [
+ 'groups[omise][fields][webhook_status][value]',
+ 'groups[omise][fields][dynamic_webhooks][value]'
+ ];
+
+ function updateWebhookFields() {
+ var enabled = upaFlag.value === '1';
+
+ webhookFieldNames.forEach(function (fieldName) {
+ var field = document.querySelector('[name="' + fieldName + '"]');
+ if (!field || field.type === 'hidden') {
+ return;
+ }
+
+ var hidden = document.querySelector('input[type="hidden"][name="' + fieldName + '"]');
+ if (enabled) {
+ field.value = '1';
+ field.disabled = true;
+ if (!hidden) {
+ hidden = document.createElement('input');
+ hidden.type = 'hidden';
+ hidden.name = fieldName;
+ hidden.value = '1';
+ field.parentNode.appendChild(hidden);
+ }
+ } else {
+ field.disabled = false;
+ if (hidden) {
+ hidden.remove();
+ }
+ }
+ });
+ }
+
+ upaFlag.addEventListener('change', updateWebhookFields);
+ updateWebhookFields();
+ };
+});