Как выставить счет из 1С и отметить оплату

Scope: crm

Кто может выполнять методы: пользователь с правом на добавление и изменение счетов

Выберите инструмент для разработки с AI-агентом:

  • используйте Битрикс24 Вайбкод, чтобы создать приложение для Битрикс24 по описанию задачи без знания языков программирования. Агент напишет код и разместит приложение на сервере без ручной настройки хостинга
  • используйте MCP-сервер, чтобы разрабатывать интеграцию через REST API в своем проекте. Агент будет обращаться к официальной REST-документации

Счет в 1С — документ «Счет на оплату покупателю» с табличной частью товаров. В Битрикс24 счет — это отдельный тип объекта CRM с идентификатором entityTypeId = 31, поэтому работать с ним нужно универсальными методами crm.item.*.

Сценарий состоит из двух частей: при проведении счета в 1С мы создаем счет в Битрикс24, при поступлении оплаты — переводим его на стадию «Оплачен».

Порядок вызовов:

  1. crm.category.list — получаем воронку счетов
  2. crm.status.list — получаем стадии этой воронки
  3. crm.item.add — создаем счет
  4. crm.item.productrow.set — записываем товарные позиции
  5. crm.item.list и crm.item.update — при оплате находим счет и меняем стадию

Перед началом

Для выполнения примеров нужны:

Методы crm.item.* работают только со счетами нового типа. Если в Битрикс24 включены старые счета entityTypeId = 5, методы вернут ошибку ENTITY_TYPE_NOT_SUPPORTED. Как устроены новые счета — на странице Счета: обзор методов и событий.

Как использовать примеры в документации

1. Получаем воронку и стадии счетов

Идентификаторы стадий содержат номер воронки — например, DT31_11:P. На разных Битрикс24 номер отличается, поэтому не записывайте его в код: получите воронку методом crm.category.list, а затем ее стадии методом crm.status.list.

&НаСервере
Функция ВоронкаСчетов()
	
	Параметры = Новый Структура;
	Параметры.Вставить("entityTypeId", 31);
	
	Ответ = ИнтеграцияБитрикс24.ВыполнитьМетод("crm.category.list", Параметры);
	
	Если НЕ Ответ.Успешно Тогда
		ВызватьИсключение "Не удалось получить воронки счетов: " + Ответ.ОписаниеОшибки;
	КонецЕсли;
	
	Воронки = Ответ.Результат.Получить("categories");
	
	Для Каждого Воронка Из Воронки Цикл
		Если Воронка.Получить("isDefault") = "Y" Тогда
			Возврат ИнтеграцияБитрикс24.ИдентификаторИзОтвета(Воронка.Получить("id"));
		КонецЕсли;
	КонецЦикла;
	
	Возврат ИнтеграцияБитрикс24.ИдентификаторИзОтвета(Воронки[0].Получить("id"));
	
КонецФункции

Ответ метода:

{
    "result": {
        "categories": [
            {
                "id": 11,
                "name": "Общая воронка",
                "sort": 500,
                "entityTypeId": 31,
                "isDefault": "Y"
            }
        ]
    },
    "total": 1
}

Стадии запрашиваем с фильтром ENTITY_ID вида SMART_INVOICE_STAGE_{categoryId}.

&НаСервере
Функция СтадииСчетов(ИдентификаторВоронки)
	
	Параметры = Новый Структура;
	Параметры.Вставить("filter",
		Новый Структура("ENTITY_ID", "SMART_INVOICE_STAGE_" + Строка(ИдентификаторВоронки)));
	Параметры.Вставить("select", СтрРазделить("STATUS_ID,NAME,SEMANTICS,SORT", ","));
	
	Ответ = ИнтеграцияБитрикс24.ВыполнитьМетод("crm.status.list", Параметры);
	
	Если НЕ Ответ.Успешно Тогда
		ВызватьИсключение "Не удалось получить стадии счетов: " + Ответ.ОписаниеОшибки;
	КонецЕсли;
	
	Возврат Ответ.Результат;
	
КонецФункции

Ответ метода:

{
    "result": [
        { "STATUS_ID": "DT31_11:N", "NAME": "Новый", "SEMANTICS": null, "SORT": "10" },
        { "STATUS_ID": "DT31_11:S", "NAME": "Отправлен клиенту", "SEMANTICS": null, "SORT": "20" },
        { "STATUS_ID": "DT31_11:P", "NAME": "Оплачен", "SEMANTICS": "S", "SORT": "30" },
        { "STATUS_ID": "DT31_11:D", "NAME": "Не оплачен", "SEMANTICS": "F", "SORT": "40" }
    ],
    "total": 4
}

Поле SEMANTICS показывает смысл стадии: S — успешная, F — провальная, null — промежуточная. По нему находят нужную стадию, не завися от названий и номеров.

&НаСервере
Функция СтадияПоСемантике(Стадии, Семантика)
	
	Для Каждого Стадия Из Стадии Цикл
		Если Стадия.Получить("SEMANTICS") = Семантика Тогда
			Возврат Стадия.Получить("STATUS_ID");
		КонецЕсли;
	КонецЦикла;
	
	Возврат "";
	
КонецФункции

// Стадии приходят в порядке сортировки, поэтому первая в ответе — начальная стадия воронки
&НаСервере
Функция ПерваяСтадия(Стадии)
	
	Возврат ?(Стадии.Количество() > 0, Стадии[0].Получить("STATUS_ID"), "");
	
КонецФункции

2. Создаем счет

Номер и дату счета из 1С записываем в наименование, а GUID документа — в поле xmlId. По нему найдем счет, когда придет оплата.

&НаСервере
Функция СоздатьСчет(СчетНаОплату, ИдентификаторКомпании)
	
	ИдентификаторВоронки = ВоронкаСчетов();
	Стадии = СтадииСчетов(ИдентификаторВоронки);
	
	Поля = Новый Структура;
	Поля.Вставить("title", СтрШаблон("Счет № %1 от %2",
		СчетНаОплату.Номер,
		Формат(СчетНаОплату.Дата, "ДЛФ=D")));
	Поля.Вставить("categoryId", ИдентификаторВоронки);
	Поля.Вставить("stageId", ПерваяСтадия(Стадии));
	Поля.Вставить("companyId", ИдентификаторКомпании);
	Поля.Вставить("currencyId", "RUB");
	Поля.Вставить("xmlId", Строка(СчетНаОплату.Ссылка.УникальныйИдентификатор()));
	Поля.Вставить("comments", "Выставлен в 1С");
	
	// Если счет относится к сделке, укажите ее идентификатор
	// Поля.Вставить("parentId2", ИдентификаторСделки);
	
	Параметры = Новый Структура;
	Параметры.Вставить("entityTypeId", 31);
	Параметры.Вставить("fields", Поля);
	
	Ответ = ИнтеграцияБитрикс24.ВыполнитьМетод("crm.item.add", Параметры);
	
	Если НЕ Ответ.Успешно Тогда
		ВызватьИсключение СтрШаблон("Не удалось создать счет № %1: %2",
			СчетНаОплату.Номер, Ответ.ОписаниеОшибки);
	КонецЕсли;
	
	Элемент = Ответ.Результат.Получить("item");
	
	Возврат ИнтеграцияБитрикс24.ИдентификаторИзОтвета(Элемент.Получить("id"));
	
КонецФункции

Ответ метода — созданный счет целиком:

{
    "result": {
        "item": {
            "id": 1,
            "xmlId": "3ac0b1d2-5f77-4a10-9b6e-000000000123",
            "title": "Счет № УТ-000123 от 21.08.2026",
            "categoryId": 11,
            "stageId": "DT31_11:N",
            "previousStageId": "",
            "companyId": 517,
            "opportunity": 0,
            "taxValue": 0,
            "currencyId": "RUB",
            "mycompanyId": 311,
            "accountNumber": "1",
            "begindate": "2026-08-21T03:00:00+03:00",
            "closedate": "2026-08-28T03:00:00+03:00",
            "comments": "Выставлен в 1С",
            "entityTypeId": 31
        }
    }
}
  • accountNumber — номер счета в Битрикс24, он присваивается автоматически и не связан с номером документа 1С
  • mycompanyId — ваша компания, ее реквизиты попадут в печатную форму счета Битрикс24
  • opportunity — сумма. Пока товарных позиций нет, она равна нулю

3. Записываем товарные позиции

Метод crm.item.productrow.set перезаписывает все позиции счета, поэтому его вызывают один раз со всей табличной частью. Тип владельца для счета — SI.

&НаСервере
Процедура ЗаписатьТоварныеПозиции(СчетНаОплату, ИдентификаторСчета)
	
	Позиции = Новый Массив;
	
	Для Каждого СтрокаТовара Из СчетНаОплату.Товары Цикл
		
		Позиция = Новый Структура;
		Позиция.Вставить("productName", СтрокаТовара.Номенклатура.Наименование);
		Позиция.Вставить("price", СтрокаТовара.Цена);
		Позиция.Вставить("quantity", СтрокаТовара.Количество);
		Позиция.Вставить("taxRate", 20);
		Позиция.Вставить("taxIncluded", "Y");
		Позиция.Вставить("measureCode", 796); // 796 — штука по ОКЕИ
		Позиция.Вставить("measureName", "шт");
		
		// Если номенклатура выгружена в торговый каталог, укажите идентификатор товара
		// Позиция.Вставить("productId", ИдентификаторТовара);
		
		Позиции.Добавить(Позиция);
		
	КонецЦикла;
	
	Параметры = Новый Структура;
	Параметры.Вставить("ownerType", "SI"); // SI — счет
	Параметры.Вставить("ownerId", ИдентификаторСчета);
	Параметры.Вставить("productRows", Позиции);
	
	Ответ = ИнтеграцияБитрикс24.ВыполнитьМетод("crm.item.productrow.set", Параметры);
	
	Если НЕ Ответ.Успешно Тогда
		ВызватьИсключение "Не удалось записать товарные позиции счета: " + Ответ.ОписаниеОшибки;
	КонецЕсли;
	
КонецПроцедуры

Ответ метода:

{
    "result": {
        "productRows": [
            {
                "id": 105,
                "ownerId": 1,
                "ownerType": "SI",
                "productId": 0,
                "productName": "Бумага офисная А4, 500 л.",
                "price": 450,
                "priceExclusive": 375,
                "priceBrutto": 450,
                "quantity": 20,
                "taxRate": 20,
                "taxIncluded": "Y",
                "measureCode": 796,
                "measureName": "шт"
            }
        ]
    }
}

После записи позиций сумма счета пересчитывается сама: для двух позиций на 9 000 и 6 000 рублей поле opportunity станет равным 15 000, а taxValue — 2 500.

Цену передавайте с учетом налога, если в поле taxIncluded указано Y. Битрикс24 сам рассчитает priceExclusive — цену без налога. Коды единиц измерения соответствуют ОКЕИ, их список возвращает метод catalog.measure.list.

4. Отмечаем оплату

Когда в 1С проводится документ оплаты, находим счет по xmlId и переводим его на стадию с семантикой S — «успешная».

Поиск счета по документу 1С пригодится и при повторном проведении счета, поэтому вынесем его в отдельную функцию.

&НаСервере
Функция НайтиСчетПоДокументу(СчетНаОплату)
	
	Фильтр = Новый Структура;
	Фильтр.Вставить("xmlId", Строка(СчетНаОплату.Ссылка.УникальныйИдентификатор()));
	
	Параметры = Новый Структура;
	Параметры.Вставить("entityTypeId", 31);
	Параметры.Вставить("filter", Фильтр);
	Параметры.Вставить("select", СтрРазделить("id,title,stageId,categoryId", ","));
	
	Ответ = ИнтеграцияБитрикс24.ВыполнитьМетод("crm.item.list", Параметры);
	
	Если НЕ Ответ.Успешно Тогда
		ВызватьИсключение "Не удалось найти счет в Битрикс24: " + Ответ.ОписаниеОшибки;
	КонецЕсли;
	
	// Списочные методы crm.item.* возвращают элементы в ключе items
	Элементы = Ответ.Результат.Получить("items");
	
	Возврат ?(Элементы.Количество() = 0, Неопределено, Элементы[0]);
	
КонецФункции

&НаСервере
Процедура ОтметитьОплатуСчета(СчетНаОплату) Экспорт
	
	Счет = НайтиСчетПоДокументу(СчетНаОплату);
	
	Если Счет = Неопределено Тогда
		ЗаписьЖурналаРегистрации("Битрикс24.REST", УровеньЖурналаРегистрации.Предупреждение, , ,
			СтрШаблон("Счет № %1 не найден в Битрикс24", СчетНаОплату.Номер));
		Возврат;
	КонецЕсли;
	
	ИдентификаторСчета = ИнтеграцияБитрикс24.ИдентификаторИзОтвета(Счет.Получить("id"));
	ИдентификаторВоронки = ИнтеграцияБитрикс24.ИдентификаторИзОтвета(Счет.Получить("categoryId"));
	
	СтадияОплачен = СтадияПоСемантике(СтадииСчетов(ИдентификаторВоронки), "S");
	
	Если ПустаяСтрока(СтадияОплачен) Тогда
		ВызватьИсключение "В воронке счетов нет успешной стадии";
	КонецЕсли;
	
	ПараметрыОбновления = Новый Структура;
	ПараметрыОбновления.Вставить("entityTypeId", 31);
	ПараметрыОбновления.Вставить("id", ИдентификаторСчета);
	ПараметрыОбновления.Вставить("fields", Новый Структура("stageId", СтадияОплачен));
	
	ОтветОбновления = ИнтеграцияБитрикс24.ВыполнитьМетод("crm.item.update", ПараметрыОбновления);
	
	Если НЕ ОтветОбновления.Успешно Тогда
		ВызватьИсключение "Не удалось изменить стадию счета: " + ОтветОбновления.ОписаниеОшибки;
	КонецЕсли;
	
КонецПроцедуры

Ответ метода crm.item.list:

{
    "result": {
        "items": [
            {
                "id": 1,
                "title": "Счет № УТ-000123 от 21.08.2026",
                "stageId": "DT31_11:N",
                "categoryId": 11
            }
        ]
    },
    "total": 1
}

Ответ метода crm.item.update содержит измененный счет — в поле previousStageId видно, с какой стадии он перешел:

{
    "result": {
        "item": {
            "id": 1,
            "stageId": "DT31_11:P",
            "previousStageId": "DT31_11:N",
            "opportunity": 15000
        }
    }
}

Проверьте результат в Битрикс24: в разделе CRM > Счета счет перейдет в колонку «Оплачен».

5. Собираем сценарий целиком

&НаСервере
Процедура ВыгрузитьСчет(СчетНаОплату, ИдентификаторКомпании) Экспорт
	
	// При повторном проведении документа счет в Битрикс24 уже есть — создавать второй не нужно
	Счет = НайтиСчетПоДокументу(СчетНаОплату);
	
	Если Счет = Неопределено Тогда
		ИдентификаторСчета = СоздатьСчет(СчетНаОплату, ИдентификаторКомпании);
	Иначе
		ИдентификаторСчета = ИнтеграцияБитрикс24.ИдентификаторИзОтвета(Счет.Получить("id"));
	КонецЕсли;
	
	ЗаписатьТоварныеПозиции(СчетНаОплату, ИдентификаторСчета);
	
КонецПроцедуры

Процедуру ВыгрузитьСчет вызывают при проведении счета, а ОтметитьОплатуСчета — при проведении оплаты. Если обмен работает по расписанию, обе процедуры вызывают из регламентного задания по документам, измененным с прошлого запуска.

Ошибки и диагностика

Если метод вернул ошибку, проверьте данные запроса.

Ошибка

Причина и решение

ENTITY_TYPE_NOT_SUPPORTED

Методы crm.item.* вызваны для счетов старого типа. Сценарий работает только со счетами entityTypeId = 31

NOT_FOUND со статусом 400

Передан неверный entityTypeId

ACCESS_DENIED

У пользователя, создавшего вебхук, нет прав на добавление или изменение счетов

OWNER_NOT_FOUND в crm.item.productrow.set

Счет с переданным ownerId не найден. Возьмите идентификатор из ответа crm.item.add

CRM_FIELD_ERROR_VALUE_NOT_VALID

Неверное значение поля. Чаще всего это stageId из чужой воронки — получите стадии методом crm.status.list для своей categoryId

100

Не переданы обязательные параметры — например, entityTypeId или fields

Что важно учитывать

  • Частичная оплата. Стадии счета отражают статус целиком. Если нужно хранить сумму оплаты, добавьте счету пользовательское поле методами userfieldconfig.* с entityId = CRM_SMART_INVOICE и записывайте в него сумму
  • Изменение состава товаров. Метод crm.item.productrow.set перезаписывает позиции целиком, поэтому при повторном проведении документа достаточно вызвать его снова со всей табличной частью
  • Валюта. В поле currencyId передают код валюты Битрикс24. Если в 1С расчеты ведут в другой валюте, сверьте коды со списком метода crm.currency.list
  • Сделка. Счет связывают со сделкой полем parentId2. Тогда в карточке сделки появится связанный счет
  • Оплата на стороне Битрикс24. Если клиент платит по ссылке из Битрикс24, обратный сценарий строят на событии ONCRMDYNAMICITEMUPDATE — оно приходит в приложение при изменении счета. События доступны приложениям, не вебхукам

Продолжите изучение