OTRS ( Open-source Ticket Request System) — открытая система обработки заявок. OTRS позволяет организациям, занимающимся технической поддержкой каких-либо проектов, совместно работать над решением проблем пользователей. Программа написана на языке Perl, поддерживает множество СУБД (MySQL, PostgreSQL и т. д.), может интегрироваться с LDAP каталогом, распространяется по лицензии — AGPL версии 3. Программный продукт протестирован на таких системах как: Linux, Solaris, AIX, FreeBSD, OpenBSD, Mac OS X и Windows.
Системы обработки заявок, такие как OTRS, обрабатывают заявки как обыкновенные почтовые сообщения (email). Когда клиент посылает по почте запрос, система создает новую заявку. Клиентам так-же доступен веб-интерфейс для создания новых заявок, проверки состояния существующих, написания ответов на старые заявки а также поиска их собственных заявок. Для интеграции собственных дополнений и приложений существует — OTRS API. Воспользуемся предоставленными возможностями для формирования заявки по телефону.
Задача: При входящем соединении на номер HelpDesk, происходит формирование заявки ( на основании определившегося номера) и вызов передается оператору. При ответе оператор открывая интерфейс работы с заявками уже имеет новую сформированную заявку и ему только необходимо ввести содержание.
Реализация: На стороне OTRS.
Для формирования заявки будем использовать протокол SOAP. SOAP ( Simple Object Access Protocol — простой протокол доступа к объектам) — протокол обмена структурированными сообщениями в распределённой вычислительной среде. Первоначально SOAP предназначался в основном для реализации удалённого вызова процедур (RPC). Сейчас протокол используется для обмена произвольными сообщениями в формате XML, а не только для вызова процедур. Официальная спецификация последней версии 1.2 протокола никак не расшифровывает название SOAP. SOAP является расширением протокола XML-RPC. SOAP может использоваться с любым протоколом прикладного уровня: SMTP, FTP, HTTP, HTTPS и др. Однако его взаимодействие с каждым из этих протоколов имеет свои особенности, которые должны быть определены отдельно. Чаще всего SOAP используется поверх HTTP. SOAP является одним из стандартов, на которых базируются технологии веб-служб.
Для использования данной возможности, необходимо задать имя пользователя и пароль. Следуем Администрирование -> Конфигурация системы. Выбираем модуль Core::SOAP и подтверждаем введенные данные.
Дальнейшие наши действия будут проходить на стороне Asterisk. Предположим номер на который приходит входящий вызов HelpDesk — 4509, а номер оператора — 4507. Отредактируем файл конфигурации vim /etc/asterisk/extensions_custom.conf следующим образом.
[otrs]
- exten => 4509,1,Answer
- exten => 4509,n,AGI(zayav.agi)
- exten => 4509,n,Dial(SIP/4507,300,tr)
Файл — zayav.agi, обычный скрипт AGI, с двумя добавленными последними строками, которыми мы получаем и передаем номер позвонившего абонента в скрипт формирования заявки (my $cid = $AGI{‘callerid’};system( «/opt/otrs/scripts/rpc_ast.pl $cid»);).
#!/usr/bin/perl use strict; $|=1; # Setup some variables my %AGI; my $tests = 0; my $fail = 0; my $pass = 0; while() { chomp; last unless length($_); if (/^agi_(\w+)\:\s+(.*)$/) { $AGI{$1} = $2; } } sub checkresult { my ($res) = @_; my $retval; $tests++; chomp $res; if ($res =~ /^200/) { $res =~ /result=(-?\d+)/; if (!length($1)) { print STDERR "FAIL ($res)\n"; $fail++; } else { print STDERR "PASS ($1)\n"; $pass++; } } else { print STDERR "FAIL (unexpected result '$res')\n"; $fail++; } } my $result = ; &checkresult($result); my $cid = $AGI{'callerid'}; system( "/opt/otrs/scripts/rpc_ast.pl $cid"); exit 0;
Скрипт — /opt/otrs/scripts/rpc_ast.pl выполняет две задачи. Первая — извлекает из базы OTRS на основании определенного номера телефона — имя пользователя и его ID (Имя пользователя и пароль для подключения к базе OTRS приведены по умолчанию). Необходимые данные находятся в таблице customer_user.
Подразумевается что данный пользователь есть в Базе OTRS и имеет необходимые атрибуты (в частности номер телефона).
$database="otrs"; $hostname="localhost"; $user="otrs"; $password='hot'; $myquery= "SELECT login,customer_id FROM customer_user where phone='$cid'"; $dbh = DBI->connect("DBI:mysql:database=$database;host=$hostname", $user, $password) || die print "Can't connect"; $sth = $dbh->prepare( $myquery ) || die "Can't prepare statement: $DBI::errstr"; $sth->execute; while ( @result = $sth->fetchrow_array) { $rez1=$result[0]; $rez2=$result[1]; } $dbh->disconnect;
Вторая — формирует заявку и ее атрибуты.
use strict; use warnings; use SOAP::Lite( 'autodispatch', proxy => 'http://127.0.0.1/otrs/rpc.pl' ); my $User = 'admin'; my $Pw = 'user'; my $RPC = Core->new(); my $TicketNumber = $RPC->Dispatch( $User, $Pw, 'TicketObject', 'TicketCreateNumber' ); my %Ticket = $RPC->Dispatch( $User, $Pw, 'TicketObject', 'TicketGet', TicketID => 1 ); my %TicketData = ( Title => "Заявка с номера $cid", Queue => 'Raw', Lock => 'unlock', Priority => '2 low', State => 'new', CustomerID => $rez2, CustomerUser => $rez1, OwnerID => 2, UserID => 'admin', ); my $TicketID = $RPC->Dispatch( $User, $Pw, 'TicketObject', 'TicketCreate', %TicketData => 1 ) || die "Failed to create ticket: $!"; my $ArticleID =$RPC->Dispatch($User, $Pw, 'TicketObject', 'ArticleCreate', TicketID => $TicketID, ArticleType => 'webrequest', SenderType => 'customer', From => ' you@firma.com', To => ' firma@firma.com', Subject => "Заявка с номера $cid", Body => "Заявка с номера $cid .... получите", ContentType => 'text/plain', Charset => 'ISO-8859-1', HistoryType => 'WebRequestCustomer', HistoryComment => '....Текст.....', UserID => 2, Loop => 0, ); exit 0;
Проверяем работу — пробуем набрать на настроенный для выполнения agi скрипта номер. Для контроля выполнения, включим режим отладки — agi set debug on.
AGI Tx >> agi_channel: SIP/84956693308-0000039a AGI Tx >> agi_language: en AGI Tx >> agi_type: SIP AGI Tx >> agi_uniqueid: 1314075508.1094 AGI Tx >> agi_version: 1.6.2.17.3 AGI Tx >> agi_callerid: 89161229624 AGI Tx >> agi_calleridname: 89161229624 AGI Tx >> agi_callingpres: 0 AGI Tx >> agi_callingani2: 0 AGI Tx >> agi_callington: 0 AGI Tx >> agi_callingtns: 1 AGI Tx >> agi_dnid: 84956693308 AGI Tx >> agi_rdnis: unknown AGI Tx >> agi_context: otrs AGI Tx >> agi_extension: 4509 AGI Tx >> agi_priority: 2 AGI Tx >> agi_enhanced: 0.0 AGI Tx >> agi_accountcode: AGI Tx >> agi_threadid: -1251619952 AGI Tx >> AGI Tx >> 200 result=0 endpos=3520 -- AGI Script zayav.agi completed, returning 0
и — voilà.
заявка сформирована. Отвечаем на входящий вызов, открываем сформированную заявку и вводим «жалобу» клиента. Конечно рекомендуется использовать несколько больше атрибутов из базы клиента для формирования более «правильной» заявки.