'Koszyk' ]; private $orderRepository; private $paymentMethodRepository; public function __construct( \Domain\Order\OrderRepository $orderRepository, \Domain\PaymentMethod\PaymentMethodRepository $paymentMethodRepository ) { $this->orderRepository = $orderRepository; $this->paymentMethodRepository = $paymentMethodRepository; } public function basketMessageSave() { \Shared\Helpers\Helpers::set_session( 'basket_message', \Shared\Helpers\Helpers::get( 'basket_message' ) ); echo json_encode( [ 'result' => 'ok' ] ); exit; } public function basketRemoveProduct() { global $lang_id; $basket = \Shared\Helpers\Helpers::get_session( 'basket' ); $coupon = \Shared\Helpers\Helpers::get_session( 'coupon' ); $product_hash = \Shared\Helpers\Helpers::get( 'product_hash' ); $basket_transport_method_id = \Shared\Helpers\Helpers::get_session( 'basket-transport-method-id' ); unset( $basket[ $product_hash ] ); $basket = (new \Domain\Promotion\PromotionRepository($GLOBALS['mdb']))->findPromotion( $basket ); \Shared\Helpers\Helpers::set_session( 'basket', $basket ); $this->jsonBasketResponse( $basket, $coupon, $lang_id, $basket_transport_method_id ); } public function basketIncreaseQuantityProduct() { global $lang_id; $basket = \Shared\Helpers\Helpers::get_session( 'basket' ); $coupon = \Shared\Helpers\Helpers::get_session( 'coupon' ); $product_hash = \Shared\Helpers\Helpers::get( 'product_hash' ); $basket_transport_method_id = \Shared\Helpers\Helpers::get_session( 'basket-transport-method-id' ); $basket[ $product_hash ][ 'quantity' ]++; \Domain\Basket\BasketCalculator::checkProductQuantityInStock( $basket, false ); $basket = \Shared\Helpers\Helpers::get_session( 'basket' ); $basket = (new \Domain\Promotion\PromotionRepository($GLOBALS['mdb']))->findPromotion( $basket ); \Shared\Helpers\Helpers::set_session( 'basket', $basket ); $this->jsonBasketResponse( $basket, $coupon, $lang_id, $basket_transport_method_id ); } public function basketDecreaseQuantityProduct() { global $lang_id; $basket = \Shared\Helpers\Helpers::get_session( 'basket' ); $coupon = \Shared\Helpers\Helpers::get_session( 'coupon' ); $product_hash = \Shared\Helpers\Helpers::get( 'product_hash' ); $basket_transport_method_id = \Shared\Helpers\Helpers::get_session( 'basket-transport-method-id' ); $basket[ $product_hash ][ 'quantity' ]--; if ( $basket[ $product_hash ][ 'quantity' ] < 1 ) unset( $basket[ $product_hash ] ); $basket = (new \Domain\Promotion\PromotionRepository($GLOBALS['mdb']))->findPromotion( $basket ); \Shared\Helpers\Helpers::set_session( 'basket', $basket ); $this->jsonBasketResponse( $basket, $coupon, $lang_id, $basket_transport_method_id ); } public function basketChangeQuantityProduct() { global $lang_id; $basket = \Shared\Helpers\Helpers::get_session( 'basket' ); $coupon = \Shared\Helpers\Helpers::get_session( 'coupon' ); $product_hash = \Shared\Helpers\Helpers::get( 'product_hash' ); $basket_transport_method_id = \Shared\Helpers\Helpers::get_session( 'basket-transport-method-id' ); $basket[ $product_hash ][ 'quantity' ] = (int)\Shared\Helpers\Helpers::get( 'quantity' ); if ( $basket[ $product_hash ][ 'quantity' ] < 1 ) unset( $basket[ $product_hash ] ); $basket = (new \Domain\Promotion\PromotionRepository($GLOBALS['mdb']))->findPromotion( $basket ); \Domain\Basket\BasketCalculator::checkProductQuantityInStock( $basket, false ); $basket = \Shared\Helpers\Helpers::get_session( 'basket' ); $this->jsonBasketResponse( $basket, $coupon, $lang_id, $basket_transport_method_id ); } public function productMessageChange() { $basket = \Shared\Helpers\Helpers::get_session( 'basket' ); $basket[ \Shared\Helpers\Helpers::get( 'position_code' ) ]['message'] = \Shared\Helpers\Helpers::get( 'product_message' ); \Shared\Helpers\Helpers::set_session( 'basket', $basket ); exit; } public function basketAddProduct() { global $lang_id; $basket = \Domain\Basket\BasketCalculator::validateBasket( \Shared\Helpers\Helpers::get_session( 'basket' ) ); $values_tmp = json_decode( \Shared\Helpers\Helpers::get( 'values' ), true ); $values = []; $attributes = []; $custom_fields = []; foreach( $values_tmp as $key => $val ) $values[ $val['name'] ] = $val['value']; foreach( $values as $key => $val ) { if ( $key != 'product-id' and $key != 'quantity' and $key != 'product-message' and strpos( $key, 'custom_field' ) === false ) $attributes[] = $val; } // Sort by attribute ID to match permutation_hash order (generated with ksort) usort( $attributes, function ( $a, $b ) { return (int) explode( '-', $a )[0] - (int) explode( '-', $b )[0]; } ); foreach( $values as $key => $val ) { if ( strpos( $key, 'custom_field' ) !== false ) { preg_match( '/\d+/', $key, $matches ); $custom_field_id = $matches[0]; $custom_fields[ $custom_field_id ] = $val; } } if ( \Shared\Helpers\Helpers::is_array_fix( $attributes ) ) { $values['parent_id'] = $values[ 'product-id' ]; $values['product-id'] = ( new \Domain\Product\ProductRepository( $GLOBALS['mdb'] ) )->getProductIdByAttributes( $values[ 'product-id' ], $attributes ); $values['attributes'] = $attributes; } $values['wp'] = ( new \Domain\Product\ProductRepository( $GLOBALS['mdb'] ) )->getWeightCached( (int)$values[ 'product-id' ] ); $attributes_implode = ''; if ( is_array( $attributes ) and count( $attributes ) > 0 ) $attributes_implode = implode( '|', $attributes ); $product_code = md5( $values['product-id'] . $attributes_implode . $values['product-message'] . json_encode( $custom_fields ) ); if ( isset( $basket[ $product_code ] ) ) $basket[ $product_code ][ 'quantity' ] += $values[ 'quantity' ]; else $basket[ $product_code ] = $values; $basket[ $product_code ]['message'] = $values['product-message']; $basket[ $product_code ]['custom_fields'] = $custom_fields; $basket = (new \Domain\Promotion\PromotionRepository($GLOBALS['mdb']))->findPromotion( $basket ); \Shared\Helpers\Helpers::set_session( 'basket', $basket ); $coupon = \Shared\Helpers\Helpers::get_session( 'coupon' ); echo json_encode( [ 'result' => 'ok', 'basket_mini_count' => \Domain\Basket\BasketCalculator::countProductsText( \Domain\Basket\BasketCalculator::countProducts( $basket ) ), 'basket_mini_value' => \Domain\Basket\BasketCalculator::summaryPrice( $basket, $coupon, $lang_id ), 'product_sets' => ( new \Domain\Product\ProductRepository( $GLOBALS['mdb'] ) )->productSetsWhenAddToBasket( (int)$values['product-id'] ) ] ); exit; } public function transportMethodInpostCheck() { $transport_id = \Shared\Helpers\Helpers::get_session( 'basket-transport-method-id' ); if ( $transport_id === '2' or $transport_id === '1' ) { if ( !\Shared\Helpers\Helpers::get_session( 'basket-inpost-info' ) ) { echo json_encode( [ 'result' => 'bad' ] ); exit; } } if ( $transport_id === '9' ) { if ( !\Shared\Helpers\Helpers::get_session( 'basket_orlen_point_id' ) ) { echo json_encode( [ 'result' => 'bad' ] ); exit; } } echo json_encode( [ 'result' => 'ok' ] ); exit; } public function inpostCheck() { if ( !\Shared\Helpers\Helpers::get_session( 'basket-inpost-info' ) ) echo json_encode( [ 'result' => 'bad' ] ); else echo json_encode( [ 'result' => 'ok' ] ); exit; } public function orlenSave() { \Shared\Helpers\Helpers::set_session( 'basket_orlen_point_id', \Shared\Helpers\Helpers::get( 'orlen_point_id' ) ); \Shared\Helpers\Helpers::set_session( 'basket_orlen_point_info', \Shared\Helpers\Helpers::get( 'orlen_point_name' ) ); echo json_encode( [ 'result' => 'ok' ] ); exit; } public function inpostSave() { \Shared\Helpers\Helpers::set_session( 'basket-inpost-info', \Shared\Helpers\Helpers::get( 'paczkomat' ) ); echo json_encode( [ 'result' => 'ok' ] ); exit; } public function basketPaymentMethodSet() { \Shared\Helpers\Helpers::set_session( 'basket-payment-method-id', \Shared\Helpers\Helpers::get( 'payment_method_id' ) ); echo json_encode( [ 'result' => 'ok' ] ); exit; } public function basketTransportMethodSet() { \Shared\Helpers\Helpers::set_session( 'basket-transport-method-id', \Shared\Helpers\Helpers::get( 'transport_method_id' ) ); echo json_encode( [ 'result' => 'ok' ] ); exit; } public function basketPaymentsMethods() { \Shared\Helpers\Helpers::set_session( 'basket-transport-method-id', \Shared\Helpers\Helpers::get( 'transport_method_id' ) ); echo json_encode( [ 'result' => 'ok', 'payment_methods' => \front\Views\ShopPaymentMethod::basketPaymentMethods( $this->paymentMethodRepository->paymentMethodsByTransport( (int)\Shared\Helpers\Helpers::get( 'transport_method_id' ) ), \Shared\Helpers\Helpers::get( 'payment_method_id' ) ) ] ); exit; } public function summaryView() { global $lang_id, $settings; if ( \Domain\Basket\BasketCalculator::checkProductQuantityInStock( \Shared\Helpers\Helpers::get_session( 'basket' ) ) ) { header( 'Location: /koszyk' ); exit; } $client = \Shared\Helpers\Helpers::get_session( 'client' ); $orderSubmitToken = $this->createOrderSubmitToken(); return \Shared\Tpl\Tpl::view( 'shop-basket/summary-view', [ 'lang_id' => $lang_id, 'client' => \Shared\Helpers\Helpers::get_session( 'client' ), 'basket' => \Shared\Helpers\Helpers::get_session( 'basket' ), 'transport' => ( new \Domain\Transport\TransportRepository( $GLOBALS['mdb'] ) )->findActiveByIdCached( \Shared\Helpers\Helpers::get_session( 'basket-transport-method-id' ) ), 'payment_method' => $this->paymentMethodRepository->paymentMethodCached( (int)\Shared\Helpers\Helpers::get_session( 'basket-payment-method-id' ) ), 'addresses' => ( new \Domain\Client\ClientRepository( $GLOBALS['mdb'] ) )->clientAddresses( (int)$client['id'] ), 'settings' => $settings, 'coupon' => \Shared\Helpers\Helpers::get_session( 'coupon' ), 'basket_message' => \Shared\Helpers\Helpers::get_session( 'basket_message' ), 'order_submit_token' => $orderSubmitToken ] ); } 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; $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 ) ) { $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-podsumowanie' ); exit; } $this->consumeOrderSubmitToken(); $client = \Shared\Helpers\Helpers::get_session( 'client' ); if ( \Domain\Basket\BasketCalculator::checkProductQuantityInStock( \Shared\Helpers\Helpers::get_session( 'basket' ) ) ) { header( 'Location: /koszyk' ); exit; } $order_id = null; try { $order_id = $this->orderRepository->createFromBasket( $client[ 'id' ], \Shared\Helpers\Helpers::get_session( 'basket' ), \Shared\Helpers\Helpers::get_session( 'basket-transport-method-id' ), \Shared\Helpers\Helpers::get_session( 'basket-payment-method-id' ), \Shared\Helpers\Helpers::get( 'email', true ), \Shared\Helpers\Helpers::get( 'phone', true ), \Shared\Helpers\Helpers::get( 'name', true ), \Shared\Helpers\Helpers::get( 'surname', true ), \Shared\Helpers\Helpers::get( 'street' ), \Shared\Helpers\Helpers::get( 'postal_code', true ), \Shared\Helpers\Helpers::get( 'city', true ), \Shared\Helpers\Helpers::get( 'firm_name', true ), \Shared\Helpers\Helpers::get( 'firm_street', true ), \Shared\Helpers\Helpers::get( 'firm_postal_code', true ), \Shared\Helpers\Helpers::get( 'firm_city', true ), \Shared\Helpers\Helpers::get( 'firm_nip', true ), \Shared\Helpers\Helpers::get_session( 'basket-inpost-info' ), \Shared\Helpers\Helpers::get_session( 'basket_orlen_point_id' ), \Shared\Helpers\Helpers::get_session( 'basket_orlen_point_info' ), \Shared\Helpers\Helpers::get_session( 'coupon' ), \Shared\Helpers\Helpers::get_session( 'basket_message' ) ); } 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' ); exit; } if ( $order_id ) { \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::delete_session( 'basket' ); \Shared\Helpers\Helpers::delete_session( 'basket-transport-method-id' ); \Shared\Helpers\Helpers::delete_session( 'basket-payment-method-id' ); \Shared\Helpers\Helpers::delete_session( 'basket-inpost-info' ); \Shared\Helpers\Helpers::delete_session( 'basket_orlen_point_id' ); \Shared\Helpers\Helpers::delete_session( 'basket_orlen_point_info' ); \Shared\Helpers\Helpers::delete_session( 'coupon' ); \Shared\Helpers\Helpers::delete_session( 'basket_message' ); \Shared\Helpers\Helpers::set_session( 'piksel_purchase', true ); \Shared\Helpers\Helpers::set_session( 'google-adwords-purchase', true ); \Shared\Helpers\Helpers::set_session( 'google-analytics-purchase', true ); \Shared\Helpers\Helpers::set_session( 'ekomi-purchase', true ); $redis = \Shared\Cache\RedisConnection::getInstance() -> getConnection(); if ( $redis ) $redis -> flushAll(); header( 'Location: /zamowienie/' . $this->orderRepository->findHashById( $order_id ) ); exit; } 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; } } public function mainView() { global $lang_id, $page, $settings; $page[ 'language' ][ 'meta_title' ] = 'Koszyk'; $basket = \Shared\Helpers\Helpers::get_session( 'basket' ); $coupon = \Shared\Helpers\Helpers::get_session( 'coupon' ); $payment_method_id = \Shared\Helpers\Helpers::get_session( 'payment_method_id' ); $basket_transport_method_id = \Shared\Helpers\Helpers::get_session( 'basket-transport-method-id' ); if ( \Domain\Basket\BasketCalculator::checkProductQuantityInStock( $basket ) ) { header( 'Location: /koszyk' ); exit; } $basket = (new \Domain\Promotion\PromotionRepository($GLOBALS['mdb']))->findPromotion( $basket ); return \Shared\Tpl\Tpl::view( 'shop-basket/basket', [ 'basket' => $basket, 'coupon' => $coupon, 'transport_id' => \Shared\Helpers\Helpers::get_session( 'basket-transport-method-id' ), 'transport_methods' => \Shared\Tpl\Tpl::view( 'shop-basket/basket-transport-methods', [ 'transports_methods' => ( new \Domain\Transport\TransportRepository( $GLOBALS['mdb'] ) )->transportMethodsFront( $basket, $coupon ), 'transport_id' => $basket_transport_method_id, 'free_delivery' => (float)($settings['free_delivery'] ?? 0), 'basket_summary' => (float)\Domain\Basket\BasketCalculator::summaryPrice( $basket, $coupon ) ] ), 'payment_method_id' => $payment_method_id, 'basket_details' => \Shared\Tpl\Tpl::view( 'shop-basket/basket-details', [ 'basket' => $basket, 'lang_id' => $lang_id, 'coupon' => $coupon, 'basket_message' => \Shared\Helpers\Helpers::get_session( 'basket_message' ), 'settings' => $settings ] ) ] ); } public function basketUpdateCustomFields() { $basket = \Shared\Helpers\Helpers::get_session( 'basket' ); $product_code = \Shared\Helpers\Helpers::get( 'product_code' ); if ( !isset( $basket[ $product_code ] ) ) { echo json_encode( [ 'result' => 'error', 'message' => 'Pozycja nie istnieje w koszyku' ] ); exit; } $position = $basket[ $product_code ]; $new_custom_fields = []; $custom_fields_raw = \Shared\Helpers\Helpers::get( 'custom_field' ); if ( is_array( $custom_fields_raw ) ) { foreach ( $custom_fields_raw as $field_id => $value ) { $new_custom_fields[ (int)$field_id ] = $value; } } $productRepo = new \Domain\Product\ProductRepository( $GLOBALS['mdb'] ); $missing_fields = []; foreach ( $new_custom_fields as $field_id => $value ) { $field_meta = $productRepo->findCustomFieldCached( $field_id ); if ( $field_meta && (int)$field_meta['is_required'] === 1 && trim( $value ) === '' ) { $missing_fields[] = $field_meta['name']; } } if ( count( $missing_fields ) > 0 ) { echo json_encode( [ 'result' => 'error', 'message' => 'Wypełnij wymagane pola: ' . implode( ', ', $missing_fields ) ] ); exit; } $attributes_implode = ''; if ( isset( $position['attributes'] ) && is_array( $position['attributes'] ) && count( $position['attributes'] ) > 0 ) { $attributes_implode = implode( '|', $position['attributes'] ); } $message = isset( $position['message'] ) ? $position['message'] : ''; $new_product_code = md5( $position['product-id'] . $attributes_implode . $message . json_encode( $new_custom_fields ) ); if ( $new_product_code === $product_code ) { $basket[ $product_code ]['custom_fields'] = $new_custom_fields; } elseif ( isset( $basket[ $new_product_code ] ) ) { $basket[ $new_product_code ]['quantity'] += $position['quantity']; unset( $basket[ $product_code ] ); } else { $position['custom_fields'] = $new_custom_fields; $basket[ $new_product_code ] = $position; unset( $basket[ $product_code ] ); } $basket = ( new \Domain\Promotion\PromotionRepository( $GLOBALS['mdb'] ) )->findPromotion( $basket ); \Shared\Helpers\Helpers::set_session( 'basket', $basket ); echo json_encode( [ 'result' => 'ok' ] ); exit; } private function jsonBasketResponse( $basket, $coupon, $lang_id, $basket_transport_method_id ) { global $settings; echo json_encode( [ 'basket' => \Shared\Tpl\Tpl::view( 'shop-basket/basket-details', [ 'basket' => $basket, 'lang_id' => $lang_id, 'coupon' => $coupon ] ), 'basket_mini_count' => \Domain\Basket\BasketCalculator::countProductsText( \Domain\Basket\BasketCalculator::countProducts( $basket ) ), 'basket_mini_value' => \Domain\Basket\BasketCalculator::summaryPrice( $basket, $coupon, $lang_id ), 'products_count' => count( $basket ), 'transport_methods' => \Shared\Tpl\Tpl::view( 'shop-basket/basket-transport-methods', [ 'transports_methods' => ( new \Domain\Transport\TransportRepository( $GLOBALS['mdb'] ) )->transportMethodsFront( $basket, $coupon ), 'transport_id' => $basket_transport_method_id, 'free_delivery' => (float)($settings['free_delivery'] ?? 0), 'basket_summary' => (float)\Domain\Basket\BasketCalculator::summaryPrice( $basket, $coupon ) ] ) ] ); exit; } 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' => $token, 'created_at' => time() ] ); \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; $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 ); return $sessionToken === $token; } private function consumeOrderSubmitToken() { \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 ); } }