EVG Connector
The eva Voice Gateway
The eva-evg-connector is an IVR integration channel with eva.
In this guide we will see how to set up a project using the eva-evg-connector.
Versions
Note that eva-evg-connector is a peer dependency of eva. This change allows greater flexibility of choosing the right version of the eva-evg-connector client version for eva version.
1.x.x
4.3.x - current
Requirements
For building and running the application you need:
Dependencies
The external dependencies of this project are:
Environment Variables
To change the default value of some project settings just set the following environment variables:
Redis
spring.cache.redis.time-to-live=1800000
spring.cache.type=${CACHETYPE}
spring.redis.host=${REDIS_HOST}
spring.redis.port=${REDIS_PORT}
spring.redis.password=${REDIS_PWD}
spring.redis.ssl=${REDIS_SSL}
Getting Started
First, we’ll start by creating a Spring Boot web project and adding the eva-evg-connector dependency to our pom.xml file:
<dependency>
<groupId>com.everis.eva</groupId>
<artifactId>eva-evg-connector</artifactId>
<version>1.0.0</version>
</dependency>
It is a maven project with Spring Boot Web, to create a project using Spring see the website: https://start.spring.io/
To download the dependency, configure your settings.xml as follows:
<?xml version="1.0" encoding="UTF-8"?>
<settings xmlns="http://maven.apache.org/SETTINGS/1.0.0"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://maven.apache.org/SETTINGS/1.0.0 http://maven.apache.org/xsd/settings-1.0.0.xsd">
<servers>
<server>
<id>artifact-registry-evg</id>
<configuration>
<httpConfiguration>
<get>
<usePreemptive>true</usePreemptive>
</get>
<head>
<usePreemptive>true</usePreemptive>
</head>
<put>
<params>
<property>
<name>http.protocol.expect-continue</name>
<value>false</value>
</property>
</params>
</put>
</httpConfiguration>
</configuration>
<username>_json_key_base64</username>
<password>ewogICJ0eXBlIjogInNlcnZpY2VfYWNjb3VudCIsCiAgInByb2plY3RfaWQiOiAiY2FsbS1wcmVtaXNlLTE2ODQyMCIsCiAgInByaXZhdGVfa2V5X2lkIjogIjQ4NTYxY2MxYzViODdhMDgwZmYwODgwOTQ0ZDcwMTEzNmZmMDY1MTIiLAogICJwcml2YXRlX2tleSI6ICItLS0tLUJFR0lOIFBSSVZBVEUgS0VZLS0tLS1cbk1JSUV2QUlCQURBTkJna3Foa2lHOXcwQkFRRUZBQVNDQktZd2dnU2lBZ0VBQW9JQkFRRFV4OWJjaE9lYVJISzBcbmcxcVNXaXdWeVZ1dDVRdkpHaUhjdTdYUW1rdGxpbjVLVmx3VkpaYUptVU1sQVpaNnZsZTVMTDBWMmh1TlhFdFJcbmlvZTVZWWFYRVhjRU5vek16dGNsbWVUcHBmdFJEWjZMUWF2b2Q0cWtxUS9nQVlTNXVHY3Y0SmNQZWFYNG91ZHJcbjNTZ1g3Ymdhd2hyZHoyYnRUdDJvVFdzMXc4K2lBc1ErRUQreUpqSFFBdVRQMnNVUjV4Ty95WGxVV1lnaEJyQ1RcbnJ5VVVFZnpQbnJLSTdoUUZsclMrMXo4WGxZb0kza2Npc1JkcVN0RGhlY1dVV2lqd2pBTkxrQklOWlZKV3kwTzBcbmF5L1RhME1ReFR0dU9WU1J2ZnZRV2VYMWhFVCtIOGZiTE5KWXNXNUhsTEx0eE1vem5WWHlxb05MNUhGY0R2emhcblZaWW1RMStmQWdNQkFBRUNnZ0VBRHpSVWN4K0FHVExvNjJNemRwL0E1TEdsdm5CT2ZrbEN3QzRkbU5GZHI5ek1cbmwyMUNXVFI5WkVteVZaT2VlQmpmMWRpUGpsOHVkdFJ3Z1Z3ZnhLeG1YS2NmMVFvODEybTBUL2lHTmZmcFZHcGZcbnVOMnhkZ1FNd1NWZmdBYzd2N1dna2ZnL2N4aWpObmdWaDB5ZlQ4NXB5R2UwV2NNM1BKL1ZFUEN2UjRFOWRmc1JcblE1OVUxVW1LQkNyVmRPZjIxb0kvdXZjMk1wVTZ6UmZyeDJJVytmNkhvaDVjanFZTUdqTjRjT3JtN1hXVDFmMXBcblhRdFpOUURsWFVpOGJ5NkRjYklYUWxaSlN3L1ZvdmdCL0pSTjgyWU5uVHhiSmpubkx1SS9FQUc1bHNpZmpRMlFcbkF6Y2x3ak84Q2dnREluaEhqemRqOFZzZVZCT2dIeUI3SXJaUHI3d253UUtCZ1FEdTM0b1JPTnRldjZObDhOcjFcbmtVT3dmNkRLSiswektkWDdKN2tuTnIrYXdyTXFjd3ZUcE9GYWZCOFg4Z0F3THNKa2hXdUw1aFZtS2tvL0szdzRcbldtcGF2Vm9JSWJPakZ3bkJuQXVsYkhlcC9lSXdLQlExQksxTzhyc3BDL1YwelpqVDFBMHJjVzJGTkRYbWE4TnJcbnRERnN1bHhka3B6cnduYy80bENBdGppd1lRS0JnUURrQ1dCOTdJL256R0NBQ0lXemZOeU9HTTErSmtiNVlmZkFcbi9vYnlHMWIreSt3MGpqbVEvd3RBaStYcXFxckRpMjVwU1RZZGtISzdWbm53eXphdXorSk5uM1Ntdk9TbVMydE5cbmVYK1p1WTBuVEdXZW53ZGMxOU1SMzlGOWF1SzArOUszYW1OVVpNQkRFWUpFbFEraW80N3hid1c3ZjFZTldVWFZcbm85QVhQVFlQL3dLQmdGTnBvY2ZUeDk2MUlyVEZQMkNEQWxVT3JESUxjU3Z0anZndDdkekFwSFhCU1Zrb1pWZlpcbmVvdmpUZVJKc0VFakF1U2hKbVhxeVV3c3RsS0t0OHpoM2NPajNWMTdqMFFERm5nU0tvcndiblRnMyt3YkFydGtcbno3UUMxTkpIaDhYcXlWUW05eFpWZkg0SU5rNHBFVXQ1MTh4MDR5NFZ0VkFxVHdQeTNsT2p6ZlhoQW9HQWVjRkhcbjgvUkxJY2pOL1k2UFZMWm1UTGlSZjdtUVM3Y3pRYWlsQkwvMFF6YytkeEU1UzJIaDhDVENMZm5TRTNadkRXZzVcbnJLOWprd01wT0poSUtpNTA5bDBkTzZtL3E4cTVFRFMvSEtVbDZNV3h2Ry9NenBXdDdPMUVQV0xFaVQycjFLTEpcblJsWkZFWXBYczZhaklvT1IzdmNZYUhRa3podk1YYldKZGQ4STdxRUNnWUFQTW0xVFRmQVR5NmJ3RXVaUnhYVktcbjRkU2NteTF3VVo1bGNobGgxNTd4bUNML1A0UDR6VGRtVThkUkhpenVydjFtUk5HaGRTOTJZckxyS2c4ZDJDVS9cbnAwZi8vU296UlltWVk2MDZYSUZ0S3BzbVdHdmg1ZmpRNnB4YjZmdlJDMHArMmdaV0V0YWowWVIwaDVLVGNVR2FcbnJxU2FzbzQxaXZ3UXptVHpNcnRaeUE9PVxuLS0tLS1FTkQgUFJJVkFURSBLRVktLS0tLVxuIiwKICAiY2xpZW50X2VtYWlsIjogInNhLWV2Zy1hcnRpZmFjdC1yZWdpc3RyeS1yZEBjYWxtLXByZW1pc2UtMTY4NDIwLmlhbS5nc2VydmljZWFjY291bnQuY29tIiwKICAiY2xpZW50X2lkIjogIjExNzg0NzcwMDQ2MDQ4ODI0NTg1OCIsCiAgImF1dGhfdXJpIjogImh0dHBzOi8vYWNjb3VudHMuZ29vZ2xlLmNvbS9vL29hdXRoMi9hdXRoIiwKICAidG9rZW5fdXJpIjogImh0dHBzOi8vb2F1dGgyLmdvb2dsZWFwaXMuY29tL3Rva2VuIiwKICAiYXV0aF9wcm92aWRlcl94NTA5X2NlcnRfdXJsIjogImh0dHBzOi8vd3d3Lmdvb2dsZWFwaXMuY29tL29hdXRoMi92MS9jZXJ0cyIsCiAgImNsaWVudF94NTA5X2NlcnRfdXJsIjogImh0dHBzOi8vd3d3Lmdvb2dsZWFwaXMuY29tL3JvYm90L3YxL21ldGFkYXRhL3g1MDkvc2EtZXZnLWFydGlmYWN0LXJlZ2lzdHJ5LXJkJTQwY2FsbS1wcmVtaXNlLTE2ODQyMC5pYW0uZ3NlcnZpY2VhY2NvdW50LmNvbSIKfQ==</password>
</server>
</servers>
<profiles>
<profile>
<id>artifact-eva</id>
<repositories>
<repository>
<id>artifact-registry-evg</id>
<url>https://us-east1-maven.pkg.dev/calm-premise-168420/eva-evg</url>
<releases>
<enabled>true</enabled>
</releases>
<snapshots>
<enabled>true</enabled>
</snapshots>
</repository>
<repository>
<id>repo1</id>
<url>https://repo1.maven.org/maven2/</url>
<releases>
<enabled>true</enabled>
</releases>
<snapshots>
<enabled>true</enabled>
</snapshots>
</repository>
<repository>
<id>Sonatype Repository</id>
<url>https://oss.sonatype.org/content/repositories/releases/</url>
<releases>
<enabled>true</enabled>
</releases>
<snapshots>
<enabled>true</enabled>
</snapshots>
</repository>
<repository>
<id>Spring Plugins Repository</id>
<url>https://repo.spring.io/plugins-release/</url>
<releases>
<enabled>true</enabled>
</releases>
<snapshots>
<enabled>true</enabled>
</snapshots>
</repository>
<repository>
<id>Spring Lib M Repository</id>
<url>https://repo.spring.io/libs-milestone/</url>
<releases>
<enabled>true</enabled>
</releases>
<snapshots>
<enabled>true</enabled>
</snapshots>
</repository>
<repository>
<id>Hortonworks Repository</id>
<url>https://repo.hortonworks.com/content/repositories/releases/</url>
<releases>
<enabled>true</enabled>
</releases>
<snapshots>
<enabled>true</enabled>
</snapshots>
</repository>
<repository>
<id>Atlassian Repository</id>
<url>https://maven.atlassian.com/content/repositories/atlassian-public/</url>
<releases>
<enabled>true</enabled>
</releases>
<snapshots>
<enabled>true</enabled>
</snapshots>
</repository>
<repository>
<id>JCenter</id>
<url>https://jcenter.bintray.com/</url>
<releases>
<enabled>true</enabled>
</releases>
<snapshots>
<enabled>true</enabled>
</snapshots>
</repository>
<repository>
<id>JBossEA Repository</id>
<url>https://repository.jboss.org/nexus/content/repositories/ea/</url>
<releases>
<enabled>true</enabled>
</releases>
<snapshots>
<enabled>true</enabled>
</snapshots>
</repository>
<repository>
<id>Spring Lib Release Repository</id>
<url>https://repo.spring.io/libs-release/</url>
<releases>
<enabled>true</enabled>
</releases>
<snapshots>
<enabled>true</enabled>
</snapshots>
</repository>
<repository>
<id>Apache Releases Repository</id>
<url>https://repository.apache.org/content/repositories/releases/</url>
<releases>
<enabled>true</enabled>
</releases>
<snapshots>
<enabled>true</enabled>
</snapshots>
</repository>
</repositories>
<pluginRepositories>
<pluginRepository>
<id>repo1</id>
<name>repo1</name>
<url>https://repo1.maven.org/maven2/</url>
<snapshots>
<enabled>true</enabled>
</snapshots>
</pluginRepository>
<pluginRepository>
<id>spring-snapshots</id>
<name>Spring Snapshots</name>
<url>https://repo.spring.io/snapshot</url>
<snapshots>
<enabled>true</enabled>
</snapshots>
</pluginRepository>
</pluginRepositories>
</profile>
</profiles>
<activeProfiles>
<activeProfile>artifact-eva</activeProfile>
</activeProfiles>
</settings>
How to Include Evg Connector
To include the evg-connector in your project, use the @EnableEvgConnector
annotation in your project's main class
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import com.everis.eva.evgconnector.annotation.EnableEvgConnector;
@EnableEvgConnector
@SpringBootApplication
public class EvgDemoApplication {
public static void main(String[] args) {
SpringApplication.run(EvgDemoApplication.class, args);
}
}
Quickstart
To give an example of the connector's usage, we will create a class called DemoService and have it extend the EvgConnectorBase class.
The ConversationRequest object is used when calling the eva. What parameters to pass and what will be sent to the eva will be further detailed down this article.
In this example we are making a call to eva in order to execute a Welcome Flow. To know how to configure the eva call see the documentation Conversation API and for more about the authentication of the Conversation API see item Client Credentials Authorization.
This results in the execution of a flow, getting the response from the eva, and generating commands in the IVR based on the eva's response.
import java.util.List;
import org.springframework.http.HttpHeaders;
import org.springframework.stereotype.Service;
import com.everis.eva.evgconnector.properties.EvgSettings;
import com.everis.eva.evgconnector.properties.conversation.ConversationAuthProperties;
import com.everis.eva.evgconnector.properties.provider.MicrosoftProvider;
import com.everis.eva.evgconnector.service.EvgConnectorBase;
import com.everis.eva.evgconnector.service.commands.EvgCommand;
import com.everis.eva.evgconnector.service.conversation.ConversationRequest;
import com.everis.eva.evgconnector.service.conversation.ConversationResponse;
import com.everis.eva.evgconnector.service.evg.Evg;
@Service
public class DemoService extends EvgConnectorBase {
private final EvgSettings evgSettings;
public DemoService(EvgSettings evgSettings) {
this.evgSettings = evgSettings;
}
@Override
public Evg start(Evg evg) {
String evaConversationAPIURL = "https://api-<your_eva_instance_label>.eva.bot/eva-broker/org/<your_org_uuid>/env/<your_env_uuid>/bot/<your_bot_uuid>/channel/<your_channel_uuid>/v1/conversations";
ConversationRequest conversationRequest = createConversationRequest(evg);
conversationRequest.getContext().put("dnis", evg.getTelcoData().getDnis());
HttpHeaders headers = new HttpHeaders();
headers.add("LOCALE", "<your_bot_locale>");
headers.add("OS", "evg");
headers.add("API-KEY", "<your_api_key>");
headers.add("USER-REF", evg.getTelcoData().getAni());
headers.add("BUSINESS-KEY", evg.getTelcoData().getAni());
ConversationAuthProperties conversationAuthProperties = ConversationAuthProperties.builder()
.keycloakUrl(
"https://keycloak-<your_eva_admin_label>.eva.bot/auth/realms/<your_realm_name>/protocol/openid-connect/token")
.clientId("<your_client_id>")
.secret("<your_secret>")
.build();
ConversationResponse conversationResponse = callEva(evg, evaConversationAPIURL,
conversationRequest,
headers, conversationAuthProperties);
MicrosoftProvider microsoftProvider = MicrosoftProvider.builder()
.region("<your_region>")
.subscriptionKey("<your_subscription_key>")
.language("<your_bot_locale>")
.build();
evgSettings.setMicrosoftProvider(microsoftProvider);
List<EvgCommand> commands = createCommands(evg, conversationResponse);
return createResponse(evg, commands, evgSettings.getFetch());
}
}
Testing the Connector
The evg (IVR) to process a call will consume the endpoint that the evg connector provides.
The following is a simple example of a request.
Sample JSON
{
"evgCallStatus": "INIT",
"telcoData": {
"ani": "<your_ani>",
"dnis": "<your_dnis>",
"sipCallId": "sip-call-id",
"originIp": "ip-example",
"customerSipDomain": "@exemple.com.br"
},
"context": {
}
}
Conversation service
Below is the endpoint documentation for the API request mentioned on the previous section:
URL
/conversations
Type
application/json
Request body and Response body
context
JSON Object
Yes
Helper object that can be used to keep the state of the call, in it we can store data that will be kept during the call, for example, the sessionCode of the eva.
commandList
Yes, unless when evgCallStatus is INIT
A list of commands that will be executed in IVR.
EvgCallStatus
INIT
Indicates the initial state of the call. The first request being made.
CONTINUE
Indicates a call in progress.
USER_DISCONNECTED
This status indicates that the user disconnected the call.
IVR_DISCONNECTED
This status indicates that the IVR disconnected the call.
TRANSFERRED
This status indicates that the IVR disconnected the call.
ERROR
Indicates a error state.
TelcoData
ani
String
Calling number.
dnis
String
Incoming number.
sipCallId
String
It is a unique call id generated by the SBC.
originIp
String
Call source address (SBC address).
customerSipDomain
String
It is the domain that identifies the provider.
EvgCommand
commandOrder
int
Orders the execution of commands.
commandType
It is an enumeration that represents the type of command that will be executed.
EvgCommandEnum
PLAY_AUDIO
It is a type of audio media playback, the supported types are: WAV or FLAC.
PLAY_TTS
It is the type that indicates sanitization of a text.
PLAY_SILENCE
It is the reproduction of silence.
VOICE_MENU
Enables the user to interact in the call through voice.
DTMF_MENU
Enables the user to interact in the call through the cell phone keypad.
DTMF_VOICE_MENU
Enables the user to interact in the call through voice and the cell phone keypad.
TRANSFER
Indicates that the call will be transfer.
HANGUP
Indicates that the call will be terminate.
EvgCommandResult
message
String
Contains the details of the execution.
digits
String
User input, the value is filled when the user uses the cell phone keyboard.
transcription
String
User input, the value is filled when the user speak.
EvgResultEnum
SUCCESS
Indicates a successful queuing of the audio file or a successful queuing of the TTS synthesizer request command.
ERROR
Informs that an error status occurred in the command. More details should be looked for in the error message.
FILLED
This enumeration indicates that the client's response to the menu (either voice or DTMF) successfully met the criteria configured therein. (e.g.: correct number of DTMF digits or successful transcription)
DISCONNECT
This status tells you that the customer disconnected the call while processing the call. Usually occurs during menus or transfer requests.
NO_INPUT
This enumeration indicates that the customer's response to the menu (either voice or DTMF) did not meet the criteria configured therein because he did not type any DTMF option or because he did not speak any words or phrases.
NO_MATCH
This enumeration indicates that the client's response to the menu (either voice or DTMF) did not meet the criteria set there because he did not type a valid DTMF length (but did type some DTMF) or because he did not speak any words or phrases that could be transcribed (But noise was detected).
Fetch
fetchTimeout
Long
The default amount of time in milliseconds the IVR will wait for a page/json fetch.
fetchAudio
String
The path to the default audio file to be used during IVR platform fetch events.
fetchAudioDelay
Long
The default value for the fetch audio delay. This is the amount of time in milliseconds the IVR will wait while transitioning and fetching resources before it starts playing the fetch audio.
fetchAudioMinimum
Long
The minimum time in milliseconds to play a fetch audio source, once started, even if the fetch result arrives in the meantime. The idea is that once the user does begin to hear a fetch audio, it should not be stopped too quickly.
fetchAudioInterval
Long
Controls the time interval between fetch audio loops. The default value is 0. A value of -1 is valid and will prevent the audio loop.
Was this helpful?