CDEK - плагин для выгрузки заказа и получения трек-номера
На волне публикаций Паши Зарубина (тыц, тыц, тыц) решил выложить прикладное решение, которое моему клиенту немножко автоматизирует жизнь и вполне себе нравится. Началось это с того, что в msCDEK не было выгрузки заказов в личный кабинет CDEK. А закончилось тем, что Паша написал свою ГдеПосылку, которая следит за передвижениями посылки по её ID в системе CDEK в том числе. Мой плагин выполняет две задачи:
1. При установке определенного статуса (названного нами «Выгрузка в CDEK») отправляет в CDEK xml-запрос в соответствии с их документацией, по которому в системе создается накладная
2. Принимает в ответ ID накладной и пишет его в поле track заказа.
Для работы в этом плагина нужны оба дополнения — msCDEK и msGdePosylka, поскольку плагин писан немножко на коленке и второпях и некоторые функции я дергал из компонента msCDEK. При наличии времени и желания вполне можно эти функции вынести в отдельный класс и обойтись без msCDEK.
Код плагина:
1. При установке определенного статуса (названного нами «Выгрузка в CDEK») отправляет в CDEK xml-запрос в соответствии с их документацией, по которому в системе создается накладная
2. Принимает в ответ ID накладной и пишет его в поле track заказа.
Для работы в этом плагина нужны оба дополнения — msCDEK и msGdePosylka, поскольку плагин писан немножко на коленке и второпях и некоторые функции я дергал из компонента msCDEK. При наличии времени и желания вполне можно эти функции вынести в отдельный класс и обойтись без msCDEK.
Код плагина:
<?php
/**
* @global modX $modx
*/
switch ($modx->event->name) {
case 'msOnChangeOrderStatus':
/**
* @var msOrder $order
*/
// $status 29 - это мой ID статуса, по которому мы отправляем заказ в CDEK. 16 и 17 - мои ID способов доставки для CDEK - самовывоз из пункта выдачи и курьерская доставка
if ($status == 29 and in_array($order->delivery, array(16, 17))) {
$cdek = $modx->getService('msCDEK', 'msCDEK', $modx->getOption('core_path').'components/mscdek/model/mscdek/', array());
$cdek->initialize();
$data = array(
'path' => 'https://integration.cdek.ru/new_orders.php',
'opts' => array(
'Date' => date('Y-m-d'),
'Account' => $modx->getOption('mscdek_login'),
'http' => array(
'header' => 'Content-Type: application/x-www-form-urlencoded',
),
),
);
$data['opts']['Secure'] = md5($data['opts']['Date'].'&'.$modx->getOption('mscdek_password'));
$q = $modx->newQuery('msOrder', $order->id);
$q->select('msOrder.id, msOrder.num, msOrder.delivery, msOrder.payment, msOrder.delivery_cost');
$q->innerJoin('modUserProfile', 'modUserProfile', 'msOrder.user_id = modUserProfile.id');
$q->select('modUserProfile.email');
$q->innerJoin('msOrderAddress', 'msOrderAddress', 'msOrder.address = msOrderAddress.id');
foreach (array('receiver', 'phone', 'country', 'index', 'region', 'city', 'metro', 'street', 'building', 'room', 'comment') as $field) {
$q->select('msOrderAddress.'.$field);
}
$q->innerJoin('msDelivery', 'msDelivery', 'msOrder.delivery = msDelivery.id');
$q->select('msDelivery.properties');
if ($q->prepare() && $q->stmt->execute()) {
$row = $q->stmt->fetch(PDO::FETCH_ASSOC);
$row['properties'] = $modx->fromJSON($row['properties']);
$row['city_id'] = $cdek->getCityId($row['city']);
$values = array(
'Number' => 1,
'Date' => $data['opts']['Date'],
'Account' => $data['opts']['Account'],
'Secure' => $data['opts']['Secure'],
'OrderCount' => 1,
);
$xml = '<?xml version="1.0" encoding="UTF-8"?><DeliveryRequest></DeliveryRequest>';
$xml = new SimpleXMLElement($xml);
foreach ($values as $k => $v) {
$xml->addAttribute($k, $v);
}
$values = array(
'Number' => $row['num'],
// Впишите свой город отправки:
'SendCityCode' => $cdek->getCityId('Санкт-Петербург'),
'RecCityCode' => $row['city_id'],
'RecipientName' => $row['receiver'],
'RecipientEmail' => $row['email'],
'Phone' => $row['phone'],
'TariffTypeCode' => $row['properties']['tariffId'],
'DeliveryRecipientCost' => $row['payment'] == 3 ? 0 : $row['delivery_cost'],
'DeliveryRecipientVATRate' => 'VAT0',
'DeliveryRecipientVATSum' => 0,
'Comment' => $row['comment'],
'SellerName' => '34play',
);
$xmlorder = $xml->addChild('Order');
foreach ($values as $k => $v) {
$xmlorder->addAttribute($k, $v);
}
if ($row['delivery'] == 16) {
$resPoints = array();
$dps = file_get_contents('https://integration.cdek.ru/pvzlist.php?type=PVZ&cityid=' . $row['city_id']);
// echo $dps;
$points = new SimpleXMLElement($dps);
foreach ($points->Pvz as $pvz) {
if ($row['street'] == $pvz['Address']) {
$row['PvzCode'] = $pvz['Code'];
}
}
unset($points);
}
$values = $row['delivery'] == 16 ? array('PvzCode' => $row['PvzCode']) : array(
'Street' => $row['street'],
'House' => $row['building'],
'Flat' => $row['room']
);
$address = $xmlorder->addChild('Address');
foreach ($values as $k => $v) {
$address->addAttribute($k, $v);
}
$values = array(
'Number' => $row['num'],
'BarCode' => $row['num'],
'Weight' => 0,
);
$package = $xmlorder->addChild('Package');
foreach ($values as $k => $v) {
$package->addAttribute($k, $v);
}
$q = $modx->newQuery('msOrderProduct', array('order_id' => $row['id']));
$q->select('id,name,count,price,cost,options');
if ($q->prepare() && $q->stmt->execute()) {
$weight = 0;
while ($item = $q->stmt->fetch(PDO::FETCH_ASSOC)) {
$options = $modx->fromJSON($item['options']);
$values = array(
'WareKey' => $item['id'],
'Cost' => $item['cost'],
'Payment' => $row['payment'] == 3 ? 0 : $item['price'],
'Weight' => $item['weight'] ? $item['weight'] * 1000 : 500,
'Amount' => $item['count'],
'Comment' => $item['name'].', '.$options['size'],
);
$item = $package->addChild('Item');
foreach ($values as $k => $v) {
$item->addAttribute($k, $v);
}
$weight += $values['Weight'] * $values['Amount'];
}
$package['Weight'] = $weight;
}
foreach (array(30, 36, 37) as $code) {
$addService = $xmlorder->addChild('AddService');
$addService->addAttribute('ServiceCode', $code);
}
$curl = curl_init();
curl_setopt_array($curl, array(
CURLOPT_URL => $data['path'],
CURLOPT_RETURNTRANSFER => true,
CURLOPT_POST => true,
CURLOPT_HTTPHEADER => $data['opts']['http'],
CURLOPT_POSTFIELDS => http_build_query(array('xml_request' => $xml->asXML())),
));
$response = curl_exec($curl);
curl_close($curl);
$response = new SimpleXMLElement($response);
foreach ($response->Order as $one) {
if (!empty($one['ErrorCode'])) {
$modx->log(modX::LOG_LEVEL_ERROR, $one['ErrorCode'].' - '.$one['Msg']);
$modx->event->output($one['Msg']);
break;
} else if (!empty($one['DispatchNumber'])) {
$order->set('track', $one['DispatchNumber']);
$order->save();
break;
}
}
}
}
break;
}
Комментарии: 4
Добрый день! Ошибка авторизации, при том что в msCDEK данные для авторизации верны.
[TIMESTAMP] => 2019-02-26T09:31:40Z
[CORRELATIONID] => dbb0a8e24567
[ACK] => Failure
[VERSION] => 74.0
[BUILD] => 51975887
[L_ERRORCODE0] => 10002
[L_SHORTMESSAGE0] => Authentication/Authorization Failed
[L_LONGMESSAGE0] => You do not have permissions to make this API call
[L_SEVERITYCODE0] => Error
)
Так же ругается на эту строку
foreach ($result['Pvz'] as $item) {
возможно, апи cdek с той поры поменялось. читайте доки
и потом, это плагин под старый компонент mscdek
Авторизуйтесь или зарегистрируйтесь, чтобы оставлять комментарии.