Broadworks

Broadworks XSI-Event webhooks

/

I started looking into webhooks for xsi-events updates. With Django, building a very basic hook took only a short amount of time!

First off, why would you use xsi-events? Xsi-events are used for notifcations of real-time events. This will allow you to monitor things like calls in queue, users on DND, and anything else found in the Receptionist or Call Center thin clients.

XSP servers have a test page built into them. You can find the URL in the XSI-events user guide from http://developers.broadsoft.com.

You can use the test page to trigger a subscription to an event. You can send the data as JSON or XML. You can also build something very easily with curl :


curl -u 'user@domain.net:password' -H "Content-Type: text/xml" -d @test.xml -X POST https://xsp.local/com.broadsoft.xsi-events/v2.0/enterprise/TEST/group/TEST-GROUP -v

 

This will require an Enterprise administrator credentials in the curl request.

Once you trigger this, the XSP will respond with POST request to the uri found in the XML file.

Now you need a way to handle this.

In your view.py file, you can build a very simple handler. Notice the csrf_exempt decorator. As the POST request will not send a csrf token, you will need a method to by pass this.

from django.core.context_processors import csrf
import callcenter.tools as ct

@csrf_exempt
def xsiEvents(request):
        if request.method == 'POST':
                data = ct.xml_xsi_ccqueue(request.body)
                return HttpResponse()
        if request.method  == 'GET' :
                return HttpResponse()

As you can see, when the request method is POST, Django will call another method for processing. I built a model where all updates matching certain criteria are stored. Yeah.. this could be better, however this is all in dev mode right now.

class callcenter_queue(models.Model):
        userId = models.CharField(max_length=100)
        externalApplicationId  = models.CharField(max_length=100)
        httpContact = models.URLField(max_length=100)
        targetId = models.CharField(max_length=100)
        eventData = models.CharField(max_length=100)
        callhalf = models.CharField(max_length=100)
        extTrackingId = models.CharField(max_length=100)
        addTime = models.CharField(max_length=50)
        acdName = models.CharField(max_length=100)

In the handler, I first parse the XSML. I turn turn various tags, text and attributes into dictionary keys and values.

I then update or delete the table (model) if the ‘eventData’ key matches certain criteria.

import xml.etree.ElementTree as ET
def xml_xsi_ccqueue(data):
        root = ET.fromstring(data)
        response = {}
        for child in root:
                if child.tag == '{http://schema.broadsoft.com/xsi}eventData' :
                        response[child.tag.replace('{http://schema.broadsoft.com/xsi}', '') ] = str(child.attrib)
                else:
                        response[child.tag.replace('{http://schema.broadsoft.com/xsi}', '') ] = child.text
                for sub in child:
                        response[sub.tag.replace('{http://schema.broadsoft.com/xsi}', '') ] = sub.text
                        for meta in sub:
                                response[meta.tag.replace('{http://schema.broadsoft.com/xsi}', '') ] = meta.text

        # Query for a extTrackingID that mathces the xsi-event POST
        if response['eventData'] == '{'{http://www.w3.org/2001/XMLSchema-instance}type': 'xsi:ACDCallAddedEvent'}':
               f.write('found eventData')
               xsi_update = callcenter_queue(
                        userId =  response['userId'],
                        externalApplicationId =  response['externalApplicationId'],
                        httpContact=  response['uri'],
                        targetId =  response['targetId'],
                        eventData =  response['eventData'],
                        callhalf =  response['callId'],
                        extTrackingId =  response['extTrackingId'],
                        addTime =  response['addTime'],
                        acdName =  response['acdName']
               )
               xsi_update.save()
               return response
        #if the call is answered, delete the event from the database
        if  'ACDCallAnsweredByAgentEvent' in response['eventData'] :
                try :
                        f.write('read to remove')
                        f.write( str(response['extTrackingId']))
                        xsi_update  = callcenter_queue.objects.get(extTrackingId = response['extTrackingId'] )
                        xsi_update.delete()
                except:
                        pass

        #if the caller bails out remove the call from queue
        if  'ACDCallAbandonedEvent' in response['eventData'] :
                try :
                        xsi_update  = callcenter_queue.objects.get(extTrackingId = response['extTrackingId'] )
                        xsi_update.delete()
                except:
                        pass

Now this is a very basic example of building a webhook for xsi-events. There’s a lot of code that I can clean up here, however it does function in a lab/dev environment.

 

 

=========

UPDATE 10/21/2014

=========

Here is a sample of the XML I use for this call:

<?xml version=”1.0″ encoding=”UTF-8″? >
<Subscription xmlns=”http://schema.broadsoft.com/xsi”  >
<targetIdType>https://xsp.local/com.broadsoft.xsi-events/v2.0/enterprise/$ENTERPRISE_NAME/group/$GROUP_NAME</targetIdType >
<event>Call Center Monitoring</event >
<expires>86400</expires>
<httpContact>
<uri>http://myserver.local/webhooks</uri >
</httpContact>
<applicationId>CUSTOM_APP_1.0</applicationId >
</Subscription>