Excerpt |
---|
This example written in Ruby allows users to manage VoipNow accounts and fetch call statistics. Download. |
Note |
---|
This demonstrative code SHOULD NOT be used in production. It is designed to show how a client application interacts with the VoipNow SystemAPI. From this perspective, validations and error-checks aiming to demonstrate the most common mistakes are minimal and can be done easily. |
How To Install It
System Requirements
In order to be able to use the SystemAPI Ruby Tool, you need to comply with the requirements below:
Setup
Please follow these steps:
STEP 1: Start by downloading the example files.
STEP 2: Install gcc
for Linux.
Tip |
---|
You may skip this step for Windows, since Ruby for Windows comes with an installation package. |
gcc should come with your operating system, otherwise simply run one of the commands below, depending on your Linux distribution.
Code Block |
---|
yum install gcc |
Code Block |
---|
apt-get install gcc |
STEP 3: Install Ruby
. You should use Ruby 1.8.6
or later for Linux and Ruby 1.8.7
or later for Windows.
Note |
---|
It seems that Ruby 1.8.6 for Windows is not fully compatible with SOAP4R and throws some errors when running with our demo scripts. You may try it, but it's recommended that you use the installer specified above. In our demo, we used Ruby 1.8.6 for Linux and Ruby 1.8.7 for Windows. |
On Linux, after download, you should extract the archive to a temporary folder, go to that folder and run:
Code Block |
---|
./configure
make
make install |
On Windows, just run the installer. You should check in the options to associate .rb
files with Ruby
and add Ruby
to PATH
.
STEP 4: You need rubygems
in order to install SOAP4R
. If rubygems
was not installed with Ruby
, you can download it from here. After downloading, extract the contents of the archive to a temporary folder, go to that folder and run:
STEP 5: You need to install SOAP4R
, a Ruby
library for accessing Web Services via SOAP
. Here is the command line to install SOAP4R
:
Code Block |
---|
gem install soap4r --include-dependencies |
Note |
---|
Although latest versions of Ruby come with SOAP4R in their standard library, it is highly recommended using the latest gem. |
STEP 6: Create a directory for 4PSA VoipNow schemas on your local disk (for example, C:\schema
or /home/your_user/schema
).
STEP 7: Now you need to run the script that generates the Ruby library from the schema.
On Linux
Code Block |
---|
|
cd /home/your_user/schema
./wsdl2ruby.sh . <IP_ADDRESS |
On Windows
Code Block |
---|
|
cd C:\schema
wsdl2ruby.bat . <IP_ADDRESS>
|
Code Block |
---|
|
cd C:\schema
wsdl2ruby.bat . voipnow2demo.4psa.com |
This utility will generate four files inside the C:\schema
folder:
Code Block |
---|
|
VoipNowService.rb
VoipNowServiceMappingRegistry.rb
AccountPortClient.rb
VoipNowServiceDriver.rb
|
The main class used by your client program is VoipNowServiceDriver.rb
.
STEP 8: At this point, you can start writing your applications for your VoipNow server.
How To Use It
Authentication
Depending on what you intend to do in the application, you will need to create an object. For example, if you want to add a new service provider, you should instantiate a new object, as follows:
Code Block |
---|
|
driver = ServiceProviderInterface.new
|
You will need a custom header for the SystemAPI message, therefore you will create a new class called AuthHeader that will be customized for each authentication method. Please find it detailed below.
In order to add the new header to the recently created driver object, please write the following line of code:
Code Block |
---|
|
driver.headerhandler << AuthHeader.new
|
Here is an explanation of how to create the AuthHeader class. The OAuth protocol requires that you to provide the access token generated for your application. In short, the code should look like this:
Code Block |
---|
|
# Custom header for authentication
class AuthHeader < SOAP::Header::SimpleHandler
# the namespace for the header data
NAMESPACE = 'http://4psa.com/HeaderData.xsd/3.0.0'
# Authentication data
ACCESS_TOKEN = 'CHANGEME'
#initializes an instance of this class
def initialize()
super(XSD::QName.new(NAMESPACE, 'userCredentials'))
end
#sets the user credentials with the authentication data
def on_simple_outbound
{"userCredentials" => {"accessToken" => ACCESS_TOKEN}}
end
end |
Examples
Add a Service Provider
The following example shows how to add a new service provider. It also fetches the list of charging plans in order to pick a random one to use with the new service provider:
Code Block |
---|
|
=begin
4PSA VoipNow SystemAPI Client for Ruby
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.
=end
require 'rubygems'
require 'securerandom'
gem 'soap4r'
require 'VoIpNowServiceDriver.rb'
require 'soap/header/simplehandler'
# Custom header for authentication
class AuthHeader < SOAP::Header::SimpleHandler
# the namespace for the header data
NAMESPACE = 'http://4psa.com/HeaderData.xsd/3.0.0'
# Authentication data
ACCESS_TOKEN = 'CHANGEME'
#initializes an instance of this class
def initialize()
super(XSD::QName.new(NAMESPACE, 'userCredentials'))
end
#sets the user credentials with the authentication data
def on_simple_outbound
{"userCredentials" => {"accessToken" => ACCESS_TOKEN}}
end
end
# 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.
driver = BillingInterface.new
driver.options['protocol.http.ssl_config.verify_mode'] = OpenSSL::SSL::VERIFY_NONE
# Add custom header
driver.headerhandler << AuthHeader.new
#the GetChargingPlans message
messagePart = GetChargingPlans.new
# Log for SystemAPI request and response
driver.wiredump_file_base = "log"
#send the SystemAPI message
chargingPlans = driver.getChargingPlans(messagePart)
# Get the id of a random charging plan
chargingPlanID = nil
if chargingPlans.chargingPlan != nil
if chargingPlans.chargingPlan.length != 0
randChargingPlan = chargingPlans.chargingPlan[rand(chargingPlans.chargingPlan.length)]
if randChargingPlan.iD != nil
chargingPlanID = randChargingPlan.iD
if randChargingPlan.name != nil
puts "Using charging plan " + randChargingPlan.name + "."
else
puts "Using charging plan with id " + chargingPlanID + "."
end
end
end
end
driver = ServiceProviderInterface.new
driver.options['protocol.http.ssl_config.verify_mode'] = OpenSSL::SSL::VERIFY_NONE
# Add custom header
driver.headerhandler << AuthHeader.new
#the AddServiceProvider message
messagePart = AddServiceProvider.new
# Fill in ServiceProvider data
messagePart.name = 'SPRuby' + rand(1000).to_s
messagePart.login = 'SPRuby' + rand(1000).to_s
messagePart.password = SecureRandom.hex(16)
messagePart.country = 'us'
if chargingPlanID != nil
messagePart.chargingPlanID = chargingPlanID
end
# Log for SystemAPI request and response
driver.wiredump_file_base = "log"
#send the SystemAPI message
begin
driver.addServiceProvider(messagePart)
puts "Service provider created successfully."
rescue Exception => ex
# Catch exception, for situations when the service provider could not be added
puts "Error: " + ex.message
end |
Add Other Account Types
Tip |
---|
These examples can be found in the downloaded package. |
If you wish to add other account types (organizations, users or extensions), there are only a few changes that you need to make to the previous Service Provider example. First of all, you need to change the type of driver object from ServiceProviderInterface to OrganizationInterface or UserInterface or ExtensionInterface. It should look like this:
Code Block |
---|
|
driver = OrganizationInterface.new
|
Then, you need to adjust the message of the request. It should also contain a new parameter, the parentID, which represents either the service provider that owns the organization (when adding a new organization) or the organization that owns the user (when adding a new user) or the user that owns the extension (when adding a new extension).
The code for picking a random parent from the list of available accounts is presented below:
Code Block |
---|
|
# We need a parent service provider for the new organization, so we make a request to
# fetch all the service providers.
driver = ServiceProviderInterface.new
driver.options['protocol.http.ssl_config.verify_mode'] = OpenSSL::SSL::VERIFY_NONE
# Add custom header
driver.headerhandler << AuthHeader.new
#the getServiceProviders message
messagePart = GetServiceProviders.new
# Log for SystemAPI request and response
driver.wiredump_file_base = "log"
#send the SystemAPI message
serviceProviders = driver.getServiceProviders(messagePart)
serviceProviderID = nil
if serviceProviders.serviceProvider != nil
if serviceProviders.serviceProvider.length != 0
randServiceProvider = serviceProviders.serviceProvider[rand(serviceProviders.serviceProvider.length)]
if randServiceProvider.iD != nil
serviceProviderID = randServiceProvider.iD
if randServiceProvider.name != nil
puts "Using parent service provider " + randServiceProvider.name + "."
else
puts "Using parent service provider with id " + serviceProviderID + "."
end
end
end
end
if serviceProviderID == nil
puts "No service providers found on the server. Can not add an organization."
exit
end |
The code for the the AddOrganization request is shown below:
Code Block |
---|
|
#the AddOrganization message
messagePart = AddOrganization.new
# Fill in Organization data
messagePart.name = 'OrgRuby' + rand(1000).to_s
messagePart.login = 'OrgRuby' + rand(1000).to_s
messagePart.password = SecureRandom.hex(16)
messagePart.country = 'us'
messagePart.parentID = serviceProviderID
if chargingPlanID != nil
messagePart.chargingPlanID = chargingPlanID
end |
Finally, you need to call the proper method (the last line of the above script). Instead of:
Code Block |
---|
|
puts driver.addServiceProvider(messagePart)
|
You should have this for adding an organization:
Code Block |
---|
|
puts driver.addOrganization(messagePart)
|
Similar modifications are made for the other 2 account types (user and extension).
CallCosts
The DEMO version also provides a CallCosts request example. Here is the code:
Code Block |
---|
|
=begin
4PSA VoipNow SystemAPI Client for Ruby
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 fetches the call costs of an extension.
=end
require 'rubygems'
require 'securerandom'
gem 'soap4r'
require 'VoIpNowServiceDriver.rb'
require 'soap/header/simplehandler'
# Custom header for authentication
class AuthHeader < SOAP::Header::SimpleHandler
# the namespace for the header data
NAMESPACE = 'http://4psa.com/HeaderData.xsd/3.0.0'
# authentication data
ACCESS_TOKEN = 'CHANGEME'
#initializes an instance of this class
def initialize()
super(XSD::QName.new(NAMESPACE, 'userCredentials'))
end
#sets the user credentials with the authentication data
def on_simple_outbound
{"userCredentials" => {"accessToken" => ACCESS_TOKEN}}
end
end
# We need an extension to check its call costs, so we make a request to
# fetch all the extensions.
driver = ExtensionInterface.new
driver.options['protocol.http.ssl_config.verify_mode'] = OpenSSL::SSL::VERIFY_NONE
# Add custom header
driver.headerhandler << AuthHeader.new
#the getExtensions message
messagePart = GetExtensions.new
# Log for SystemAPI request and response
driver.wiredump_file_base = "log"
#send the SystemAPI message
extensions = driver.getExtensions(messagePart)
extensionIdentifier = nil
if extensions.extension != nil
if extensions.extension.length != 0
randExtension = extensions.extension[rand(extensions.extension.length)]
if randExtension.identifier != nil
extensionIdentifier = randExtension.identifier
if randExtension.name != nil
puts "Fetching call costs for extension " + randExtension.name + "."
else
puts "Fetching call costs for extension with identifier " + extensionIdentifier + "."
end
end
end
end
if extensionIdentifier == nil
puts "No extensions found on the server. Can not make the call costs request."
exit
end
driver = ReportInterface.new
driver.options['protocol.http.ssl_config.verify_mode'] = OpenSSL::SSL::VERIFY_NONE
# Add custom header
driver.headerhandler << AuthHeader.new
#the CallCosts message
messagePart = CallCosts.new
# Fill in Request data
messagePart.userIdentifier = extensionIdentifier
interval = Interval.new
interval.startDate = "2012-01-01"
interval.endDate = DateTime.now.strftime('%Y-%m-%d')
messagePart.interval = interval
# Log for SystemAPI request and response
driver.wiredump_file_base = "log"
#send the SystemAPI message
begin
callCosts = driver.callCosts(messagePart)
puts callCosts.totalCalls + " calls have been made between " + interval.startDate + " and " + interval.endDate + " with a total cost of " + callCosts.cost + " " + callCosts.currency
rescue Exception => ex
# Catch exception, for situations when the call costs could not be fetched
puts "Error: " + ex.message
end |