gifts2017

Интеграция 1С с SIP телефонией, или CRM за 3 рубля.

Опубликовал Сергей Лактионов (lavrov) в раздел Оборудование - Телефония, SIP

Сейчас многие компании используют SIP телефонию как внутри офиса так и для внешних звонков. Возникла задача сделать в CRM-системе возможность отслеживания входящих / исходящих звонков.

Был проведен поиск решения, но оказалось, что почему-то никто из операторов не предоставляет API для этих целей. Были только какие то попытки сделать что-то подобное на своих ресурсах, но пользоваться этим не удобно, да и, как правило, за использование просят немало денег.
Парсить отчет по звонкам просто нереально, и получается, что не в реальном времени.

Был найден простой выход из ситуации . Во многих моделях современных телефонов существует возможность при наступлении 
события передавать данные на web сервер.

Например для телефонов Yealink это выглядит так.



Для телефонов Dlink это выглядит так.



Нас интересуют основные 4 события:

Входящий вызов (трубку еще не поднимали )

Вызов установлен — разговор начался .

Вызов завершен — разговор закончен

Исходящий вызов — мы кому-то звоним.

Таблица параметров из инструкции к аппарату.

п/п

Параметр

Описание на англ

Описание на русском

 

$mac

MAC address of the IP phone

MAC-адрес IP телефона

 

$ip

The current IP address of the IP phone

IP-адрес IP-телефона

 

$model

Phone model

Модель телефона

 

$firmware

Phone firmware version

Номер прошавки

 

$active_url

The SIP URI of the current account when the IP phone is

in the incoming, outgoing or connecting state.

SIP URI текущего соеденения , когда IP-телефон в сети.

 

$active_user

The username of the current account when the IP

phone is in the incoming, outgoing or connecting

state.

Имя пользователя используемого для подключения, когда IP-

телефон находится сети.

 

$active_host

The host name of the current account when the IP

phone is in the incoming, outgoing or connecting

state.

Имя хоста используемого для подключения, когда IP-

телефон находится сети.

 

$local

The SIP URI of the caller when the IP phone places a

call.

The SIP URI of the callee when the IP phone receives

an incoming call.

SIP URI вызывающего абонента, когда IP-телефон далет исходящий вызов

SIP URI вызываемого абонента, когда получает IP-телефон

делает входящий вызов.

 

$remote

The SIP URI of the callee when the IP phone places a

call.

The SIP URI of the caller when the IP phone receives

an incoming call.

SIP URI из вызывается, когда IP-телефон делает исходящий вызов.

SIP URI вызывающего абонента, когда получает IP-телефон

входящий вызов.

 

$display_local

The display name of the caller when the IP phone

places a call.

The display name of the callee when receives an

incoming call.

Имя отображаемое на дисплее когда телефон

осуществляет вызов.

Имя отображаемое на дисплее когда телефон получает

входящий вызов.

 

$display_remote

The display name of the callee when the IP phone

places a call.

The display name of the caller when the IP phone

receives an incoming call.

На дисплее вызываемого абонента, когда IP-телефон

осуществляет вызов.

На дисплее имя звонящего, когда IP-телефон

получает входящий вызов.

 

$call_id

The caller ID when in incoming, outgoing or

connecting state.

Показания АОН, входящие, исходящие или состояние

подключения.


Переводил через гугл транслит так что не пинайте сильно.

Наша строка инициализации выглядит примерно так.

http://myserver.ru/checkphone.php?event=1&p1=$remote&p2=$display_local


Где event=1 — это номер события чтобы понимать что за событие у нас происходит.

Для каждой строки у нас будет свой номер события
1 - Входящий звонок
2 - Разговор
3 - Исходящий звонок
4 - Вызв завершен.

p1=$remote - первый параметр это номер входящего звонка в формате SIP

примерный вид получаемых данных такой sip:74951234567@operatorsip.ru

Из этого номер очень просто вытащить сам номер телефона с помощью простой функции .

функция ПреобразоватьНомерТелефона(Номер)
   Номер= СтрЗаменить(Номер,"sip:","");
   Номер= СтрЗаменить(Номер,"@operatorsip.ru","");
   Номер= СтрЗаменить(Номер," ","");
   Номер= сокрЛП(Номер);
   Возврат Номер;
КонецФункции

р2 =$display_local — внутренний номер аппарата , с которого делается вызов. Например 101 ,105 и так далее.

Возможно на ваших аппаратах параметры будут по другому называться.

Телефон делает запрос на веб сервер, на веб сервере нам нужен скрипт , который бы преобразовал запрос с параметрами в запрос к WEB сервису 1с. Так как 1с параметризированные запросы через WEB сервер обрабатывать не может.

Скрипт сделан для двух параметров P1 и P2 , при желании их количество можно увеличить.

Архив со скриптом прикреплен к статье.

Создаем в 1с web сервис с именем TelData с функцией .


Функция TelData(Nomer_Sobitia, Nomer_sip, moi_nomer)
   результат="Cобытие "+Nomer_Sobitia+" Входящий номер "+(Nomer_sip)+" Мой номер "+Moi_nomer;
   ЗаписьЖурналаРегистрации("Телефон",,,,результат);
   ЗвонкиПривелигированный.ЗаписатьТелефон(Nomer_Sobitia, Nomer_sip,moi_nomer); // наша процедура по обработке звонка. 
   возврат результат;
КонецФункции 

Дальше уже по событию,  номеру телефона и по внутреннему номеру закрепленному за телефоном определяем кто звонит, кому звонит, создаем события, обрабатываем события в 1с .

Время срабатывания такой связки составляет около секунды.

Описание того как сделать WEB сервис и опубливать его выходят за рамки данной статьи. Информации об этом море, ищите... 

Скачать файлы

Наименование Файл Версия Размер
Файл скрипта по преобразованию строки с параметрами в запрос к WEB сервису 1с 27
.zip 0,78Kb
19.06.14
27
.zip 1 0,78Kb Скачать

См. также

Вознаграждение за ответ
Сумма: 0 $m
Добавили:
Two World (Prometeus2011) (0.99 $m)
Подписаться Добавить вознаграждение

Комментарии

1. Егор Иванов (Infactum) 20.06.14 08:21
На сколько я помню, начиная с 8.3.5 в платформе есть поддержка HTTP сервисов. Так что можно будет спокойно отказаться от промежуточного PHP скрипта.
Да и в целом не совсем ясно: у вас что, каждый телефон подключен к сип провайдеру напрямую? Странно, что в качестве единой точки подключения не используется IP PBX: тот же Asterisk или FreeSwitch. Потому что в этом случае все события можно генерировать в самой PBX, и в случае необходимости что-то поменять это делается в одном месте; не надо бегать к каждому телефону.

P.S. Называть параметры веб-сервиса транслитом - моветон.
2. Сергей Лактионов (lavrov) 20.06.14 10:14
Да , каждый телефон подключен к провайдеру напрямую.
3. panvartan panvartan (panvartan) 20.06.14 10:40
Может не увидел, а набрать номер из 1с на телефоне получилось?
4. Сергей Лактионов (lavrov) 20.06.14 16:05
Задача такая не стояла, но это совсем просто сделать - нужно на телефон передать ссылку. Вида
http://admin:123@192.168.10.10/cgi-bin/ConfigManApp.com?key=74951234567/#/POUND
Где admin - логин
123 - пароль
192.168.10.10 - ip адрес телефона
74951234567 - номер телефона
panvartan; +1 Ответить
5. Ловыгин Антон (wunderland) 23.06.14 10:25
Когда-то занимался SIP, правда, сервер был на наш, а не стороннего провайдера, на базе Asterisk TrixBox. Вся информация писалась в базу на MySQL - и никаких проблем. Програмку правда сам писал: статистика, поиск, графики, прослушка записей, управление архивом и т.д. Остались приятные воспоминания.
6. Two World (Prometeus2011) 26.06.14 13:04
Стояла похожая задача. Надо было выводить информацию о произведенных пользователем звонках. Использовали прямые sql-запросы к ИБ. Сервер - октелл. Идея подсмотрена в одном решении. Не буду называть, кто разработчик, чтобы не сочли за рекламу.

Функция ВыполнитьSQLЗапрос(ТекстЗапроса, СтруктураПредставленияПолей = Неопределено, ТестСтрокиПодключения = Ложь) Экспорт
	Соединение = Новый COMОбъект("ADODB.Connection");
	База = Новый COMОбъект("ADOX.Catalog");

	СтрокаПодключения = СоздатьСтрокуПодключения(ТестСтрокиПодключения);
	
	Command = Новый COMОбъект("ADODB.Command");
	Command.ActiveConnection = Соединение;
	Command.CommandText = ТекстЗапроса;


	Записи = Новый COMОбъект("ADODB.RecordSet");
	Записи = Command.Execute();

	ТаблицаЗначений = Новый ТаблицаЗначений;


	КолВоПолей = Записи.Fields.Count - 1;
	Для Н = 0 По КолВоПолей Цикл
		СКЛИмяПоля = Записи.Fields.Item(Н).Name;
		ИмяПоля = СКЛИмяПоля;
		Если СтруктураПредставленияПолей <> Неопределено И СтруктураПредставленияПолей.Свойство(СКЛИмяПоля) Тогда
			ИмяПоля = СтруктураПредставленияПолей[СКЛИмяПоля];
		КонецЕсли;
		Если ТаблицаЗначений.Колонки.Найти(ИмяПоля) = Неопределено Тогда
			ТаблицаЗначений.Колонки.Добавить(ИмяПоля);
		КонецЕсли;
	КонецЦикла;

	Если Записи.Bof Тогда
		Возврат ТаблицаЗначений;
	КонецЕсли;

	Записи.MoveFirst();
	Пока Записи.EOF() = 0 Цикл
		СтрокаТЧ = ТаблицаЗначений.Добавить();
		Для Н = 0 По КолВоПолей Цикл
			СКЛИмяПоля = Записи.Fields.Item(Н).Name;
			ИмяПоля = СКЛИмяПоля;
			Если СтруктураПредставленияПолей <> Неопределено И СтруктураПредставленияПолей.Свойство(СКЛИмяПоля) Тогда
				ИмяПоля = СтруктураПредставленияПолей[СКЛИмяПоля];
			КонецЕсли;
			ЗначениеПоля = Записи.Fields.Item(Н).Value;
			СтрокаТЧ[ИмяПоля] = ЗначениеПоля;
		КонецЦикла;
		Записи.MoveNext();
	КонецЦикла;
	Записи.Close();

	Возврат ТаблицаЗначений;
КонецФункции

Функция СоздатьСтрокуПодключения(ТестСтрокиПодключения)
	Если Не ТестСтрокиПодключения И ПараметрыСеанса.ОктеллСтрокаПодключения <> "" Тогда
		Возврат ПараметрыСеанса.ОктеллСтрокаПодключения;
	КонецЕсли;
	Логин = Константы.БДОктелЛогин.Получить();
	Пароль = Константы.БДОктелПароль.Получить();
	Компьютера = Константы.БДОктелИмяКомпьютера.Получить();
	Базы = Константы.БДОктелИмяБазы.Получить();
	СтрокаСоединения = "Provider=SQLOLEDB.1;
	|Persist Security Info=False;
	|User ID=" + Логин + ";
	|Pwd=" + Пароль + ";
	|Data Source=" + Компьютера + ";
	|Initial Catalog=" + Базы + "";
	ПараметрыСеанса.ОктеллСтрокаПодключения = СтрокаСоединения;
	Возврат СтрокаСоединения;
КонецФункции

//Строка соединения выглядит так:
Provider=SQLOLEDB.1;
Persist Security Info=False;
User ID=AutelService;
Pwd=Version2;
Data Source=192.168.1.39;
Initial Catalog=oktell

//Вызов Запроса:
Процедура КнопкаВыполнитьНажатие(Кнопка)
	//ОбновлениеДанныхПоЗвонкамПользователя.ОбновлениеДанныхПоЗвонкамПользователя();
	ТекстЗапроса = "Select A_Stat_Connections_1x1.Id, A_Stat_Connections_1x1.AUserID, A_Stat_Connections_1x1.TimeAnswer, 
 |A_Stat_Connections_1x1.IsBetweenUsers, A_Stat_Connections_1x1.BStr as UserName,
 |A_Stat_Connections_1x1.TimeStop, A_Stat_Connections_1x1.BOutNumber as TelNumber, A_Users.Name,
 |A_Stat_Connections_1x1.AOutNumber, A_Stat_Connections_1x1.TimeStart, A_Stat_Connections_1x1.TimeStop,
 |A_Stat_Connections_1x1.TimeAnswer, A_Stat_Connections_1x1.ReasonStart, A_Stat_Connections_1x1.ReasonStop
 |from A_Stat_Connections_1x1 left outer join A_Users on A_Stat_Connections_1x1.AUserID = A_Users.ID
 |where A_Stat_Connections_1x1.Bstr = 'Иванов Иван Иванович'
 |and TimeStart  between  '2014-02-01 00:00:00.000' and CURRENT_TIMESTAMP
 |and IsBetweenUsers = 0";
 
 ТекстЗапроса = СтрЗаменить(ТекстЗапроса,"Иванов Иван Иванович",СокрЛП(ПараметрыСеанса.ТекущийПользователь.Наименование));
 Запрос = новый запрос;
 Запрос.Текст = "ВЫБРАТЬ ПЕРВЫЕ 1
                |	МАКСИМУМ(СостояниеЗвонков.НачалоЗвонка) КАК НачалоЗвонка
                |ИЗ
                |	РегистрСведений.СостояниеЗвонков КАК СостояниеЗвонков
                |ГДЕ
                |	СостояниеЗвонков.Пользователь = &Пользователь";
Запрос.УстановитьПараметр("Пользователь",ПараметрыСеанса.ТекущийПользователь);
ВыбЗап = Запрос.Выполнить().Выбрать();
Если ВЫбЗап.Следующий() тогда
	ТекстЗапроса = СтрЗаменить(ТекстЗапроса,"2014-02-01 00:00:00.000",Формат(ВЫбЗап.НачалоЗвонка, "ДФ='yyyy-MM-dd чч:мм:сс.000'"));
КонецЕсли;

ТаблицаЗвонка = ОктеллСервер.ВыполнитьSQLЗапрос(ТекстЗапроса);


КонецПроцедуры
...Показать Скрыть
7. Николай Крылов (Nikola23) 07.07.14 16:51
Странно, что не нашли готовых решений. Полный интернет...
Цена - копейки, настраивается за 2 часа.
Работает в онлайн и никаких секундных задержек.
Заинтересует - пишите.
8. Николай Крылов (Nikola23) 07.07.14 16:53
Да, кстати, при чем тут CRM? CRM - это далеко не автоматическая фиксация звонка или определение карточки клиента.
Напишите в заголовке Интеграция с виртуальной АТС и не путайте людей.
9. Сергей Лактионов (lavrov) 07.07.14 17:11
Приведите пример готовых решений, без выделенного сервера при подключении напрямую к виртуальной АТС провайдера. Например для zadarma.com или mango.ru
10. Николай Крылов (Nikola23) 10.07.14 14:56
(9) lavrov,
БИТ:Phone, Рарус:СофтФон.
11. Сергей Лактионов (lavrov) 10.07.14 19:42
Эти системы не интегрируются с виртуальными АТС.
12. Николай Крылов (Nikola23) 17.07.14 19:24
(11) lavrov, На что спорим? Показать вам БИТ:Phone подключенный к Манго телеком?
13. Михаил Жирнов (mzhirnov) 10.11.15 21:29
Мы интегрировали нашу виртуальную АТС и программную Sipteco с панелью телефонии 1С Мико и Рарус софтфон. Вы можете подключить любых облачных операторов связи, Манго, Задарма и любых других к 1С.

http://sipteco.ru/index.php/integracia-ats-1c/
14. Merab Nick (merabn) 16.02.16 17:00
(1) Infactum,
Сейчас через HTTP-сервисы можно организовать связь через API таких провайдеров SIP как Задарма и Манго-офис.
Таким образом можно интегрировать в конфигурацию 1С уведомления о звонках и callback, и т.п. И телефоны не нужны, у Манго свой софтфон, да и любой может использоваться. Для небольших организаций, на мой взгляд, хорошее решение, если телефонная инфраструктура не навязана и только создается. Даже существующие телефонные линии можно интегрировать через SIP-шлюз, подключив к Задарма. Это интеграция не за 3 рубля, конечно, но цены за виртуальный PBX, особенно у Задарма, вполне приемлемые. А вот, если в организации уже есть Астерикс, то тратить ничего не надо - только труд.
Для написания сообщения необходимо авторизоваться
Прикрепить файл
Дополнительные параметры ответа