* @version 4 * @package baselinker */ /** ----------------------------------------------------------------------------------------------------------- * Ustawienia wpisywane przez sprzedawcę * - Należy uzupełnić dane wprowadzając je między apostrofy */ $options['baselinker_pass'] = 'femwtyqlyy8bhglqe0x8584vv2i9xxqp'; //hasło do komunikacji (dostępne w panelu Baselinkera w zakładce 'sklep internetowy') $options['db_host'] = 'localhost'; //adres hosta bazy danych (najczęściej localhost) $options['db_user'] = 'rsduvqkeer_grzanie'; //użytkownik bazy danych $options['db_pass'] = '[QD-*l7%0M-Hicik'; //hasło bazy danych $options['db_name'] = 'rsduvqkeer_grzanieplus-pl'; //nazwa bazy danych $options['db_prefix'] = ''; //prefiks tabel bazy danych - domyślnie pozostaw pusty aby wykryć automatycznie $options['images_folder'] = 'http://grzanieplus.pl/'; //adres folderu zawierającego zdjęcia produktów i producentów (rozpoczęty 'http://', zakończony /) $options['special_price'] = 1; //czy używać ceny promocyjnej jeśli produkt jest w promocji? (0 - nie, 1 - tak) $options['charset'] = 'UTF-8'; //zestaw znaków bazy danych (standardowo UTF-8) $options['ean_fld'] = 'man_code'; // pole w bazie sklepu, z którego ma być pobierany kod EAN dla produktów głównych $options['vean_fld'] = ''; // pole w bazie sklepu, z którego ma być pobierany kod EAN dla wariantów $options['sote_shophash'] = 'f9862393534ee289a67584de0b0768a0'; // klucz rozkodowywania danych zamówienia (zawarty w pliku core/data/config/__stRegister.yml) $options['sote_dir'] = '..'; // ścieżka do głównego katalogu sote (zwykle nazwya się soteshop) $options['og_host'] = ''; // jeśli wypełniony, ogranicza pobieranie zamówień tylko do podanego hosta $options['lang'] = ''; // język tłumaczeń - zostaw pusty aby wykryć automatycznie $options['use_order_numbers'] = 0; // indeksuj zamówienia wg 0: ID lub 1: numeru $options['pa_fields'] = ''; // mapowanie pól dodatkowych produktu w formacie A:nazwa_pola_1, B:nazwa_pola_2, itd. error_reporting(E_ERROR | E_WARNING); date_default_timezone_set('Europe/Warsaw'); /** ----------------------------------------------------------------------------------------------------------- * Funkcje zarządzające komunikacją (przedrostek Conn_) oraz funkcje ułatwiające zapytania SQL (przedrostek DB_) * - Jednakowe niezależnie od platformy * - Nie należy edytować poniższego kodu */ /** * Definicja funkcji json_encode oraz json_decode dla PHP4 (istnieją domyślnie w PHP5.2), iconv() dla tablic, oraz array_walk_recursive() * Nie należy edytować. Credits goes to Steve http://usphp.com/manual/en/function.json-encode.php#82904 */ if (!function_exists('json_encode')) { function json_encode($a=false,$is_key=false) {if (is_null($a)) return 'null';if ($a === false) return 'false';if ($a === true) return 'true'; if (is_scalar($a)){if(is_int($a)&&$is_key){return '"'.$a.'"';} if (is_float($a)){return floatval(str_replace(",", ".", strval($a)));}if (is_string($a)){ static $jsonReplaces = array(array("\\", "/", "\n", "\t", "\r", "\b", "\f", '"'), array('\\\\', '\\/', '\\n', '\\t', '\\r', '\\b', '\\f', '\"')); return '"' . str_replace($jsonReplaces[0], $jsonReplaces[1], $a) . '"';} else return $a;} $isList = true; for ($i = 0, reset($a); $i < count($a); $i++, next($a)){if (key($a) !== $i){$isList = false;break;}} $result = array(); if ($isList){foreach ($a as $v) $result[] = json_encode($v); return '[' . join(',', $result) . ']';} else {foreach ($a as $k => $v) $result[] = json_encode($k,true).':'.json_encode($v); return '{' . join(',', $result) . '}';}} } if (!function_exists('json_decode')) { function json_decode($json, $assoc = true) {$comment = false; $out = '$x='; for ($i=0; $i $value){ if (is_array($input[$key])){array_walk_recursive($input[$key], $funcname, $userdata);}else{$saved_value = $value; if (!empty($userdata)){$funcname($value, $key, $userdata);}else{$funcname($value, $key);}if ($value != $saved_value) {$input[$key] = $value;}}}return true;} } function array_iconv(&$val, $key, $userdata) {$val = iconv($userdata[0], $userdata[1], $val);} function recursive_iconv($in_charset, $out_charset, $arr) {if (!is_array($arr)){return iconv($in_charset, $out_charset, $arr);}$ret = $arr; array_walk_recursive($ret, "array_iconv", array($in_charset, $out_charset));return $ret;} // środowisko odkodowywania danych z nowej wersji Sote if (!function_exists('random_bytes')) { function random_bytes($octets) { $out = ''; for ($i = 0; $i < $octets; $i++) { $out .= chr(rand(0, 255)); } return $out; } } if (file_exists($options['sote_dir'] . '/plugins/stSecurityPlugin/lib/vendor/defuse/autoload.php')) { @include $options['sote_dir'] . '/plugins/stSecurityPlugin/lib/vendor/defuse/autoload.php'; } elseif (file_exists($options['sote_dir'] . '/plugins/stSecurityPlugin/lib/vendor/DefuseCrypto/Core.php')) { @include $options['sote_dir'] . '/plugins/stSecurityPlugin/lib/vendor/DefuseCrypto/Core.php'; @include $options['sote_dir'] . '/plugins/stSecurityPlugin/lib/vendor/DefuseCrypto/Crypto.php'; @include $options['sote_dir'] . '/plugins/stSecurityPlugin/lib/vendor/DefuseCrypto/Key.php'; @include $options['sote_dir'] . '/plugins/stSecurityPlugin/lib/vendor/DefuseCrypto/Encoding.php'; @include $options['sote_dir'] . '/plugins/stSecurityPlugin/lib/vendor/DefuseCrypto/KeyOrPassword.php'; @include $options['sote_dir'] . '/plugins/stSecurityPlugin/lib/vendor/DefuseCrypto/RuntimeTests.php'; @include $options['sote_dir'] . '/plugins/stSecurityPlugin/lib/vendor/DefuseCrypto/DerivedKeys.php'; @include $options['sote_dir'] . '/plugins/stSecurityPlugin/lib/vendor/DefuseCrypto/Exception/CryptoException.php'; @include $options['sote_dir'] . '/plugins/stSecurityPlugin/lib/vendor/DefuseCrypto/Exception/WrongKeyOrModifiedCiphertextException.php'; } /** * Funkcje wykonujące zapytania SQL */ function DB_Query($sql) { global $dbh; if (func_num_args() > 1){$i = 0; foreach(func_get_args() as $val){if ($i==0){$i++; continue;}$sql = str_replace("{".($i-1)."}", substr($dbh->quote($val), 1, -1), $sql); $i++;}} if (!($sth = $dbh->prepare($sql))) { $err = $dbh->errorInfo(); Conn_error('db_query', 'SQL error: ' . $err[2]); } if (!($sth->execute())) { $err = $sth->errorInfo(); Conn_error('db_query', 'SQL error: ' . $err[2]); } return $sth; } function DB_Result($sth, $num = 0) { if (DB_NumRows($sth) > $num){return $sth->fetchColumn($num);} return false; } function DB_Identity() { global $dbh; return $dbh->lastInsertId(); } function DB_NumRows($sth) { return $sth->rowCount(); } function DB_Fetch($sth) { return $sth->fetch(PDO::FETCH_ASSOC); } /** * Funkcja obsługująca żądania i wysyłająca odpowiedź. * Zalecane jest pozostawienie funkcji w tej postaci niezależnie od platformy * @global array $options : tablica z ustawieniami ogólnymi */ function Conn_Init() { global $options; //sprawdzanie poprawności hasła wymiany danych if(!isset($_POST['bl_pass'])) {Conn_Error("no_password","Odwołanie do pliku bez podania hasła. Jest to poprawny komunikat jeśli plik integracyjny został otworzony w przeglądarce internetowej.");} elseif($options['baselinker_pass'] == "" || $options['baselinker_pass'] !== $_POST['bl_pass']) {Conn_Error("incorrect_password");} //zmiana kodowania danych wejściowych if($options['charset'] != "UTF-8") { foreach($_POST as $key => $val) {$_POST[$key] = iconv('UTF-8', $options['charset'].'//IGNORE', $val);} } //łączenie z bazą danych sklepu Shop_ConnectDatabase($_POST); //rozbijanie tablic z danymi if(isset($_POST['orders_ids'])){$_POST['orders_ids'] = explode(',', $_POST['orders_ids']);} if(isset($_POST['products_id'])){$_POST['products_id'] = explode(',', $_POST['products_id']);} if(isset($_POST['fields'])){$_POST['fields'] = explode(',', $_POST['fields']);} if(isset($_POST['products'])){$_POST['products'] = json_decode($_POST['products'], true);} //sprawdzanie czy podana metoda jest zaimplementowana if(function_exists("Shop_".$_POST['action'])) { $method = "Shop_".$_POST['action']; Conn_SendResponse($method($_POST)); } else {Conn_Error("unsupported_action", "No action: ".$_POST['action']);} } /** * Funkcja generująca odpowiedź do systemu w formacie JSON * @global array $options tablica z ustawieniami ogólnymi */ function Conn_SendResponse($response) { global $options; //zmiana kodowania danych wyjściowych if($options['charset'] != "UTF-8" && count($response) > 0) { foreach($response as $key => $val) {$response[$key] = recursive_iconv($options['charset'], 'UTF-8//IGNORE', $val);} } print json_encode($response); exit(); } /** * Funkcja wypisująca kominukat błędu w formacie JSON i kończąca skrypt * Zalecane jest pozostawienie funkcji w tej postaci niezależnie od platformy * @param string $error_code kod błędu (standardowe wartości: db_connect, db_query, no_action) * @param string $error_text opis błędu */ function Conn_Error($error_code, $error_text = '') { print json_encode(array('error' => true, 'error_code' => $error_code, 'error_text' => $error_text)); exit(); } /** * Ewentualne wczytanie dodatkowych funkcji z pliku baselinker_pm.php (BaseLinker Product Managment) * Zawarte w dodatkowym pliku funkcje rozszerzają możliwości integracji ze sklepem o funkcje pozwalające dodawać i zmieniać kategorie, produkty oraz warianty. * Obsługa tych funkcji jest wymagana przez niektóre moduły BaseLinkera (np. moduły integrujące system z programami typu ERP) * Plik baselinker_pm.php jest dostępny dla wybranych platform sklepów. Skontaktuj się z administratorem w cely uzyskania pliku. */ if(file_exists("baselinker_pm.php")) {include("baselinker_pm.php");} //inicjacja komunikacji Conn_Init(); /** ----------------------------------------------------------------------------------------------------------- * Funkcje obsługiwania żądań (przedrostek Shop_) * - Zależne od platformy sklepu * - Do edycji dla deweloperów */ /** * Funkcja zwracająca wersję pliku wymiany danych * Przy tworzeniu pliku należy skonsultować numer wersji i nazwę platformy * z administracją systemu Baselinker * @param array $request tablica z żadaniem od systemu, w przypadku tej funkcji nie używana * @return array $response tablica z danymi platformy z polami: * platform => nazwa platformy * version => numer wersji pliku */ function Shop_FileVersion($request) { $response['platform'] = "SoteShop"; $response['version'] = "4.1.69"; //wersja pliku integracyjnego, nie wersja sklepu! $response['standard'] = 4; //standard struktury pliku integracyjnego - obecny standard to 4. return $response; } /** * Funkcja zwracająca listę zaimplementowanych metod pliku * Zalecane jest pozostawienie funkcji w tej postaci niezależnie od platformy */ function Shop_SupportedMethods() { $result = array(); $methods = get_defined_functions(); foreach($methods['user'] as $m) { if (stripos($m, 'shop_') === 0) {$result[] = substr($m,5);} } return $result; } /** * Funkcja nawiązująca komunikację z bazą danych sklepu * @global array $options : tablica z ustawieniami ogólnymi z początku pliku * @param array $request tablica z żadaniem od systemu, w przypadku tej funkcji nie używana * @return boolean wartość logiczna określajaca sukces połączenia z bazą danych */ function Shop_ConnectDatabase($request) { global $options; //globalna tablica z ustawieniami global $dbh; // handler bazy danych $dbp = $options['db_prefix']; //Data Base Prefix - prefix tabel bazy // wydzielenie portu z nazwy hosta if (preg_match('/^\s*([\w\-\.]+):(\d+)\s*$/', $options['db_host'], $m)) { $options['db_host'] = $m[1]; $options['db_port'] = $m[2]; } // wygenerowanie DSN $dsn = "mysql:dbname=${options['db_name']};host=${options['db_host']}"; if ($options['db_port']) { $dsn .= ";port=${options['db_port']}"; } // nawiązanie połączenia z bazą danych sklepu try { $dbh = new PDO($dsn, $options['db_user'], $options['db_pass']); } catch (Exception $ex) { Conn_Error('db_connection', $ex->getMessage()); } if($options['charset'] == "UTF-8") {DB_Query("SET NAMES utf8");} DB_Query("SET SESSION sql_mode = 'NO_ENGINE_SUBSTITUTION'"); // automatyczne wyszukiwanie prefiksu bazy danych if ($dbp == '') { // wyszukiwanie tabeli z unikalną nazwą $unique_table = 'st_product_has_category'; $search_table = DB_Query("SHOW TABLES LIKE '%${unique_table}'"); if (DB_NumRows($search_table) == 1) { $options['db_prefix'] = str_replace($unique_table, '', DB_Result($search_table)); $dbp = $options['db_prefix']; } else // nie wykryto jednoznacznie prefiksu { Conn_Error("database_prefix"); } } if (!$options['lang']) { $options['lang'] = DB_Result(DB_Query("SELECT language FROM `${dbp}st_language` WHERE active ORDER BY is_default DESC LIMIT 1")); } if ($options['ean_code']) // weryfikacja pola EAN { if (!DB_NumRows(DB_Query("SHOW FIELDS FROM `${dbp}st_product` LIKE '${options['ean_code']}'"))) { $options['ean_code'] = ''; } } // zniżki już wliczone w opt_price_brutto $options['use_discounts'] = false;//$options['special_price'] && DB_NumRows(DB_Query("SHOW TABLES LIKE '${dbp}st_discount_has_product'")); } /** * Funkcja zwraca listę kategorii sklepowych * Zwracana tabela powinna być posortowana alfabetycznie * W nazwie kategorii podrzędnej powinna być zawrta nazwa nadkategorii - np "Komputery/Karty graficzne" zamiast "Karty graficzne" * @global array $options : tablica z ustawieniami ogólnymi z początku pliku * @param array $request tablica z żadaniem od systemu, w przypadku tej funkcji nie używana * @return array $response tablica z listą kategori sklepowch w formacie: * id kategorii => nazwa kategorii */ function Shop_ProductsCategories($request) { global $options; // globalna tablica z ustawieniami $dbp = $options['db_prefix']; // Data Base Prefix - prefix tabel bazy // pobieranie kategorii z bazy i zapisywanie do tabeli $sql = "SELECT c.*, ci.name FROM `${dbp}st_category` c LEFT JOIN `${dbp}st_category_i18n` ci ON ci.id = c.id AND ci.culture = '{0}' WHERE is_active = 1 AND is_hidden = 0"; $res = DB_Query($sql, $options['lang']); while ($category = DB_Fetch($res)) { $categories[$category['id']] = empty($category['name']) ? $category['opt_name'] : $category['name']; $parents[$category['id']] = $category['parent_id']; } // budowanie drzewa kategorii na podstawie tablicy $category_tree = array(); foreach ($categories as $id => $name) { $cat_name = ""; $this_id = $id; while (isset($parents[$this_id]) and $parents[$this_id] != 0) { if (isset($categories[$parents[$this_id]])) { $cat_name = $categories[$parents[$this_id]] .'/' . $cat_name; } $this_id = $parents[$this_id]; } $category_tree[$id] = $cat_name.$name; } // sortowanie alfabetycznie wg nazw asort($category_tree); return $category_tree; } /** * Funkcja zwraca listę produktów z bazy sklepu * Zwracane liczby (np ceny) powinny mieć format typu: 123456798.12 (kropka oddziela część całkowitą, 2 miejsca po przecinku) * @global array $options : tablica z ustawieniami ogólnymi z początku pliku * @param array $request tablica z żadaniem od systemu zawierająca pola: * category_id => id kategori (wartość 'all' jeśli wszystkie przedmioty) * filter_limit => limit zwróconych kategorii w formacie SQLowym ("ilość pomijanych, ilość pobieranych") * filter_sort => wartość po której ma być sortowana lista produktów. Możliwe wartości: * "id [ASC|DESC]", "name [ASC|DESC]", "quantity [ASC|DESC]", "price [ASC|DESC]" * filter_id => ograniczenie wyników do konkretnego id produktu * filter_ean => ograniczenie wyników do konkretnego ean * filter_sku => ograniczenie wyników do konkretnego sku (numeru magazynowego) * filter_name => filtr nazw przedmiotów (fragment szukanej nazwy lub puste pole) * filter_price_from => dolne ograniczenie ceny (nie wyświetlane produkty z niższą ceną) * filter_price_to => górne ograniczenie ceny * filter_quantity_from => dolne ograniczenie ilości produktów * filter_quantity_to => górne ograniczenie ilości produktów * filter_available => wyświetlanie tylko produktów oznaczonych jako dostępne (wartość 1) lub niedostępne (0) lub wszystkich (pusta wartość) * @return array $response tablica z listą produktów w formacie: * id produktu => 'name' => nazwa produktu 'quantity' => dostępna ilość 'price' => cena w PLN */ function Shop_ProductsList($request) { global $options; //globalna tablica z ustawieniami $dbp = $options['db_prefix']; //Data Base Prefix - prefix tabel bazy // wyrażenie SQL zwracające cenę, nazwę, stan mag. $price_spec = 'p.opt_price_brutto'; $name_spec = 'p.opt_name'; $name_spec = 'pi.name'; $qty_spec = 'p.stock'; // zmiana nazw kolumn na nazwy pól $request['filter_sort'] = str_replace(array('id', 'name', 'quantity', 'price'), array('p.id', $name_spec, $qty_spec, $price_spec), $request['filter_sort']); //pobieranie produktow z bazy danych $sql = "SELECT p.id, $name_spec name, code, $price_spec price, $qty_spec stock FROM `${dbp}st_product` p LEFT JOIN `${dbp}st_product_i18n` pi ON pi.id = p.id AND pi.culture = '{0}' WHERE 1"; // pobieranie zniżek if ($options['use_discounts']) { $sql = "SELECT p.id, $name_spec name, code, $price_spec price, $qty_spec stock, d.value discount, d.conditions, d.price_type FROM `${dbp}st_product` p LEFT JOIN `${dbp}st_discount_has_product` dp ON dp.product_id = p.id LEFT JOIN `${dbp}st_discount` d ON d.id = dp.discount_id AND d.active = 1 AND d.type = 'P' LEFT JOIN `${dbp}st_product_i18n` pi ON pi.id = p.id AND pi.culture = '{0}' WHERE 1"; } if ($request['category_id'] != 'all' && $request['category_id'] != '') // wybór kategorii { $sql = preg_replace('/(\s+WHERE\s+)/', "\nJOIN `${dbp}st_product_has_category` phc ON phc.product_id = p.id$1", $sql); $sql .= " AND phc.category_id = '${request['category_id']}'"; } if ($request['filter_id'] != '') { $sql .= " AND p.id = '${request['filter_id']}'"; } //filtrowanie id if ($request['filter_name'] != '') { $sql .= " AND $name_spec LIKE '%${request['filter_name']}%'"; } //filtrowanie nazwy if ($request['filter_sku'] != '') { $sql .= " AND p.code LIKE '%${request['filter_sku']}%'"; } //filtrowanie SKU if ($options['ean_fld']) { $sql = preg_replace('/^SELECT/is', '$0 '.$options['ean_fld'].',', $sql); if ($request['filter_ean'] != '') { $sql .= " AND p.${options['ean_fld']} LIKE '%${request['filter_ean']}%'"; } // filtrowanie EAN } if ($request['filter_quantity_from'] != '') { $sql .= " AND $qty_spec >= '${request['filter_quantity_from']}'"; } //filtrowanie ilości if ($request['filter_quantity_to'] != '') { $sql .= " AND $qty_spec <= '${request['filter_quantity_to']}'"; } //filtrowanie ilości if ($request['filter_available'] != '') { $sql .= " AND p.active = '${request['filter_available']}'"; } //produkty dostępne/niedostępne if ($request['filter_price_from'] != '') { $sql .= " AND $price_spec >= '${request['filter_price_from']}'"; } if ($request['filter_price_to'] != '') { $sql .= " AND $price_spec <= '${request['filter_price_to']}'"; } if ($request['filter_sort'] != '') { $sql .= " ORDER BY ${request['filter_sort']}"; } if ($request['filter_limit'] != '') { $sql .= " LIMIT ${request['filter_limit']}"; } $response = array(); $result = DB_Query($sql, $options['lang']); while ($prod = DB_Fetch($result)) { if (isset($prod['discount']) and $prod['discount'] > 0) // produkt posiada zniżkę ... { if ($prod['price_type'] == '%' and $prod['discount'] < 100) // procentową { $prod['price'] = number_format($prod['price']*(100-$prod['discount'])/100, 2, '.', ''); } elseif ($prod['price'] > $prod['discount']) // kwotową { $prod['price'] = number_format($prod['price']-$prod['discount'], 2, '.', ''); } } $response[$prod['id']] = array('name' => $prod['name'], 'quantity' => (int)$prod['stock'], 'price' => $prod['price'], 'sku' => $prod['code'], 'ean' => $prod[$options['ean_fld']]); } return $response; } /** * Funkcja zwraca szczegółowe dane wybranych produktów * Zwracane liczby (np ceny) powinny mieć format typu: 123456798.12 (kropka oddziela część całkowitą, 2 miejsca po przecinku) * @global array $options : tablica z ustawieniami ogólnymi z początku pliku * @param array $request tablica z żadaniem od systemu zawierająca pola: * products_id => tablica z numerami id produktów * fields => tablica z nazwami pól do zwrócenia (jeśli pusta zwracany jest cały wynik) * @return array $response tablica z listą produktów w formacie: * id produktu => 'name' => nazwa produktu, 'ean' => Kod EAN, 'sku' => numer katalogowy, 'model' => nazwa modelu lub inny identyfikator np ISBN, 'description' => opis produktu (może zawierać tagi HTML), 'description_extra1' => drugi opis produktu (np opis krótki) 'weight' => waga produktu w kg, 'quantity' => dostępna ilość, 'man_name' => nazwa producenta, 'man_image' => pełny adres obrazka loga producenta, 'category_id' => numer ID głównej kategorii, 'category_name' => nazwa kategori do której należy przedmiot, 'tax' => wielkość podatku w formie liczby (np 23) 'price' => cena brutto w PLN, 'images' => tablica z pełnymi adresami dodatkowych obrazków (pierwsze zdjęcie główne, reszta w odpowiedniej kolejności), 'features' => tablica z opisem cech produktu. Poszczególny element tablicy zawiera nazwę i wartość cechy, np array('Rozdzielczość','Full HD') 'variants' => tablica z wariantami produktu do wyboru (np kolor, rozmiar). Format pola opisany jest w kodzie poniżej */ function Shop_ProductsData($request) { global $options; // globalna tablica z ustawieniami $dbp = $options['db_prefix']; //Data Base Prefix - prefix tabel bazy $category_tree = Shop_ProductsCategories($request); $response = array(); $prodcat = array(); $has_desc2 = DB_NumRows(DB_Query("SHOW FIELDS FROM `${dbp}st_product_i18n` LIKE 'description2'")); $afs = array(); if (preg_match_all('/([A-E])\s*:\s*(.+?)(?=[A-EZ]:)/', $options['pa_fields'].'Z:', $m, PREG_SET_ORDER)) { foreach ($m as $fld) { $afs['field'.(ord($fld[1])-64)] = trim($fld[2], ',; '); } } // mapowanie produktów do kategorii $sql = "SELECT product_id, category_id FROM `${dbp}st_product_has_category` WHERE product_id IN ({0}) ORDER BY is_default"; $res = DB_Query($sql, implode(', ', $request['products_id'])); while ($map = DB_Fetch($res)) { $prodcat[$map['product_id']] = $map['category_id']; } // pobieranie danych produktów z bazy danych $sql = "SELECT p.id, p.code sku, p.code model, m.opt_name man_name, m.image man_image, p.stock quantity, p.opt_url url, p.opt_vat tax, p.weight, p.opt_price_brutto price, pi.name, pi.description, pi.short_description description_extra1, " . ($has_desc2 ? 'pi.description2 description_extra2,' : '') . " p.width, p.height, p.depth " . ($afs ? (', ' . implode(', ', array_keys($afs))) : '') . " FROM `${dbp}st_product` p LEFT JOIN `${dbp}st_product_i18n` pi ON pi.id = p.id AND pi.culture = '{1}' LEFT JOIN `${dbp}st_producer` m ON m.id = p.producer_id WHERE p.id IN ({0})"; if ($options['ean_fld']) { $sql = preg_replace('/^SELECT/is', '$0 p.'.$options['ean_fld'].' ean,', $sql); } $res = DB_Query($sql, implode(', ', $request['products_id']), $options['lang']); $site_root_url = preg_replace('/^(https?:\/\/[^\/]+).*?$/', '$1', $options['images_folder']); while ($p = DB_Fetch($res)) { $product_id = $p['id']; $price_add = 0; $price_mult = 1; // link do strony produktu if ($p['url']) { $p['url'] = "$site_root_url/${p['url']}.html"; } // pobieranie zniżek if ($options['use_discounts']) { $sql = "SELECT d.value, d.conditions, d.price_type FROM `${dbp}st_discount_has_product` dp LEFT JOIN `${dbp}st_discount` d ON d.id = dp.discount_id AND d.active = 1 AND d.type = 'P' WHERE dp.product_id = $product_id"; if ($disc = DB_Fetch(DB_Query($sql))) { if (isset($disc['value']) and $disc['value'] > 0) // produkt posiada zniżkę ... { if ($disc['price_type'] == '%' and $disc['value'] < 100) // procentową { $price_mult = (100-$disc['value'])/100; } elseif ($disc['price'] > $disc['value']) // kwotową { $price_add = -$disc['value']; } } } } // zdjęcie producenta if ($p['man_image']) { $p['man_image'] = $options['images_folder'] . $p['man_image']; } // uzupełnienie powiązania z kategorią if ($prodcat[$product_id]) { $p['category_id'] = $prodcat[$product_id]; $p['category_name'] = $category_tree[$prodcat[$product_id]]; } // warianty $sql = "SELECT pov.id pov_id, if(isnull(povi.value), pov.opt_value, povi.value) name, if(isnull(pofi.name), pof.opt_name, pofi.name) opt_name, pov.price, pov.stock, depth, product_options_field_id field_id, pov.use_product sku" . (empty($options['vean_fld']) ? '' : ", pov.${options['vean_fld']} ean") . " FROM `${dbp}st_product_options_value` pov LEFT JOIN `${dbp}st_product_options_value_i18n` povi ON povi.id = pov.id AND povi.culture = '{2}' LEFT JOIN `${dbp}st_product_options_field` pof ON pof.id = pov.product_options_field_id LEFT JOIN `${dbp}st_product_options_field_i18n` pofi ON pofi.id = pov.product_options_field_id AND pofi.culture = '{2}' WHERE pov.product_id = {0} AND NOT isnull(pov.opt_value) ORDER by pov.depth, pov.lft"; $res2 = DB_Query($sql, $product_id, $options['lang']); $multiopt2 = array(array('name' => '', 'price' => $p['price'])); $depth = 0; $field_id = 0; while ($opt = DB_Fetch($res2)) { $vfeatures = array(array($opt['opt_name'], $opt['name'])); if ($opt['depth'] != $depth) { $depth_col = 0; $multiopt = $multiopt2; $multiopt2 = array(); $depth = $opt['depth']; } elseif ($opt['field_id'] != $field_id) { $depth_col++; } $v = array( 'id' => $opt['pov_id'], 'name' => $multiopt[$depth_col]['name'] . ' ' . $opt['name'], 'quantity' => (int)$opt['stock'], 'price' => $opt['price'], 'sku' => $opt['sku'], 'ean' => empty($opt['ean']) ? $p['ean'] : $opt['ean'], 'features' => $vfeatures, ); if (!$opt['price']) { $v['price'] = $multiopt[$depth_col]['price']; //cena z poprzedniego poziomu } // opcja zmienia cenę o N % elseif (preg_match('/([\+-]?[\.\d]+)%/', $v['price'], $m)) { $v['price'] = number_format($multiopt[$depth_col]['price']*(100+$m[1])/100, 2, '.', ''); } // opcja zmienia cenę o określoną kwotę elseif (preg_match('/([\+-]?[\.\d]+)/', $v['price'], $m)) { $v['price'] = number_format($multiopt[$depth_col]['price']+$m[1], 2, '.', ''); } $v['vfeatures'][] = $vfeatures; $multiopt2[] = $v; $field_id = $opt['field_id']; } $p['variants'] = array(); foreach ($multiopt2 as $v) { if (empty($v['id'])) { continue; } $p['variants'][$v['id']] = array( 'full_name' => $p['name'] . ' ' . $v['name'], 'name' => $v['name'], 'price' => $v['price'], 'quantity' => $v['quantity'], 'sku' => $v['sku'], 'ean' => $v['ean'], 'features' => $v['features'], ); } if ($price_add or $price_mult != 1) { $p['price'] = number_format($p['price']*$price_mult + $price_add, 2, '.', ''); foreach ($p['variants'] as $vid => $v) { $p['variants'][$vid]['price'] = number_format($v['price']*$price_mult + $price_add, 2, '.', ''); } } // pobieranie obrazków $p['images'] = array(); $sql = "SELECT relative_path, filename FROM `${dbp}st_product_has_sf_asset` sphsa JOIN `${dbp}sf_asset` sa ON sphsa.sf_asset_id = sa.id JOIN `${dbp}sf_asset_folder` saf ON sa.folder_id = saf.id WHERE sphsa.product_id = '{0}' ORDER BY is_default DESC, sphsa.id"; $res2 = DB_Query($sql, $product_id); while ($img = DB_Fetch($res2)) { $p['images'][] = "${options['images_folder']}${img['relative_path']}/${img['filename']}"; } //pobieranie cech produktu (np. długość, kolor, rozmiar itp.) $p['features'] = array(); $sql = "SELECT a.opt_name AS name, av.opt_value AS value FROM `${dbp}app_product_attribute_variant_has_product` vhp INNER JOIN `${dbp}app_product_attribute_variant` av ON av.id = vhp.variant_id INNER JOIN `${dbp}app_product_attribute_has_variant` ahv ON ahv.variant_id = vhp.variant_id INNER JOIN `${dbp}app_product_attribute` a ON a.id = ahv.attribute_id WHERE vhp.product_id = '{0}' AND a.is_visible_on_pp"; $res2 = DB_Query($sql, $product_id); while ($f = DB_Fetch($res2)) { $p['features'][$f['name']] = isset($p['features'][$f['name']]) ? ($p['features'][$f['name']] . "|${f['value']}") : $f['value']; } foreach (array_keys($p['features']) as $f) { $p['features'][] = array($f, $p['features'][$f]); unset($p['features'][$f]); } // wymiary produktu foreach (array('width' => 'szerokość', 'height' => 'wysokość', 'depth' => 'głębokość') as $fld => $fld_name) { if ($p[$fld]) { $p['features'][] = array($fld_name, $p[$fld]); } } foreach ($afs as $af => $label) { $p['features'][] = array($label, $p[$af]); unset($p[$af]); } //pobieranie wartości tagu [special] z zewnętrznego skryptu //poniższy warunek może pozostać identyczny niezależnie od platformy sklepu if (file_exists("baselinker_extra.php")) { //pobranie dodatkowych informacji z zewnętrznego pliku pliku. //Plik tworzony jest indywidualnie dla każdego sprzedawcy jeśli zgłosi potrzebę pobierania dodatkowych danych ze sklepu. //Pozwala to uniknąć ingerowania w standardowy plik baselinker.php include("baselinker_extra.php"); } //wyrzucanie niepotrzebnych wartości jeśli określono pola do pobrania //poniższy kod może pozostać identyczny niezależnie od platformy sklepu if (isset($request['fields']) and is_array($request['fields']) and !(count($request['fields']) == 1 && $request['fields'][0] == "") && !count($request['fields']) == 0) { $temp_p = array(); foreach($request['fields'] as $field) {$temp_p[$field] = $p[$field];} $p = $temp_p; } $response[$product_id] = $p; } return $response; } /** * Funkcja zwraca ceny wszystkich produktów i ich wariantów * @global array $options : tablica z ustawieniami ogólnymi z początku pliku * @param array $request tablica z żadaniem od systemu, w przypadku tej funkcji nie używana * @return array $response tablica z cenami wszystkich produktów, w formacie: * id produktu => ID produktu jest kluczem tablicy, wartością jest tablica składająca się z cen wariantów * id wariantu => kluczem tablicy jest ID wariantu (0 w przypadku produktu głównego) * cena => wartościa jest cena brutto produktu lub wariantu * * Przykład: array('432' => array('0' => 230.00, '543' => 210.00, '567' => 230.00)) - produkt ID 432, cena głównego * produktu to 230, posiada dwa warianty (ID 543 i 563), pierwszy w cenie niższej o 20.00. */ function Shop_ProductsPrices($request) { global $options; // globalna tablica z ustawieniami $dbp = $options['db_prefix']; //Data Base Prefix - prefix tabel bazy $response = array(); $page = isset($request['page']) ? (int)$request['page'] : 1; $page = $page ? $page : 1; $per_page = 1000; // pobieranie danych produktów z bazy danych $sql = "SELECT id, opt_price_brutto price FROM `${dbp}st_product` ORDER BY id LIMIT " . ($per_page*($page-1)) . ", $per_page"; $res = DB_Query($sql); while ($p = DB_Fetch($res)) { $product_id = $p['id']; $price_add = 0; $price_mult = 1; // pobieranie zniżek if ($options['use_discounts']) { $sql = "SELECT d.value, d.conditions, d.price_type FROM `${dbp}st_discount_has_product` dp LEFT JOIN `${dbp}st_discount` d ON d.id = dp.discount_id AND d.active = 1 AND d.type = 'P' WHERE dp.product_id = $product_id"; if ($disc = DB_Fetch(DB_Query($sql))) { if (isset($disc['value']) and $disc['value'] > 0) // produkt posiada zniżkę ... { if ($disc['price_type'] == '%' and $disc['value'] < 100) // procentową { $price_mult = (100-$disc['value'])/100; } elseif ($disc['price'] > $disc['value']) // kwotową { $price_add = -$disc['value']; } } } } // warianty $sql = "SELECT pov.id pov_id, pov.price, depth, product_options_field_id field_id, pov.opt_value FROM `${dbp}st_product_options_value` pov LEFT JOIN `${dbp}st_product_options_field` pof ON pof.id = pov.product_options_field_id WHERE pov.product_id = {0} AND NOT isnull(pov.opt_value) ORDER by pov.depth, pov.lft"; $res2 = DB_Query($sql, $product_id); $multiopt2 = array(array('price' => $p['price'], 'opt_vals' => array())); $depth = 0; $field_id = 0; while ($opt = DB_Fetch($res2)) { $vfeatures = array(array($opt['opt_name'], $opt['name'])); if ($opt['depth'] != $depth) { $depth_col = 0; $multiopt = $multiopt2; $multiopt2 = array(); $depth = $opt['depth']; } elseif ($opt['field_id'] != $field_id) { $depth_col++; } $v = array( 'id' => $opt['pov_id'], 'price' => $opt['price'], ); if (!empty($opt['opt_value'])) { $v['opt_vals'] = array_merge((isset($multiopt[$depth_col]['opt_vals']) and is_array($multiopt[$depth_col]['opt_vals'])) ? $multiopt[$depth_col]['opt_vals'] : array(), array($opt['pov_id'])); } if (!$opt['price']) { $v['price'] = $multiopt[$depth_col]['price']; //cena z poprzedniego poziomu } // opcja zmienia cenę o N % elseif (preg_match('/([\+-]?[\d\.]+)%/', $v['price'], $m)) { $v['price'] = number_format($multiopt[$depth_col]['price']*(100+$m[1])/100, 2, '.', ''); } // opcja zmienia cenę o określoną kwotę elseif (preg_match('/([\+-]?[\d\.]+)/', $v['price'], $m)) { $v['price'] = number_format($multiopt[$depth_col]['price']+$m[1], 2, '.', ''); } $v['vfeatures'][] = $vfeatures; $multiopt2[] = $v; $field_id = $opt['field_id']; } $p = array($p['price']); foreach ($multiopt2 as $v) { if (empty($v['opt_vals'])) { continue; } if (!$v['id']) { continue; } $p[implode('_', $v['opt_vals'])] = $v['price']; } if ($price_add or $price_mult != 1) { foreach ($p as $vid => $vprice) { $p[$vid] = number_format($vprice*$price_mult + $price_add, 2, '.', ''); } } $response[$product_id] = $p; } $response['pages'] = ceil((int)DB_Result(DB_Query("SELECT COUNT(*) FROM `${dbp}st_product`"))/$per_page); return $response; } /** * Funkcja ustawia ceny wybranych produktów i ich wariantów * @global array $options : tablica z ustawieniami ogólnymi z początku pliku * @param array $request tablica z żadaniem od systemu: * products => tablica zawierająca informacje o zmianach stanu produktu. Każdy element tablicy jest * również tablicą składającą się z pól: * product_id => ID produktu * variant_id => ID wariantu (0 jeśli produkt główny) * price => nowa cena * @return array $response tablica zawierajaca pole z ilością zmienionych produktów: * counter => ilość zmienionych produktów */ function Shop_ProductsPriceUpdate($request) { global $options; // globalna tablica z ustawieniami $dbp = $options['db_prefix']; //Data Base Prefix - prefix tabel bazy $set_price = array(); $counter = 0; foreach ($request['products'] as $p) { if (isset($p['variant_id']) and !empty($p['variant_id'])) { return array('error' => true, 'error_code' => 'NOT_SUPPORTED', 'Zmiana cen wariantów nie obsługiwana w tej wersji integracji'); } $set_price[(int)$p['product_id']] = $p['price']; } $sql = "SELECT p.id, p.opt_price_brutto price, p.price net_price, p.opt_vat tax FROM `${dbp}st_product` p WHERE p.id IN (" . implode(', ', array_keys($set_price)) . ")"; $res = DB_Query($sql); $sql = "UPDATE `${dbp}st_product` SET opt_price_brutto = '{0}', price = '{1}' WHERE id = '{2}' LIMIT 1"; while ($p = DB_Fetch($res)) { if (isset($set_price[$p['id']]) and $set_price[$p['id']] >= 0.01) { $price = $set_price[$p['id']]; $counter += (DB_Query($sql, $price, $price/(1+$p['tax']/100), $p['id']) ? 1 : 0); } } return array('counter' => $counter); } /** * Funkcja zwraca stan magazynowy wszystkich produktów i ich wariantów * @global array $options : tablica z ustawieniami ogólnymi z początku pliku * @param array $request tablica z żadaniem od systemu, w przypadku tej funkcji nie używana * @return array $response tablica ze stanem magazynowym wszystkich produktów, w formacie: * id produktu => ID produktu jest kluczem tablicy, wartością jest tablica składająca się ze stanów wariantów * id wariantu => kluczem tablicy jest ID wariantu (0 w przypadku produktu głównego) * stan => wartościa jest stan magazynowy * Przykład: array('432' => array('0' => 4, '543' => 2, '567' => 3)) - produkt ID 432, stan głównego produktu to 4, posiada dwa warianty (ID 543 i 563) o stanach 2 i 3. */ function Shop_ProductsQuantity($request) { global $options; //globalna tablica z ustawieniami $dbp = $options['db_prefix']; //Data Base Prefix - prefix tabel bazy $response = array(); $sql = "SELECT p.id product_id, p.stock qty, pov.id pov_id, pov.stock, pov.depth FROM `${dbp}st_product` p LEFT JOIN `${dbp}st_product_options_value` pov ON pov.product_id = p.id AND NOT isnull(pov.product_options_value_id) ORDER by p.id, pov.depth DESC"; $res = DB_Query($sql, $product_id); //TODO join with product_options_value_id = null to get true main product count //or check for null in the loop! Also fix PL with join to pov //Actually here just use the last level without all this fuancy logic! $prod_id = 0; $depth = 0; while ($opt = DB_Fetch($res)) { if ($prod_id == $opt['product_id'] and $depth > $opt['depth']) { continue; } $response[$opt['product_id']][0] = (int)$opt['qty']; if ($opt['pov_id']) { $response[$opt['product_id']][$opt['pov_id']] = (int)$opt['stock']; } $prod_id = $opt['product_id']; $depth = $opt['depth']; } return $response; } /** * Funkcja ustawia stan magazynowy wybranych produktów i ich wariantów * @global array $options : tablica z ustawieniami ogólnymi z początku pliku * @param array $request tablica z żadaniem od systemu: * products => tablica zawierająca informacje o zmianach stanu produktu. Każdy element tablicy jest również tablicą składającą się z pól: * product_id => ID produktu * variant_id => ID wariantu (0 jeśli produkt główny) * operation => rodzaj zmiany, dopuszczalne wartości to: 'set' (ustawia konkretny stan), 'change' (dodaje do stanu magazynowego, ujemna liczba w polu quantity zmniejszy stan o daną ilość sztuk, dodatnia zwiększy) * quantity => zmiana stanu magazynowego (ilośc do ustawienia/zmniejszenia/zwiększenia zależnie od pola operation) * @return array $response tablica zawierajaca pole z ilością zmienionych produktów: * counter => ilość zmienionych produktów */ function Shop_ProductsQuantityUpdate($request) { global $options; // globalna tablica z ustawieniami $dbp = $options['db_prefix']; // Data Base Prefix - prefix tabel bazy foreach ($request['products'] as $prod) { $prod['quantity'] = (int)$prod['quantity']; if ($prod['variant_id']) { $sql = "SELECT stock, lft, rgt FROM `${dbp}st_product_options_value` WHERE product_id = '{0}' AND id = '{1}'"; $res = DB_Query($sql, $prod['product_id'], $prod['variant_id']); if (!DB_NumRows($res)) { continue; // nie znaleziono wariantu } $node = DB_Fetch($res); } if ($prod['operation'] == 'change') // zmiana względem aktualnego stanu { $mod = "if(stock >= -${prod['quantity']}, stock+${prod['quantity']}, 0)"; } elseif ($prod['variant_id']) // podana liczba sztuk wariantu { // dla wszystkich powiązanych rekordów (gałęzie pov + produkt gł) // używamy wartości względnej $prod['quantity'] = $prod['quantity'] - (int)$node['stock']; $mod = "if(stock >= -${prod['quantity']}, stock+${prod['quantity']}, 0)"; } else // ustawienie konkretnej ilości sztuk dla produktu głównego { $mod = $prod['quantity']; } // aktualizacja stanu produktu głównego w tabeli st_product DB_Query("UPDATE `${dbp}st_product` SET stock = $mod WHERE id = '{0}'", $prod['product_id']); // aktualizacja stanu produktu głównego w tabeli st_product_options_value DB_Query("UPDATE `${dbp}st_product_options_value` SET stock = $mod WHERE product_id = '{0}' AND depth = 0", $prod['product_id']); if ($prod['variant_id']) { $upd = "UPDATE `${dbp}st_product_options_value` SET stock = $mod WHERE product_id = {0} AND id = {1}"; // aktualizacja stanów wszystkich atrybutów wariantu $sql = "SELECT id FROM `${dbp}st_product_options_value` WHERE product_id = {0} AND depth > 0 AND lft <= {1} AND rgt >= {2}"; $res = DB_Query($sql, $prod['product_id'], $node['lft'], $node['rgt']); while ($opt = DB_Fetch($res)) { DB_Query($upd, $prod['product_id'], $opt['id']); } } } return array('counter' => count($request['products'])); } /** * Funkcja tworzy zamówienie w sklepie na podstawie nadesłanych danych * Jeśli funkcja otrzyuje na wejściu ID zamówienia, aktualizuje dane zamówienie zamiast tworzyć nowe * @global array $options : tablica z ustawieniami ogólnymi z początku pliku * @param array $request tablica z żadaniem od systemu, zawiera informacje o zamówieniu w formacie: * previous_order_id => ID zamówienia (jeśli pierwszy raz dodawane do sklepu, wartość jest pusta. Jeśli było już wcześniej dodane, wartość zawiera poprzedni numer zamówienia) * delivery_fullname, delivery_company, delivery_address, delivery_city, delivery_postcode, delivery_country => dane dotyczące adresu wysyłki * invoice_fullname, invoice_company, invoice_address, invoice_city, invoice_postcode, invoice_country, invoice_nip => dane dotyczące adresu płatnika faktury * phone => nr telefonu, email => adres email, * delivery_method => nazwa sposóbu wysyłki, delivery_method_id => numer ID sposobu wysyłki, delivery_price => cena wysyłki * user_comments => komentarz kupującego, currency => waluta zamówienia, status_id => status nowego zamówienia * change_products_quantity => flaga (bool) informująca, czy po stworzeniu zamówienia zmniejszony ma zostać stan zakupionych produktów * products => tablica z zakupionymi produktami w formacie: * [] => * id => ID produktu * variant_id => ID wariantu * name => nazwa produktu (używana jeśli nie można pobrać jej z bazy na podstawie id) * price => cena brutto w PLN * currency => waluta * quantity => zakupiona ilość * attributes => tablica z atrybutami produktu w formacie: * [] => * name => nazwa atrybutu (np. "kolor") * value => wartość atybutu (np. "czerwony") * price => różnica ceny dla tego produktu (np. "-10.00") * zmiana ceny jest już uwzględniona w cenie produktu * @return array $response tablica zawierająca numer nowego zamówienia: * 'order_id' => numer utworzonego zamówienia */ function Shop_OrderAdd($request) { global $options; // globalna tablica z ustawieniami $dbp = $options['db_prefix']; // Data Base Prefix - prefix tabel bazy // zdefiniowanie waluty $request['currency'] = $request['currency'] ? $request['currency'] : 'PLN'; $sql = "SELECT * FROM `${dbp}st_currency` WHERE shortcut = '${request['currency']}' LIMIT 1"; $res = DB_Query($sql); $currency = DB_Fetch($res); // jeśli zamówienie jest ponownie dodawane do bazy sklepu, wcześniejsze dane są usuwane // przy ponownym dodawaniu zamówienia (aktualizowaniu), $request['previous_order_id'] zawiera poprzedni numer danego zamówienia w sklepie if ($request['previous_order_id'] != "") { if ($options['use_order_numbers']) { if (!($request['previous_order_id'] = DB_Result(DB_Query("SELECT id FROM `${dbp}st_order` WHERE number = '{0}' ORDER BY id DESC", $request['previous_order_id'])))) { return array('error' => true, 'error_code' => 'NO_MATCH', 'error_text' => "Zamówienie #${request['previous_order_id']} nie istnieje."); // nie udało się dopasować zamówienia po numerze } } $sql = "SELECT o.* FROM `${dbp}st_order` o WHERE o.id = '${request['previous_order_id']}' "; $old = DB_Fetch(DB_Query($sql)); DB_Query("DELETE FROM `${dbp}st_order_delivery` WHERE `id` = '{0}'", $old['order_delivery_id']); DB_Query("DELETE FROM `${dbp}st_order_user_data_billing` WHERE `id` = '{0}'", $old['order_user_data_billing_id']); DB_Query("DELETE FROM `${dbp}st_order_user_data_delivery` WHERE `id` = '{0}'", $old['order_user_data_delivery_id']); DB_Query("DELETE FROM `${dbp}st_order_currency` WHERE `id` = '{0}'", $old['order_currency_id']); DB_Query("DELETE FROM `${dbp}st_order_product` WHERE `order_id` = '{0}'", $old['id']); DB_Query("DELETE FROM `${dbp}st_order` WHERE `id` = '{0}'", $old['id']); DB_Query("DELETE FROM `${dbp}st_order_has_payment` WHERE `order_id` = '{0}'", $old['id']); } // dodawanie waluty zamówienia $sql = "INSERT INTO `${dbp}st_order_currency` (created_at, updated_at, exchange, shortcut, front_symbol, back_symbol, name) VALUES (now(), now(), '{0}', '{1}', '{2}', '{3}', '{4}')"; $res = DB_Query($sql, $currency['exchange'], $request['currency'], $currency['front_symbol'], $currency['back_symbol'], $currency['opt_name']); $currency_id = DB_Identity(); // pobieranie id kraju $sql = "SELECT id FROM `${dbp}st_countries` WHERE iso_a2 = '{0}' OR opt_name = '{1}' LIMIT 1"; $invoice_country_id = DB_Result(DB_Query($sql, $request['invoice_country_code'], $request['invoice_country'])); $sql = "SELECT id FROM `${dbp}st_countries` WHERE iso_a2 = '{0}' OR opt_name = '{1}' LIMIT 1"; $delivery_country_id = DB_Result(DB_Query($sql, $request['delivery_country_code'], $request['delivery_country'])); // język $culture = strtolower($request['invoice_country_code']); if ($culture == 'pl') { $culture .= '_PL'; } elseif ($culture == 'uk' or $culture == 'us' or $culture == 'au' or $culture == 'ca' or $culture == 'ie' or $culture == 'gb') { $culture = 'en_US'; } // dodstawa do punktu odbioru $has_paczkomaty = false; // czy sote obsługuje dodatkowe pole w st_order_delivery $has_pickup_point = false; // czy sote obsługuje pole pickup_point w st_order_delivery if (isset($request['delivery_point_name']) and !empty($request['delivery_point_name'])) { if (!empty($request['delivery_point_name']) and preg_match('/paczkomat/i', $request['delivery_method']) and DB_NumRows(DB_Query("SHOW FIELDS FROM `${dbp}st_order_delivery` LIKE 'paczkomaty_number'"))) { $has_paczkomaty = true; } elseif (DB_NumRows(DB_Query("SHOW FIELDS FROM `${dbp}st_order_delivery` LIKE 'pickup_point'"))) { $has_pickup_point = true; } else { $request['delivery_fullname'] = $request['delivery_point_name']; } foreach (array('city', 'postcode', 'address') as $fld) { $request["delivery_$fld"] = $request["delivery_point_$fld"]; } } // sprawdzanie czy użytkownik już istnieje w bazie danych $sql = "SELECT id FROM `${dbp}sf_guard_user` WHERE username = '{0}'"; $res = DB_Query($sql, $request['email']); if (DB_NumRows($res) > 0) { $user_id = DB_Result($res); } else { // dodawanie użytkownika do tabeli sf_guard_user $sql = "INSERT INTO `${dbp}sf_guard_user` (username, algorithm, salt, password, created_at, last_login, is_active, is_super_admin, is_confirm, is_admin_confirm, hash_code, language, external_account, wholesale, points, points_available, points_release) VALUES ('{0}', 'sha1', 'allegro_user', 'allegro_user', '{1}', '{1}', 1, 0, 0, 0, '{2}', '{3}', NULL, '', 0, 1, 0);"; DB_Query($sql, $request['email'], date('Y-m-d H:i:s'), md5(microtime(true)*rand(10,10000000)), $culture); $user_id = DB_Identity(); $sql = "INSERT INTO `sf_guard_user_group` (`user_id`, `group_id`) VALUES ('{0}', 2);"; DB_Query($sql, $user_id); } $invoice_street = explode(' ',$request['invoice_address']); $invoice_house = array_pop($invoice_street); $invoice_street = implode(' ',$invoice_street); $request['invoice_country'] = $request['invoice_country'] ? $request['invoice_country'] : 'Polska'; $request['delivery_country'] = $request['delivery_country'] ? $request['delivery_country'] : 'Polska'; // prawidłowa nazwa kraju - ważna w niektórych instalacjach Sote $sql = "SELECT name FROM `st_countries` c JOIN `st_countries_i18n` ci ON c.id = ci.id AND ci.culture = 'pl_PL' WHERE iso_a2 = '{0}'"; foreach (array('invoice', 'delivery') as $type) { if (!empty($request["${type}_country_code"])) { if ($cname = DB_Result(DB_Query($sql, $request["${type}_country_code"]))) { $request["${type}_country"] = $cname; } } } // wybór funkcji szyfrującej if (!empty($options['sote_dir'])) { $crypt = 2; } else { $crypt = ('a' == Sote_Encrypt('a')) ? 0 : 1; } // dodawanie adresu płatnika do tabeli st_order_user_data_billing $sql = "INSERT INTO `${dbp}st_order_user_data_billing` ( created_at, updated_at, country , full_name, company, address ,code , town , street, house, phone, vat_number, countries_id, crypt) VALUES ( '{0}', '{0}', '{1}', '{2}', '{3}', '{4}', '{5}', '{6}', NULL, NULL, '{9}' , '{10}', '{11}', '{12}')"; DB_Query($sql, date('Y-m-d H:i:s'), $request['invoice_country'], $request['invoice_fullname'], $request['invoice_company'], Sote_Encrypt($request['invoice_address'], $crypt), Sote_Encrypt($request['invoice_postcode'], $crypt), Sote_Encrypt($request['invoice_city'], $crypt), Sote_Encrypt($invoice_street, $crypt), Sote_Encrypt($invoice_house, $crypt), Sote_Encrypt($request['phone'], $crypt), $request['invoice_nip'], $invoice_country_id, $crypt); $invoice_address_id = DB_Identity(); $delivery_street = explode(' ', $request['delivery_address']); $delivery_house = array_pop($delivery_street); $delivery_street = implode(' ', $delivery_street); // dodawanie adresu dostawy do tabeli st_order_user_data_delivery $sql = "INSERT INTO `${dbp}st_order_user_data_delivery` ( created_at, updated_at, country, full_name, company, address, code, town, street, house, phone, countries_id, crypt) VALUES ( '{0}', '{0}', '{1}', '{2}', '{3}', '{4}', '{5}', '{6}', NULL, NULL, '{9}', '{10}', '{11}')"; DB_Query($sql, date('Y-m-d H:i:s'), $request['delivery_country'], $request['delivery_fullname'], $has_paczkomaty ? "Paczkomat - ${request['delivery_point_id']}" : $request['delivery_company'], Sote_Encrypt($request['delivery_address'], $crypt), Sote_Encrypt($request['delivery_postcode'], $crypt), Sote_Encrypt($request['delivery_city'], $crypt), Sote_Encrypt($delivery_street, $crypt), Sote_Encrypt($delivery_house, $crypt), Sote_Encrypt($request['phone'], $crypt), $delivery_country_id, $crypt); $delivery_address_id = DB_Identity(); // VAT kosztów wysyłki $sql = "SELECT d.tax_id, t.vat FROM `${dbp}st_delivery` d JOIN `st_tax` t ON d.tax_id = t.id ORDER BY (d.id = '{0}') DESC, d.is_default DESC, d.is_system_default DESC LIMIT 1"; $res = DB_Query($sql, $request['delivery_method_id']); if (!($delivery_tax = DB_Fetch($res))) { $delivery_tax = array('tax_id' => 0, 'vat' => 23); } // dodawanie informacji o dostawie do tabeli st_order_delivery $delivery_netto = number_format($request['delivery_price']/(100+$delivery_tax['vat'])*100, 2, '.', ''); $sql = "INSERT INTO `${dbp}st_order_delivery` (created_at, updated_at, name, cost, opt_tax, cost_brutto, delivery_id, tax_id" . ($has_paczkomaty ? ', paczkomaty_number' : ($has_pickup_point ? ', pickup_point' : '')) . ") VALUES ('{0}', '{0}', '{1}', '{2}', '{3}', '{4}', '{5}', '{6}'" . (($has_paczkomaty or $has_pickup_point) ? ", '{7}'" : '') . ")"; DB_Query($sql, date('Y-m-d H:i:s'), $request['delivery_method'], $delivery_netto, $delivery_tax['vat'], $request['delivery_price'], $request['delivery_method_id'], $delivery_tax['tax_id'], ($has_paczkomaty or $has_pickup_point) ? $request['delivery_point_id'] : ''); $delivery_id = DB_Identity(); // karta klienta - adresy dostawy i płatności $sql = "INSERT INTO `${dbp}st_user_data` (crypt, created_at, updated_at, is_billing, is_default, sf_guard_user_id, countries_id, street, house, code, town, phone, full_name, address, company, vat_number) VALUES ('{11}', '{0}', '{0}', {10}, 1, {1}, '{2}', NULL, NULL, '{5}', '{6}', '{7}', '{8}', '{9}', '{12}', '{13}') ON DUPLICATE KEY UPDATE is_billing = {10}"; DB_Query($sql, date('Y-m-d H:i:s'), $user_id, $invoice_country_id, Sote_Encrypt($invoice_street, $crypt), Sote_Encrypt($invoice_house, $crypt), Sote_Encrypt($request['invoice_postcode'], $crypt), Sote_Encrypt($request['invoice_city'], $crypt), Sote_Encrypt($request['phone'], $crypt), $request['invoice_fullname'], Sote_Encrypt($request['invoice_address'], $crypt), 1, $crypt, $request['invoice_company'], $request['invoice_nip']); DB_Query($sql, date('Y-m-d H:i:s'), $user_id, $delivery_country_id, Sote_Encrypt($delivery_street, $crypt), Sote_Encrypt($delivery_house, $crypt), Sote_Encrypt($request['delivery_postcode'], $crypt), Sote_Encrypt($request['delivery_city'], $crypt), Sote_Encrypt($request['phone'], $crypt), $request['delivery_fullname'], Sote_Encrypt($request['delivery_address'], $crypt), 0, $crypt, $request['delivery_company'], ''); // klucz bezpieczeństwa klienta $secure_key = md5(microtime(true)*rand(10,10000000)); $secure_key2 = md5(microtime(true)*rand(10,10000000)); // wyliczanie całkowitego kosztu zamówienia $total_sum = 0; foreach ($request['products'] as $prod) { $total_sum += $prod['price'] * $prod['quantity']; } $total_sum += $request['delivery_price']; $lock = false; // lock zapobiegający dublowaniu numeracji // pobieranie numeru ostatniego zamowienia if ($request['previous_order_id'] != '') { $last_nr = $request['previous_order_id']; } else { if ($lock = @fopen('bl.lock', 'r+')) { flock($lock, LOCK_EX); } $sql = "SELECT number FROM `${dbp}st_order` ORDER BY ABS(number) DESC LIMIT 1"; $res = DB_Query($sql); $last_nr = (int)DB_Result($res)+1; } // dodanie zamowienia do tabeli orders $sql = "INSERT INTO `${dbp}st_order` ( created_at, updated_at, id, order_delivery_id, order_user_data_delivery_id, order_user_data_billing_id, order_currency_id, order_status_id, sf_guard_user_id, hash_code, number, description, client_culture, is_confirmed, opt_client_name, opt_client_email, opt_client_company, opt_total_amount) VALUES ('{0}', '{0}', '{1}' , '{2}', '{3}', '{4}', '{5}', '{6}', '{7}', '{8}', '{9}', '{10}', '{11}', '1', '{12}', '{13}', '{14}', '{15}')"; DB_Query($sql, date('Y-m-d H:i:s'), $request['previous_order_id'], $delivery_id, $delivery_address_id, $invoice_address_id, $currency_id, $request['status_id'], $user_id, $secure_key, $last_nr, $request['user_comments'], $culture, $request['invoice_fullname'], $request['email'], $request['invoice_company'], $total_sum); // pobieranie numeru nowego zamówienia $this_order_id = $request['previous_order_id'] ? $request['previous_order_id'] : DB_Identity(); if (!$request['previous_order_id'] and $this_order_id) { // jeżeli w przeciągu 10 sekund dodało się  zamówienie z tym samym numerem while (DB_Result(DB_Query("SELECT count(*) FROM `${dbp}st_order` WHERE number = '{0}' AND created_at > '{1}'", $last_nr, date('Y-m-d H:i:s', time()-10))) > 1) { // zwiększamy numer zamówienia DB_Query("UPDATE `${dbp}st_order` SET number = '{0}' WHERE id = '{1}' LIMIT 1", ++$last_nr, $this_order_id); } } if ($lock) { flock($lock, LOCK_UN); fclose($lock); } // typ płatności if (empty($request['payment_method_id'])) { $sql = "SELECT id FROM `${dbp}st_payment_type` WHERE active ORDER BY (module_name = 'stStandardPayment') DESC, (opt_name {0} like '%pobran%') DESC LIMIT 1"; $res = DB_Query($sql, $request['payment_method_cod'] ? '' : 'not'); $payment_type_id = DB_Result($res); } else { $payment_type_id = $request['payment_method_id']; } // dodawanie płatności $sql = "INSERT INTO `${dbp}st_payment` (created_at, updated_at, sf_guard_user_id, payment_type_id, amount, status, cancel, hash, version) VALUES ('{0}', '{0}', '{1}', '{2}', '{3}', 0, 0, '{4}', 2)"; DB_Query($sql, date('Y-m-d H:i:s'), $user_id, $payment_type_id, $total_sum, $secure_key2); $this_payment_id = DB_Identity(); if (DB_NumRows(DB_Query("SHOW FIELDS FROM `${dbp}st_order_has_payment` LIKE 'created_at'"))) { $sql = "INSERT INTO `${dbp}st_order_has_payment` (created_at, updated_at, order_id, payment_id) VALUES ('{0}', '{0}', '{1}', '{2}')"; } else { $sql = "INSERT INTO `${dbp}st_order_has_payment` (order_id, payment_id) VALUES ('{1}', '{2}')"; } DB_Query($sql, date('Y-m-d H:i:s'), $this_order_id, $this_payment_id); // obsługa produktów w zamówieniu foreach ($request['products'] as $prod) { $sql = "SELECT * FROM `${dbp}st_product` p WHERE p.id = '{0}'"; $res = DB_Query($sql, $prod['id']); $prod_data = DB_Fetch($res); if (!$prod_data) { $prod_data = array('opt_vat' => isset($prod['tax']) ? $prod['tax'] : 0); } $price_netto = $prod['price'] / (1+$prod_data['opt_vat']/100); $price_modifiers = array(); // obsługa wariantu if (!empty($prod['variant_id'])) { $sql = "SELECT pov.depth, pov.lft, pov.rgt, pov.opt_value, pov.use_product, pov.color, pof.opt_name FROM `${dbp}st_product_options_value` pov LEFT JOIN `${dbp}st_product_options_field` pof ON pof.id = pov.product_options_field_id WHERE pov.product_id = '{0}' AND pov.id = '{1}'"; $res = DB_Query($sql, $prod['id'], $prod['variant_id']); if (DB_NumRows($res)) { $leaf = DB_Fetch($res); $price_modifiers[] = array( 'value' => (float)0, 'type' => 'percent', 'level' => (int)$leaf['depth'], 'prefix' => '+', 'custom' => array( 'id' => (int)$prod['variant_id'], 'color' => $leaf['color'], 'field' => $leaf['opt_name'], 'type' => 'product_options', ), 'label' => $leaf['opt_value'] ); $prod_data['code'] = $leaf['use_product']; // pozostałe opcje wyboru dla tego wariantu $sql = "SELECT id, depth, opt_value FROM `${dbp}st_product_options_value` WHERE product_id = {0} AND depth > 0 AND lft < {1} and rgt > {2} ORDER BY depth desc"; $res = DB_Query($sql, $prod['id'], $leaf['lft'], $leaf['rgt']); while ($opt = DB_Fetch($res)) { array_unshift($price_modifiers, array( 'value' => (float)0, 'type' => 'percent', 'level' => $opt['depth'], 'prefix' => '+', 'custom' => array( 'id' => (int)$opt['id'], 'type' => 'product_options', ), 'label' => $opt['opt_name'], )); } } // nazwa produktu pobrana ze sklepu if ($prod_data['name'] and $prod['name']) { $prod['name'] = $prod_data['name']; } } // dodawanie produktu do zamowienia $sql = "INSERT INTO `${dbp}st_order_product` ( created_at, updated_at, order_id, product_id, quantity, code, name, image, price, price_brutto, vat, price_modifiers, version, tax_id, discount) VALUES ( '{0}', '{0}', '{1}', '{2}', '{3}', '{4}', '{5}', '{6}', '{7}', '{8}', '{9}', '{10}', '{11}', '{12}', '{13}')"; DB_Query($sql, date('Y-m-d H:i:s'), $this_order_id, $prod['id'], $prod['quantity'], $prod_data['code'], $prod['name'], $prod_data['opt_image'], $price_netto, $prod['price'], $prod_data['opt_vat'], serialize($price_modifiers), 3, $prod_data['tax_id'], serialize(array())); // zmniejszanie stanu magazynowego produktu (jeśli ustawiona flaga change_products_quantity) if ($request['previous_order_id'] == '' and $request['change_products_quantity']) { Shop_ProductsQuantityUpdate(array('products' => array(array('product_id' => $prod['id'], 'variant_id' => $prod['variant_id'], 'operation' => 'change', 'quantity' => -1*$prod['quantity'])))); } } if ($options['use_order_numbers']) { $this_order_id = DB_Result(DB_Query("SELECT number FROM `${dbp}st_order` WHERE id = '{0}' ORDER BY id DESC", $this_order_id)); } return array('order_id' => $this_order_id); } /** * Funkcja pobiera zamówienia złożone w sklepie internetowym * Zwracane liczby (np ceny) powinny mieć format typu: 123456798.12 (kropka oddziela część całkowitą, 2 miejsca po przecinku) * @global array $options : tablica z ustawieniami ogólnymi z początku pliku * @param array $request tablica z żadaniem od systemu, zawiera informacje o zamówieniu w formacie: * time_from => czas od którego mają zastać pobrane zamówienia - format UNIX TIME * id_from => ID od którego mają zastać pobrane zamówienia * only_paid => flaga określająca czy pobierane mają być tylko zamówienia opłacone (0/1) * @return array $response tablica zawierająca dane zamówień: * id zamówienia => array: * delivery_fullname, delivery_company, delivery_address, delivery_city, delivery_postcode, delivery_country => dane dotyczące adresu wysyłki * invoice_fullname, invoice_company, invoice_address, invoice_city, invoice_postcode, invoice_country, invoice_nip => dane dotyczące adresu płatnika faktury * phone => nr telefonu, email => adres email, * date_add => data złożenia zamówienia, * payment_method => nazwa metody płatności, * user_comments => komentarz klienta do zamówienia, * status_id => numer ID statusu zamówienia, * delivery_method_id => numer ID metody wysyłki, delivery_method => nazwa metody wysyłki, * delivery_price => cena wysyłki * products => array: * [] => * id => id produktu, variant_id => id wariantu produktu (0 jeśli produkt główny), name => nazwa produktu * quantity => zakupiona ilość, price => cena sztuki brutto (uwzględniająca atrybuty) * weight => waga produktu w kg, tax => wysokość podatku jako liczba z zakresu 0-100 * attributes => array: - tablica z wybieralnymi atrybutami produktów (jeśli istnieją) * [] => * name => nazwa atrybutu (np 'kolor'), * value => wartość atrubutu (np 'czerwony'), * price => różnica w cenie w stosunku do ceny standardowe */ function Shop_OrdersGet($request) { global $options; // globalna tablica z ustawieniami $dbp = $options['db_prefix']; // Data Base Prefix - prefix tabel bazy $response = array(); // dostawa w weekend? $has_weekend_delivery = DB_NumRows(DB_Query("SHOW FIELDS FROM `${dbp}st_order_delivery` LIKE 'weekend_delivery_cost_brutto'")); //sprawdzamy czy sklep obsługuje punkty odbioru Poczty Polskiej $poczta_polska_punkt_odbioru = DB_NumRows(DB_Query("SHOW TABLES LIKE '${dbp}st_poczta_polska_punkt_odbioru'")); //plugin paczki w ruchu $pwr_number = DB_NumRows(DB_Query("SHOW FIELDS FROM `${dbp}st_order_delivery` LIKE 'pwr_number'"))*DB_NumRows(DB_Query("SHOW TABLES LIKE '${dbp}aa_pwr_points'")); $pickup_point = DB_NumRows(DB_Query("SHOW FIELDS FROM `${dbp}st_order_delivery` LIKE 'pickup_point'")); //dodatkowe dane dostawy w oddzielnej tabeli? $sheepla_orders = DB_NumRows(DB_Query("SHOW TABLES LIKE '${dbp}sheepla_orders'")); $has_paczkomaty = DB_NumRows(DB_Query("SHOW FIELDS FROM `${dbp}st_order_delivery` LIKE 'paczkomaty_number'")); $has_dhl = DB_NumRows(DB_Query("SHOW FIELDS FROM `${dbp}st_order_delivery` LIKE 'aa_dhl_service_point'")); //formatowanie daty od której mają być pobrane zamówienia $time_from = date("Y-m-d H:i:s", $request['time_from']); $id_from = (int)$request['id_from']; //zapytanie pobierające zamówienia od określonego czasu $sql = "SELECT o.*, UNIX_TIMESTAMP(o.created_at) time_purchased, od.crypt od_crypt, ob.crypt ob_crypt, od.full_name delivery_name, od.address delivery_street_address, od.address_more delivery_street_address2, od.town delivery_city, od.code delivery_postcode, od.company delivery_company, od.phone delivery_phone, ob.full_name customers_name, ob.address customers_street_address, ob.address_more customers_street_address2, ob.town customers_city, ob.code customers_postcode, ob.company customers_company, ob.phone customers_phone, ob.vat_number customers_nip, del.cost_brutto + if(del.payment_cost_brutto, del.payment_cost_brutto, 0) delivery_cost, del.name delivery_method, oc.shortcut currency, od.country delivery_country, ob.country customers_country, cod.name delivery_country_pl, cob.name customers_country_pl, oc.exchange, obc.iso_a2 invoice_country_code, obd.iso_a2 delivery_country_code, del.delivery_id " . ($pwr_number ? ', del.pwr_number' : '') . " " . ($pickup_point ? ', del.pickup_point' : '') . " " . ($has_paczkomaty ? ', del.paczkomaty_number' : '') . " " . ($has_weekend_delivery ? ', del.weekend_delivery_cost_brutto, del.is_weekend_delivery' : '') . " " . ($has_dhl ? ', del.aa_dhl_service_point' : '') . " FROM `${dbp}st_order` o LEFT JOIN `${dbp}st_order_user_data_billing` ob ON ob.id = o.order_user_data_billing_id LEFT JOIN `${dbp}st_order_user_data_delivery` od ON od.id = o.order_user_data_delivery_id LEFT JOIN `${dbp}st_order_delivery` del ON del.id = o.order_delivery_id LEFT JOIN `${dbp}st_order_currency` oc ON oc.id = o.order_currency_id LEFT JOIN `${dbp}st_countries_i18n` cod ON cod.id = od.countries_id AND cod.culture LIKE 'pl%' LEFT JOIN `${dbp}st_countries_i18n` cob ON cob.id = ob.countries_id AND cob.culture LIKE 'pl%' LEFT JOIN `${dbp}st_countries` obc ON obc.id = ob.countries_id LEFT JOIN `${dbp}st_countries` obd ON obd.id = od.countries_id WHERE o.created_at >= '{0}' AND o.id >= {1}"; $sql .= ($options['og_host'] ? " AND o.host = '{2}'" : ''); $res = DB_Query($sql, $time_from, $id_from, $options['og_host']); while ($order = DB_Fetch($res)) { $o = array('currency' => $order['currency']); $o['delivery_fullname'] = $order['delivery_name']; $o['delivery_company'] = html_entity_decode($order['delivery_company']); $o['delivery_address'] = Sote_Decrypt($order['delivery_street_address'], $order['od_crypt'])." ".Sote_Decrypt($order['delivery_street_address2'], $order['od_crypt']); $o['delivery_city'] = Sote_Decrypt($order['delivery_city'], $order['od_crypt']); $o['delivery_postcode'] = Sote_Decrypt($order['delivery_postcode'], $order['od_crypt']); $o['delivery_country'] = $order['delivery_country_pl'] ? $order['delivery_country_pl'] : $order['delivery_country']; $o['delivery_country_code'] = $order['delivery_country_code']; $o['invoice_fullname'] = $order['customers_name']; $o['invoice_company'] = html_entity_decode($order['customers_company']); $o['invoice_nip'] = $order['customers_nip']; $o['invoice_address'] = Sote_Decrypt($order['customers_street_address'], $order['ob_crypt'])." ".Sote_Decrypt($order['customers_street_address2'], $order['ob_crypt']); $o['invoice_city'] = Sote_Decrypt($order['customers_city'], $order['ob_crypt']); $o['invoice_postcode'] = Sote_Decrypt($order['customers_postcode'], $order['ob_crypt']); $o['invoice_country'] = $order['customers_country_pl'] ? $order['customers_country_pl'] : $order['customers_country']; $o['invoice_country_code'] = $order['invoice_country_code']; $billing_phone = Sote_Decrypt($order['customers_phone'], $order['ob_crypt']); $delivery_phone = Sote_Decrypt($order['delivery_phone'], $order['ob_crypt']); $o['phone'] = $delivery_phone ? $delivery_phone : $billing_phone; $o['email'] = $order['opt_client_email']; $o['date_add'] = $order['time_purchased']; $o['payment_method'] = ""; $o['user_comments'] = $order['description']; $o['delivery_method'] = $order['delivery_method']; $o['delivery_method_id'] = $order['delivery_id']; $o['status_id'] = $order['order_status_id']; // most likely undecrypted order data if (preg_match('/\w{40}/', $o['phone'])) { return array('error' => true, 'error_code' => 'DECRYPT_ERROR', 'error_text' => 'Unable to decode order data: ' . $o['phone']); } if (preg_match('/\w{40}/', $o['delivery_address'])) { return array('error' => true, 'error_code' => 'DECRYPT_ERROR', 'error_text' => 'Unable to decode order data: ' . $o['delivery_address']); } // dostawa do paczkomatu if (preg_match('/^(Paczkomat)?(\s+|\s+-\s+)?((POP-)?([A-Z]{3}\d+[A-Z]*))\s*$/', $o['delivery_company'], $m)) { $o['delivery_point_name'] = $m[3]; $o['delivery_point_id'] = $m[3]; foreach (array('address', 'city', 'country', 'postcode') as $fld) { $o["delivery_point_$fld"] = $o["delivery_$fld"]; $o["delivery_$fld"] = $o["invoice_$fld"]; } foreach (array('company', 'fullname') as $fld) { $o["delivery_$fld"] = $o["invoice_$fld"]; } } elseif (isset($order['shipping_module']) and preg_match('/paczkomat/', $order['shipping_module']) and preg_match('/^([^,]+), (\d\d-\d{3}) (.+?), (.+?) \((\w+)\)/', $order['shipping_info'], $m)) { $o['delivery_point_name'] = $m[5]; $o['delivery_point_address'] = "${m[4]}, ${m[1]}"; $o['delivery_point_city'] = $m[3]; $o['delivery_point_postcode'] = $m[2]; } elseif (preg_match('/paczkomat/i', $order['delivery_method']) and isset($order['in_post_terminal']) and preg_match('/^([\w\-]+)\|.*?\|[\w\-]+ - (\d\d-\d{3}) ([\w\-]+) (.+)/u', $order['in_post_terminal'], $m)) { $addr = explode(' ', $m[4]); // dwu-członowa nazwa miejscowości? if (count($addr) > 1 and strlen($add[0]) > 2 and preg_match('/^[A-ZĆŁÓŚŻŹ]/', $addr[0])) { $m[3] .= ' ' . array_splice($addr, 0, 1); $m[4] = implode(' ', $addr); } $o['delivery_point_id'] = $m[1]; $o['delivery_point_name'] = $m[1]; $o['delivery_point_address'] = $m[4]; $o['delivery_point_city'] = $m[3]; $o['delivery_point_postcode'] = $m[2]; } elseif ($sheepla_orders) { $sql = "SELECT adddata FROM `${dbp}sheepla_orders` WHERE order_id = {0}"; if ($so_data = DB_Result(DB_Query($sql, $order['id']))) { if ($so_data = @unserialize($so_data)) { if ($so_data['sheepla-widget-plinpost-paczkomat']) { $o['delivery_point_name'] = $so_data['sheepla-widget-plinpost-paczkomat']; } } } } //punkt odbioru PP if (empty($o['delivery_point_name']) and $poczta_polska_punkt_odbioru) { if ($dp = DB_Fetch(DB_Query("SELECT * FROM `${dbp}st_poczta_polska_punkt_odbioru` WHERE order_id = '{0}'", $order['id']))) { $o['delivery_point_id'] = $dp['pni']; $o['delivery_point_name'] = $dp['name']; $o['delivery_point_address'] = $dp['street']; $o['delivery_point_city'] = $dp['city']; $o['delivery_point_postcode'] = $dp['zip_code']; $o['delivery_fullname'] = $o['delivery_fullname'] ? $o['delivery_fullname'] : $o['invoice_fullname']; if ($dp['name'] == $o['delivery_company']) { $o['delivery_company'] = ''; } } } // Paczka w RUCHu if ($pwr_number and !$request['only_paid'] and !isset($o['delivery_point_name']) and !empty($order['pwr_number'])) { $o['delivery_point_name'] = $order['pwr_number']; if ($pwr = DB_Fetch(DB_Query("SELECT * FROM `${dbp}aa_pwr_points` WHERE destination_code = '{0}'", $order['pwr_number']))) { $o['delivery_point_city'] = $pwr['city']; $o['delivery_point_address'] = $pwr['street_name']; } } // Orlen Paczka if (empty($o['delivery_point_id']) and preg_match('/orlen/i', $o['delivery_method']) and isset($o['delivery_company']) and preg_match('/Punkt nr: ([\S]+)\s*$/', $o['delivery_company'], $m)) { $o['delivery_point_id'] = $o['delivery_point_name'] = $m[1]; $o['delivery_point_address'] = $o['delivery_address']; $o['delivery_point_city'] = $o['delivery_city']; $o['delivery_point_postcode'] = $o['delivery_postcode']; $o['delivery_company'] = $o['invoice_company']; $o['delivery_address'] = $o['invoice_address']; } // DHL if (empty($o['delivery_point_id']) and preg_match('/dhl.+?pop/i', $o['delivery_method']) and $has_dhl and !empty($order['aa_dhl_service_point'])) { $o['delivery_point_id'] = $o['delivery_point_name'] = $order['aa_dhl_service_point']; } // paczkomat z pola paczkomaty_number if (empty($o['delivery_point_id']) and preg_match('/inpost|paczkom/i', $o['delivery_method']) and !empty($order['paczkomaty_number'])) { $o['delivery_point_id'] = $o['delivery_point_name'] = $order['paczkomaty_number']; } // new versions of sote store delivery point ID here if (empty($o['delivery_point_id']) and !empty($order['pickup_point'])) { $o['delivery_point_id'] = $o['delivery_point_name'] = $order['pickup_point']; foreach (array('address', 'city', 'country', 'postcode', 'fullname', 'company') as $fld) { $o["delivery_$fld"] = $o["invoice_$fld"]; } } // jeśli zamówienie jest w walucie innej niż PLN, trzeba przeliczyć koszt wysyłki if ($order['currency'] != 'PLN' and $order['exchange']) { $order['delivery_cost'] /= $order['exchange']; } $o['delivery_price'] = number_format($order['delivery_cost'] + (($has_weekend_delivery and $order['is_weekend_delivery']) ? (float)$order['weekend_delivery_cost_brutto'] : 0), 2, ".", ""); if ($has_weekend_delivery and $order['is_weekend_delivery']) { $o['delivery_method'] .= ' dostawa w weekend'; } // czy klient chce fakturę if ($o['invoice_nip']) { $o['want_invoice'] = 1; } else { $sql = "SELECT count(*) FROM `${dbp}st_invoice` WHERE order_id = '{0}' AND is_request = 1"; $o['want_invoice'] = DB_Result(DB_Query($sql, $order['id'])); } $deductions = array(); // bony, itp $total_paid = 0; // zaksięgowana wpłata // sposób platności $sql = "SELECT pt.opt_name, p.payed_at, p.status, p.amount, gc.code FROM `${dbp}st_order_has_payment` op JOIN `${dbp}st_payment` p ON p.id = op.payment_id LEFT JOIN `${dbp}st_payment_type` pt ON pt.id = p.payment_type_id LEFT JOIN `${dbp}st_gift_card` gc ON gc.id = p.gift_card_id WHERE op.order_id = '{0}'"; $result = DB_Query($sql, $order['id']); while ($payment = DB_Fetch($result)) { if ($payment['code']) // bon jako dodatkowa pozycja zamówienia { $deductions[] = array( 'id' => '-', 'name' => 'Bon zakupowy ' . $payment['code'], 'price' => -$payment['amount'], 'quantity' => 1, ); } else { $o['payment_method'] = $payment['opt_name']; } if ($payment['status']) { $total_paid += $payment['amount']; } } $o['paid'] = ($total_paid >= $order['opt_total_amount']) ? 1 : ($order['opt_is_payed'] ? 1 : 0); if (preg_match('/pobran|przy odb|obírk/i', $o['payment_method']) or preg_match('/dobírk/i', $o['delivery_method'])) { $o['payment_method_cod'] = 1; $o['paid'] = 0; } //produkty zamówienia $o['products'] = array(); $total_products = 0; $sql = "SELECT op.*, p.weight, p.code, ops.code scode, ops.name sname, ops.product_id sproduct_id, p.opt_short_description, ops.price_brutto sprice_brutto" . ($options['ean_fld'] ? ", p.${options['ean_fld']} ean" : '') . " FROM `${dbp}st_order_product` op LEFT JOIN `${dbp}st_order_product_has_set` ops ON ops.order_product_id = op.id LEFT JOIN `${dbp}st_product` p ON p.id = if(op.is_set, ops.product_id, op.product_id) WHERE op.order_id = '{0}' "; if ($options['ean_fld']) { $sql = preg_replace('/^SELECT/is', '$0 p.'.$options['ean_fld'].' ean,', $sql); } $max_tax_rate = 0; $result = DB_Query($sql, $order['id']); while ($product = DB_Fetch($result)) { $set_pref = $product['is_set'] ? 's' : ''; if ($set_pref) { $std_set_price = DB_Result(DB_Query("SELECT SUM(price_brutto) FROM `${dbp}st_order_product_has_set` WHERE order_product_id = '{0}'", $product['id'])); $product['sprice_brutto'] *= $product['price_brutto']/$std_set_price; } $op = array( 'id' => $product[$set_pref.'product_id'], 'name' => $product[$set_pref.'name'], 'quantity' => $product['quantity'], 'price' => $product[$set_pref.'price_brutto'], 'tax' => $product['vat'], 'weight' => $product['weight'], 'sku' => $product[$set_pref.'code'], 'ean' => $product['ean'], ); if ($op['tax'] > $max_tax_rate) { $max_tax_rate = $op['tax']; } if ($product['is_set']) { if (isset($product['discount']) and $disc = @unserialize($product['discount'])) { if (isset($disc[0]['type']) and $disc[0]['type'] == '%') { $op['price'] = number_format($op['price']*(100-$disc[0]['value'])/100, 2, '.', ''); } } // ten sam produkt pojawia się w zestawie wielokrotnie if (!$request['only_paid'] and DB_Result(DB_Query("SELECT count(*) FROM `${dbp}st_order_product_has_set` WHERE order_product_id = '{0}'", $product['id'])) == 1) { $price_ratio = $product['price_brutto']/$product['sprice_brutto']; if ($price_ratio == (int)$price_ratio) { $op['quantity'] *= $price_ratio; } } $total_products += $op['price']*$op['quantity']; $o['products'][] = $op; continue; } if ($product['price_modifiers'] != '') { $opts = unserialize($product['price_modifiers']); $depth = 0; foreach ($opts as $opt) { // modyfikacja ceny if (!empty($opt['value'])) { if ($opt['prefix'] == '-') { if (isset($opt['value']['brutto'])) { $opt['value']['brutto'] = -$opt['value']['brutto']; } else { $opt['value'] = -$opt['value']; } } if ($opt['type'] == 'percent') { //$op['price'] = $opt['price'] + $opt['value']*$opt['price']/100; //$op['price'] = $opt['value']*$op['price']/100; } else { if (is_array($opt['value'])) { if ($opt['value']['brutto']) { // $op['price'] = $opt['value']['brutto'] / (($o['currency'] != 'PLN' AND $order['exchange']) ? $order['exchange'] : 1); } } else { // $op['price'] += $opt['value']; } } } // id odstatniego poziomu zagłębienia identyfikuje wariant if ($opt['level'] > $depth and !empty($opt['custom']) and $opt['custom']['type'] == 'product_options') { $op['variant_id'] = $opt['custom']['id']; $depth = $opt['level']; // jeszcze tylko SKU (+EAN) wariantu ... $sql = "SELECT use_product sku" . ($options['vean_fld'] ? ", ${options['vean_fld']} ean" : '') . " FROM `${dbp}st_product_options_value` WHERE id = '{0}' LIMIT 1"; if ($v = DB_Fetch(DB_Query($sql, $op['variant_id']))) { $op['sku'] = $v['sku'] ? $v['sku'] : $op['sku']; $op['ean'] = $v['ean'] ? $v['ean'] : $op['ean']; } } $op['name'] .= ' ' . $opt['label']; } $op['price'] = number_format($op['price'],2,".",""); } if($product['discount'] != "") { $discounts = unserialize($product['discount']); foreach($discounts as $d) { if($d['type'] == "%") {$op['price'] *= 1-($d['value']/100);} else {$op['price'] -= $d['value'];} $op['price'] = number_format($op['price'],2,".",""); } } $total_products += $op['price']*$op['quantity']; $o['products'][] = $op; } $order_total = $o['delivery_price']; foreach ($o['products'] as $op) { $order_total += $op['quantity']*$op['price']; } // rabat od całości zamówienia if ($order['discount_id'] and $order['order_discount']) { if ($discount = @unserialize($order['order_discount'])) { if ($discount['value']) { $op = array('name' => 'Rabat', 'quantity' => 1, 'id' => '', 'tax' => $max_tax_rate); // ustalenie nazwy rabatu $sql = "SELECT name FROM `${dbp}st_discount` WHERE id = '{0}'"; if ($dname = DB_Result(DB_Query($sql, $order['discount_id']))) { $op['name'] = preg_match('/rabat/i', $dname) ? $dname : "Rabat $dname"; } if ($discount['type'] == '%') // rabat procentowy { $op['price'] = number_format(-$discount['value']*$total_products/100, 2, '.', ''); } else // rabat kwotowy { $op['price'] = -$discount['value']; } $o['products'][] = $op; } } } elseif (count($deductions)) { $o['products'] = array_merge($o['products'], $deductions); } elseif ($order['opt_total_amount'] - $order_total <= -0.01) { $o['products'][] = array('name' => 'Rabat', 'quantity' => 1, 'id' => '', 'tax' => $max_tax_rate, 'price' => number_format($order['opt_total_amount']-$order_total, 2, '.', '')); } $response[$options['use_order_numbers'] ? $order['number'] : $order['id']] = $o; } return $response; } /** * Funkcja aktualizuje zamówienia wcześniej dodane do bazy * W przypadku zapisywania numeru nadawaczego, parametr orders_ids będzie przyjmował zawsze tablicę z jedną pozycją * @global array $options : tablica z ustawieniami ogólnymi z początku pliku * @param array $request tablica z żadaniem od systemu, zawiera informacje o aktualizacji zamówienia w formacie: * orders_ids => ID zamówień * update_type => typ zmiany - 'status', `delivery_number`, lub 'paid' (aktualizacja statusu zamówienia, dodanie numeru nadawczego i dodanie/usunięcie wpłaty) * update_value => aktualizowana wartość - ID statusu, numer nadawczy lub informacja o opłaceniu zamówienia (bool true/false) * @return array $response tablica zawierająca potwierdzenie zmiany: * 'counter' => ilość zamówień w których dokonano zmiany (nawet jeśli zamówienie pozostało takie jak wcześniej) */ function Shop_OrderUpdate($request) { global $options; // globalna tablica z ustawieniami $dbp = $options['db_prefix']; // Data Base Prefix - prefix tabel bazy $counter = 0; // dla wszystkich nadesłanych numerów zamówień foreach ($request['orders_ids'] as $order_id) { if ($options['use_order_numbers']) { if (!($order_id = DB_Result(DB_Query("SELECT id FROM `${dbp}st_order` WHERE number = '{0}' ORDER BY id DESC", $order_id)))) { continue; // nie udało się dopasować zamówienia po numerze } } // zmiana statusu if ($request['update_type'] == 'status') { DB_Query("UPDATE `${dbp}st_order` SET order_status_id = '{0}', updated_at = '{1}' WHERE id = '{2}'", $request['update_value'], date('Y-m-d H:i:s'), $order_id); } // zapisanie numeru nadawczego elseif ($request['update_type'] == 'delivery_number') { DB_Query("UPDATE `${dbp}st_order_delivery` SET number = '{0}' WHERE id = (SELECT order_delivery_id FROM `${dbp}st_order` WHERE id = '{1}') LIMIT 1", $request['update_value'], $order_id); } // zmiana statusu wpłaty elseif ($request['update_type'] == 'paid') { DB_Query("UPDATE `${dbp}st_payment` SET updated_at = '{0}', status = '{2}', payed_at = " . ($request['update_value'] ? '"{0}"' : 'NULL') . " WHERE id = (SELECT payment_id FROM `${dbp}st_order_has_payment` WHERE order_id = '{1}' ORDER BY created_at DESC LIMIT 1) LIMIT 1", date('Y-m-d H:i:s'), $order_id, $request['update_value'] ? 1 : 0); DB_Query("UPDATE `${dbp}st_order` SET opt_is_payed = '{0}' WHERE id = '{1}'", $request['update_value'] ? 1 : 0, $order_id); } $counter++; } return array('counter' => $counter); } /** * Funkcja zwraca listę dostępnych statusów zamówień * @global array $options : tablica z ustawieniami ogólnymi z początku pliku * @param array $request tablica z żadaniem od systemu, w przypadku tej funkcji nie używana * @return array $response tablica zawierająca dostępne statusy zamówień: * 'status_id' => nazwa statusu */ function Shop_StatusesList($request) { global $options; // globalna tablica z ustawieniami $dbp = $options['db_prefix']; // Data Base Prefix - prefix tabel bazy $response = array(); $sql = "SELECT id, opt_name FROM `${dbp}st_order_status` ORDER BY is_default DESC"; $res = DB_Query($sql); while ($status = DB_Fetch($res)) { $response[$status['id']] = $status['opt_name']; } return $response; } /** * Funkcja zwraca listę dostępnych sposobów wysyłki * @global array $options : tablica z ustawieniami ogólnymi z początku pliku * @param array $request tablica z żadaniem od systemu, w przypadku tej funkcji nie używana * @return array $response tablica zawierająca dostępne sposoby_wysyłki: * 'delivery_id' => nazwa wysyłki */ function Shop_DeliveryMethodsList($request) { global $options; //globalna tablica z ustawieniami $dbp = $options['db_prefix']; //Data Base Prefix - prefix tabel bazy $response = array(); $sql = "SELECT id, opt_name FROM `${dbp}st_delivery` WHERE active ORDER BY is_default DESC"; $res = DB_Query($sql); while ($method = DB_Fetch($res)) { $response[$method['id']] = $method['opt_name']; } return $response; } /** * Funkcja zwraca listę dostępnych metod płatności * @global array $options : tablica z ustawieniami ogólnymi z początku pliku * @param array $request tablica z żadaniem od systemu, w przypadku tej funkcji nie używana * @return array $response tablica zawierająca dostępne metody płatności * 'payment_id' => nazwa płatności */ function Shop_PaymentMethodsList($request) { global $options; //globalna tablica z ustawieniami $dbp = $options['db_prefix']; //Data Base Prefix - prefix tabel bazy $response = array(); $sql = "SELECT id, opt_name FROM `${dbp}st_payment_type` WHERE active ORDER BY opt_name"; $res = DB_Query($sql); while ($method = DB_Fetch($res)) { $response[$method['id']] = $method['opt_name']; } return $response; } function Sote_Decrypt($text = '', $decrypt = true) { global $options; static $key; if ($decrypt == '2' and preg_match('/^def/', $text) and (isset($key) or file_exists($options['sote_dir'] . '/data/encrypt.key.php'))) { $key = include $options['sote_dir'] . '/data/encrypt.key.php'; try { return \Defuse\Crypto\Crypto::decrypt((string)$text, $key); } catch (Exception $ex) { return $text; } } if($decrypt != "1"){return $text;} $key = $options['sote_shophash']; $string = $text; $string = base64_decode($string); $td = mcrypt_module_open('des', '','cfb', ''); $key = substr($key, 0, mcrypt_enc_get_key_size($td)); $iv_size = mcrypt_enc_get_iv_size($td); $iv = substr($string,0,$iv_size); $string = substr($string,$iv_size); if (strlen($iv) == 0) { return $text; } if (mcrypt_generic_init($td, $key, $iv) != -1) { $c_t = @mdecrypt_generic($td, $string); mcrypt_generic_deinit($td); mcrypt_module_close($td); return $c_t; } } function Sote_Encrypt($text, $mode = 1) { global $options; static $key; if ($mode == 2) { if (file_exists($options['sote_dir'] . '/data/encrypt.key.php')) { $key = include $options['sote_dir'] . '/data/encrypt.key.php'; } if (!isset($key)) { Conn_Error('CRYPTO_FAILIURE', 'Nie można pobrać klucza szyfrowania'); } try { return \Defuse\Crypto\Crypto::encrypt((string)$text, $key); } catch (Exception $ex) { Conn_Error('CRYPTO_FAILIURE', 'Błąd szyfrowania'); } } if ($key = $options['sote_shophash']) { $td = mcrypt_module_open('des', '','cfb', ''); $key = substr($key, 0, mcrypt_enc_get_key_size($td)); $iv_size = mcrypt_enc_get_iv_size($td); $iv = substr(base64_encode(md5(microtime(true))), 0, $iv_size); if (@mcrypt_generic_init($td, $key, $iv) != -1) { $enc = @mcrypt_generic($td, $text); mcrypt_generic_deinit($td); mcrypt_module_close($td); return base64_encode($iv.$enc); } } return $text; } ?>