Как настроить службу доставки для CRM
Кто может выполнять методы: администратор
Выберите инструмент для разработки с AI-агентом:
- используйте Битрикс24 Вайбкод, чтобы создать приложение для Битрикс24 по описанию задачи без знания языков программирования. Агент напишет код и разместит приложение на сервере без ручной настройки хостинга
- используйте MCP-сервер, чтобы разрабатывать интеграцию через REST API в своем проекте. Агент будет обращаться к официальной REST-документации
К Битрикс24 можно подключать внешние сервисы доставки. Это позволяет менеджеру работать со службой доставки в карточках CRM: рассчитывать стоимость и отслеживать статус.
В результате сценария в CRM появится служба доставки с профилями, адресными свойствами отгрузки и дополнительной услугой.
Сценарий состоит из пяти шагов.
- Зарегистрируем обработчик доставки методом sale.delivery.handler.add
- Создадим родительскую службу и профили методом sale.delivery.add
- Добавим свойства отгрузки для адресов методом sale.shipmentproperty.add
- Привяжем свойства к профилям доставки методом sale.propertyRelation.add
- Подключим дополнительную услугу методом sale.delivery.extra.service.add
Перед началом
Подготовьте значения, которые понадобятся в примерах.
- Входящий вебхук или OAuth-токен пользователя с правами администратора
- Публичные HTTPS-адреса обработчика:
CALCULATE_URL,CREATE_DELIVERY_REQUEST_URL,CANCEL_DELIVERY_REQUEST_URL - Уникальный код обработчика доставки, например
uber - Идентификатор типа плательщика
personTypeId. Получить список типов можно методом sale.persontype.list - Идентификатор группы свойств
propsGroupId. Получить список групп можно методом sale.propertygroup.list
1. Создадим обработчик службы доставки
Зарегистрируем обработчик с помощью sale.delivery.handler.add. В метод передадим четыре параметра.
-
CODE— символьный код обработчика службы доставки. Укажем, например,uber. -
NAME— название обработчика службы доставки. ПередадимUber. -
SETTINGS— объект с информацией о настройках обработчика.-
CALCULATE_URL— URL расчета стоимости доставки, напримерhttps://gateway.bx/calculate.php. -
CREATE_DELIVERY_REQUEST_URL— URL оформления доставки. Укажемhttps://gateway.bx/create_delivery_request.php. -
CANCEL_DELIVERY_REQUEST_URL— URL отмены доставки, напримерhttps://gateway.bx/cancel_delivery_request.php. -
HAS_CALLBACK_TRACKING_SUPPORT— индикатор, будет ли служба присылать оповещения. ЗададимY. Создать оповещения можно с помощью sale.delivery.request.sendmessage. -
CONFIG— список настроек. УкажемMY_FIRST_SETTINGиMY_SECOND_SETTINGс типомSTRING.
-
-
PROFILES— массив профилей доставки. Обработчик должен иметь хотя бы один профиль. ЗададимTaxiиCargo.
Сервис доставки по указанным URL должен принять запрос, обработать его и выдать ответ в формате, который ожидает CRM.
Подробнее о формате запросов и ответов читайте в разделе Вебхуки при работе с доставками.
Как использовать примеры в документации
import { B24Hook } from '@bitrix24/b24jssdk'
const $b24 = B24Hook.fromWebhookUrl(process.env.B24_HOOK)
// B24_HOOK = 'https://your-domain.bitrix24.ru/rest/USER_ID/TOKEN/'
const response = await $b24.actions.v2.call.make({
method: 'sale.delivery.handler.add',
params: {
CODE: "uber",
NAME: "Uber",
SETTINGS: {
CALCULATE_URL: "https://gateway.bx/calculate.php",
CREATE_DELIVERY_REQUEST_URL: "https://gateway.bx/create_delivery_request.php",
CANCEL_DELIVERY_REQUEST_URL: "https://gateway.bx/cancel_delivery_request.php",
HAS_CALLBACK_TRACKING_SUPPORT: "Y",
CONFIG: [
{
TYPE: "STRING",
CODE: "MY_FIRST_SETTING",
NAME: "My first setting",
},
{
TYPE: "STRING",
CODE: "MY_SECOND_SETTING",
NAME: "My second setting",
},
],
},
PROFILES: [
{
NAME: "Taxi",
CODE: "TAXI",
DESCRIPTION: "Taxi Delivery",
},
{
NAME: "Cargo",
CODE: "CARGO",
DESCRIPTION: "Cargo Delivery",
},
],
},
requestId: 'delivery-handler-add'
})
if (response.isSuccess) {
console.info(response.getData().result)
} else {
console.error(response.getErrorMessages().join('; '))
}
from b24pysdk import BitrixWebhook, Client
from b24pysdk.errors import BitrixAPIError
token = BitrixWebhook(
domain="your-domain.bitrix24.com",
webhook_token="user_id/webhook_key",
)
client = Client(token)
try:
response = client.sale.delivery.handler.add(
code="uber",
name="Uber",
settings={
"CALCULATE_URL": "https://gateway.bx/calculate.php",
"CREATE_DELIVERY_REQUEST_URL": "https://gateway.bx/create_delivery_request.php",
"CANCEL_DELIVERY_REQUEST_URL": "https://gateway.bx/cancel_delivery_request.php",
"HAS_CALLBACK_TRACKING_SUPPORT": "Y",
"CONFIG": [
{
"TYPE": "STRING",
"CODE": "MY_FIRST_SETTING",
"NAME": "My first setting",
},
{
"TYPE": "STRING",
"CODE": "MY_SECOND_SETTING",
"NAME": "My second setting",
},
],
},
profiles=[
{
"NAME": "Taxi",
"CODE": "TAXI",
"DESCRIPTION": "Taxi Delivery",
},
{
"NAME": "Cargo",
"CODE": "CARGO",
"DESCRIPTION": "Cargo Delivery",
},
],
).response
print(response.result)
except BitrixAPIError as error:
print(error)
<?php
// composer require bitrix24/b24phpsdk:"^3.0"
require_once 'vendor/autoload.php';
use Bitrix24\SDK\Services\ServiceBuilderFactory;
use Symfony\Component\EventDispatcher\EventDispatcher;
use Monolog\Logger;
use Monolog\Handler\StreamHandler;
$log = new Logger('b24');
$log->pushHandler(new StreamHandler('php://stdout'));
$sb = (new ServiceBuilderFactory(new EventDispatcher(), $log))
->initFromWebhook('https://your-domain.bitrix24.ru/rest/USER_ID/TOKEN/');
$result = $sb->getSaleScope()->deliveryHandler()->add([
'CODE' => 'uber',
'NAME' => 'Uber',
'SETTINGS' => [
'CALCULATE_URL' => 'https://gateway.bx/calculate.php',
'CREATE_DELIVERY_REQUEST_URL' => 'https://gateway.bx/create_delivery_request.php',
'CANCEL_DELIVERY_REQUEST_URL' => 'https://gateway.bx/cancel_delivery_request.php',
'HAS_CALLBACK_TRACKING_SUPPORT' => 'Y',
'CONFIG' => [
[
'TYPE' => 'STRING',
'CODE' => 'MY_FIRST_SETTING',
'NAME' => 'My first setting',
],
[
'TYPE' => 'STRING',
'CODE' => 'MY_SECOND_SETTING',
'NAME' => 'My second setting',
],
],
],
'PROFILES' => [
[
'NAME' => 'Taxi',
'CODE' => 'TAXI',
'DESCRIPTION' => 'Taxi Delivery',
],
[
'NAME' => 'Cargo',
'CODE' => 'CARGO',
'DESCRIPTION' => 'Cargo Delivery',
],
],
]);
echo '<PRE>';
print_r($result->getId());
echo '</PRE>';
Если обработчик успешно добавлен, метод вернет его идентификатор.
{
"result": 23
}
2. Создадим службу доставки
Создадим службу доставки с помощью метода sale.delivery.add. В метод передадим следующие параметры:
-
REST_CODE— символьный код обработчика службы доставки. Укажемuber, который задали на первом шаге. -
NAME— название службы доставки, например,Uber Taxi. -
CURRENCY— символьный код валюты. ПередадимRUB. Получить список валют можно с помощью метода crm.currency.list. -
ACTIVE— флаг активности службы доставки. УкажемY. -
CONFIG— значения настроек обработчика. Передаем значения дляMY_FIRST_SETTINGиMY_SECOND_SETTING, которые задали на первом шаге.
const response = await $b24.actions.v2.call.make({
method: 'sale.delivery.add',
params: {
REST_CODE: "uber",
NAME: "Uber Taxi",
CURRENCY: "RUB",
ACTIVE: "Y",
CONFIG: [
{
CODE: "MY_FIRST_SETTING",
VALUE: "My first setting value",
},
{
CODE: "MY_SECOND_SETTING",
VALUE: "My second setting value",
},
]
},
requestId: 'delivery-add'
})
if (response.isSuccess) {
console.info(response.getData().result)
} else {
console.error(response.getErrorMessages().join('; '))
}
try:
response = client.sale.delivery.add(
rest_code="uber",
name="Uber Taxi",
currency="RUB",
active=True,
config=[
{
"CODE": "MY_FIRST_SETTING",
"VALUE": "My first setting value",
},
{
"CODE": "MY_SECOND_SETTING",
"VALUE": "My second setting value",
},
],
).response
print(response.result)
except BitrixAPIError as error:
print(error)
$result = $sb->getSaleScope()->delivery()->add([
'REST_CODE' => 'uber',
'NAME' => 'Uber Taxi',
'CURRENCY' => 'RUB',
'ACTIVE' => 'Y',
'CONFIG' => [
[
'CODE' => 'MY_FIRST_SETTING',
'VALUE' => 'My first setting value',
],
[
'CODE' => 'MY_SECOND_SETTING',
'VALUE' => 'My second setting value',
],
]
]);
echo '<PRE>';
print_r($result->getParent()->ID);
echo '</PRE>';
Если служба доставки успешно создана, метод вернет объект родительской службы и массив профилей. Сохраните идентификаторы профилей из массива profiles: они понадобятся для привязки свойств отгрузки и дополнительных услуг.
{
"result": {
"parent": {
"NAME": "Uber Taxi",
"ACTIVE": "Y",
"CURRENCY": "RUB",
"ID": 226,
"PARENT_ID": null
},
"profiles": [
{
"NAME": "Taxi",
"ACTIVE": "Y",
"ID": 227,
"PARENT_ID": 226
},
{
"NAME": "Cargo",
"ACTIVE": "Y",
"ID": 228,
"PARENT_ID": 226
}
]
}
}
3. Создадим свойства отгрузки
В отгрузке менеджер указывает адрес отправки и адрес доставки. Последовательно создадим два свойства Address From и Address To с помощью метода sale.shipmentproperty.add.
В примерах используются personTypeId: 3 и propsGroupId: 6. Если в вашем Битрикс24 другие типы плательщиков или группы свойств, подставьте значения, полученные методами sale.persontype.list и sale.propertygroup.list.
Свойство Address From
В метод передадим объект fields со значениями полей свойства Address From.
-
personTypeId— идентификатор типа плательщика. Передадим3. Список типов можно получить с помощью метода sale.persontype.list. -
propsGroupId— идентификатор группы свойств. Укажем6. Список групп можно получить методом sale.propertygroup.list. -
name— название свойства отгрузки. УкажемAddress From. -
active— флаг активности. ПередадимY. -
sort— сортировка. -
type— тип свойства отгрузки. ПередадимADDRESS. Список возможных значений смотрите в документации метода sale.shipmentproperty.add. -
required— флаг, обязательное ли свойство. УкажемY. -
isAddressFrom— флаг, используется ли свойство отгрузки как адрес отправителя. ПередадимY.
const response = await $b24.actions.v2.call.make({
method: 'sale.shipmentproperty.add',
params: {
fields: {
personTypeId: 3,
propsGroupId: 6,
name: "Address From",
active: "Y",
sort: "100",
type: "ADDRESS",
required: "Y",
isAddressFrom: "Y"
}
},
requestId: 'shipmentproperty-add-from'
})
if (response.isSuccess) {
console.info(response.getData().result)
} else {
console.error(response.getErrorMessages().join('; '))
}
try:
response = client.sale.shipmentproperty.add(
fields={
"personTypeId": 3,
"propsGroupId": 6,
"name": "Address From",
"active": "Y",
"sort": "100",
"type": "ADDRESS",
"required": "Y",
"isAddressFrom": "Y",
},
).response
print(response.result)
except BitrixAPIError as error:
print(error)
$result = $sb->getSaleScope()->shipmentProperty()->add([
'personTypeId' => 3,
'propsGroupId' => 6,
'name' => 'Address From',
'active' => 'Y',
'sort' => '100',
'type' => 'ADDRESS',
'required' => 'Y',
'isAddressFrom' => 'Y'
]);
echo '<PRE>';
print_r($result->getId());
echo '</PRE>';
Если свойство успешно добавлено, метод вернет объект property с идентификатором свойства. Сохраните значение property.id: оно понадобится для привязки свойства к профилям доставки.
{
"result": {
"property": {
"id": 102,
"name": "Address From",
"isAddressFrom": "Y",
"isAddressTo": "N",
"type": "ADDRESS"
}
}
}
Свойство Address To
В объекте fields для свойства Address To передаем название Address To. Остальные параметры — аналогично Address From.
const response = await $b24.actions.v2.call.make({
method: 'sale.shipmentproperty.add',
params: {
fields: {
personTypeId: 3,
propsGroupId: 6,
name: "Address To",
active: "Y",
sort: "100",
type: "ADDRESS",
required: "Y",
isAddressTo: "Y"
}
},
requestId: 'shipmentproperty-add-to'
})
if (response.isSuccess) {
console.info(response.getData().result)
} else {
console.error(response.getErrorMessages().join('; '))
}
try:
response = client.sale.shipmentproperty.add(
fields={
"personTypeId": 3,
"propsGroupId": 6,
"name": "Address To",
"active": "Y",
"sort": "100",
"type": "ADDRESS",
"required": "Y",
"isAddressTo": "Y",
},
).response
print(response.result)
except BitrixAPIError as error:
print(error)
$result = $sb->getSaleScope()->shipmentProperty()->add([
'personTypeId' => 3,
'propsGroupId' => 6,
'name' => 'Address To',
'active' => 'Y',
'sort' => '100',
'type' => 'ADDRESS',
'required' => 'Y',
'isAddressTo' => 'Y'
]);
echo '<PRE>';
print_r($result->getId());
echo '</PRE>';
Если свойство успешно добавлено, метод вернет объект property с идентификатором свойства. Сохраните значение property.id: оно понадобится для привязки свойства к профилям доставки.
{
"result": {
"property": {
"id": 103,
"name": "Address To",
"isAddressFrom": "N",
"isAddressTo": "Y",
"type": "ADDRESS"
}
}
}
4. Привяжем свойства отгрузки к службе доставки
Чтобы привязать свойства Address From и Address To к профилям Taxi и Cargo, вызовем метод sale.propertyRelation.add четыре раза. В метод передадим объект fields со значениями полей для привязки свойств.
-
entityId— идентификатор профиля доставки. Для профиляTaxiпередадим227, дляCargo—228, которые были получены на втором шаге. -
entityType— тип объекта. Возможные значения:P— платежная система,D— доставка,L— лендинг,T— торговая платформа. Укажем значениеD. -
propertyId— идентификатор свойства. ДляAddress Fromукажем102, дляAddress To—103, которые были получены на третьем шаге.
Значения 227, 228, 102 и 103 — демонстрационные. В рабочем сценарии подставьте идентификаторы из ответов методов sale.delivery.add и sale.shipmentproperty.add.
const response = await $b24.actions.v2.call.make({
method: 'sale.propertyRelation.add',
params: {
fields: {
entityId: 227,
entityType: 'D',
propertyId: 102
}
},
requestId: 'propertyrelation-add'
})
if (response.isSuccess) {
console.info(response.getData().result)
} else {
console.error(response.getErrorMessages().join('; '))
}
try:
response = client.sale.propertyrelation.add(
fields={
"entityId": 227,
"entityType": "D",
"propertyId": 102,
},
).response
print(response.result)
except BitrixAPIError as error:
print(error)
$result = $sb->getSaleScope()->propertyRelation()->add([
'entityId' => 227,
'entityType' => 'D',
'propertyId' => 102
]);
Вызываем метод sale.propertyRelation.add по очереди.
-
Служба
Taxi, свойствоAddress From— передаемentityId: 227, propertyId: 102. -
Служба
Taxi, свойствоAddress To— передаемentityId: 227, propertyId: 103. -
Служба
Cargo, свойствоAddress From— передаемentityId: 228, propertyId: 102. -
Служба
Cargo, свойствоAddress To— передаемentityId: 228, propertyId: 103.
Если привязки успешно добавлены, метод вернет объекты с информацией о них.
{
"result": {
"propertyRelation": {
"entityId": 227,
"entityType": "D",
"propertyId": 102
}
}
}
5. Добавим услуги в службы доставки
Чтобы добавить дополнительную услугу в службу доставки, вызовем метод sale.delivery.extra.service.add. В него передадим следующие параметры:
-
DELIVERY_ID— идентификатор службы доставки, к которой будет привязана услуга. Для профиляTaxiукажем идентификатор227, который получен на втором шаге. Для других профилей подставьте собственный идентификатор. Получить список идентификаторов служб доставки можно с помощью метода sale.delivery.getlist. -
ACTIVE— флаг активности услуги. Возможные значения:Y— да,N— нет. ПередадимY. -
CODE— символьный код услуги. Укажемdoor_delivery. -
NAME— название услуги, например,Door Delivery. -
TYPE— тип услуги. Возможные значения:enum— список,checkbox— единичная услуга,quantity— количественная услуга. Укажемcheckbox. -
PRICE— стоимость услуги типа в валюте службы доставки. Укажем1000.Для услуг типа
enumстоимость указывается с помощью параметраITEMS. Подробнее читайте в документации к методу sale.delivery.extra.service.add.
const response = await $b24.actions.v2.call.make({
method: 'sale.delivery.extra.service.add',
params: {
DELIVERY_ID: 227,
ACTIVE: "Y",
CODE: "door_delivery",
NAME: "Door Delivery",
TYPE: "checkbox",
PRICE: 1000
},
requestId: 'delivery-extra-service-add'
})
if (response.isSuccess) {
console.info(response.getData().result)
} else {
console.error(response.getErrorMessages().join('; '))
}
try:
response = client.sale.delivery.extra.service.add(
delivery_id=227,
type="checkbox",
name="Door Delivery",
active=True,
code="door_delivery",
price=1000.0,
).response
print(response.result)
except BitrixAPIError as error:
print(error)
$result = $sb->getSaleScope()->deliveryExtraService()->add([
'DELIVERY_ID' => 227,
'ACTIVE' => 'Y',
'CODE' => 'door_delivery',
'NAME' => 'Door Delivery',
'TYPE' => 'checkbox',
'PRICE' => 1000,
]);
echo '<PRE>';
print_r($result->getId());
echo '</PRE>';
Если услуга добавлена, метод вернет идентификатор в параметре result.
{
"result": 140
}
Проверим результат
Откройте карточку CRM с отгрузкой и проверьте, что в списке доставок доступна служба Uber Taxi, ее профили Taxi и Cargo, адресные свойства Address From и Address To, а также услуга Door Delivery.
Через REST проверьте созданные объекты методами sale.delivery.getlist, sale.shipmentproperty.list, sale.propertyRelation.list и sale.delivery.extra.service.get.
const deliveryResponse = await $b24.actions.v2.call.make({
method: 'sale.delivery.getlist',
params: {
SELECT: ['ID', 'NAME', 'PARENT_ID', 'ACTIVE'],
FILTER: { '=NAME': 'Uber Taxi' },
},
requestId: 'delivery-getlist-check',
})
const propertyResponse = await $b24.actions.v2.call.make({
method: 'sale.shipmentproperty.list',
params: {
select: ['id', 'name', 'isAddressFrom', 'isAddressTo'],
filter: { '=name': ['Address From', 'Address To'] },
},
requestId: 'shipmentproperty-list-check',
})
const relationResponse = await $b24.actions.v2.call.make({
method: 'sale.propertyRelation.list',
params: {
select: ['entityId', 'entityType', 'propertyId'],
filter: { entityId: 227, entityType: 'D' },
},
requestId: 'propertyrelation-list-check',
})
const extraServiceResponse = await $b24.actions.v2.call.make({
method: 'sale.delivery.extra.service.get',
params: { DELIVERY_ID: 227 },
requestId: 'delivery-extra-service-get-check',
})
console.log(deliveryResponse.getData().result)
console.log(propertyResponse.getData().result)
console.log(relationResponse.getData().result)
console.log(extraServiceResponse.getData().result)
deliveries = token.call_method(
"sale.delivery.getlist",
{
"SELECT": ["ID", "NAME", "PARENT_ID", "ACTIVE"],
"FILTER": {"=NAME": "Uber Taxi"},
},
)
properties = token.call_method(
"sale.shipmentproperty.list",
{
"select": ["id", "name", "isAddressFrom", "isAddressTo"],
"filter": {"=name": ["Address From", "Address To"]},
},
)
relations = token.call_method(
"sale.propertyRelation.list",
{
"select": ["entityId", "entityType", "propertyId"],
"filter": {"entityId": 227, "entityType": "D"},
},
)
extra_services = token.call_method(
"sale.delivery.extra.service.get",
{"DELIVERY_ID": 227},
)
print(deliveries)
print(properties)
print(relations)
print(extra_services)
$deliveryResponse = $sb->core->call('sale.delivery.getlist', [
'SELECT' => ['ID', 'NAME', 'PARENT_ID', 'ACTIVE'],
'FILTER' => ['=NAME' => 'Uber Taxi'],
]);
$propertyResponse = $sb->core->call('sale.shipmentproperty.list', [
'select' => ['id', 'name', 'isAddressFrom', 'isAddressTo'],
'filter' => ['=name' => ['Address From', 'Address To']],
]);
$relationResponse = $sb->core->call('sale.propertyRelation.list', [
'select' => ['entityId', 'entityType', 'propertyId'],
'filter' => ['entityId' => 227, 'entityType' => 'D'],
]);
$extraServiceResponse = $sb->core->call('sale.delivery.extra.service.get', [
'DELIVERY_ID' => 227,
]);
print_r($deliveryResponse->getResponseData()->getResult());
print_r($propertyResponse->getResponseData()->getResult());
print_r($relationResponse->getResponseData()->getResult());
print_r($extraServiceResponse->getResponseData()->getResult());
Успешное выполнение сценария подтверждают данные из ответов методов:
sale.delivery.addвернул родительскую службу в объектеparentи профили в массивеprofilessale.shipmentproperty.addвернул идентификаторы свойствAddress FromиAddress Tosale.propertyRelation.addвернул привязки свойств к профилям доставкиsale.delivery.extra.service.addвернул идентификатор дополнительной услуги
Оповещения о статусах доставки
Чтобы отправлять уведомления о ходе доставки, можно использовать методы группы sale.delivery.request.*.
|
Метод |
Описание |
|
Обновляет объект заказа на доставку: статус и набор его свойств |
|
|
Посылает сообщение менеджеру или грузополучателю о текущем статусе заказа на доставку |
|
|
Сообщает об отмене заказа на доставку на стороне внешней системы и пытается отменить заказ на доставку на стороне Битрикс24 |
Ошибки и диагностика
Если метод вернул ошибку, проверьте данные запроса и значения, которые передаются между шагами.
|
Код или текст ошибки |
Причина и действие |
|
|
Метод вызвал пользователь без прав администратора |
|
|
Не передан обязательный параметр или значение не прошло проверку. Проверьте |
|
|
Обработчик с таким |
|
|
Служба доставки создается с |
|
|
Ошибка при добавлении службы, обработчика или услуги. Подробности смотрите в |
|
|
Служба доставки с указанным |
|
|
В привязке свойства не передан идентификатор профиля доставки. Возьмите его из массива |
|
|
Такая привязка свойства уже существует. Повторный запуск примера не требует создавать ее заново |
|
|
Свойство не найдено. Проверьте |
Что важно учитывать
- Повторный запуск примера с тем же
CODEможет вернуть ошибку, потому что код обработчика должен быть уникальным - Профили доставки создаются на втором шаге. Их идентификаторы нужно сохранить до настройки свойств и услуг
- Внешний сервис должен принимать запросы по HTTPS-адресам, указанным в настройках обработчика