*Эти библиотеки упрощают использование Twilio REST API для разработчиков .NET и предоставляют набор утилит, которые облегчают работу с TwiML и Twilio Client. Ознакомьтесь с первой, второй, третьей, четвёртой, пятой и шестой частями серии.*
В предыдущей статье мы рассмотрели, как можно создать систему интерактивного голосового ответа (IVR) с многошаговым голосовым рабочим процессом, используя HTTP-обработчик в ASP.NET веб-приложении. В этой статье мы рассмотрим, как создать такую же IVR-систему с использованием фреймворка ASP.NET MVC.
Прежде чем приступить к созданию приложения, напомним, какой рабочий процесс должно поддерживать наше приложение. На диаграмме ниже показаны различные пути, которые пользователь может пройти в рамках этого процесса:
Поскольку рабочий процесс остаётся таким же, как и в предыдущей статье, основная часть логики может быть повторно использована при создании приложения на базе ASP.NET MVC.
Конечно, есть некоторые различия. Первое и, вероятно, самое заметное отличие, которое вы увидите в приложении на базе MVC, — это способ отслеживания нашего положения в рабочем процессе. В веб-приложении ASP.NET мы использовали один HTTP-обработчик в качестве конечной точки, поэтому нам приходилось использовать параметры запроса для отслеживания нашего местоположения в рабочем процессе.
Однако ASP.NET MVC включает мощный механизм маршрутизации, который мы можем использовать в нашем приложении. Вместо того чтобы направлять каждый запрос на одну конечную точку, мы используем механизм маршрутизации для предоставления различных частей логики рабочего процесса через разные URL-адреса. Например, мы можем выделить различные логические шаги рабочего процесса в несколько методов действий, каждый из которых доступен по уникальному URL.
Как и в прошлой статье, начнём создание приложения с создания нового сайта ASP.NET MVC, а затем настроим Twilio-номер для работы с конечной точкой приложения.
В Visual Studio создайте новый сайт ASP.NET MVC 3. После создания базового приложения добавьте библиотеки Twilio REST, Twilio TwiML и Twilio MVC из NuGet, как это было описано в N-й части этой серии.
Затем щёлкните правой кнопкой мыши на папке контроллеров проекта и добавьте новый контроллер с именем IvrController:
Мы будем использовать этот контроллер для обработки всех входящих запросов от Twilio, обработки запросов на основе логики приложения и возврата ответов TwiML в Twilio.
Кроме того, поскольку мы знаем, что методы действий в этом контроллере будут возвращать TwiML, мы можем сразу изменить класс, от которого наследуется контроллер, на TwilioController:
Наследуясь от класса TwilioController, мы можем использовать метод TwiML внутри наших методов действий. Метод TwiML упрощает возврат результата TwiML из метода действия, преобразуя объект TwilioResponse в ActionResult и устанавливая тип содержимого ответа в application/xml.
Теперь, когда контроллер создан, настроим маршрут по умолчанию в приложении MVC для использования его в качестве значения контроллера по умолчанию:
Настройка механизма маршрутизации для использования нашего контроллера в качестве значения по умолчанию означает, что нам не придётся явно указывать имя контроллера в URL-адресах, которые мы используем для доступа к приложению. Вместо этого механизм маршрутизации просто подставит установленное нами значение по умолчанию.
После настройки базового сайта разверните его в общедоступном месте в Интернете, например, в Windows Azure или AppHarbor.
Теперь, когда у нас есть общедоступная конечная точка, настроим Twilio-номер для указания на эту конечную точку. Как мы показали в предыдущей статье, вы можете настроить Twilio-номер, войдя в свой аккаунт twilio.com, открыв панель управления аккаунтом и выбрав номер для настройки. На рисунке ниже показано, что я настроил свой номер для указания на мой домен.
Помните, что поскольку мы настроили маршрут по умолчанию для использования класса контроллера IvrController и метода действия Index по умолчанию, нам не нужно явно указывать URL при настройке номера.
Также помните, что, как объяснялось в предыдущей статье, вместо покупки и использования Twilio-номера можно использовать бесплатный песочничный номер, который включён в каждый аккаунт Twilio. Если вы решите использовать песочничный номер, то звонящим нужно будет знать и вводить PIN-код песочницы после набора номера. Кроме того, для отправки текстовых сообщений вам нужно будет подтвердить исходящий номер в Twilio, что можно сделать из панели управления аккаунтом.
Как только базовая инфраструктура настроена, мы можем приступить к добавлению логики рабочего процесса в наше приложение. Помните, что когда поступает звонок на наш номер, Twilio отвечает и сообщает об этом нашему приложению, делая HTTP-запрос на URL обработчика голосовых вызовов.
Поскольку мы настроили наше приложение ASP.NET MVC с маршрутами по умолчанию, это означает, что когда Twilio делает этот запрос, он будет направлен к классу IvrController и затем к методу действия Index.
Поскольку мы знаем, что в нашем приложении первое, что должны услышать пользователи при ответе на звонок, — это приветственный звуковой файл, мы можем вернуть набор инструкций TwiML из метода действия Index, которые сообщат Twilio воспроизвести этот звуковой файл. Используя библиотеку Twilio TwiML, как показано ниже, мы можем ответить глаголом, который указывает Twilio воспроизвести предоставленный звуковой файл:
После того как мы создали необходимый ответ TwiML, мы можем вызвать метод TwiML и передать ему ответ. Метод TwiML установит тип содержимого HTTP-ответа в «application/xml» и преобразует TwilioResponse в ActionResult, который возвращается в качестве результата метода действия Index.
Ещё один интересный момент в методе действия Index — использование объекта UrlHelper. Обычно UrlHelper используется в представлениях MVC для генерации ссылок на другие представления, но в данном случае, поскольку у нас нет представления, мы используем помощник и пользовательский метод расширения ContentAbsolute для разрешения местоположения аудиофайла приветствия в контроллере.
После настройки метода Index вы можете протестировать приложение, позвонив на настроенный ранее номер. Вы должны услышать приветствие, после чего звонок завершится.
Далее мы хотим добавить в наше приложение меню, которое позволит пользователям выбрать, что они хотят сделать. Мы хотим, чтобы меню было отделено от приветствия, чтобы позже пользователи могли вернуться в главное меню, не слушая приветствие повторно.
Добавление меню создаст новую ветвь в рабочем процессе приложения. После воспроизведения приветствия мы хотим, чтобы приложение сразу перенаправляло пользователя в ветвь главного меню. Для этого мы можем использовать метод Redirect для добавления глагола в ответ TwiML приветствия. Глагол указывает Twilio продолжить обработку звонка с использованием нового URL. В данном случае предоставленный URL включает значение «mainmenu» в качестве параметра действия.
Когда Twilio вызывает URL перенаправления, механизм маршрутизации MVC оценивает URL и определяет, что необходимо выполнить метод MainMenu в классе IvrController. Этот метод показан ниже:
Вы можете протестировать изменения в приложении, снова позвонив на номер телефона. На этот раз вы должны услышать приветствие, за которым сразу последует содержимое главного меню.
После добавления главного меню нам нужно добавить способ прослушивания выбора, который делает пользователь. В IVR-приложениях пользователи делают выбор, нажимая клавиши на своих телефонах, что вызывает отправку DTMF-тона. Включив глагол
Обратите внимание, как мы начинаем сбор данных перед первым вызовом метода Say с помощью метода BeginGather, а заканчиваем его после последнего Say с помощью метода EndGather. Окружая глаголы тегом
Также обратите внимание, что мы используем анонимный тип для установки двух атрибутов глагола Gather. Первый, атрибут action, сообщает Twilio, какой URL запрашивать после завершения Gather. Этот URL называется обработчиком действия. Второй атрибут сообщает Twilio, сколько цифр нужно собрать от пользователя перед запросом к обработчику действия.
Согласно TwiML, который мы возвращаем в Twilio, во время звонка, если DTMF-тоны обнаружены во время выполнения
URL, установленный для обработчика действия глагола Gather, изменяет параметр действия на «MenuOptions», который является новым параметром действия, задача которого — определить, какой пункт меню выбрал пользователь, и какую ветвь в рабочем процессе приложения использовать.
Код ниже показывает метод действия MenuOptions:
Обратите внимание, что метод действия имеет один параметр метода с именем Digits. Этот параметр соответствует параметру HTTP-запроса, который отправляет Twilio и который содержит значение, собранное Twilio от конечного пользователя. Используя параметр Digits, мы определяем, какой ветви рабочего процесса должно следовать приложение.
Первый пункт меню позволяет пользователю проверить статус посылки. В нашем приложении это будет реализовано как двухэтапный процесс. Сначала нам нужно позволить пользователю ввести номер идентификатора посылки для получения информации о статусе. Во-вторых, нам нужно найти посылку по идентификатору и сообщить статус конечному пользователю.
Первый шаг обрабатывается обработчиком действия MenuOptions, который, как было показано в предыдущем разделе, оценивает, какой пункт меню выбрал пользователь из главного меню. Если выбран первый пункт меню, приложение предлагает пользователю ввести идентификатор посылки:
Как и раньше, мы определяем обработчик действия для глагола Gather, однако на этот раз указываем новое значение параметра действия: ‘lookup’. Теперь мы можем добавить в наш контроллер новый метод действия для обработки идентификатора посылки, введённого конечным пользователем:
Метод действия Lookup отвечает за поиск посылки и возврат её статуса пользователю и выполняется после того, как пользователь ввёл идентификатор посылки.
Как и в методе действия MenuOptions, метод действия Lookup принимает один параметр метода Digits, который содержит значение, введённое конечным пользователем.
На данный момент наше приложение должно позволять пользователю прослушать пункты меню, выбрать опцию проверки статуса посылки и затем услышать статус. Вы можете протестировать приложение, позвонив на свой номер и нажав «1», когда воспроизводится главное меню.
Следующая основная опция, доступная пользователям в нашем приложении, — это регистрация для получения уведомлений по SMS при изменении статуса посылки. Если вы посмотрите на диаграмму рабочего процесса приложения, показанную в начале этой статьи, вы, вероятно, заметите, что рабочий процесс для этой ветви практически идентичен ветви проверки статуса посылки, и, следовательно, код для добавления этой части приложения практически идентичен коду для проверки статуса посылки.
Для начала снова нужно добавить код, который обрабатывает выбор пользователем опции из главного меню, в обработчик действия MenuOptions:
Глагол выше определяет новый обработчик действия Register, который показан ниже:
В качестве примера того, как это может работать в реальном приложении, наш пример использует статический метод Create на фиктивном объекте Notifications для создания нового уведомления с использованием идентификатора посылки, введённого пользователем, и его номера телефона (из параметра запроса ‘From’). В реальном приложении это уведомление можно сохранить в базе данных для использования отдельным приложением мониторинга.
Как и в предыдущих разделах, вы можете протестировать приложение, позвонив на свой номер. Теперь вы должны иметь возможность как проверять статус посылки, так и выбирать второй пункт меню и регистрироваться для получения обновлений статуса.
Последняя опция, которую мы предоставляем пользователям нашего приложения, — это подключение к представителю службы поддержки. Для этого мы хотим, чтобы наше приложение совершило исходящий звонок в наш центр обслуживания клиентов и соединило клиента и агента.
Для этого наше приложение обнаруживает выбор третьего пункта в обработчике действия MainMenu и просто возвращает TwiML, который указывает Twilio соединиться с другим звонком.
Здесь мы используем глагол Dial, чтобы указать Twilio создать новый звонок на предоставленный номер. Twilio автоматически соединит существующий звонок с новым, позволяя клиенту поговорить с агентом.
Если вы посмотрите на диаграмму рабочего процесса из начала этой статьи, то увидите, что есть несколько мест, где звонящий может вернуться назад, чтобы либо повторно ввести идентификатор посылки, либо вернуться в главное меню. Логика для этого в основном одинакова для обеих ветвей потока.
Давайте сначала добавим пункты меню в ветвь поиска.
Как видно, мы добавили код для создания нашего меню в конец блока поиска. Опять же, используя глагол
Для обработки их ввода нам нужно создать ещё одну логическую ветвь, которая будет выполняться после завершения Gather. Мы указываем эту новую ветвь, как и раньше, создавая новый метод действия с именем MenuRedirect, который вы можете видеть как часть URL обработчика действия.
Также обратите внимание, что в URL обработчика действия есть ещё один сегмент после MenuRedirect. Если вы помните начало этой статьи, мы зарегистрировали маршрут по умолчанию, который выглядел так:
Дополнительный параметр в URL обработчика действия будет сопоставлен с сегментом source нашего маршрута. Мы можем использовать это в методе действия перенаправления, чтобы определить, пришёл ли пользователь из ветви поиска или ветви регистрации.
Код ниже показывает код, который мы используем для метода действия перенаправления:
Логика довольно проста. Если пользователь вводит «1», мы определяем, из какой ветви он пришёл — поиска или регистрации — и используем вспомогательный метод RedirectToAction MVC для перенаправления запроса к соответствующему методу действия.
Если пользователь вводит «2», мы перенаправляем его обратно к методу действия главного меню.
Как мы показали в этой статье, создание сложных потоков звонков с использованием ASP.NET MVC несложно, но требует некоторого планирования заранее для проектирования и реализации рабочего процесса. Как только вы поймёте рабочий процесс, реализация кода становится довольно простой с использованием базовых возможностей ASP.NET MVC.
В следующей и заключительной статье этой серии мы рассмотрим некоторые инструменты и методы, которые вы можете использовать, когда столкнётесь с проблемой и вам нужно отладить приложение, интегрированное с Twilio.
**Ознакомьтесь с остальными частями серии .NET:**
*Twilio для разработчиков .NET. Часть 1: Знакомство с вспомогательными библиотеками*
*Twilio для разработчиков .NET. Часть 2: Добавление вспомогательных библиотек Twilio в ваш проект*
*Twilio для разработчиков .NET. Часть 3: Использование вспомогательной библиотеки Twilio REST API*
*Twilio для разработчиков .NET. Часть 4: Использование вспомогательной библиотеки Twilio.TwiML*
*Twilio для разработчиков .NET. Часть 5: Вспомогательные библиотеки Twilio Client, MVC и WebMatrix*
*Twilio для разработчиков .NET. Часть 6: Создание потоков SMS и голосовых приложений с использованием ASP.NET Web Forms*