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

Получение информации о входящем звонке из 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:ProgramData3CXDataLogs3CXDialer.log";
//ПутьКЛогФайлу = "C:Documents and SettingsAll UsersApplication Data3CXDataLogs3CXDialer.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)3CXPhone3CXPhone.exe""" + " sip:" + НабираемыйНомер);  // в 64
//ЗапуститьПриложение("""C:Program Files3CXPhone3CXPhone.exe""" + " sip:" + НабираемыйНомер);
КонецПроцедуры

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

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

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

10 Comments

  1. sytkosa

    Раскрась код, добавь скриншоты и будет тебе плюс

    Reply
  2. petunov

    Читать лог-файл по таймеру — не самый лучший вариант. Можно воспользоваться внешней компонентой (есть на Инфостарте), которая мониторит изменение файла и вызывает внешнее событие. А если уже все-таки использовать таймер, то сначала логичней будет проверить изменение файла по атрибутам (время, размер), и только потом читать.

    Reply
  3. SiAl

    Поставил + за хорошее оформление публикации. Работа проделана не зря.

    Reply
  4. leles

    Спасибо за советы.

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

    Что-то не смог её найти, адрес или название не подскажите?

    (3) Конечно, это не совсем серьезная работа, а простая попытка быстро получить доступ к 3CX.

    И Ваш плюс мне особенно дорог. Это первые 10 центов Скруджа Макдака:)

    Reply
  5. petunov
  6. leles

    (5) О! Это для меня открытие!

    По сравнению с таймером это очень элегантный способ.

    Беру на вооружение.

    Mucho gracias, Вам и автору!

    Reply
  7. itwonline

    Спасибо! Только у нас почему то в окне служебных сообщений ничего не пишется..

    Reply
  8. leles

    (7) Одна из причин — не подключена внешняя компонента, для проверки в процедуре ВнешнееСобытие вместо ПрочитатьЛогФайл() напишите Сообщить(Данные), при открытии обработки должны ритмично появляться сообщения.

    Вторая возможная — убедитесь что файл 3CXDialer.log действительно находится по указанному Вами адресу.

    Откройте его, в нём должны быть записи о совершённых вызовах.

    Это для начала. Спасибо

    Reply
  9. Diversus

    (0) Лучше все таки не

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

    а

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

    Скажите, а Вы не пробовали через параметры коммандной строки 3CXPhone завершить разговор?

    Получается, для начала разговора достаточно в коммандной строке дописать » dial:НомерТелефона», а можно ли завершить текущий разговор, аналогично?

    Reply
  10. Igorro82IT

    Очень полезная публикация для меня!

    Пришлась и ко времени и к месту.

    Благодарен автору за доброту. (Голос по умолчанию прилагается))

    Reply

Leave a Comment

Ваш адрес email не будет опубликован. Обязательные поля помечены *