https://a.storyblok.com/f/270183/215036/25b3bbbe65/ivr-java-feature-image.png

Como criar um IVR simples com Java e o Spark Framework

Publicado em April 26, 2021

Tempo de leitura: 17 minutos

IVR é o nome técnico dado a uma chamada telefônica automatizada na qual você digita números no teclado do seu telefone e o sistema responde de forma adequada — lendo informações para você, conectando-o a um número ou o que for necessário. O melhor é que você pode criá-los com o Nexmo Voice!

Neste tutorial, você criará um pequeno microsserviço para hospedar um IVR básico. Vou explicar tudo o que você precisa saber para configurar um serviço Spark capaz de receber chamadas e capturar as entradas do usuário digitadas pelo teclado.

A ideia é criar um IVR bem pequeno que permita ao usuário inserir um código DTMF. Nesse esse caso, a chamada simplesmente repetirá para você o número que você digitou.

Acho bastante útil ter um roteiro ou um fluxograma à mão ao criar um IVR. Aqui está o roteiro para o seu serviço:

[Caller dials Nexmo number]

IVR: Welcome to my Nexmo IVR! Please enter a digit.

[Caller enters '5']

IVR: You entered 5. Thank you for calling!

[IVR hangs up]

O código deste tutorial pode ser encontrado no GitHub.

Requisitos

Antes de começar, você deve ter o seguinte configurado:

  • O CLI da Nexmo. (É possível se virar sem ele usando o Painel da Nexmo, mas ele facilita muito a vida muito mais fácil!)

  • A JDK instalado (eu compilei isso com o JDK 8).

  • Maven para compilar seu código Java.

  • Ngrok para que a Nexmo possa acessar o serviço em execução na sua máquina de desenvolvimento

Introdução

Primeiro, o `create` deve inicializar um projeto Maven usando o seguinte comando:

mvn archetype:generate -DgroupId=com.nexmo.xwithy -DartifactId=ivr-demo -DarchetypeArtifactId=maven-archetype-quickstart -DarchetypeVersion=1.4

Ao executar esse comando, será criado um arquivo de projeto do Maven e um arquivo-fonte no local correto — algo parecido com isto:

ivr-demo
├───pom.xml
└───src
    └───main
        └───java
            └───com
                └───nexmo
                    └───xwithy
                        └───App.java

Abra pom.xml no seu editor de código favorito (estou usando o o VSCode) e, primeiro, altere a versão de destino do Java de 1.7 para 1.8:

<maven.compiler.source>1.8</maven.compiler.source>
<maven.compiler.target>1.8</maven.compiler.target>

Em seguida, adicione as dependências do Nexmo e do Spark à <dependencies> seção:

<dependency>
    <groupId>com.nexmo</groupId>
    <artifactId>client</artifactId>
    <version>4.4.0</version>
</dependency>

<dependency>
    <groupId>com.sparkjava</groupId>
    <artifactId>spark-core</artifactId>
    <version>2.7.2</version>
</dependency>

<dependency>
    <groupId>org.slf4j</groupId>
    <artifactId>slf4j-simple</artifactId>
    <version>1.7.21</version>
</dependency>

Agora, recomendo que você compile o projeto, apenas para baixar as dependências e verificar se está tudo certo no seu projeto:

mvn compile

Você deverá ver muitas mensagens de saída enquanto o Maven baixa tudo o que precisa e, em seguida, a mensagem BUILD SUCCESS. Caso contrário, verifique seu arquivo XML para ter certeza de que inseriu a configuração acima corretamente e no lugar certo.

Vamos atender as ligações

Vou explicar como construir o código passo a passo, mas talvez seja útil dar uma olhada no resultado final, que você pode encontrar no GitHub. Está tudo em uma única classe, e adicionei muitos comentários, então espero que não seja muito difícil de acompanhar.

Quase tudo vai para dentro do nosso main método, que é executado quando executamos a App classe. O Spark pode funcionar de maneira um pouco diferente do que você está acostumado. Você define como deseja que o Spark se comporte chamando métodos estáticos, e então o Spark hospedará sua aplicação web até que você peça para ele parar!

Insira a seguinte linha no seu main método:

port(4567);

A linha acima indica ao Spark em qual porta TCP você deseja hospedar seu serviço. Escolhi a 4567. Você pode escolher um número diferente, mas certifique-se de anotar o número escolhido — você precisará dele mais tarde! (Escolha um número acima de 1024 — isso pode evitar alguns problemas.)

A próxima coisa que você deve fazer é registrar um endpoint HTTP para que a Nexmo possa chamá-lo. Ele ficará hospedado em /inbound e será chamado pelo Nexmo quando alguém ligar para o seu Número Virtual do Nexmo. Coloque o código a seguir dentro de seu main método, após a port chamada:

post("/inbound", (req, res) -> {
    res.type("application/json");
    return new Ncco(
        TalkAction.builder("Welcome to my Nexmo IVR!").build()
    ).toJson();
});

Quando a Nexmo ligar para esse número, seu aplicativo deverá retornar uma resposta JSON semelhante a esta:

[
  {
    "text": "Welcome to my Nexmo IVR!",
    "action": "talk"
  }
]

Isso fará com que o Nexmo atenda a chamada e reproduza uma mensagem cordial. Você pode testar isso agora, compilando e executando o seguinte no prompt de comando:

mvn compile mvn exec:java -Dexec.mainClass="com.nexmo.xwithy.App"

O Spark exibirá algumas mensagens de log e, quando terminar, você poderá testá-lo usando curl na linha de comando, desta forma:

curl -X POST http://localhost:4567/inbound [{"text":"Welcome to my Nexmo IVR!","action":"talk"}]

O comando `curl` acima faz uma solicitação HTTP POST ao seu servidor e exibe a resposta. Se você não se sente muito à vontade com a linha de comando, ou simplesmente prefere um aplicativo gráfico, pode usar o Postman para fazer a mesma coisa.

Você pode interromper o serviço a qualquer momento digitando Ctrl-C. Você precisará fazer isso, além de recompilar e executar novamente sempre que alterar seu código-fonte e quiser testar seu serviço.

Agora, esperamos que você já tenha um aplicativo capaz de atender chamadas de Voice recebidas pelo Nexmo. É hora de associar um número de telefone do Nexmo ao seu aplicativo.

Conecte o Nexmo ao seu serviço

Você se lembra do Requisitos acima, onde eu disse que você precisaria ter o Ngrok instalado? Felizmente, meu colega Aaron escreveu um ótimo guia sobre como usar o Ngrok e o Nexmo. Você deveria dar uma olhada! Você pode colocar o Ngrok em funcionamento abrindo uma aba do console (é preciso executá-lo ao mesmo tempo que seu serviço Java) e executando o seguinte comando:

ngrok http 4567 ... Web Interface http://127.0.0.1:4040 Forwarding http://r6nd0m.ngrok.io -> http://localhost:4567 Forwarding https://r6nd0m.ngrok.io -> http://localhost:4567

Você vai notar na saída que há duas linhas chamadas “Forwarding”; uma contém uma URL HTTP e a outra, uma URL HTTPS. Anote a URL HTTPS — você vai precisar dela daqui a pouco. Outro detalhe a ser observado é a linha “Web Interface”. Recomendo que você abra essa URL no seu navegador agora mesmo — pois você está prestes a verificar se o Ngrok está conectado ao seu serviço IVR em Java.

Usando curl (ou o Postman), execute uma solicitação semelhante à que você fez acima, mas, desta vez, use a URL do Ngrok que acabou de receber, com /inbound adicionado ao final. O meu fica assim:

curl -X POST https://r6nd0m.ngrok.io/inbound [{"text":"Welcome to my Nexmo IVR!","action":"talk"}]

Você deve ver a mesma saída de antes. Isso significa que o Nexmo poderá acessar seu serviço (enquanto tanto o Ngrok e seu serviço ainda estiverem em execução).

Espero que você já tenha um Account no Nexmo e que a ferramenta CLI do Nexmo esteja configurada. Se não for o caso, agora é a hora! Quando estiver pronto...

Compre um número da Nexmo

Você pode começar a alugar um número da Nexmo executando o seguinte nexmo na sua linha de comando:

nexmo number:buy --country_code US

Se você gostar do número que foi selecionado para você, digite “confirm” e pressione Enter. Se preferir escolher um número de uma lista, recomendo usar o Painel da Nexmo. Anote o número.

Criar um aplicativo de voz da Nexmo

Agora você precisa criar um aplicativo Nexmo Voice, que agrupa um ou mais Numbers Nexmo com uma configuração de webhook. Lembre-se de alterar o nome do host do Ngrok para aquele que foi fornecido acima!

nexmo app:create --keyfile private.key "My IVR Demo" --answer_method POST --event_method POST https://r6nd0m.ngrok.io/inbound https://r6nd0m.ngrok.io/event

O comando acima configura um aplicativo Nexmo que sabe como chamar seu serviço quando uma chamada recebida é detectada. Você também salvou a chave privada em um arquivo local private.key. Você não vai usá-la neste tutorial, mas ela pode ser útil mais adiante, à medida que você for adicionando mais funcionalidades ao seu serviço.

Anote o ID do seu pedido. Você vai precisar dele mais tarde.

Vincule seu número Nexmo

Usando o número de telefone e o ID do aplicativo fornecidos acima, execute o seguinte comando:

nexmo link:app NEXMO_NUMBER APPLICATION_ID

Testando seu serviço

Agora, se você ligar para o número da Nexmo do seu celular, a Nexmo deve atender, e você deve ouvir a mensagem “Bem-vindo ao meu IVR da Nexmo!”, e então a ligação será encerrada.

Se isso não funcionar, verifique o console do Ngrok no seu navegador em http://localhost:4040/ e certifique-se de que a chamada foi recebida pelo Ngrok e encaminhada com sucesso para o serviço Java em execução na sua máquina de desenvolvimento.

Transforme isso em um IVR

Seu IVR ainda não é muito útil! Vou mostrar como permitir que o usuário insira dados pelo teclado (isso é chamado de DTMF, sigla para Dual Tone Modulated Frequency, mas isso não é muito importante).

Peça opiniões

Primeiro, volte à get chamada que você escreveu e adicione um segundo parâmetro à Ncco chamada do construtor, para que fique assim:

return new Ncco(
    TalkAction.builder("Welcome to my Nexmo IVR! Please enter a digit.")
            .build(),
    InputAction.builder()
            .maxDigits(1)
            .timeOut(5)
            .eventUrl(pathToUrl(req, "/input"))
            .build()
).toJson();

Esta InputAction instrui a Nexmo a aguardar 5 segundos para que o usuário digite 1 dígito no teclado. Quando o dígito for digitado, a Nexmo fará uma chamada para o seu servidor em /input com os detalhes do código DTMF digitado pelo usuário. Você escreverá o manipulador para /input daqui a pouco.

Também modifiquei a chamada do TalkAction, de modo que definimos bargeIn como “true”. Isso significa que um ouvinte com pressa não precisa esperar a mensagem terminar para digitar o código DTMF.

Outro ponto a ser observado é o pathToUrl método que está sendo usado para gerar uma URL absoluta para o seu serviço. Trata-se de um método utilitário de 10 linhas que eu escrevi. Cole-o na sua App classe a partir do código no GitHub. Não vou explicar como ele funciona aqui, porque não é exatamente o tema deste tutorial!

Processar a entrada

Agora que você configurou o Nexmo para ligar /input quando o usuário digitar um código DTMF, você precisa atender essa chamada. Insira o código a seguir no final do seu main método:

post("/input", (req, res) -> {
    InputEvent input = InputEvent.fromJson(req.body());

    res.type("application/json");
    String message = "You entered " + input.getDtmf();
    return new Ncco(TalkAction.builder(message).build()).toJson();
});

O código acima é muito semelhante ao seu /inbound , mas, neste caso, ele analisa o JSON recebido em um InputEvent na solicitação e extrai o código DTMF a partir dele. Em seguida, responde ao usuário lendo em voz alta uma mensagem informando o código que ele digitou.

Teste seu aplicativo ligando para o seu número da Nexmo e digitando um código no teclado quando for solicitado!

Conclusão

Este é um exemplo bem simples de como responder a um código DTMF, mas você pode adaptá-lo para atender às necessidades da sua aplicação. Talvez você possa consultar um registro em um banco de dados usando um ID inserido pelo usuário, ou criar uma central telefônica para transferir a chamada para alguém da sua organização. As possibilidades são muitas!

Para mais informações, confira nossa documentação premiada em Nexmo Developer.

Se você estiver desenvolvendo um serviço Spark de grande porte, não recomendo colocar todo o seu código em um único main método! Felizmente, a equipe do Spark escreveu um postagem no blog descrevendo as melhores práticas para aplicativos maiores.

Se você tiver algum comentário ou precisar de ajuda com este tutorial, estou à disposição @judy2k no Twitter — me mande uma mensagem direta. Como alternativa, você pode enviar um e-mail para nossa equipe de Relações com Desenvolvedores em devrel@nexmo.comou participar da comunidade da Nexmo no Slack.

Compartilhar:

https://a.storyblok.com/f/270183/150x150/a3d03a85fd/placeholder.svg
Mark SmithEx-funcionários da Vonage

Mark era o responsável nominal pelas bibliotecas de clientes da Nexmo (embora ele só desenvolva as bibliotecas em Python e Java). Ele começou como desenvolvedor Java, já trabalha com Python há 18 anos e vem se aventurando cada vez mais com Go e Rust. Ele gosta de levar as linguagens de programação ao limite e, depois, ensinar essas técnicas a outros programadores. Ele tem um chapéu de viking, mas não é um viking, e no Twitter usa o nome Judy2k por motivos que prefere não revelar.