How to connect to AES WTI Websocket API's

Collapse
X
 
  • Filter
  • Time
  • Show
Clear All
new posts
  • jain225
    Aspiring Member
    .
    • Apr 2021
    • 2

    How to connect to AES WTI Websocket API's

    I'm new to AES Websocket API's. And i'm try to connect to websocket API on wss://<AE Server IP>:443/api/wti/session but i'm not able to connect to the websocket. Not sure if i'm doing something wrong. I have already included SMGR CA as Trusted Root Certificates in my Browser. Do we have any sample clients plus any example requests documentation.

    Even with the RestAPI the API's dont execute itself, i keep getting BAD request. I have gone through the Tips for working with WTI, the DMCC forms request in a separate way while the WTI API's show the request in different way.

    Any sample request documentation would help. We are trying to build a softphone for Call Center Elite.
  • flynn1
    Brainiac
    .
    • Jun 2011
    • 82

    #2
    A few points to make here:

    1. If you are trying to use WTI to implement a softphone, just bear in mind that the media will still be transported as RTP to/from an IP address & port. So, you will still have some of the same limitations as DMCC - i.e. the softphone will have to be routable from the Media Server/Gateway. The only difference is that the signaling will be transported via http(s) instead of a socket.

    2. I am able to use the Websocket and REST APIs unencrypted which makes debugging easier. However, it is possible that I had to do some hacking that I've forgotten about.

    3. When trying to debug problems, your first port of call should be telrestsvc.log on AES.

    4. Make sure there are no firewalls interfering with your progress.

    5. There are a few 'quirks' with the current version of the Websocket API which should be sorted out in the next release. One of them is that AES expects the header to be the first field in each request. If you are using a standard library to generate the body of the request, there is no guarantee of this. For now, you may need to do something like the following Java sample:

    JSONObject header = new JSONObject();
    JSONObject payload = new JSONObject();
    <Fill in Header & payload>
    String bodyText = "{"header":" + header.toString(4) + ",\n"payload":" + payload.toString(4) + "}";
    <Send bodyTest to AES via websocket>


    As an example, here is the body for a Start Application session request

    {"header":{
    "invokeId": 1,
    "request": "StartApplicationSession",
    "headerType": "request",
    "version": "v2"
    },
    "payload":{
    "SessionDuration": "180",
    "ProtocolVersionList": [
    "10.2.0",
    "10.1.0"
    ],
    "ApplicationID": "TestTool Proxy"
    }}


    The header must include a Basic Authorization with the CTI User & password:

    String auth = user + ":" + "password";
    String auth64= Base64.getEncoder().encodeToString(auth.getBytes() );
    cc.setHeader("Authorization", "Basic " + auth64);


    The response will include an Access Token and subsequent requests must use this in the header:

    cc.setHeader("Authorization", "Bearer " + AccessToken);

    Comment

    • jain225
      Aspiring Member
      .
      • Apr 2021
      • 2

      #3
      Thanks flynn1 let me try that and let you know how it goes, in the meantime while using the REST API's we realised that Bearer token expires and there is no API to just refresh the bearer token, we need to create an ApplicationSession to get the bearer token. Not sure how it will impact the existing calls on the front end and do we have to again place a monitor request for all the events. Is there a better way to manage the Bearer token? Or am i missing anything.

      Comment

      • flynn1
        Brainiac
        .
        • Jun 2011
        • 82

        #4
        In order to keep a session active for more than a few minutes, the application must call /api/fe/v1/ResetApplicationSessionTimer periodically. For more information, see the "Reset Application Session Timer" section of one of the DMCC Programmers Guides.

        There is information in https://support.avaya.com/forums/for...rking-with-wti on how to get these documents.

        Martin

        Comment

        • gdevaraju
          Member
          .
          • Jun 2022
          • 3

          #5
          Hi Team,

          Any sample/reference client available for to establish the websocket session, through postman/our sample code when we try the AES log say's " FINER - Authorization Header starts with Bearer."

          It's really unclear on how to pass the Basic authorization headers for the webscoket.

          Comment

          • flynn1
            Brainiac
            .
            • Jun 2011
            • 82

            #6
            I haven't used websockets before so hopefully the following will be helpful:

            1. You must first create a websocket connection to AES and put the Basic Auth into the header.
            For example, using a client based on the Java library org.java_websocket.client.WebSocketClient, would be something like:

            Code:
            WebSocketClient cc = null;
            private void connect(String user, String password, String webSocketAddress) {
                try {
                    String authStr = user + ":" + "password";
                    String auth = Base64.getEncoder().encodeToString(auth.getBytes() );
                    cc = new WebSocketClient(new URI(webSocketAddress)) {
            
                    @Override
                     public void onMessage(String message) {
                        System.out.println("got: " + message + "\n");
                        handleIncomingWTIMessage(String message)
                     }
            
                    @Override
                    public void onOpen(ServerHandshake handshake) {
                        System.out.println("You are connected to ChatServer: " + getURI() + "\n");
                    }
            
                   @Override
                   public void onClose(int code, String reason, boolean remote) {
                       System.out.println("You have been disconnected from: " + getURI() + "; Code: " + code + " " + reason + "\n");
                    }
            
                    @Override
                    public void onError(Exception ex) {
                        System.out.println("Exception occurred ...\n" + ex + "\n");
                        ex.printStackTrace();
                    }
                };
                setHeader("Authorization", "Basic " + auth);
                cc.connect();
            
                } catch (URISyntaxException ex) {
                    System.out.println(webSocketAddress + " is not a valid WebSocket URI\n");
                }
            }
            You can then send data using
            Code:
            cc.send(String message);
            2. Then start a session like:
            Code:
            private void startSession(String user, String password) {
                try {
                    // Find out the user & password
                    System.out.println("Starting session for:" + user +":"+ password);
            
                    String auth = user + ":" + "password";
                    String auth64= Base64.getEncoder().encodeToString(auth.getBytes() );
            
                    JSONObject header = new JSONObject();
                    JSONObject payload = new JSONObject();
                    payload.put("ApplicationID", "TestTool Proxy");
                    payload.append("ProtocolVersionList", "10.2.0");
                    payload.append("ProtocolVersionList", "10.1.0");
                    payload.put("SessionDuration", "180");
                    header.put("headerType", "request");
                    header.put("request", "StartApplicationSession");
                    header.put("invokeId", 1);
                    header.put("version", "v2");
                    String bodyText = "{\"header\":" + header.toString(4) + ",\n\"payload\":" + payload.toString(4) + "}";
                    System.out.println(bodyText);
            
                    cc.setHeader("Authorization", "Basic " + auth64);
                    cc.send(bodyText);
            
                }
                catch(Exception e)
                {
                    e.printStackTrace();
                }
            }
            Note: Currently, AES requires the header section of the data to be before the payload section - that's why the above is more clunky than it should be. I have opened a bug report for this so it should be fixed in future releases.

            Also note that the Basic auth token is required both when opening the websocket and when starting the WTI session. I dunno if there is a good reason for this but I think it is required.

            3. Note that there is currently an error in how the SessionStartResponse is formatted by AES so it requires special handling. Again, this should be fixed in future.
            Code:
            // This method should be called whenever the websocket client receives an incoming message
            public void handleIncomingWTIMessage(String message)
            {
                JSONObject json = new JSONObject (message);
                System.out.println("Received: \n" + json.toString(6));
                JSONObject header = json.getJSONObject("header");
                String type = header.get("headerType").toString();
                String command = header.get(type).toString();
                // TODO payload should be a JSONObject but is incorrectly coded by AES
                String payload = json.getString("payload");
                if(command.compareTo("StartApplicationSession") == 0)
                    receivedSessionStartResponse(payload, header)
                else
                    normalMessageHandling(payload, header);
            }
            
            // Special handling for receivedSessionStartResponse because of its bad formatting and we need to collect the access token. The actualSessionDuration may be important in some implementations also but the sessionID does not seem to be required
            private void receivedSessionStartResponse(String payload, JSONObject header)
            {
                JSONObject obj = new JSONObject(payload);
                if(obj.has("token"))
                {
                    // Save access token and session ID for future use
                    AccessToken = obj.getString("token");
                    SessionID = obj.getString("sessionID");
                    int actualSessionDuration= obj.getInt("actualSessionDuration");
            
                    // Handle the Session Start Response
                }
            }
            4. When sending subsequent requests to AES, put the Access token into the header before sending the request:
            Code:
            cc.setHeader("Authorization", "Bearer " + AccessToken);
            c.send(bodyText);
            ​

            Comment

            • gdevaraju
              Member
              .
              • Jun 2022
              • 3

              #7
              thanks for your detailed steps, however what would be the beginning URL to establish the websocket session?

              Comment

              • flynn1
                Brainiac
                .
                • Jun 2011
                • 82

                #8
                ws://<AES>/api/wti/session
                or
                wss://<AES>/api/wti/session

                ws (unsecure) may be disabled on AES by default
                wss will require that you have the AES's CA cert stored in your keystore.

                Comment

                • ltenoro
                  Member
                  .
                  • Oct 2016
                  • 4

                  #9
                  flynn1 The AES version must be 4.2 to use the websocket API? When I try to connect using basic authentication, it fails, and I see in the telrestsvc.log the message "Authorization Header present, but it does not start with 'Bearer '".
                  Did you get to connect using this code?
                  Thanks!__PRESENT__PRESENT

                  Comment

                  • flynn1
                    Brainiac
                    .
                    • Jun 2011
                    • 82

                    #10
                    AES must be version 10.2 or later (I think 10.1.2 may be OK too).

                    The snippets I posted are taken from a test application that I have used many times. I did edit them a bit to make sense without the rest of the app.

                    I would suggest that you use the unsecure connection (ws) and view the WS messages using Wireshark so that you can see exactly what requests the application is sending. You may need to first enable unsecure ports (e.g. 80) using the AES web manager.

                    Martin

                    Comment

                    • ltenoro
                      Member
                      .
                      • Oct 2016
                      • 4

                      #11
                      I have enabled the unsecure port on the AES and I'm using the unsecure connection (ws) on websocket client side. The question is about the authentication header when I try to connect. Using setHeader("Authorization", "Basic " + auth); I got error 401 and ckecking AES log I see Authorization Header present, but it does not start with 'Bearer '. Did you got to connect using the "Basic" in the header?

                      Leuzinger
                      Last edited by ltenoro; 02-04-2025, 03:08 PM.

                      Comment

                      • flynn1
                        Brainiac
                        .
                        • Jun 2011
                        • 82

                        #12
                        The AES log is normal. Can you connect to the AES with the same credentials using DMCC?

                        Comment

                        • ltenoro
                          Member
                          .
                          • Oct 2016
                          • 4

                          #13
                          I got to connect after upgrade the AES to 10.2 version.
                          Thanks!

                          Comment

                          • gdevaraju
                            Member
                            .
                            • Jun 2022
                            • 3

                            #14
                            Hi Team,

                            We also able to connect now after upgrading to AES 10.2 version, now got stuck on "Monitor deviceID"



                            Step-0:connect websocket with basic credentials

                            Step-1-: Start applciationsession with basic credentials

                            Step-2: Get deviceID with Bearer details

                            Step3: monitor deviceid (Payload structure for this method unclear); tried with multiple options and taken reference from DMCC API's ; so far not helpful.

                            Feedback with sample payload would be really helpful.. Secondly any reference client to understand the sequence/payloads/documentation would be helpful. Thanks in advance!

                            Comment

                            • flynn1
                              Brainiac
                              .
                              • Jun 2011
                              • 82

                              #15
                              The request body should look something like:
                              Code:
                              {
                                  "monitorObject": {
                                      "deviceObject": "5590:CM55:0.0.0.0:0"
                                  },
                                  "requestedMonitorFilter": {
                                       . . .
                                      . . .
                                  },
                                  "targetUrl": "https://127.0.0.1/events/"
                              }

                              Comment

                              Loading