init
This commit is contained in:
commit
df7a781e27
5
.gitignore
vendored
Normal file
5
.gitignore
vendored
Normal file
@ -0,0 +1,5 @@
|
||||
.idea
|
||||
vendor
|
||||
config/config.php
|
||||
composer.lock
|
||||
composer.json
|
155
classes/ApiHelper.php
Normal file
155
classes/ApiHelper.php
Normal file
@ -0,0 +1,155 @@
|
||||
<?php
|
||||
|
||||
require_once(__DIR__ . "/../vendor/autoload.php");
|
||||
require(__DIR__ . "/Parser.php");
|
||||
|
||||
class ApiHelper {
|
||||
|
||||
protected $config;
|
||||
protected $crmClient;
|
||||
protected $parser;
|
||||
|
||||
public function __construct($config) {
|
||||
|
||||
$this->config = $config;
|
||||
|
||||
$this->crmClient = new \RetailCrm\ApiClient(
|
||||
$this->config['retailcrm_url'],
|
||||
$this->config['retailcrm_apikey']
|
||||
);
|
||||
|
||||
$this->parser = new Parser($config);
|
||||
}
|
||||
|
||||
public function processXMLOrders() {
|
||||
$url = $this->config['tiu_xml_url'];
|
||||
$xml = simplexml_load_file($url);
|
||||
if (! $xml instanceof SimpleXMLElement) {
|
||||
$this->writeLog("ApiHelper::processXmlOrders: cannot get XML from $url");
|
||||
return false;
|
||||
}
|
||||
|
||||
$orders = array();
|
||||
foreach($xml as $xmlOrder) {
|
||||
$order = $this->parser->parseXMLNewOrder($xmlOrder);
|
||||
if ($order) {
|
||||
$customerId = $this->checkCustomers($order);
|
||||
if ($customerId === false) {
|
||||
echo "upload failed" . PHP_EOL;
|
||||
return false;
|
||||
} elseif ($customerId !== 0) {
|
||||
$order['customerId'] = $customerId;
|
||||
}
|
||||
$orders[$order['number']] = $order;
|
||||
}
|
||||
}
|
||||
$orders = $this->filterOrders($orders);
|
||||
if ($this->uploadOrders($orders)) {
|
||||
$a = sizeof($orders);
|
||||
echo "uploaded $a orders" . PHP_EOL;
|
||||
return true;
|
||||
} else {
|
||||
echo "upload failed" . PHP_EOL;
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
protected function uploadOrders($orders) {
|
||||
if ($orders === false)
|
||||
return false;
|
||||
if (sizeof($orders)) {
|
||||
$orders = array_chunk($orders, $this->config['retailcrm_order_chunk_size']);
|
||||
foreach ($orders as $chunk) {
|
||||
try {
|
||||
$result = $this->crmClient->ordersUpload($chunk);
|
||||
} catch (\RetailCrm\Exception\CurlException $e) {
|
||||
$this->writeLog(
|
||||
'\Retailcrm\ApiClient::ordersUpload: ' . $e,
|
||||
'error'
|
||||
);
|
||||
return false;
|
||||
}
|
||||
if (! $result->isSuccessful()) {
|
||||
$this->writeLog(
|
||||
'\Retailcrm\ApiClient::ordersUpload: ' . $result['errorMsg'] . (isset($result['errors']) ? ': ' . json_encode($result['errors']) : '')
|
||||
);
|
||||
}
|
||||
time_nanosleep(0, 200000000);
|
||||
}
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
protected function checkCustomers($order) {
|
||||
$customerId = 0;
|
||||
if ($order['email'] != '')
|
||||
$filter = array('email' => $order['email']);
|
||||
if ($order['phone'] != '')
|
||||
$filter = array('name' => $order['phone']);
|
||||
if (isset($filter)) {
|
||||
try {
|
||||
$customers = $this->crmClient->customersList($filter);
|
||||
} catch (\RetailCrm\Exception\CurlException $e) {
|
||||
$this->writeLog(
|
||||
'\Retailcrm\ApiClient::customersList: ' . $e,
|
||||
'error'
|
||||
);
|
||||
return false;
|
||||
}
|
||||
if (isset($customers['customers']) && sizeof($customers['customers'] && isset($customers['customers'][0]['externalId']))) {
|
||||
$customerId = $customers['customers'][0]['externalId'];
|
||||
}
|
||||
time_nanosleep(0, 200000000);
|
||||
}
|
||||
return $customerId;
|
||||
}
|
||||
|
||||
protected function writeLog($text, $type = null) {
|
||||
if (! file_exists(__DIR__ ."/../logs"))
|
||||
mkdir(__DIR__ ."/../logs");
|
||||
$date = date('Y-m-d H:i:s');
|
||||
file_put_contents(__DIR__ . "/../logs/error.log", "[$date]$text" . PHP_EOL, FILE_APPEND);
|
||||
if ($type == 'error') {
|
||||
$this->sendAlertEmail($text);
|
||||
}
|
||||
}
|
||||
|
||||
protected function sendAlertEmail($text) {
|
||||
mail($this->config['support_email'], $this->config['support_email_subject'], $text);
|
||||
}
|
||||
|
||||
protected function filterOrders($toUpload) {
|
||||
$numbers = array_keys($toUpload);
|
||||
if (date_create_from_format('Y-m-d H:i:s', $this->config['filter_date'])) {
|
||||
foreach ($toUpload as $i => $order) {
|
||||
if ($order['createdAt'] < $this->config['filter_date']) {
|
||||
unset($toUpload[$i]);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
$ordersListPage = 0;
|
||||
do {
|
||||
$ordersListPage++;
|
||||
try {
|
||||
$orders = $this->crmClient->ordersList(array(
|
||||
'numbers' => $numbers
|
||||
), $ordersListPage, 100);
|
||||
} catch (\RetailCrm\Exception\CurlException $e) {
|
||||
$text = '\Retailcrm\ApiClient::ordersList: ' . $e;
|
||||
$this->writeLog($text, 'error');
|
||||
return false;
|
||||
}
|
||||
if (isset($orders['orders']) && sizeof($orders['orders'])) {
|
||||
foreach ($orders['orders'] as $order) {
|
||||
if (isset($toUpload[$order['number']]))
|
||||
unset($toUpload[$order['number']]);
|
||||
}
|
||||
}
|
||||
time_nanosleep(0, 200000000);
|
||||
} while ($ordersListPage < $orders['pagination']['totalPageCount']);
|
||||
|
||||
return $toUpload;
|
||||
}
|
||||
|
||||
}
|
83
classes/Parser.php
Normal file
83
classes/Parser.php
Normal file
@ -0,0 +1,83 @@
|
||||
<?php
|
||||
|
||||
class Parser {
|
||||
|
||||
const ENCODING = 'UTF-8';
|
||||
protected $config;
|
||||
|
||||
public function __construct($config) {
|
||||
$this->config = $config;
|
||||
}
|
||||
|
||||
public function parseXMLNewOrder(SimpleXMLElement $xml) {
|
||||
$order = $this->explodeFIO((string)$xml->name);
|
||||
|
||||
foreach($xml->attributes() as $key => $val) {
|
||||
switch ($key) {
|
||||
case 'id':
|
||||
$val = (string)$val;
|
||||
$order['number'] = $this->config['order_prefix'] . $val;
|
||||
break;
|
||||
case 'state':
|
||||
$orderStatuses = array_flip($this->config['order_statuses']);
|
||||
$order['status'] = $orderStatuses[(string)$val];
|
||||
break;
|
||||
}
|
||||
}
|
||||
$createdAt = \DateTime::createFromFormat('d.m.y H:i', (string)$xml->date);
|
||||
$createdAt = $createdAt->format('Y-m-d H:i:s');
|
||||
if (isset($this->config['date_from']) && $createdAt < $this->config['date_from'])
|
||||
return false;
|
||||
|
||||
$order = array_merge($order, array(
|
||||
'email' => (string)$xml->email,
|
||||
'phone' => (string)$xml->phone,
|
||||
'orderMethod' => $this->config['order_method'],
|
||||
'createdAt' => $createdAt,
|
||||
'paymentType' => $this->config['payment'][(string)$xml->paymentType],
|
||||
'delivery' => array(
|
||||
'address' => array(
|
||||
'text' => (string)$xml->address
|
||||
),
|
||||
'code' => $this->config['delivery'][(string)$xml->deliveryType]
|
||||
)
|
||||
));
|
||||
$items = array();
|
||||
$xmlItems = $xml->items;
|
||||
foreach($xmlItems as $xmlItem) {
|
||||
$xmlItem = $xmlItem->item;
|
||||
$items[] = array(
|
||||
'productId' => (string)$xmlItem->external_id,
|
||||
'productName' => (string)$xmlItem->name,
|
||||
'quantity' => (string)$xmlItem->quantity,
|
||||
'initialPrice' => (string)$xmlItem->price
|
||||
);
|
||||
}
|
||||
$order['items'] = $items;
|
||||
return $order;
|
||||
}
|
||||
|
||||
public function explodeFIO($name) {
|
||||
$name = explode(' ', $name, 3);
|
||||
$firstName = $lastName = $patronymic = '';
|
||||
switch (sizeof($name)) {
|
||||
case 1:
|
||||
$firstName = $name[0];
|
||||
break;
|
||||
case 2:
|
||||
$firstName = $name[0];
|
||||
$lastName = $name[1];
|
||||
break;
|
||||
case 3:
|
||||
$firstName = $name[1];
|
||||
$lastName = $name[0];
|
||||
$patronymic = $name[2];
|
||||
break;
|
||||
}
|
||||
return array(
|
||||
'firstName' => $firstName,
|
||||
'lastName' => $lastName,
|
||||
'patronymic' => $patronymic
|
||||
);
|
||||
}
|
||||
}
|
47
config/config-dist.php
Normal file
47
config/config-dist.php
Normal file
@ -0,0 +1,47 @@
|
||||
<?php
|
||||
$сonfig = array(
|
||||
// ссылка вида https://my.tiu.ru/cabinet/export_orders/xml/1234567?hash_tag=472g8fzb1af38d35f2c521dc8a1e1208
|
||||
// берется отсюда: https://my.tiu.ru/cabinet/order/export_orders
|
||||
'tiu_xml_url' => '',
|
||||
|
||||
'retailcrm_url' => 'https://site.retailcrm.ru',
|
||||
'retailcrm_apikey' => 'qwerty123',
|
||||
'retailcrm_order_chunk_size' => 50,
|
||||
|
||||
// загружать заказы только с определенной даты (Y-m-d H:i:s)
|
||||
'date_from' => '',
|
||||
|
||||
'order_prefix' => 'TIU', // приписывается к номеру заказа в CRM
|
||||
'set_external_ids' => false, // задавать ли externalId заказам
|
||||
'order_method' => 'tiu', // способ оформления заказа
|
||||
// соответствие доставок tiu => CRM
|
||||
// https://my.tiu.ru/cabinet/shop_settings/delivery_options
|
||||
'delivery' => array(
|
||||
'Транспортная компания' => 'courier',
|
||||
'Доставка курьером' => 'courier',
|
||||
'Самовывоз' => 'courier'
|
||||
),
|
||||
|
||||
// соответствие оплат tiu => CRM
|
||||
// https://my.tiu.ru/cabinet/shop_settings/payment_options
|
||||
'payment' => array(
|
||||
'Наличными' => 'cash',
|
||||
'Оплата банковской картой' => 'bank-card',
|
||||
'Безналичный расчет' => 'bank-transfer'
|
||||
),
|
||||
|
||||
// статусы заказов CRM => tiu
|
||||
// https://my.tiu.ru/cabinet/order_v2
|
||||
// по умолчанию заданы 4 статуса:
|
||||
// 'opened' - новый, 'accepted' - принят, 'declined' - отменен, 'closed' - выполнен
|
||||
'order_statuses' => array(
|
||||
'new' => 'opened',
|
||||
'processing' => 'accepted',
|
||||
'complete' => 'closed',
|
||||
'cancel-other' => 'declined',
|
||||
),
|
||||
|
||||
// почта для логов с ошибками
|
||||
'support_email' => '',
|
||||
'support_email_subject' => 'tiu fail'
|
||||
);
|
0
logs/.gitkeep
Normal file
0
logs/.gitkeep
Normal file
22
run.php
Normal file
22
run.php
Normal file
@ -0,0 +1,22 @@
|
||||
<?php
|
||||
require(__DIR__ . "/classes/ApiHelper.php");
|
||||
require(__DIR__ . "/config/config.php");
|
||||
|
||||
if (! file_exists(__DIR__ . "/logs"))
|
||||
mkdir(__DIR__ . "/logs");
|
||||
if (file_exists(__DIR__ . "/logs/cookie.txt"))
|
||||
unlink(__DIR__ . "/logs/cookie.txt");
|
||||
|
||||
$lockFile = __DIR__ . "/run.lock";
|
||||
if (file_exists($lockFile)) {
|
||||
if ((int)file_get_contents($lockFile) > time()) {
|
||||
echo "script is busy";
|
||||
exit();
|
||||
}
|
||||
}
|
||||
file_put_contents("run.lock", strtotime('+5 minutes'));
|
||||
|
||||
$apiHelper = new ApiHelper($сonfig);
|
||||
|
||||
if ($apiHelper->processXMLOrders())
|
||||
unlink($lockFile);
|
Loading…
Reference in New Issue
Block a user