This commit is contained in:
2026-03-28 11:42:27 +01:00
parent aa8e21862d
commit 16e5cce249
4 changed files with 110 additions and 29 deletions

View File

@@ -3,6 +3,9 @@ namespace front\Controllers;
class ShopBasketController class ShopBasketController
{ {
private const ORDER_SUBMIT_TOKEN_SESSION_KEY = 'order-submit-token';
private const ORDER_SUBMIT_LAST_ORDER_ID_SESSION_KEY = 'order-submit-last-order-id';
public static $title = [ public static $title = [
'mainView' => 'Koszyk' 'mainView' => 'Koszyk'
]; ];
@@ -274,6 +277,7 @@ class ShopBasketController
} }
$client = \Shared\Helpers\Helpers::get_session( 'client' ); $client = \Shared\Helpers\Helpers::get_session( 'client' );
$orderSubmitToken = $this->createOrderSubmitToken();
return \Shared\Tpl\Tpl::view( 'shop-basket/summary-view', [ return \Shared\Tpl\Tpl::view( 'shop-basket/summary-view', [
'lang_id' => $lang_id, 'lang_id' => $lang_id,
@@ -284,12 +288,35 @@ class ShopBasketController
'addresses' => ( new \Domain\Client\ClientRepository( $GLOBALS['mdb'] ) )->clientAddresses( (int)$client['id'] ), 'addresses' => ( new \Domain\Client\ClientRepository( $GLOBALS['mdb'] ) )->clientAddresses( (int)$client['id'] ),
'settings' => $settings, 'settings' => $settings,
'coupon' => \Shared\Helpers\Helpers::get_session( 'coupon' ), 'coupon' => \Shared\Helpers\Helpers::get_session( 'coupon' ),
'basket_message' => \Shared\Helpers\Helpers::get_session( 'basket_message' ) 'basket_message' => \Shared\Helpers\Helpers::get_session( 'basket_message' ),
'order_submit_token' => $orderSubmitToken
] ); ] );
} }
public function basketSave() public function basketSave()
{ {
$orderSubmitToken = (string)\Shared\Helpers\Helpers::get( 'order_submit_token', true );
$existingOrderId = isset( $_SESSION[ self::ORDER_SUBMIT_LAST_ORDER_ID_SESSION_KEY ] ) ? (int)$_SESSION[ self::ORDER_SUBMIT_LAST_ORDER_ID_SESSION_KEY ] : 0;
if ( !$this->isValidOrderSubmitToken( $orderSubmitToken ) )
{
if ( $existingOrderId > 0 )
{
$existingOrderHash = $this->orderRepository->findHashById( $existingOrderId );
if ( $existingOrderHash )
{
header( 'Location: /zamowienie/' . $existingOrderHash );
exit;
}
}
\Shared\Helpers\Helpers::error( \Shared\Helpers\Helpers::lang( 'zamowienie-zostalo-zlozone-komunikat-blad' ) );
header( 'Location: /koszyk' );
exit;
}
$this->consumeOrderSubmitToken();
$client = \Shared\Helpers\Helpers::get_session( 'client' ); $client = \Shared\Helpers\Helpers::get_session( 'client' );
if ( \Domain\Basket\BasketCalculator::checkProductQuantityInStock( \Shared\Helpers\Helpers::get_session( 'basket' ) ) ) if ( \Domain\Basket\BasketCalculator::checkProductQuantityInStock( \Shared\Helpers\Helpers::get_session( 'basket' ) ) )
@@ -322,6 +349,7 @@ class ShopBasketController
\Shared\Helpers\Helpers::get_session( 'basket_message' ) \Shared\Helpers\Helpers::get_session( 'basket_message' )
) ) ) )
{ {
\Shared\Helpers\Helpers::set_session( self::ORDER_SUBMIT_LAST_ORDER_ID_SESSION_KEY, (int)$order_id );
\Shared\Helpers\Helpers::alert( \Shared\Helpers\Helpers::lang( 'zamowienie-zostalo-zlozone-komunikat' ) ); \Shared\Helpers\Helpers::alert( \Shared\Helpers\Helpers::lang( 'zamowienie-zostalo-zlozone-komunikat' ) );
\Shared\Helpers\Helpers::delete_session( 'basket' ); \Shared\Helpers\Helpers::delete_session( 'basket' );
\Shared\Helpers\Helpers::delete_session( 'basket-transport-method-id' ); \Shared\Helpers\Helpers::delete_session( 'basket-transport-method-id' );
@@ -414,4 +442,45 @@ class ShopBasketController
] ); ] );
exit; exit;
} }
private function createOrderSubmitToken()
{
$token = $this->generateOrderSubmitToken();
\Shared\Helpers\Helpers::set_session( self::ORDER_SUBMIT_TOKEN_SESSION_KEY, $token );
\Shared\Helpers\Helpers::delete_session( self::ORDER_SUBMIT_LAST_ORDER_ID_SESSION_KEY );
return $token;
}
private function generateOrderSubmitToken()
{
try
{
return bin2hex( random_bytes( 16 ) );
}
catch ( \Exception $exception )
{
return md5( uniqid( (string)mt_rand(), true ) );
}
}
private function isValidOrderSubmitToken( $token )
{
if ( !$token )
return false;
$sessionToken = isset( $_SESSION[ self::ORDER_SUBMIT_TOKEN_SESSION_KEY ] ) ? (string)$_SESSION[ self::ORDER_SUBMIT_TOKEN_SESSION_KEY ] : '';
if ( !$sessionToken )
return false;
if ( function_exists( 'hash_equals' ) )
return hash_equals( $sessionToken, $token );
return $sessionToken === $token;
}
private function consumeOrderSubmitToken()
{
\Shared\Helpers\Helpers::delete_session( self::ORDER_SUBMIT_TOKEN_SESSION_KEY );
}
} }

View File

@@ -34,6 +34,7 @@
<? endif;?> <? endif;?>
<? if ( $this -> client ):?><div class="right"><? endif;?> <? if ( $this -> client ):?><div class="right"><? endif;?>
<form class="form-horizontal" action="/zloz-zamowienie" method="POST" id="form-order"> <form class="form-horizontal" action="/zloz-zamowienie" method="POST" id="form-order">
<input type="hidden" name="order_submit_token" value="<?= htmlspecialchars( (string)($this -> order_submit_token ?? ''), ENT_QUOTES, 'UTF-8' );?>">
<? if ( !$this -> client ):?> <? if ( !$this -> client ):?>
<div class="form-group row"> <div class="form-group row">
<div class="col-12"> <div class="col-12">

View File

@@ -140,14 +140,16 @@
</div> </div>
<div class="right"> <div class="right">
<?= \Shared\Tpl\Tpl::view( 'shop-basket/address-form', [ <?= \Shared\Tpl\Tpl::view( 'shop-basket/address-form', [
'transport_method' => $this -> transport 'transport_method' => $this -> transport,
'order_submit_token' => $this -> order_submit_token
] );?> ] );?>
</div> </div>
<? else:?> <? else:?>
<?= \Shared\Tpl\Tpl::view( 'shop-basket/address-form', [ <?= \Shared\Tpl\Tpl::view( 'shop-basket/address-form', [
'client' => $this -> client, 'client' => $this -> client,
'addresses' => $this -> addresses, 'addresses' => $this -> addresses,
'transport_method' => $this -> transport 'transport_method' => $this -> transport,
'order_submit_token' => $this -> order_submit_token
] );?> ] );?>
<? endif;?> <? endif;?>
</div> </div>
@@ -156,17 +158,20 @@
<? endif;?> <? endif;?>
</div> </div>
<script class="footer" type="text/javascript"> <script class="footer" type="text/javascript">
document.getElementById('order-send').addEventListener('click', function() { var orderForm = document.getElementById('form-order');
var form = document.getElementById('form-order'); // Zastąp 'form-id' rzeczywistym ID Twojego formularza var orderSendButton = document.getElementById('order-send');
if (form.checkValidity()) {
this.classList.add('loading-button'); if (orderForm && orderSendButton) {
this.disabled = true; orderForm.addEventListener('submit', function(event) {
form.submit(); if (orderSendButton.disabled) {
} else { event.preventDefault();
// Opcjonalnie: wywołaj funkcję reportValidity(), aby wyświetlić komunikaty o błędach formularza return;
form.reportValidity(); }
}
}); orderSendButton.classList.add('loading-button');
orderSendButton.disabled = true;
});
}
<? if ( $this -> settings['google_tag_manager_id'] ):?> <? if ( $this -> settings['google_tag_manager_id'] ):?>
dataLayer.push({ ecommerce: null }); dataLayer.push({ ecommerce: null });
dataLayer.push({ dataLayer.push({

View File

@@ -134,14 +134,16 @@
</div> </div>
<div class="right"> <div class="right">
<?= \Shared\Tpl\Tpl::view( 'shop-basket/address-form', [ <?= \Shared\Tpl\Tpl::view( 'shop-basket/address-form', [
'transport_method' => $this -> transport 'transport_method' => $this -> transport,
'order_submit_token' => $this -> order_submit_token
] );?> ] );?>
</div> </div>
<? else:?> <? else:?>
<?= \Shared\Tpl\Tpl::view( 'shop-basket/address-form', [ <?= \Shared\Tpl\Tpl::view( 'shop-basket/address-form', [
'client' => $this -> client, 'client' => $this -> client,
'addresses' => $this -> addresses, 'addresses' => $this -> addresses,
'transport_method' => $this -> transport 'transport_method' => $this -> transport,
'order_submit_token' => $this -> order_submit_token
] );?> ] );?>
<? endif;?> <? endif;?>
</div> </div>
@@ -150,18 +152,22 @@
<? endif;?> <? endif;?>
</div> </div>
<script class="footer" type="text/javascript"> <script class="footer" type="text/javascript">
document.getElementById('order-send').addEventListener('click', function() { var orderForm = document.getElementById('form-order');
var form = document.getElementById('form-order'); // Zastąp 'form-id' rzeczywistym ID Twojego formularza var orderSendButton = document.getElementById('order-send');
if (form.checkValidity()) {
this.classList.add('loading-button'); if (orderForm && orderSendButton) {
this.disabled = true; orderForm.addEventListener('submit', function(event) {
form.submit(); if (orderSendButton.disabled) {
} else { event.preventDefault();
// Opcjonalnie: wywołaj funkcję reportValidity(), aby wyświetlić komunikaty o błędach formularza return;
form.reportValidity(); }
}
}); orderSendButton.classList.add('loading-button');
orderSendButton.disabled = true;
});
}
<? if ( $this -> settings['google_tag_manager_id'] ):?> <? if ( $this -> settings['google_tag_manager_id'] ):?>
dataLayer.push({ ecommerce: null });
dataLayer.push({ dataLayer.push({
event: "begin_checkout", event: "begin_checkout",
ecommerce: { ecommerce: {