Інтеграція 1С-Бітрікс зі службою доставки DPD
DPD — міжнародна кур'єрська служба з потужним покриттям у Росії та Європі. Відрізняється від більшості російських служб SOAP-інтерфейсом замість REST. Це не проблема, але вимагає іншого підходу: робота з WSDL, SoapClient, специфічний формат даних. Інтеграція з 1С-Бітрікс реалізується через стандартний механізм кастомних служб доставки.
API DPD: SOAP-інтерфейс
DPD надає кілька WSDL-сервісів:
-
https://ws.dpd.ru/services/calculator2?wsdl— розрахунок вартості -
https://ws.dpd.ru/services/geography2?wsdl— міста та ПВЗ -
https://ws.dpd.ru/services/order2?wsdl— створення замовлення -
https://ws.dpd.ru/services/tracking2?wsdl— трекінг
Авторизація однакова для всіх: клієнтський номер (clientNumber) та ключ (clientKey) передаються в кожному запиті як частина структури auth.
private function createSoapClient(string $wsdl): \SoapClient
{
return new \SoapClient($wsdl, [
'soap_version' => SOAP_1_1,
'trace' => true,
'exceptions' => true,
'cache_wsdl' => WSDL_CACHE_DISK,
'encoding' => 'utf-8',
]);
}
private function getAuth(): array
{
return [
'clientNumber' => $this->getOption('CLIENT_NUMBER'),
'clientKey' => $this->getOption('CLIENT_KEY'),
];
}
Кешування WSDL (WSDL_CACHE_DISK) є обов'язковим — без нього кожен запит завантажує схему, що критично для розрахунку вартості на сторінці чекауту.
Розрахунок вартості доставки
private function calcCost(
string $fromCityCode,
string $toCityCode,
int $weightGram
): float {
$client = $this->createSoapClient(
'https://ws.dpd.ru/services/calculator2?wsdl'
);
$request = [
'auth' => $this->getAuth(),
'pickup' => ['cityId' => (int)$fromCityCode],
'delivery' => ['cityId' => (int)$toCityCode],
'selfPickup' => false,
'selfDelivery' => false,
'weight' => $weightGram / 1000, // грами → кг (float)
'volume' => 0.001, // мінімальний об'єм
];
$response = $client->getServiceCost2($request);
$services = $response->return ?? [];
// Знаходимо тариф "DPD Classic" (serviceCode = 'CUR')
foreach ((array)$services as $service) {
if ($service->serviceCode === 'CUR') {
return $service->cost;
}
}
return 0;
}
DPD повертає вартість для всіх доступних тарифів. Основні: CUR (DPD Classic — доставка до дверей), PCL (DPD Online Express), ECO (DPD Economy). Код тарифу обирається в налаштуваннях модуля.
Маппінг міст DPD
DPD використовує власні ідентифікатори міст (cityId). Конвертація з назви міста або коду КЛАДР:
public function findCity(string $cityName): ?int
{
$client = $this->createSoapClient(
'https://ws.dpd.ru/services/geography2?wsdl'
);
// Кешуємо результат на 24 години
$cacheKey = 'dpd_city_' . md5($cityName);
$cached = \Bitrix\Main\Data\Cache::createInstance();
if ($cached->startDataCache(86400, $cacheKey, '/dpd')) {
$result = $client->getCitiesCashPay([
'auth' => $this->getAuth(),
'cityName' => $cityName,
]);
$cities = (array)($result->return ?? []);
$cityId = !empty($cities) ? $cities[0]->cityId : null;
$cached->endDataCache(['cityId' => $cityId]);
} else {
$cityId = $cached->getVars()['cityId'];
}
return $cityId;
}
Кеш на 24 години є критичним: список міст DPD не змінюється щогодини, а без кешу кожен розрахунок вартості виконує два SOAP-запити.
Створення замовлення DPD
public function createOrder(\Bitrix\Sale\Shipment $shipment): string
{
$client = $this->createSoapClient(
'https://ws.dpd.ru/services/order2?wsdl'
);
$order = $shipment->getOrder();
$props = $order->getPropertyCollection();
$request = [
'auth' => $this->getAuth(),
'header' => [
'datePickup' => date('Y-m-d', strtotime('+1 day')),
'senderAddress' => $this->getSenderAddress(),
'pickupTimePeriod' => '9:00-18:00',
],
'order' => [[
'orderNumberInternal' => (string)$order->getId(),
'serviceCode' => 'CUR',
'serviceVariant' => 'ДД', // двері-двері
'weight' => $this->getWeight($shipment) / 1000,
'declaredValue' => $order->getPrice(),
'cargoRegistered' => false,
'cargoCategory' => 'Товар',
'receiverName' => $props->getItemByOrderPropertyCode('FIO')?->getValue(),
'receiverPhone' => $props->getItemByOrderPropertyCode('PHONE')?->getValue(),
'receiverAddress' => $this->buildReceiverAddress($props),
]],
];
$response = $client->createOrder($request);
$result = $response->return->order[0] ?? null;
return $result->orderNum ?? '';
}
Трекінг
public function trackOrder(string $dpdOrderNum): array
{
$client = $this->createSoapClient(
'https://ws.dpd.ru/services/tracking2?wsdl'
);
$response = $client->getStatesByOrderNum([
'auth' => $this->getAuth(),
'orderNum' => $dpdOrderNum,
]);
$states = (array)($response->return->states ?? []);
$last = end($states);
return [
'status' => $last->newState ?? '',
'city' => $last->city ?? '',
'timestamp' => $last->transitionTime ?? '',
];
}
DPD не надає push-вебхуки. Тільки polling — агент 1С-Бітрікс раз на 2–3 години для активних замовлень.
Терміни
| Склад | Термін |
|---|---|
| SOAP-клієнт + розрахунок + маппінг міст | 3–4 дні |
| + Створення замовлень + polling трекінгу | +2 дні |
| + ПВЗ DPD на карті | +2 дні |







