Интеграция 3CX Phone System с 1С. Звонки туда и обратно.

Опубликовал leles в раздел Оборудование - Телефония, SIP

Получение информации о входящем звонке из 3CX Phone System. Набор номера в 3CXPhone.

Здравствуйте, друзья!

Установил у себя 3CX Phone System. Какие ощущения? Как бесплатный вариант АТС для небольшой компании или для дома даже очень хорош. Можно быстро её настроить, интуитивно всё понятно, но есть ограничения в бесплатной версии.
В бесплатном варианте 4 одновременные коммутации. Некоторые незначительные ограничения,
и среди них одно важное: модуль интеграции с 1С, который они рекламируют отдельно, в 3CX Free Edition не поддерживается.
Если активировать 3CX демонстрационным ключом, заработает модуль 1С, но вместо 4 одновременных коммутаций будет только две.
Да и сам модуль в бесплатном варианте можно установить только на одно рабочее место. Всё это не вписывалось в мои планы.

Но очень загорелось подключить 1С к этой АТС из-за таких нужных удобств:
- звонить не набирая номера, ткнув мышкой в номер контрагента,
- при звонке клиента, до снятия трубки увидеть подсказку: контрагент, вероятное контактное лицо, его долги, свои долги.
- возможность вести журнал звонков в 1С.

Пришлось идти в обход. В файле 3CXDialer.log АТС записывает каждый звонок в реальном времени. Если оперативно эту информацию забирать, то можно, всё чудно и устроить. Ну а в обычном файловом варианте работы 1С с оперативностью может помочь, например, внешняя компонента AddInNative.dll, которая создаёт внешнее событие десять раз в секунду. Но так часто не нужно, поэтому мы частоту слегка уменьшим.

Теперь за дело:
Находим AddInNative.dll, качаем, размещаем её в нужном месте, запускаем из командной строки Regsvr32.exe "C:\наше нужное место\AddInNative.dll"
Не забываем в свойствах формы подключить ВнешнееСобытие, ПриОткрытии, ПриЗакрытии.

Перем Таймер, ВремяСтарта, РазмерЛогФайла, НомерТекущейСтроки;

Процедура ВнешнееСобытие(Источник, Событие, Данные)
	Если Данные - ВремяСтарта > 600 Тогда
		ВремяСтарта = Данные;
		Попытка
			ПрочитатьЛогФайл();
		Исключение
		КонецПопытки;
	КонецЕсли;
КонецПроцедуры

Процедура ПриОткрытии()
	ПолноеИмяФайла = "C:\Наше нужное место\AddInNative.dll";
	Файл = Новый Файл(ПолноеИмяФайла);
	Если Не Файл.Существует() Тогда
		Сообщить("Не обнаружен файл внешней компоненты " + ПолноеИмяФайла + ОписаниеОшибки(), СтатусСообщения.Внимание);
		Отказ = Истина;
		Возврат;
	КонецЕсли;
	Попытка
		ПодключитьВнешнююКомпоненту(ПолноеИмяФайла, "AddInNative", ТипВнешнейКомпоненты.Native);
		Таймер = Новый("AddIn.AddInNative.AddInNativeExtension");
		Таймер.StartTimer();
	Исключение
		Сообщить("Компонента " + ПолноеИмяФайла + " не загружена! " + ОписаниеОшибки(), СтатусСообщения.Внимание);
		Возврат;
	КонецПопытки;
	ВремяСтарта = 0;
	РазмерЛогФайла = 0;
	НомерТекущейСтроки = 0;
КонецПроцедуры

Процедура ПриЗакрытии()
	Если Таймер <> Неопределено Тогда
		Таймер.StopTimer();
		Таймер.Включен = Ложь;
		Таймер = Неопределено;
	КонецЕсли;
КонецПроцедуры

Процедура ПрочитатьЛогФайл()
	ПутьКЛогФайлу = "C:\ProgramData\3CX\Data\Logs\3CXDialer.log";
	//ПутьКЛогФайлу = "C:\Documents and Settings\All Users\Application Data\3CX\Data\Logs\3CXDialer.log";   // в XP
	фсо = Новый ComОбъект("Scripting.FileSystemObject");
	Файл = фсо.GetFile(ПутьКЛогФайлу);
	текРазмерЛогФайла = Файл.Size();
	Если РазмерЛогФайла = текРазмерЛогФайла Тогда
		фсо = Неопределено;
		Возврат;
	КонецЕсли;
	РазмерЛогФайла = текРазмерЛогФайла;
	ЛогФайл = фсо.OpenTextFile(ПутьКЛогФайлу, 1);
	Если НомерТекущейСтроки > 0 Тогда
		Для i = 1 По НомерТекущейСтроки Цикл
			ЛогФайл.SkipLine();
		КонецЦикла;
	КонецЕсли;
	Пока Не ЛогФайл.AtEndOfStream Цикл
		НомерТекущейСтроки = НомерТекущейСтроки + 1;
		текСтрока = ЛогФайл.Readline();
		Если Найти(текСтрока, "[Ringing]") = 0 Тогда Продолжить КонецЕсли;
		датаДействия = Дата("20" + СтрЗаменить(СтрЗаменить(СтрЗаменить(Лев(текСтрока, 17), ".", ""), " ", ""), ":", ""));
		Если датаДействия + 3 < ТекущаяДата() Тогда Продолжить КонецЕсли;
		Если Найти(текСтрока, " Ins: ") > 0 Тогда
			Действие = "Звонок"
		Иначе
			Действие = "Отбой"
		КонецЕсли;
		меткаВходВнутНомера = Найти(текСтрока, " DN=");
		меткаИсходВнутрНомера = Найти(текСтрока, " IP=");
		меткаНомераКонтрагента = Найти(текСтрока, " EP=");
		ВходВнутрНомер = Сред(текСтрока, меткаВходВнутНомера + 4, меткаИсходВнутрНомера - 4 - меткаВходВнутНомера);
		ИсходВнутрНомер = Сред(текСтрока, меткаИсходВнутрНомера + 4, меткаНомераКонтрагента - 4 - меткаИсходВнутрНомера);
		текНомерКонтрагента = Прав(текСтрока, СтрДлина(текСтрока) - меткаНомераКонтрагента - 3);
		Сообщить("датаДействия = " + датаДействия + ", Действие = " + Действие + ", ВходВнутрНомер = " + ВходВнутрНомер + ", ИсходВнутрНомер = " + ИсходВнутрНомер + ", НомерКонтрагента = " + текНомерКонтрагента);
	КонецЦикла;
	ЛогФайл.Close();
	фсо = Неопределено;
КонецПроцедуры

Процедура Позвонить(НабираемыйНомер)
	ЗапуститьПриложение("""C:\Program Files (x86)\3CXPhone\3CXPhone.exe""" + " sip:" + НабираемыйНомер);  // в 64
	//ЗапуститьПриложение("""C:\Program Files\3CXPhone\3CXPhone.exe""" + " sip:" + НабираемыйНомер);
КонецПроцедуры

3CXPhone.exe - это софтфон той же компании, устанавливается отдельно.
Встроенная функция ЧтениеТекста не смогла открыть лог-файл, поскольку он постоянно открыт самой АТС, пришлось прибегнуть к помощи FSO.

В Windows7 первый запуск формы выполняем по следующему сценарию: "Параметры управления учетными записями пользователей"  - ползунок вниз "Никогда не уведомлять", затем перезагрузка, теперь запускаем форму и можно ползунок возвращать на место.

Теперь имея входящий, исходящий внутренние номера, номер контрагента и события "Звонок" и "Отбой" в 1С, мы ограничены только фантазией.
Всем удачи и всяческих благ!
Ваш Лёлёсь

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

Наименование Файл Версия Размер
Интеграция3CX.epf
.epf 7,51Kb
10.02.12
51
.epf 7,51Kb 51 Скачать

См. также

Комментарии
1. Сергей Сытько (8SiriuS8) 114 07.02.12 22:31 Сейчас в теме
Раскрась код, добавь скриншоты и будет тебе плюс
2. Alex (petunov) 09.02.12 13:42 Сейчас в теме
Читать лог-файл по таймеру - не самый лучший вариант. Можно воспользоваться внешней компонентой (есть на Инфостарте), которая мониторит изменение файла и вызывает внешнее событие. А если уже все-таки использовать таймер, то сначала логичней будет проверить изменение файла по атрибутам (время, размер), и только потом читать.
3. Алексей Ситников (SiAl) 69 09.02.12 20:37 Сейчас в теме
Поставил + за хорошее оформление публикации. Работа проделана не зря.
4. leles 61 10.02.12 01:46 Сейчас в теме
Спасибо за советы.

(1), (2) Да, да всё правильно, тут же исправил, но пока без той компоненты.
Что-то не смог её найти, адрес или название не подскажите?

(3) Конечно, это не совсем серьезная работа, а простая попытка быстро получить доступ к 3CX.
И Ваш плюс мне особенно дорог. Это первые 10 центов Скруджа Макдака:)
6. leles 61 10.02.12 20:07 Сейчас в теме
(5) О! Это для меня открытие!
По сравнению с таймером это очень элегантный способ.
Беру на вооружение.
Mucho gracias, Вам и автору!
7. Александр Бобов (itwonline) 17.05.12 12:26 Сейчас в теме
Спасибо! Только у нас почему то в окне служебных сообщений ничего не пишется..
8. leles 61 20.05.12 11:27 Сейчас в теме
(7) Одна из причин - не подключена внешняя компонента, для проверки в процедуре ВнешнееСобытие вместо ПрочитатьЛогФайл() напишите Сообщить(Данные), при открытии обработки должны ритмично появляться сообщения.
Вторая возможная - убедитесь что файл 3CXDialer.log действительно находится по указанному Вами адресу.
Откройте его, в нём должны быть записи о совершённых вызовах.
Это для начала. Спасибо
9. Виталий Барилко (Diversus) 2242 26.02.14 16:35 Сейчас в теме
(0) Лучше все таки не
ЗапуститьПриложение("""C:\Program Files (x86)\3CXPhone\3CXPhone.exe""" + " sip:" + НабираемыйНомер);

а
ЗапуститьПриложение("""C:\Program Files (x86)\3CXPhone\3CXPhone.exe""" + " dial:" + НабираемыйНомер);


Скажите, а Вы не пробовали через параметры коммандной строки 3CXPhone завершить разговор?
Получается, для начала разговора достаточно в коммандной строке дописать " dial:НомерТелефона", а можно ли завершить текущий разговор, аналогично?
10. Игорь Кахановский (IgorroPadavan) 25.09.14 14:06 Сейчас в теме
Очень полезная публикация для меня!
Пришлась и ко времени и к месту.
Благодарен автору за доброту. (Голос по умолчанию прилагается))