Excerpt |
---|
This example written in Python allows users to manage VoipNow accounts and fetch call statistics. Download. |
Table of Contents | ||
---|---|---|
|
...
How To Install It
In order to To be able to use the SystemAPI Python Tool, you must first check what components you need depending on your operating system and after that follow the installation steps.ensure that you have the following resources:
System Requirements for Linux
- gccGCC
- Download Python-2.6.2
- Download fpconst-0.7.2.tar.gz
- Download PyXML-0.8.4.tar.gz
- Download SOAPpy-0.12.0.tar.gz
- Download ZSI-2.1-a1.tar.gz
System Requirements for Microsoft Windows
- Download Visual Studio 2008 Express
- Download Python 2.4.4 installer
- Download fpconst-0.7.2.tar.gz
- Download PyXML-0.8.4.win32-py2.4.exe
- Download SOAPpy-0.12.0.tar.gz
- Download ZSI-2.1-a1.tar.gz
Setup
Note | |
---|---|
|
Download the tool files.
Note |
---|
During the installation procedure, you will be asked to extract some archives. The folder names and locations are not important. You simply need to run the commands shown below. |
Linux
| |
Download here. Do not hesitate to contribute in order to make this example better - we welcome Pull Requests! |
Linux
STEP 1: Install GCC and Python and download fpconst
. Then unzip the STEP 1: As soon as gcc
and Python
are installed and fpconst
is downloaded, please extract the contents of the fpconst
archive, open the extracted folder, and run the following commands:
Code Block | ||||
---|---|---|---|---|
| ||||
python setup.py build python setup.py install |
To check that make sure fpconst
has has been properly installed, type the following in in your Python command-line:
Code Block | ||
---|---|---|
| ||
import fpconst |
If you don't have re not getting any error messages, it means fpconst
is correctly installed.
STEP 2: As soon as PyXML
is downloaded, please extract the contents of the Download PyXML
, then unzip the archive, open the extracted folder, and run the following commands:
Code Block | ||||
---|---|---|---|---|
| ||||
python setup.py build python setup.py install |
To check that PyXML make sure PyXML has been properly installed, type the following in your Python command-line:
Code Block | ||
---|---|---|
| ||
import xml |
If you do 're not have getting any error messages, PyXML it means that PyXML is correctly installed.
STEP 3: As soon as SOAPpy
is downloaded, please extract the contents of Download SOAPpy
, then unzip the archive, open the extracted folder, and run the following commands:
Code Block | ||||
---|---|---|---|---|
| ||||
python setup.py build python setup.py install |
To check that SOAPpy make sure SOAPpy has been properly installed, type the following in your Python command-line:
Code Block | ||
---|---|---|
| ||
import SOAPpy |
If you do 're not have getting any error messages, SOAPpy it means SOAPpy is correctly installed.
...
If during installation you're prompted the following error
...
:
Code Block |
---|
File ".../SOAPpy/Client.py", line 46 from _future_ import nested_scopes SyntaxError: from _future_ imports must occur at the beginning of the file |
You need to open your temporary folder SOAPpy\Client.py and copy/paste the "from _future_ imports" line to be the first import.
...
The Client.py is just a temporary folder used by the SOAPpy engine, so ignore it.
Note |
---|
Please note that the same error will occur with other files as well during installation. Therefore, it is recommended that you repeat this step whenever necessary. You don't need to bother with it. |
STEP 4: As soon as ZSI
is downloaded, please extract the contents of Download ZSI
, then unzip the archive, open the extracted folder, and run the following commands:
Code Block | ||||
---|---|---|---|---|
| ||||
python setup.py build python setup.py install |
To check that ZSI make sure ZSI has been properly installed, type the following in your Python command-line:
Code Block | ||
---|---|---|
| ||
import ZSI |
If you do 're not have getting any error messages, it means ZSI
is is correctly installed.
STEP 5: You At this point, you can start writing applications for your VoipNow server using the SOAPpy
web services toolkit.
Microsoft Windows
STEP 1: As soon as Install Visual Studio 2008 Express and and Python are installed , and fpconst
is downloaded, please extract the contents of the fpconst
download fpconst
. Then unzip the fpconst archive, open the extracted folder, and run the following commands:
Code Block | ||||
---|---|---|---|---|
| ||||
python setup.py build python setup.py install |
STEP 2: As soon as PyXML
is downloaded, you need to Download PyXML
and run the installer:
Note |
---|
There are different |
STEP 3: As soon as Download SOAPpy
is downloaded, please extract the contents of , then unzip the archive, open the extracted folder, and run the following commands:
Code Block | ||||
---|---|---|---|---|
| ||||
python setup.py build python setup.py install | ||||
Warning |
If during installation you're prompted the following error
...
:
Code Block |
---|
File ".../SOAPpy/Client.py", line 46 from _future_ import nested_scopes SyntaxError: from _future_ imports must occur at the beginning of the file |
You must open your temporary folder SOAPpy\Client.py and copy/paste the "from _future_ imports" line to be the first import.
Note |
---|
Please note that the The same error will appear occur with other files as well during installation; therefore. Therefore, it is recommended that you repeat this step whenever necessary. |
STEP 4: As soon as Download ZSI
is downloaded, please extract the contents of , then unzip the archive, open the extracted folder, and run the following commands:
Code Block | ||||
---|---|---|---|---|
| ||||
python setup.py build python setup.py install |
STEP 5: You At this point, you can start writing applications for your VoipNow server VoipNow server using the SOAPpy
web services toolkit.
...
When writing applications, you may
...
be prompted the following error:
Code Block |
---|
Traceback (most recent call last):
File "pythonDemo.py", line 61, in ?
server._callWithBody(body1)
File "/usr/lib/python2.4/site-packages/SOAPpy/Client.py", line 436, in _callWithBody
return self.__call(None, body, {})
File "/usr/lib/python2.4/site-packages/SOAPpy/Client.py", line 395, in __call
p, attrs = parseSOAPRPC(r, attrs = 1)
File "/usr/lib/python2.4/site-packages/SOAPpy/Parser.py", line 1049, in parseSOAPRPC
t = _parseSOAP(xml_str, rules = rules)
File "/usr/lib/python2.4/site-packages/SOAPpy/Parser.py", line 1029, in _parseSOAP
parser.parse(inpsrc)
File "/usr/lib/python2.4/site-packages/_xmlplus/sax/expatreader.py", line 109, in parse
xmlreader.IncrementalParser.parse(self, source)
File "/usr/lib/python2.4/site-packages/_xmlplus/sax/xmlreader.py", line 123, in parse
self.feed(buffer)
File "/usr/lib/python2.4/site-packages/_xmlplus/sax/expatreader.py", line 216, in feed
self._parser.Parse(data, isFinal)
File "/usr/lib/python2.4/site-packages/_xmlplus/sax/expatreader.py", line 363, in end_element_ns
self._cont_handler.endElementNS(pair, None)
File "/usr/lib/python2.4/site-packages/SOAPpy/Parser.py", line 235, in endElementNS
kind = (self._prem[kind[:i]], kind[i + 1:])
KeyError: u'http' |
Note |
---|
If Whenever this happens to you, please make sure you download the latest patch for the |
How To Use It
Authentication
First you need to create STEP 1: Create a headerType object.
Code Block | ||||
---|---|---|---|---|
| ||||
header1 = SOAPpy.Types.headerType() |
Then you need to fill STEP 2: Fill in the user credentials. VoipNow VoipNow uses the OAuth protocol, where the user must provide his access token. The old legacy authentication and OAuth with consumer key and consumer secret are deprecated.
...
Code Block | ||||
---|---|---|---|---|
| ||||
# Authentication data ACCESS_TOKEN = sys.argv[2] # Start constructing the Header soapHeader = "CHANGEME" SOAPpy.Types.headerType() #XML template for sending the authentication data authenticationTemplate = """ <ns1:accessToken>%s</ns1:accessToken>""" # filling in the template above with our authentication data credentials = authenticationTemplate % (ACCESS_TOKEN) soapHeader.userCredentials = SOAPpy.Types.headerType(credentials) # the namespace for the user credentials soapHeader.userCredentials._ns = "http://4psa.com/HeaderData.xsd/3.0.0" soapHeader.userCredentials.userCredentials = SOAPpy.Types.untypedType(credentials) |
Examples
Add a Service Provider
Examples
Add a Service Provider
In DemoAddServiceProvider.py, you have an example on how to The following example shows how to add a new service provider. It The script also fetches the list of charging plans in order to pick a random one to use with you can choose from and use for the new service provider.
For more information on how to get the access token, please check the access management documentation. The code should look like this:
Adding Other Account Types
If you want to add other account types (organizations, users or extensions), simply tweak the previous Service Provider example using the recommendations below.
Most important, you will need the ID of a parent account. Depending on the account type you want to add, this ID can be:
- The ID of the service provider that owns the organization (when adding a new organization)
- The ID of the organization that owns the user (when adding a new user)
- The ID of the user that owns the extension (when adding a new extension)
Therefore, the list of appropriate accounts will be fetched and a random one will be chosen as the parent of the new account:
Code Block | ||
---|---|---|
| ||
# We need a parent service provider for the new organization, so we make a request to
# fetch all the service providers.
# Construct the Body
soapBody | ||
Code Block | ||
python | python | """ 4PSA VoipNow SystemAPI Client for Python Copyright (c) 2013, Rack-Soft (www.4psa.com). All rights reserved. VoipNow is a Trademark of Rack-Soft, Inc 4PSA is a Registered Trademark of Rack-Soft, Inc. All rights reserved. This script adds a service provider. """ import sys import string import random import SOAPpy from SOAPpy import SOAPProxy # To view soap request/response set SOAPpy.Config.debug = 1 SOAPpy.Config.debug = 0 # Authentication data ACCESS_TOKEN = "CHANGEME" # Start constructing the Header soapHeader = SOAPpy.Types.headerTypeuntypedType("") #XML template for sending the authentication data authenticationTemplate = """ <ns1:accessToken>%s</ns1:accessToken>""" # filling in the template above with our authentication data credentials = authenticationTemplate % (ACCESS_TOKEN) soapHeader.userCredentials = SOAPpy.Types.headerType(credentials) # the namespace for the user credentials soapHeader.userCredentials._ns = "http://4psa.com/HeaderData.xsd/3.0.0" soapHeader.userCredentials.userCredentials = SOAPpy.Types.untypedType(credentials) # We need a charging plan for the new account, so we make a request to # fetch all the charging plans and then pick a random one from the response list. # Construct the Body soapBody = SOAPpy.Types.untypedType("") soapBody._name = "ns2:GetChargingPlans" # Set namespaces soapBody._setAttr("xmlns:ns2", "http://4psa.com/BillingMessages.xsd/3.0.0") # Set endpoint endpoint = "https://voipnow2demo.4psa.com/soap2/billing_agent.php" # Set soapaction soapaction = "http://4psa.com/Billing/3.0.0:getChargingPlansIn" # Set service connection server = SOAPProxy(endpoint, noroot = 1, soapaction = soapaction, header = soapHeader) #run our soap request try: chargingPlans = server._callWithBody(soapBody) except SOAPpy.Types.faultType, error: # Catch exception, for situations when the charging plans could not be fetched print "Error " + error[0] + ": " + error[1] sys.exit(1) # Get the id of a random charging plan chargingPlanID = None if len(chargingPlans) != 0: randChargingPlan = chargingPlans[random.randint(0, len(chargingPlans) - 1)] if hasattr(randChargingPlan, 'ID'): chargingPlanID = randChargingPlan.ID if hasattr(randChargingPlan, 'name'): print "Using charging plan " + randChargingPlan.name + "." else: print "Using charging plan with id " + chargingPlanID + "." #XML template for sending the new service provider data bodyTemplate = """ <ns3:name>%s</ns3:name> <ns3:login>%s</ns3:login> <ns3:password>%s</ns3:password> <ns3:country>%s</ns3:country>""" if chargingPlanID != None: bodyTemplate += """ <ns3:chargingPlanID>%s</ns3:chargingPlanID>""" # Service Provider data name = "SPPython" + str(random.randint(1, 1000)) login = "SPPython" + str(random.randint(1, 1000)) password = ''.join(random.choice(string.ascii_uppercase + string.digits) for x in range(10)) country = "us" # Filling in the template above with the service provider data if chargingPlanID != None: body = bodyTemplate % (name, login, password, country, chargingPlanID) else: body = bodyTemplate % (name, login, password, country) soapBody = SOAPpy.Types.untypedType(body) soapBody._name = "ns2:AddServiceProvider" # Set namespaces soapBody._setAttr("xmlns:ns2", "http://4psa.com/ServiceProviderMessages.xsd/3.0.0") soapBody._setAttr("xmlns:ns3", "http://4psa.com/ServiceProviderData.xsd/3.0.0") # Set endpoint endpoint = "https://voipnow2demo.4psa.com/soap2/sp_agent.php" # Set soapaction soapaction = "http://4psa.com/ServiceProvider/3.0.0:addServiceProviderIn" # Set service connection server = SOAPProxy(endpoint, noroot = 1, soapaction = soapaction, header = soapHeader) #run our soap request try: server._callWithBody(soapBody) print "Service provider created successfully." except SOAPpy.Types.faultType, error: # Catch exception, for situations when the service provider could not be added print "Error " + error[0] + ": " + error[1] |
Adding Other Account Types
Tip |
---|
These examples can be found in the package downloaded with the SystemAPI Python Tool. |
If you wish to add other account types (organizations, users or extensions), there is not much to change from the program listed above. First of all, you will also need the id of a parent account. This stands for the ID of the service provider that owns the organization (when adding a new organization) or the ID of the organization that owns the user (when adding a new user) or the ID of the user that owns the extension (when adding a new extension). Therefore, the list of appropriate accounts will be fetched and a random one will be chosen as the parent for the new account:
Code Block | ||
---|---|---|
| ||
# We need a parent service provider for the new organization, so we make a request to
# fetch all the service providers.
# Construct the Body
soapBody = SOAPpy.Types.untypedType("")
soapBody._name = "ns2:GetServiceProviders"
# Set namespaces
soapBody._setAttr("xmlns:ns2", "http://4psa.com/ServiceProviderMessages.xsd/3.0.0")
# Set endpoint
endpoint = "https://voipnow2demo.4psa.com/soap2/sp_agent.php"
# Set soapaction
soapaction = "http://4psa.com/ServiceProvider/3.0.0:getServiceProvidersIn"
# Set service connection
server = SOAPProxy(endpoint, noroot = 1, soapaction = soapaction, header = soapHeader)
#run our soap request
try:
serviceProviders = server._callWithBody(soapBody)
except SOAPpy.Types.faultType, error:
# Catch exception, for situations when the service providers could not be fetched
print "Error " + error[0] + ": " + error[1]
sys.exit(1)
# Get the id of a random service provider
serviceProviderID = None
if len(serviceProviders) != 0:
randServiceProvider = serviceProviders[random.randint(0, len(serviceProviders) - 1)]
if hasattr(randServiceProvider, 'ID'):
serviceProviderID = randServiceProvider.ID
if hasattr(randServiceProvider, 'name'):
print "Using parent service provider " + randServiceProvider.name + "."
else:
print "Using parent service provider with id " + serviceProviderID + "."
if serviceProviderID == None:
print "No service providers found on the server. Can not add an organization."
sys.exit(1) |
You will also need to make adjustments to the parameters of the new request, in order to match the new account type:
Code Block | ||
---|---|---|
| ||
# Organization data
name = "OrgPython" + str(random.randint(1, 1000))
login = "OrgPythong" + str(random.randint(1, 1000))
password = ''.join(random.choice(string.ascii_uppercase + string.digits) for x in range(10))
country = "us"
parentID = serviceProviderID
# Filling in the template above with the organization data
if chargingPlanID != None:
body = bodyTemplate % (name, login, password, country, parentID, chargingPlanID)
else:
body = bodyTemplate % (name, login, password, country, parentID)
soapBody = SOAPpy.Types.untypedType(body)
soapBody._name = "ns2:AddOrganization"
# Set namespaces
soapBody._setAttr("xmlns:ns2", "http://4psa.com/OrganizationMessages.xsd/3.0.0")
soapBody._setAttr("xmlns:ns3", "http://4psa.com/OrganizationData.xsd/3.0.0")
# Set endpoint
endpoint = "https://voipnow2demo.4psa.com/soap2/organization_agent.php"
# Set soapaction
soapaction = "http://4psa.com/Organization/3.0.0:addOrganizationIn" |
Adding an user or an extension is very similar. You only need to adjust the namespaces, endpoint and soapaction variables. Also, for extension accounts, you should use the label field instead of name and login.
CallCosts
The DEMO version also provides a CallCosts request. Here is the code:
...
language | python |
---|
...
soapBody._name = "ns2:GetServiceProviders"
# Set namespaces
soapBody._setAttr("xmlns:ns2", "http://4psa.com/ServiceProviderMessages.xsd/" + version)
# Set endpoint
endpoint = "https://" + str(sys.argv[1]) + "/soap2/sp_agent.php"
# Set soapaction
soapaction = "http://4psa.com/ServiceProvider/" + version + ":getServiceProvidersIn"
# Set service connection
server = SOAPProxy(endpoint, noroot = 1, soapaction = soapaction, header = soapHeader)
#run our soap request
try:
serviceProviders = server._callWithBody(soapBody)
except SOAPpy.Types.faultType, error:
# Catch exception, for situations when the service providers could not be fetched
print "Error " + error[0] + ": " + error[1]
sys.exit(1)
# Get the id of a random service provider
serviceProviderID = None
if len(serviceProviders) != 0:
randServiceProvider = serviceProviders[random.randint(0, len(serviceProviders) - 1)]
if hasattr(randServiceProvider, 'ID'):
serviceProviderID = randServiceProvider.ID
if hasattr(randServiceProvider, 'name'):
print "Using parent service provider " + randServiceProvider.name + "."
else:
print "Using parent service provider with id " + serviceProviderID + "."
if serviceProviderID == None:
print "No service providers found on the server. Can not add an organization."
sys.exit(1) |
You will also need to make adjustments to the parameters of the new request so that they match the new type of account:
Code Block | ||
---|---|---|
| ||
# Organization data
name = "OrgPython" + str(random.randint(1, 1000))
login = "OrgPython" + str(random.randint(1, 1000))
firstname = "FirstnamePython" + str(random.randint(1, 1000))
lastname = "LastnamePython" + str(random.randint(1, 1000))
email = "Email" + str(random.randint(1, 1000)) + "@example.com"
password = ''.join(random.choice(string.ascii_uppercase + string.digits) for x in range(10))
country = "us"
parentID = serviceProviderID
company = "test_company"
# Filling in the template above with the organization data
if chargingPlanID != None:
body = bodyTemplate % (name, login, firstname, lastname, email, password, country, parentID, company, chargingPlanID)
else:
body = bodyTemplate % (name, login, firstname, lastname, email, password, country, parentID, company)
soapBody = SOAPpy.Types.untypedType(body)
soapBody._name = "ns2:AddOrganization"
# Set namespaces
soapBody._setAttr("xmlns:ns2", "http://4psa.com/OrganizationMessages.xsd/" + version)
soapBody._setAttr("xmlns:ns3", "http://4psa.com/OrganizationData.xsd/" + version)
# Set endpoint
endpoint = "https://" + str(sys.argv[1]) + "/soap2/organization_agent.php"
# Set soapaction
soapaction = "http://4psa.com/Organization/" + version + ":addOrganizationIn" |
Adding a user or an extension is very similar. You only need to adjust the namespaces, endpoint, and soapaction variables. Also, for extension accounts, you should use the label field.
CallCosts
The DEMO version also provides a CallCosts request. Here is the code.
...
Except where otherwise noted, content in this space is licensed under a Creative Commons Attribution 4.0 International.