diff --git a/api/ApiExact.php b/api/ApiExact.php new file mode 100644 index 0000000..014169f --- /dev/null +++ b/api/ApiExact.php @@ -0,0 +1,119 @@ + + * @date 11.07.22 + */ + +require_once('Product.php'); + +class ApiExact +{ + const API_URL = "https://start.exactonline.de/api"; + const CLIENT_ID = "5a04d118-349c-4750-aac3-fa3a386999c6"; + const CLIENT_SECRET = "E7Wuqcsp4Lih"; + const ACCESS_TOKEN_VALID_DURATION = 600 - 50; + + const DIVISION = '58687'; + const ITEM_GROUP_UUID = 'df17bdaf-2af7-4e9f-8d60-326e36b57764'; + const PRODUCT_CODE_PREFIX = "WR"; + + public function getAccessToken() + { + $tokenData = json_decode(file_get_contents('./tokenData', true)); + if (!property_exists($tokenData, 'expiry_time') || (int)$tokenData->expiry_time < time()) { + $postData = array( + 'grant_type' => 'refresh_token', + 'refresh_token' => $tokenData->refresh_token, + 'client_id' => self::CLIENT_ID, + 'client_secret' => self::CLIENT_SECRET + ); + + $ch = curl_init(); + curl_setopt_array($ch, array( + CURLOPT_URL => self::API_URL . '/oauth2/token', + CURLOPT_RETURNTRANSFER => TRUE, + CURLOPT_HTTPHEADER => array('Content-Type: application/x-www-form-urlencoded'), + CURLOPT_POSTFIELDS => http_build_query($postData) + )); + + $response = curl_exec($ch); + curl_close($ch); + + $jsonResult = json_decode($response); + + if (property_exists($jsonResult, 'error')) { + $msg = $jsonResult->error; + throw new Exception($msg); + } + + + $jsonResult->expiry_time = time() + self::ACCESS_TOKEN_VALID_DURATION; + file_put_contents('./tokenData', json_encode($jsonResult)); + + $tokenData = json_decode(file_get_contents('./tokenData', true)); + } + return $tokenData->access_token; + } + + public function getProducts() + { + $baseUrl = self::API_URL . '/v1/' . self::DIVISION . "/bulk/Logistics/Items?"; + $fields = [ + 'ID', + 'StandardSalesPrice', + 'SalesVatCode', + 'SalesVatCodeDescription', + 'Description', + 'ExtraDescription', + 'IsWebshopItem', + 'ItemGroup', + 'ItemGroupCode', + 'Stock', + 'NetWeight', + 'GrossWeight', + 'Code' + ]; + $filter = "\$filter=ItemGroup eq guid'".self::ITEM_GROUP_UUID."'"; + $select = "&\$select=".$this->getFieldString($fields); + $requestUrl = $baseUrl . $filter . $select; + $response = $this->getApiData($requestUrl); + $responseArr = json_decode($response, 1)['d']['results']; + + $res = []; + foreach ($responseArr as $productItem) { + if ( + array_key_exists('IsWebshopItem', $productItem) && + $productItem['IsWebshopItem'] === 1 && + array_key_exists('Code', $productItem) && + stripos(strtoupper($productItem['Code']), self::PRODUCT_CODE_PREFIX) === 0 + ) { + $res[] = Product::createProductFromApiItem($productItem); + } + } + return $res; + } + + private function getApiData($url) + { + $ch = curl_init(); + curl_setopt_array($ch, array( + CURLOPT_URL => $url, + CURLOPT_HTTPHEADER => array('Accept: application/json' , "Authorization: Bearer " . $this->getAccessToken() ), + CURLOPT_RETURNTRANSFER => TRUE, + )); + return curl_exec($ch); + } + + private function getFieldString($fields) + { + $res = ''; + $cnt = count($fields); + $i = 1; + foreach ($fields as $field) { + $res .= $cnt !== $i ? $field . ',' : $field; + $i++; + } + return $res; + } + +} \ No newline at end of file diff --git a/api/IsotopeDatabaseHandler.php b/api/IsotopeDatabaseHandler.php new file mode 100644 index 0000000..ee89e1d --- /dev/null +++ b/api/IsotopeDatabaseHandler.php @@ -0,0 +1,147 @@ + + * @date 11.07.22 + */ + +require_once('Product.php'); + +class IsotopeDatabaseHandler +{ + const USER = 'root'; + const PASSWORD = ''; + const HOST = '127.0.0.1'; + const DB_NAME = 'wash_n_roll'; + + private $dbHandle; + + public function __construct() + { + try { + $this->dbHandle = new PDO('mysql:host='.self::HOST.';dbname='.self::DB_NAME.';charset=utf8',self::USER, self::PASSWORD); + $this->dbHandle->setAttribute(PDO::ATTR_ERRMODE, PDO::ERRMODE_EXCEPTION); + + } catch (PDOException $e) { + print "Error!: " . $e->getMessage() . "
"; + die(); + } + } + + + public function updateProducts(array $products) + { + /** @var Product $product */ + foreach ($products as $product) { + $productId = $this->updateProduct($product); + $productPriceId = $this->updatePrice($product, $productId); + $this->updatePriceTier($product, $productPriceId); + } + + + } + + private function updateProduct(Product $product) + { + $alias = 'exact-product-'.$product->getCode(); + $shippingWeight = $product->getGrossWeight() !== '' ? + ($product->getNetWeight() !== '' ? $product->getNetWeight() : '') : ''; + $sql = + "INSERT into `tl_iso_product` ( + pid, + gid, + tstamp, + language, + dateAdded, + type, + fallback, + alias, + gtin, + sku, + name, + description, + meta_title, + baseprice, + shipping_weight, + shipping_exempt, + shipping_pickup, + shipping_price, + protected, + guests, + cssID, + published, + start, + stop + ) VALUES ( + 0, + 0, + ".time().", + '', + ".time().", + 2, + '', + '$alias', + '', + '".$product->getCode()."', + '".$product->getDescription()."', + '".$product->getExtraDescription()."', + '', + '', + '$shippingWeight', + '', + '', + 0.00, + '', + '', + '', + '0', + '', + '' + )"; + $this->dbHandle->query($sql); + return $this->dbHandle->lastInsertId(); + } + + private function updatePrice(Product $product, $productDbId) + { + $sql = + "INSERT INTO `tl_iso_product_price` ( + pid, + tstamp, + tax_class, + config_id, + member_group, + start, + stop + ) VALUES ( + $productDbId, + ".time().", + 1, + 0, + 0, + '', + '' + )"; + $this->dbHandle->query($sql); + return $this->dbHandle->lastInsertId(); + } + + private function updatePriceTier(Product $product, $productPriceDbId) + { + $price = $product->getStandardSalesPrice() * (1 + Product::VAT); + $sql = + "INSERT INTO `tl_iso_product_pricetier` ( + pid, + tstamp, + min, + price + ) VALUES ( + $productPriceDbId, + ".time().", + 1, + $price + )"; + $this->dbHandle->query($sql); + return $this->dbHandle->lastInsertId(); + } + +} \ No newline at end of file diff --git a/api/Product.php b/api/Product.php new file mode 100644 index 0000000..3ddb5de --- /dev/null +++ b/api/Product.php @@ -0,0 +1,271 @@ + + * @date 11.07.22 + */ + + +class Product +{ + const VAT = 0.19; + + private $id; + private $standardSalesPrice; + private $salesVatCode; + private $salesVatCodeDescription; + private $description; + private $extraDescription; + private $isWebShopItem; + private $itemGroup; + private $itemGroupCode; + private $stock; + private $netWeight; + private $grossWeight; + private $code; + + public static function getFields() + { + return [ + 'ID', + 'StandardSalesPrice', + 'SalesVatCode', + 'SalesVatCodeDescription', + 'Description', + 'ExtraDescription', + 'IsWebshopItem', + 'ItemGroup', + 'ItemGroupCode', + 'Stock', + 'NetWeight', + 'GrossWeight', + 'Code', + ]; + } + + public static function createProductFromApiItem(array $item) + { + $res = new self(); + $res->setId($item['ID']); + $res->setStandardSalesPrice($item['StandardSalesPrice']); + $res->setSalesVatCode($item['SalesVatCode']); + $res->setSalesVatCodeDescription($item['SalesVatCodeDescription']); + $res->setDescription($item['Description']); + $res->setExtraDescription($item['ExtraDescription']); + $res->setIsWebShopItem($item['IsWebshopItem']); + $res->setItemGroup($item['ItemGroup']); + $res->setItemGroupCode($item['ItemGroupCode']); + $res->setStock($item['Stock']); + $res->setNetWeight($item['NetWeight']); + $res->setGrossWeight($item['GrossWeight']); + $res->setCode($item['Code']); + return $res; + } + + /** + * @return mixed + */ + public function getId() + { + return $this->id; + } + + /** + * @param mixed $id + */ + public function setId($id) + { + $this->id = $id; + } + + /** + * @return mixed + */ + public function getStandardSalesPrice() + { + return $this->standardSalesPrice; + } + + /** + * @param mixed $standardSalesPrice + */ + public function setStandardSalesPrice($standardSalesPrice) + { + $this->standardSalesPrice = $standardSalesPrice; + } + + /** + * @return mixed + */ + public function getSalesVatCode() + { + return $this->salesVatCode; + } + + /** + * @param mixed $salesVatCode + */ + public function setSalesVatCode($salesVatCode) + { + $this->salesVatCode = $salesVatCode; + } + + /** + * @return mixed + */ + public function getSalesVatCodeDescription() + { + return $this->salesVatCodeDescription; + } + + /** + * @param mixed $salesVatCodeDescription + */ + public function setSalesVatCodeDescription($salesVatCodeDescription) + { + $this->salesVatCodeDescription = $salesVatCodeDescription; + } + + /** + * @return mixed + */ + public function getDescription() + { + return $this->description; + } + + /** + * @param mixed $description + */ + public function setDescription($description) + { + $this->description = $description; + } + + /** + * @return mixed + */ + public function getExtraDescription() + { + return $this->extraDescription; + } + + /** + * @param mixed $extraDescription + */ + public function setExtraDescription($extraDescription) + { + $this->extraDescription = $extraDescription; + } + + /** + * @return mixed + */ + public function getIsWebShopItem() + { + return $this->isWebShopItem; + } + + /** + * @param mixed $isWebShopItem + */ + public function setIsWebShopItem($isWebShopItem) + { + $this->isWebShopItem = $isWebShopItem; + } + + /** + * @return mixed + */ + public function getItemGroup() + { + return $this->itemGroup; + } + + /** + * @param mixed $itemGroup + */ + public function setItemGroup($itemGroup) + { + $this->itemGroup = $itemGroup; + } + + /** + * @return mixed + */ + public function getItemGroupCode() + { + return $this->itemGroupCode; + } + + /** + * @param mixed $itemGroupCode + */ + public function setItemGroupCode($itemGroupCode) + { + $this->itemGroupCode = $itemGroupCode; + } + + /** + * @return mixed + */ + public function getStock() + { + return $this->stock; + } + + /** + * @param mixed $stock + */ + public function setStock($stock) + { + $this->stock = $stock; + } + + /** + * @return mixed + */ + public function getNetWeight() + { + return $this->netWeight; + } + + /** + * @param mixed $netWeight + */ + public function setNetWeight($netWeight) + { + $this->netWeight = $netWeight; + } + + /** + * @return mixed + */ + public function getGrossWeight() + { + return $this->grossWeight; + } + + /** + * @param mixed $grossWeight + */ + public function setGrossWeight($grossWeight) + { + $this->grossWeight = $grossWeight; + } + + /** + * @return mixed + */ + public function getCode() + { + return $this->code; + } + + /** + * @param mixed $code + */ + public function setCode($code) + { + $this->code = $code; + } +} \ No newline at end of file diff --git a/api/apiUpdateProducts.php b/api/apiUpdateProducts.php new file mode 100644 index 0000000..45b2f92 --- /dev/null +++ b/api/apiUpdateProducts.php @@ -0,0 +1,12 @@ +getAccessToken() . "\n"; +$products = $apiConnector->getProducts(); +$databaseHandler->updateProducts($products); + +$b = 0; diff --git a/api/tokenData b/api/tokenData new file mode 100644 index 0000000..d2c44ae --- /dev/null +++ b/api/tokenData @@ -0,0 +1 @@ +{"access_token":"stampDE001.gAAAAHwOSGEkvQm9cR0GLsLKi-DF5HztPTxwFs1cElb0YqYwsA4Du2xEN2_QDZQaRP2S7JqojAxH7Pgh9bGX8aMk_w2Mc6E8Za3DfOCs5_IU89TUfIZfo-OlriYaWguDBjIhWDV7uyb0fyMk83Vplk4hffbmyTdvoTA1GbmvO9x-wEWYVAIAAIAAAAAMQCUSoZTK5-qcCHPI6G15WhlRHy2qHRJKJIJ3ugg6F95dz8Wq4oLsgD4Ej7n_9zloDUbYzABmiTMs6vu-wa4R3DjXmDtvZ5tFauTNTvlSVdbo-rT5rbHUo_LcdGTdE18njXZDBpK7K58cQXVq4zGxViUoqzrEu8aiqDhfwI93_pAXr1ABdwTj6sFxzeqRTAwIo2WVBG7uwzvYLQCrCUqpzxfxUgwH0FBbjEzcglBx56hNshomL4SNqbqqGIKaK1lNGOKz0jkxnuRdY0-nlBPsi0FN6goQDAE3wfKUFzj8DU0nyQAZhdedAtk4q3AT1mPnM9wuOxIwp3EXDeuYkiCIQNWSvU7WJJaWMqfRPrab86diQ5ffBxWDVc0HnpHgQVWr0peKvzLXS4lx5_pTgwLaJUurvlRbG0LI88x-qcMmGgbj2a54FaF93RrNOtHaheiGZh_CBDwqbT54vrFaxxwp-yNmYLVk2-2c70RUwobUInw9E_eR2RNPU9oHGQTMTQR9at_3jZ5dR68UyrY6BMCGJrqrTvSpXkmJNKhkjP9WHlWtz-dC-gt_m2cYaWifow76NAKHONyRk3-i6Qu3vKDc8vXyyi-RLeX6R0nLYV07p7yHsgSo2E8em5C6KdkHIQjJIanYyHUVf7noHJMuKIrrvaHBfdTuiC1ZbemwzPCsb7sdOftAb5vW3oxSEMmckuCVEROmeTyoZCDAV5oyecNAah73Sx7WLx87npWFhC0F71myL11vkWf5MSt8lQ-o-kZCt0Wws7h9KStVrb3mux9v","token_type":"bearer","expires_in":"600","refresh_token":"stampDE001.vhK0!IAAAANf_ePo7TNLoW4eBzZwdyynZfR7KhO8joJp6EgWw0pF58QEAAAFBqPStZfQ04DNGVJ23edCAkbZsdhwNjz3GfWOQoMaGhf3uoG8iydpqma1dDKY3MmFI5CNNxIKvpiN0jnvHqgi0g6O5QijAmgtB3_sVmzs4L0ODxGt3Befp2rJKu2MMBDySEJ_00XVZzBIKmZqVA6XUflZ7mfbotp22vTRbthYOMZlyz0OIT1leJKHfU8XYgB5Zzp8gPHxsSca93Kh3_3CQRp0ZoGR5YKSh1C2zw8QyVCBU_092gLonzTGHKlaIUd6nVT4oIhzXC9i9Dh7wL-9PSfk7m9OqJ7wX0h-p8wkO4bqjkSJofeglSrAvS3G1U8yo0QpxmJQW1FHsm-7q1s6w4O03LV9LsSZX93Wjm8mMq789tlZFZh7-MqO5_zQcwmgizMVDMbBsxPUMU1ITOrTYBAalNf9kyLvrGE-M4jhK_qQbGQ3FATy25U3QjoEQC9K_PWNyqY2XrzPDHSAoprI6hZxY9lYY71tDg3L10KB6BFXDM6bDj_oWa0BAI-TfO_cKRPhXxt9bAquWxhLYHNFdV-d0Il7FeRgI_Dmp7OsKYuFw6rrd6C8Vuz1AxuTaNT1G3V-ugUn5L-VV12JiLgMTTrBLK6OGh5fooDE3Li8tM7WiA5-K9HgP3Jsesdrl2O7ClBUFRrrhtiQINNgkLN1f","expiry_time":1657581261} \ No newline at end of file