This commit is contained in:
2026-03-28 11:29:41 +01:00
parent d366a58d28
commit bf82685e8f
9 changed files with 131 additions and 46 deletions

View File

@@ -5,6 +5,7 @@ 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';
private const ORDER_SUBMIT_TOKEN_TTL = 1800;
public static $title = [
'mainView' => 'Koszyk'
@@ -276,19 +277,6 @@ class ShopBasketController
exit;
}
$existingOrderId = isset( $_SESSION[ self::ORDER_SUBMIT_LAST_ORDER_ID_SESSION_KEY ] )
? (int)$_SESSION[ self::ORDER_SUBMIT_LAST_ORDER_ID_SESSION_KEY ]
: 0;
if ( $existingOrderId > 0 )
{
$existingOrderHash = $this->orderRepository->findHashById( $existingOrderId );
if ( $existingOrderHash )
{
header( 'Location: /zamowienie/' . $existingOrderHash );
exit;
}
}
$client = \Shared\Helpers\Helpers::get_session( 'client' );
$orderSubmitToken = $this->createOrderSubmitToken();
@@ -311,20 +299,23 @@ class ShopBasketController
$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;
$basket = \Shared\Helpers\Helpers::get_session( 'basket' );
if ( empty( $basket ) && $existingOrderId > 0 )
{
$existingOrderHash = $this->orderRepository->findHashById( $existingOrderId );
if ( $existingOrderHash )
{
$this->logOrder( 'Double-submit detected, redirecting to existing order id=' . $existingOrderId );
header( 'Location: /zamowienie/' . $existingOrderHash );
exit;
}
}
if ( !$this->isValidOrderSubmitToken( $orderSubmitToken ) )
{
if ( $existingOrderId > 0 )
{
$existingOrderHash = $this->orderRepository->findHashById( $existingOrderId );
if ( $existingOrderHash )
{
header( 'Location: /zamowienie/' . $existingOrderHash );
exit;
}
}
$this->logOrder( 'Token validation failed. formToken=' . $orderSubmitToken . ' existingOrderId=' . $existingOrderId );
\Shared\Helpers\Helpers::error( \Shared\Helpers\Helpers::lang( 'zamowienie-zostalo-zlozone-komunikat-blad' ) );
header( 'Location: /koszyk' );
header( 'Location: /koszyk-podsumowanie' );
exit;
}
@@ -367,6 +358,7 @@ class ShopBasketController
}
catch ( \Exception $e )
{
$this->logOrder( 'createFromBasket exception: ' . $e->getMessage() );
error_log( '[basketSave] createFromBasket exception: ' . $e->getMessage() );
\Shared\Helpers\Helpers::error( \Shared\Helpers\Helpers::lang( 'zamowienie-zostalo-zlozone-komunikat-blad' ) );
header( 'Location: /koszyk' );
@@ -400,6 +392,7 @@ class ShopBasketController
}
else
{
$this->logOrder( 'createFromBasket returned falsy order_id. client_id=' . ( $client['id'] ?? '?' ) . ' email=' . ( \Shared\Helpers\Helpers::get( 'email', true ) ?: '?' ) );
\Shared\Helpers\Helpers::error( \Shared\Helpers\Helpers::lang( 'zamowienie-zostalo-zlozone-komunikat-blad' ) );
header( 'Location: /koszyk' );
exit;
@@ -544,8 +537,23 @@ class ShopBasketController
private function createOrderSubmitToken()
{
$sessionData = isset( $_SESSION[ self::ORDER_SUBMIT_TOKEN_SESSION_KEY ] )
? $_SESSION[ self::ORDER_SUBMIT_TOKEN_SESSION_KEY ]
: null;
if ( is_array( $sessionData ) && isset( $sessionData['token'], $sessionData['created_at'] ) )
{
if ( ( time() - $sessionData['created_at'] ) < self::ORDER_SUBMIT_TOKEN_TTL )
{
return $sessionData['token'];
}
}
$token = $this->generateOrderSubmitToken();
\Shared\Helpers\Helpers::set_session( self::ORDER_SUBMIT_TOKEN_SESSION_KEY, $token );
\Shared\Helpers\Helpers::set_session( self::ORDER_SUBMIT_TOKEN_SESSION_KEY, [
'token' => $token,
'created_at' => time()
] );
\Shared\Helpers\Helpers::delete_session( self::ORDER_SUBMIT_LAST_ORDER_ID_SESSION_KEY );
return $token;
@@ -568,10 +576,29 @@ class ShopBasketController
if ( !$token )
return false;
$sessionToken = isset( $_SESSION[ self::ORDER_SUBMIT_TOKEN_SESSION_KEY ] ) ? (string)$_SESSION[ self::ORDER_SUBMIT_TOKEN_SESSION_KEY ] : '';
if ( !$sessionToken )
$sessionData = isset( $_SESSION[ self::ORDER_SUBMIT_TOKEN_SESSION_KEY ] )
? $_SESSION[ self::ORDER_SUBMIT_TOKEN_SESSION_KEY ]
: null;
if ( !$sessionData )
return false;
// Backward compatibility: stary format (plain string)
if ( is_string( $sessionData ) )
{
$sessionToken = $sessionData;
}
elseif ( is_array( $sessionData ) && isset( $sessionData['token'], $sessionData['created_at'] ) )
{
if ( ( time() - $sessionData['created_at'] ) >= self::ORDER_SUBMIT_TOKEN_TTL )
return false;
$sessionToken = $sessionData['token'];
}
else
{
return false;
}
if ( function_exists( 'hash_equals' ) )
return hash_equals( $sessionToken, $token );
@@ -582,4 +609,11 @@ class ShopBasketController
{
\Shared\Helpers\Helpers::delete_session( self::ORDER_SUBMIT_TOKEN_SESSION_KEY );
}
private function logOrder( $message )
{
$logFile = __DIR__ . '/../../../logs/logs-order-' . date( 'Y-m-d' ) . '.log';
$line = '[' . date( 'Y-m-d H:i:s' ) . '] ' . $message . "\n";
@file_put_contents( $logFile, $line, FILE_APPEND );
}
}

View File

@@ -1,4 +1,46 @@
<? global $settings; ?>
<?
if ( $settings['google_tag_manager_id'] && is_array( $this -> basket ) && count( $this -> basket ) ):
$view_cart_items = '';
$view_cart_value = 0;
foreach ( $this -> basket as $position ):
$vc_product = (new \Domain\Product\ProductRepository($GLOBALS['mdb']))->findCached( (int)$position['product-id'], (new \Domain\Languages\LanguagesRepository($GLOBALS['mdb']))->defaultLanguage() );
if ( !$vc_product )
continue;
$vc_price = (float)$vc_product['price_brutto_promo'] > 0 && (float)$vc_product['price_brutto_promo'] < (float)$vc_product['price_brutto']
? (float)$vc_product['price_brutto_promo']
: (float)$vc_product['price_brutto'];
$vc_qty = (int)$position['quantity'];
$view_cart_value += $vc_price * $vc_qty;
if ( $view_cart_items )
$view_cart_items .= ',';
$view_cart_items .= '{';
$view_cart_items .= 'item_id: "' . $vc_product['id'] . '",';
$view_cart_items .= 'item_name: "' . str_replace( '"', '', $vc_product['language']['name'] ) . '",';
$view_cart_items .= 'price: ' . \Shared\Helpers\Helpers::normalize_decimal( $vc_price ) . ',';
$view_cart_items .= 'quantity: ' . $vc_qty . ',';
$view_cart_items .= 'google_business_vertical: "retail"';
$view_cart_items .= '}';
endforeach;
?>
<script type="text/javascript">
dataLayer.push({ ecommerce: null });
dataLayer.push({
event: "view_cart",
ecommerce: {
currency: "PLN",
value: <?= \Shared\Helpers\Helpers::normalize_decimal( $view_cart_value );?>,
items: [<?= $view_cart_items;?>]
}
});
</script>
<? endif; ?>
<div id="basket-container">
<div id="content">
<?= $this->basket_details; ?>

View File

@@ -73,10 +73,11 @@
$begin_checkout_items .= ',';
$begin_checkout_items .= '{';
$begin_checkout_items .= '"id": "' . $product['id'] . '",';
$begin_checkout_items .= '"name": "' . $product['language']['name'] . '",';
$begin_checkout_items .= '"item_id": "' . $product['id'] . '",';
$begin_checkout_items .= '"item_name": "' . str_replace( '"', '', $product['language']['name'] ) . '",';
$begin_checkout_items .= '"price": ' . \Shared\Helpers\Helpers::normalize_decimal( $price_product['price_new'] ) . ',';
$begin_checkout_items .= '"quantity": ' . $position['quantity'];
$begin_checkout_items .= '"quantity": ' . (int)$position['quantity'] . ',';
$begin_checkout_items .= '"google_business_vertical": "retail"';
$begin_checkout_items .= '}';
?>
<? endforeach;?>

View File

@@ -169,17 +169,17 @@
event: "purchase",
ecommerce: {
transaction_id: "<?= $this -> order['id'];?>",
value: 25.42,
currency: "PLN",
value: <?= \Shared\Helpers\Helpers::normalize_decimal( round( $this -> order['summary'], 2 ) ) - str_replace( ',', '.', round( $this -> order['transport_cost'], 2 ) );?>,
shipping: <?= \Shared\Helpers\Helpers::normalize_decimal( $this -> order['transport_cost'] );?>,
items: [
<? foreach ( $this -> order['products'] as $product ):?>
{
'id': <?= (int)$product['product_id'];?>,
'name': '<?= $product['name'];?>',
'quantity': <?= $product['quantity'];?>,
'price': <?= ((float)$product['price_brutto_promo'] > 0 && (float)$product['price_brutto_promo'] < (float)$product['price_brutto']) ? (float)$product['price_brutto_promo'] : (float)$product['price_brutto'];?>
item_id: "<?= $product['product_id'];?>",
item_name: "<?= str_replace( '"', '', $product['name'] );?>",
quantity: <?= (int)$product['quantity'];?>,
price: <?= ((float)$product['price_brutto_promo'] > 0 && (float)$product['price_brutto_promo'] < (float)$product['price_brutto']) ? \Shared\Helpers\Helpers::normalize_decimal( $product['price_brutto_promo'] ) : \Shared\Helpers\Helpers::normalize_decimal( $product['price_brutto'] );?>,
google_business_vertical: "retail"
}<? if ( $product != end( $this -> order['products'] ) ) echo ',';?>
<? endforeach;?>
]

View File

@@ -275,12 +275,15 @@
dataLayer.push({
event: "view_item",
ecommerce: {
currency: "PLN",
value: <? if ( $this -> product['price_brutto_promo'] ): echo \Shared\Helpers\Helpers::normalize_decimal( $this -> product['price_brutto_promo'] ); else: echo \Shared\Helpers\Helpers::normalize_decimal( $this -> product['price_brutto'] ); endif;?>,
items: [
{
item_id: "<?= $this -> product['id'];?>",
item_name: "<?= str_replace( '"', '', $this -> product['language']['name'] );?>",
price: '<? if ( $this -> product['price_brutto_promo'] ): echo \Shared\Helpers\Helpers::normalize_decimal( $this -> product['price_brutto_promo'] ); else: echo \Shared\Helpers\Helpers::normalize_decimal( $this -> product['price_brutto'] ); endif;?>',
quantity: 1
price: <? if ( $this -> product['price_brutto_promo'] ): echo \Shared\Helpers\Helpers::normalize_decimal( $this -> product['price_brutto_promo'] ); else: echo \Shared\Helpers\Helpers::normalize_decimal( $this -> product['price_brutto'] ); endif;?>,
quantity: 1,
google_business_vertical: "retail"
}
]
}
@@ -617,7 +620,8 @@
item_id: "<?= $this -> product['id'];?>",
item_name: "<?= str_replace( '"', '', $this -> product['language']['name'] );?>",
price: <? if ( $this -> product['price_brutto_promo'] ): echo \Shared\Helpers\Helpers::normalize_decimal( $this -> product['price_brutto_promo'] ); else: echo \Shared\Helpers\Helpers::normalize_decimal( $this -> product['price_brutto'] ); endif;?>,
quantity: quantity
quantity: parseInt(quantity),
google_business_vertical: "retail"
}
]
}

View File

@@ -35,6 +35,7 @@
</div>
<? if ( $this -> settings['google_tag_manager_id'] && is_array( $this -> basket ) && count( $this -> basket ) ):?>
<script>
dataLayer.push({ ecommerce: null });
dataLayer.push({
event: "view_cart",
ecommerce: {
@@ -49,7 +50,7 @@
if ( $view_cart_items ) $view_cart_items .= ',';
$view_cart_items .= '{';
$view_cart_items .= '"item_id": "' . $product['id'] . '",';
$view_cart_items .= '"item_name": "' . $product['language']['name'] . '",';
$view_cart_items .= '"item_name": "' . str_replace( '"', '', $product['language']['name'] ) . '",';
$view_cart_items .= '"price": ' . \Shared\Helpers\Helpers::normalize_decimal( $price_product['price_new'] ) . ',';
$view_cart_items .= '"quantity": ' . (int)$position['quantity'] . ',';
$view_cart_items .= '"google_business_vertical": "retail"';

View File

@@ -74,7 +74,7 @@
$begin_checkout_items .= '{';
$begin_checkout_items .= '"item_id": "' . $product['id'] . '",';
$begin_checkout_items .= '"item_name": "' . $product['language']['name'] . '",';
$begin_checkout_items .= '"item_name": "' . str_replace( '"', '', $product['language']['name'] ) . '",';
$begin_checkout_items .= '"price": ' . \Shared\Helpers\Helpers::normalize_decimal( $price_product['price_new'] ) . ',';
$begin_checkout_items .= '"quantity": ' . (int)$position['quantity'] . ',';
$begin_checkout_items .= '"google_business_vertical": "retail"';
@@ -186,4 +186,4 @@
}
});
<? endif;?>
</script>
</script>

View File

@@ -163,6 +163,7 @@
<? if ( \Shared\Helpers\Helpers::get_session('google-analytics-purchase') ):?>
<? if ( $this -> settings['google_tag_manager_id'] ):?>
dataLayer.push({ ecommerce: null });
dataLayer.push({
event: "purchase",
ecommerce: {
@@ -174,9 +175,9 @@
<? foreach ( $this -> order['products'] as $product ):?>
{
item_id: "<?= $product['product_id'];?>",
item_name: '<?= $product['name'];?>',
item_name: "<?= str_replace( '"', '', $product['name'] );?>",
quantity: <?= (int)$product['quantity'];?>,
price: <?= (float)$product['price_brutto_promo'] > 0 ? \Shared\Helpers\Helpers::normalize_decimal( $product['price_brutto_promo'] ) : \Shared\Helpers\Helpers::normalize_decimal( $product['price_brutto'] );?>,
price: <?= ((float)$product['price_brutto_promo'] > 0 && (float)$product['price_brutto_promo'] < (float)$product['price_brutto']) ? \Shared\Helpers\Helpers::normalize_decimal( $product['price_brutto_promo'] ) : \Shared\Helpers\Helpers::normalize_decimal( $product['price_brutto'] );?>,
google_business_vertical: 'retail'
}<? if ( $product != end( $this -> order['products'] ) ) echo ',';?>
<? endforeach;?>
@@ -194,7 +195,7 @@
}
});
<? endif;?>
<? unset( $_SESSION['google-adwords-purchase'] );?>
<? unset( $_SESSION['google-analytics-purchase'] );?>
<? endif;?>
});
</script>
</script>

View File

@@ -244,6 +244,7 @@
<script type="text/javascript">
$( function() {
<? if ( $this -> settings['google_tag_manager_id'] ):?>
dataLayer.push({ ecommerce: null });
dataLayer.push({
event: "view_item",
ecommerce: {
@@ -564,6 +565,7 @@
<? if ( $this -> settings['google_tag_manager_id'] ):?>
var add_to_cart_value = <? if ( $this -> product['price_brutto_promo'] ): echo \Shared\Helpers\Helpers::normalize_decimal( $this -> product['price_brutto_promo'] ); else: echo \Shared\Helpers\Helpers::normalize_decimal( $this -> product['price_brutto'] ); endif;?> * quantity;
dataLayer.push({ ecommerce: null });
dataLayer.push({
event: "add_to_cart",
ecommerce: {
@@ -665,4 +667,4 @@
});
return false;
}
</script>
</script>