Skip to content

Commit f38bcbf

Browse files
[PT-887] Implement Hosted Checkout (#12)
1 parent 2b6398f commit f38bcbf

10 files changed

+169
-29
lines changed

Controller/CancelController.php

+15
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,15 @@
1+
<?php
2+
3+
namespace OxidEsales\MonduPayment\Controller;
4+
5+
use OxidEsales\Eshop\Core\Registry;
6+
use OxidEsales\Eshop\Core\UtilsView;
7+
8+
class CancelController extends \OxidEsales\Eshop\Application\Controller\FrontendController
9+
{
10+
public function render()
11+
{
12+
Registry::get(UtilsView::class)->addErrorToDisplay('Mondu: Order has been canceled');
13+
Registry::getUtils()->redirect(Registry::getConfig()->getShopSecureHomeUrl() . 'cl=payment', false);
14+
}
15+
}

Controller/DeclinedController.php

+15
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,15 @@
1+
<?php
2+
3+
namespace OxidEsales\MonduPayment\Controller;
4+
5+
use OxidEsales\Eshop\Core\Registry;
6+
use OxidEsales\Eshop\Core\UtilsView;
7+
8+
class DeclinedController extends \OxidEsales\Eshop\Application\Controller\FrontendController
9+
{
10+
public function render()
11+
{
12+
Registry::get(UtilsView::class)->addErrorToDisplay('Mondu: Order has been declined');
13+
Registry::getUtils()->redirect(Registry::getConfig()->getShopSecureHomeUrl() . 'cl=payment', false);
14+
}
15+
}

Controller/MonduCheckoutController.php

+4-1
Original file line numberDiff line numberDiff line change
@@ -38,7 +38,10 @@ public function createOrder()
3838
$session->setVariable('mondu_order_uuid', $token);
3939
}
4040

41-
echo json_encode(['token' => $token]);
41+
echo json_encode([
42+
'token' => $token,
43+
'hostedCheckoutUrl' => $response['hosted_checkout_url'] ?? false
44+
]);
4245

4346
exit();
4447
}

Controller/OrderController.php

+97-13
Original file line numberDiff line numberDiff line change
@@ -2,22 +2,106 @@
22

33
namespace OxidEsales\MonduPayment\Controller;
44

5+
use OxidEsales\Eshop\Application\Model\Basket;
6+
use OxidEsales\Eshop\Application\Model\Order;
7+
use OxidEsales\Eshop\Application\Model\User;
8+
use OxidEsales\Eshop\Core\Exception\StandardException;
59
use OxidEsales\Eshop\Core\Registry;
10+
use OxidEsales\Eshop\Core\Request;
11+
use OxidEsales\Eshop\Core\UtilsView;
12+
use OxidEsales\MonduPayment\Core\Http\MonduClient;
613
use OxidEsales\MonduPayment\Core\Utils\MonduHelper;
14+
use Symfony\Component\Config\Definition\Exception\Exception;
715

816
class OrderController extends OrderController_parent
917
{
10-
public function isMonduPayment()
11-
{
12-
$session = Registry::getSession();
13-
$paymentId = $session->getVariable("paymentid");
14-
15-
return MonduHelper::isMonduPayment($paymentId);
16-
}
17-
18-
public function getPaymentPageUrl()
19-
{
20-
$shopUrl = $this->getConfig()->getShopSecureHomeURL();
21-
return $shopUrl . '&cl=payment&payerror=2';
22-
}
18+
private MonduClient $_client;
19+
private User|null|false $_oUser;
20+
21+
public function __construct()
22+
{
23+
parent::__construct();
24+
25+
$this->_client = oxNew(MonduClient::class);
26+
$this->_oUser = $this->getUser();
27+
}
28+
29+
public function isMonduPayment()
30+
{
31+
$session = Registry::getSession();
32+
$paymentId = $session->getVariable('paymentid');
33+
34+
return MonduHelper::isMonduPayment($paymentId);
35+
}
36+
37+
public function getPaymentPageUrl()
38+
{
39+
$shopUrl = \OxidEsales\Eshop\Core\Registry::getConfig()->getShopSecureHomeURL();
40+
return $shopUrl . '&cl=payment&payerror=2';
41+
}
42+
43+
/**
44+
* @throws \Exception
45+
*/
46+
public function execute()
47+
{
48+
if($this->isMonduPayment()){
49+
$orderUuid = Registry::get(Request::class)->getRequestEscapedParameter('order_uuid');
50+
51+
if (!$orderUuid) {
52+
throw new \Exception('Mondu: Not found');
53+
}
54+
55+
$monduOrder = $this->_client->getMonduOrder($orderUuid);
56+
$response = $this->_client->confirmOrder($orderUuid);
57+
58+
if (isset($response['state']) && $response['state'] == 'confirmed') {
59+
try {
60+
$iSuccess = $this->monduExecute($this->getBasket());
61+
62+
return $this->_getNextStep($iSuccess);
63+
} catch (Exception $e) {
64+
throw new \Exception('Mondu: Error during the order process');
65+
}
66+
}
67+
}
68+
69+
// if user is not logged in set the user
70+
if(!$this->getUser() && isset($this->_oUser)){
71+
$this->setUser($this->_oUser);
72+
}
73+
74+
return parent::execute();
75+
}
76+
77+
/**
78+
* Save order to database, delete order_id from session and redirect to thank you page
79+
*
80+
* @param Basket $oBasket
81+
*
82+
* @return bool|int|mixed
83+
*/
84+
protected function monduExecute(Basket $oBasket)
85+
{
86+
if (!Registry::getSession()->getVariable('sess_challenge')) {
87+
Registry::getSession()->setVariable('sess_challenge', Registry::getUtilsObject()->generateUID());
88+
}
89+
90+
$iSuccess = 0;
91+
$oBasket->calculateBasket(true);
92+
$oOrder = oxNew(Order::class);
93+
94+
try {
95+
$iSuccess = $oOrder->finalizeOrder($oBasket, $oBasket->getUser());
96+
} catch (StandardException $e) {
97+
Registry::get(UtilsView::class)->addErrorToDisplay($e);
98+
}
99+
100+
if ($iSuccess === 1) {
101+
// performing special actions after user finishes order (assignment to special user groups)
102+
$this->_oUser->onOrderExecute($oBasket, $iSuccess);
103+
}
104+
105+
return $iSuccess;
106+
}
23107
}

Core/Http/HttpRequest.php

+4-1
Original file line numberDiff line numberDiff line change
@@ -143,7 +143,10 @@ public function send_request(string $url, array $data, string $method)
143143

144144
$response = json_decode($response, true);
145145

146-
if (@$response['errors'] != null || @$response['error'] != null) {
146+
if (
147+
(isset($response['errors']) && $response['errors'] != null) ||
148+
(isset($response['error']) && $response['error'] != null)
149+
) {
147150
throw new InvalidRequestException('[MONDU__ERROR] ' . json_encode($response), $data, $response);
148151
}
149152

Core/Http/MonduClient.php

+10-4
Original file line numberDiff line numberDiff line change
@@ -13,8 +13,8 @@ class MonduClient
1313
{
1414
private Config $_config;
1515
private HttpRequest $_client;
16-
private $_baseUrl = '';
17-
private $_logger = null;
16+
private $_baseUrl;
17+
private $_logger;
1818

1919
public function __construct()
2020
{
@@ -46,6 +46,12 @@ public function updateOrderExternalInfo($orderUuid, $data = [])
4646
return $order['order'] ?? null;
4747
}
4848

49+
public function confirmOrder($orderUuid, $data = [])
50+
{
51+
$order = $this->sendRequest('POST', 'orders/' . $orderUuid . '/confirm', $data);
52+
return $order['order'] ?? null;
53+
}
54+
4955
public function getMonduOrder($orderUuid)
5056
{
5157
$order = $this->sendRequest('GET', 'orders/' . $orderUuid);
@@ -108,8 +114,8 @@ protected function sendRequest($method = 'GET', $url = '', $body = [])
108114
{
109115
try {
110116
$url = $this->_baseUrl . $url;
111-
$response = $this->_client->send_request($url, $body, $method);
112-
return $response;
117+
118+
return $this->_client->send_request($url, $body, $method);
113119
} catch (InvalidRequestException $e) {
114120
$this->_logger->error("MonduClient [{$method} {$url}]: Failed with an exception message: {$e->getString()}");
115121

Core/Mappers/MonduOrderMapper.php

+10-2
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,7 @@
22

33
namespace OxidEsales\MonduPayment\Core\Mappers;
44

5+
use OxidEsales\Eshop\Core\Registry;
56
use OxidEsales\MonduPayment\Core\Utils\MonduHelper;
67

78
class MonduOrderMapper
@@ -36,20 +37,27 @@ protected function getBasketUser()
3637

3738
public function getMappedOrderData($paymentMethod)
3839
{
40+
$session = Registry::getSession();
3941
$basket = $this->getBasket();
40-
42+
$monduOrderUuid = $session->getVariable('mondu_order_uuid');
4143
$tax = array_values($basket->getProductVats(false))[0];
4244
$discount = $basket->getTotalDiscount()->getPrice();
4345
$shipping = $basket->getDeliveryCost()->getPrice();
46+
$shopUrl = Registry::getConfig()->getCurrentShopUrl();
4447

48+
$externalReferenceId = uniqid('M_OX_');
4549
$data = [
4650
"currency" => $basket->getBasketCurrency()->name,
4751
"payment_method" => $paymentMethod,
48-
"external_reference_id" => uniqid('M_OX_'),
52+
"external_reference_id" => $externalReferenceId,
4953
"gross_amount_cents" => round($basket->getPriceForPayment() * 100),
5054
"buyer" => MonduHelper::removeEmptyElementsFromArray($this->getBuyerData()),
5155
"billing_address" => MonduHelper::removeEmptyElementsFromArray($this->getUserBillingAddress()),
5256
"shipping_address" => MonduHelper::removeEmptyElementsFromArray($this->getUserDeliveryAddress()),
57+
"success_url" => $shopUrl . '?cl=order&fnc=execute&order_uuid=' . $monduOrderUuid . '&sDeliveryAddressMD5=' . $this->getBasketUser()->getEncodedDeliveryAddress(),
58+
"cancel_url" => $shopUrl . '?cl=oemonducancel',
59+
"declined_url" => $shopUrl . '?cl=oemondudeclined',
60+
"state_flow" => 'authorization_flow',
5361
"lines" => [[
5462
"tax_cents" => round($tax * 100),
5563
"shipping_price_cents" => round($shipping * 100),

composer.json

+1-1
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,7 @@
22
"name": "mondu/bnpl-checkout-oxid",
33
"description": "Mondu payment method for the OXID eShop.",
44
"type": "oxideshop-module",
5-
"version": "1.0.3",
5+
"version": "1.1.0",
66
"license": [
77
"OSL-3.0",
88
"AFL-3.0"

metadata.php

+4-2
Original file line numberDiff line numberDiff line change
@@ -10,7 +10,7 @@
1010
'en' => 'Module for Mondu payment.',
1111
),
1212
'thumbnail' => 'out/src/images/logo.png',
13-
'version' => '1.0.3',
13+
'version' => '1.1.0',
1414
'author' => 'Mondu GmbH',
1515
'url' => 'https://www.mondu.ai',
1616
'email' => '[email protected]',
@@ -34,7 +34,9 @@
3434
),
3535
'controllers' => array(
3636
'oemonducheckout' => \OxidEsales\MonduPayment\Controller\MonduCheckoutController::class,
37-
'oemonduwebhooks' => \OxidEsales\MonduPayment\Controller\MonduWebhooksController::class
37+
'oemonduwebhooks' => \OxidEsales\MonduPayment\Controller\MonduWebhooksController::class,
38+
'oemonducancel' => \OxidEsales\MonduPayment\Controller\CancelController::class,
39+
'oemondudeclined' => \OxidEsales\MonduPayment\Controller\DeclinedController::class
3840
),
3941
'blocks' => array(
4042
array(

out/src/js/mondu_checkout.js

+9-5
Original file line numberDiff line numberDiff line change
@@ -36,13 +36,17 @@ class MonduCheckout {
3636
event.preventDefault();
3737

3838
if (this._isWidgetLoaded) {
39-
const token = await this._getMonduToken();
39+
const monduOrderData = await this._getMonduOrderData();
4040

41-
if (!token) {
41+
if (!monduOrderData || !monduOrderData.token) {
4242
window.location.href = this._paymentUrl;
4343
}
4444

45-
this._renderWidget(token);
45+
if (monduOrderData.hostedCheckoutUrl) {
46+
window.location.href = monduOrderData.hostedCheckoutUrl;
47+
} else {
48+
this._renderWidget(monduOrderData.token);
49+
}
4650
}
4751
}
4852

@@ -57,13 +61,13 @@ class MonduCheckout {
5761
});
5862
}
5963

60-
async _getMonduToken() {
64+
async _getMonduOrderData() {
6165
try {
6266
const client = new HttpRequest();
6367
const { data } = await client.post('?cl=oemonducheckout&fnc=createOrder', {});
6468

6569
if (data.token !== 'error') {
66-
return data.token;
70+
return data;
6771
} else {
6872
return null;
6973
}

0 commit comments

Comments
 (0)