developergarden_sdk 0.0.8
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- data/LICENSE +3 -0
- data/README +177 -0
- data/Rakefile +63 -0
- data/lib/authenticated_service.rb +30 -0
- data/lib/basic_response.rb +45 -0
- data/lib/basic_service.rb +88 -0
- data/lib/common/xml_tools.rb +25 -0
- data/lib/quota_service/quota_information.rb +36 -0
- data/lib/quota_service/quota_service.rb +53 -0
- data/lib/service_environment.rb +21 -0
- data/lib/service_exception.rb +8 -0
- data/lib/sms_service/sms_response.rb +19 -0
- data/lib/sms_service/sms_service.rb +86 -0
- data/lib/telekom_sdk.rb +15 -0
- data/lib/token_service/security_token_validator.rb +46 -0
- data/lib/token_service/token_service.rb +162 -0
- data/lib/voice_call_service/call_status_response.rb +31 -0
- data/lib/voice_call_service/voice_call_response.rb +22 -0
- data/lib/voice_call_service/voice_call_service.rb +137 -0
- metadata +116 -0
data/LICENSE
ADDED
data/README
ADDED
@@ -0,0 +1,177 @@
|
|
1
|
+
== developergarden_sdk
|
2
|
+
This library provides access to open development services of the Deutsche Telekom AG.
|
3
|
+
For more details about the services see
|
4
|
+
http://www.developergarden.com
|
5
|
+
|
6
|
+
Depending on your operating system you might want to skip the "sudo" command prior to the
|
7
|
+
commands listed here.
|
8
|
+
|
9
|
+
=== Dependencies
|
10
|
+
In order to use this library the following dependencies need to be met:
|
11
|
+
Ruby 1.8.6
|
12
|
+
Ruby Gems >= 1.3.1
|
13
|
+
|
14
|
+
There might be issues with Ruby 1.8.7 regarding to curb so it is highly recommended to use Ruby 1.8.6.
|
15
|
+
|
16
|
+
==== Gems
|
17
|
+
The following gems need to be installed:
|
18
|
+
* handsoap (Version 0.2.8)
|
19
|
+
* nokogiri
|
20
|
+
* httpclient (Version 2.1.14)
|
21
|
+
* htmlentities
|
22
|
+
|
23
|
+
=== Install the handsoap gem
|
24
|
+
For production use the official release of handsoap should be installed.
|
25
|
+
More information about handsoap can be found at:
|
26
|
+
http://github.com/troelskn/handsoap/tree/master
|
27
|
+
|
28
|
+
==== Install official handsoap release
|
29
|
+
gem sources -a http://gems.github.com
|
30
|
+
sudo gem install troelskn-handsoap
|
31
|
+
|
32
|
+
==== Install handsoap developer version
|
33
|
+
If you want to use the bleeding edge version of handsoap proceed as follows.
|
34
|
+
Note that you do not need to perform these steps if you have already installed the official release!
|
35
|
+
|
36
|
+
Checkout handsoap from github
|
37
|
+
git clone git://github.com/troelskn/handsoap.git
|
38
|
+
|
39
|
+
Install jeweler
|
40
|
+
sudo gem install jeweler
|
41
|
+
|
42
|
+
Build handsoap package
|
43
|
+
cd handsoap_git_repo
|
44
|
+
rake build
|
45
|
+
|
46
|
+
Install the resulting gem file
|
47
|
+
cd pkg
|
48
|
+
sudo gem install handsoap-0.2.7.gem
|
49
|
+
|
50
|
+
Attention: if you you use the development version you might need to change the gem statement in
|
51
|
+
basic_service.rb from
|
52
|
+
|
53
|
+
gem 'troelskn-handsoap'
|
54
|
+
|
55
|
+
to
|
56
|
+
|
57
|
+
gem 'handsoap'
|
58
|
+
|
59
|
+
=== Installation of the developergarden_sdk Gem
|
60
|
+
Install the gem using the following command
|
61
|
+
gem install developergarden_sdk-0.0.x.gem
|
62
|
+
|
63
|
+
Where x stands for the current version. For the version 0.0.4 this could look like this:
|
64
|
+
gem install developergarden_sdk-0.0.x.gem
|
65
|
+
|
66
|
+
=== Basic usage
|
67
|
+
You can use the gem from pure Ruby applications and of course from Ruby on Rails apps as well.
|
68
|
+
|
69
|
+
==== To use the gem from your Ruby app:
|
70
|
+
|
71
|
+
require 'rubygems'
|
72
|
+
gem 'developergarden_sdk'
|
73
|
+
require 'token_Service/token_service'
|
74
|
+
require 'sms_service/sms_service'
|
75
|
+
require 'voice_call_service/voice_call_service'
|
76
|
+
require 'quota_service/quota_service'
|
77
|
+
require 'service_environment'
|
78
|
+
|
79
|
+
==== Ruby Example to send a sms
|
80
|
+
#!/usr/bin/env ruby -d
|
81
|
+
|
82
|
+
require 'rubygems'
|
83
|
+
gem 'developergarden_sdk'
|
84
|
+
require 'token_Service/token_service'
|
85
|
+
require 'sms_service/sms_service'
|
86
|
+
require 'service_environment'
|
87
|
+
|
88
|
+
sms = SmsService::SmsService.new("<USER>@t-online.de", "<PASSWORD>")
|
89
|
+
sms_response = sms.send_sms("+49177 0000001", "Your message text.", "RubySDK", ServiceEnvironment.PRODUCTION, "")
|
90
|
+
|
91
|
+
|
92
|
+
==== To use your gem from your Ruby on Rails app
|
93
|
+
In your environment.rb add the following line in the config block:
|
94
|
+
config.gem 'developergarden_sdk'
|
95
|
+
|
96
|
+
==== Ruby on Rails Example
|
97
|
+
|
98
|
+
class SmsNotification
|
99
|
+
|
100
|
+
USERNAME = "<USER>@t-online.de"
|
101
|
+
PASSWORD = "<PASSWORD>"
|
102
|
+
|
103
|
+
# Send SMS to Numbers.
|
104
|
+
def send_sms(number, message, originator, environment = 2)
|
105
|
+
|
106
|
+
# Create new SmsService instance
|
107
|
+
@sms = SmsService::SmsService.new(USERNAME, PASSWORD)
|
108
|
+
|
109
|
+
# Send SMS to cell phone
|
110
|
+
@sms.send_sms(number, message, originator, environment)
|
111
|
+
|
112
|
+
end
|
113
|
+
|
114
|
+
end
|
115
|
+
|
116
|
+
=== More Examples
|
117
|
+
In order to see more examples have a look the unit tests included in the gem's source code.
|
118
|
+
You might also want to have a look at the actual source code and source code comments.
|
119
|
+
|
120
|
+
=== Debug
|
121
|
+
Per default all generated and received soap xml messages are not visible. These can be print to stdout for debugging
|
122
|
+
purposes by starting the ruby interpreter with the -d option. You will then see all http xml soap requests and responses.
|
123
|
+
This can be done by invoking your ruby app by using a shebang like this:
|
124
|
+
#!/usr/bin/ruby -d
|
125
|
+
|
126
|
+
=== Testing
|
127
|
+
Before you run the tests you will need to modify config/test_settings.yml by entering your developer garden credentials.
|
128
|
+
|
129
|
+
Executing tests will be done in the "sandbox" or "mock" environment which are free of charge.
|
130
|
+
Be ware that the services itself have quotas on these test environments so your tests may fail after a while.
|
131
|
+
The quotas are on a daily basis so they should pass again the next day.
|
132
|
+
|
133
|
+
Failures when reaching the SANDBOX QUOTA might look like this:
|
134
|
+
0030 quotas have exceeded
|
135
|
+
|
136
|
+
Phone numbers in test files are fictive and for testing purposes only.
|
137
|
+
|
138
|
+
The testsuite can be run by invoking the test raketask.
|
139
|
+
cd /home/yourhome/developergarden_sdk
|
140
|
+
rake test
|
141
|
+
|
142
|
+
In order to run a single test perform the following command:
|
143
|
+
cd /home/yourhome/developergarden_sdk/lib
|
144
|
+
ruby -d ../test/voice_call_service_test.rb --name teardown_call
|
145
|
+
|
146
|
+
==== QuotaService
|
147
|
+
* QuotaService can be tested as it is. There is no need to pass an environment such as "production" or "sandbox" because
|
148
|
+
it is free of charge.
|
149
|
+
|
150
|
+
==== SmsService
|
151
|
+
* SmsService can be tested using the "sandbox" environment. Be aware that there is a 5 credit quota per day. So you can
|
152
|
+
send 5 test sms per day. After that you will receive a corresponding quota error message.
|
153
|
+
|
154
|
+
==== VoiceCallService
|
155
|
+
* In the "sandbox" environment there is a quota limit of 5 calls per day (each up to 10 sec) for the VoiceCallService
|
156
|
+
* In the "production" environment a call may not last more than 60 minutes. After 60 min the call will be cancelled.
|
157
|
+
* There is also a quota for the "mock" environment.
|
158
|
+
|
159
|
+
For more information about service environments have a look at the documentation at http://www.developergarden.com
|
160
|
+
|
161
|
+
=== Build the developergarden_sdk gem
|
162
|
+
You can build the gem by invoking the gem rake task
|
163
|
+
rake gem
|
164
|
+
The resulting gem will be generated to the pkg/ directory and can be installed like this:
|
165
|
+
sudo gem install developergarden_sdk-0.0.6.gem
|
166
|
+
Depending on the current version number you will need to adapt the gem filename correspondingly.
|
167
|
+
|
168
|
+
==More Information
|
169
|
+
More information about developer garden services can be found at:
|
170
|
+
http://www.developergarden.com
|
171
|
+
|
172
|
+
==FAQ
|
173
|
+
=== Did not understand "MustUnderstand" header(s)
|
174
|
+
Handsoap::Fault: Handsoap::Fault { :code => 'soapenv:MustUnderstand', :reason => 'Did not understand "MustUnderstand" header(s):{http://docs.oasis-open.org/wss/2004/01/oasis-200401-wss-wssecurity-secext-1.0.xsd}Security' }
|
175
|
+
|
176
|
+
You will receive this error message if a mandatory header element is not present or the remote service was unable to process it.
|
177
|
+
Most likely this will happen if something is wrong during the authentication process such as missing parameters like username, password.
|
data/Rakefile
ADDED
@@ -0,0 +1,63 @@
|
|
1
|
+
#
|
2
|
+
# To change this template, choose Tools | Templates
|
3
|
+
# and open the template in the editor.
|
4
|
+
|
5
|
+
|
6
|
+
require 'rubygems'
|
7
|
+
require 'rake'
|
8
|
+
require 'rake/clean'
|
9
|
+
require 'rake/gempackagetask'
|
10
|
+
require 'rake/rdoctask'
|
11
|
+
require 'rake/testtask'
|
12
|
+
require 'fileutils'
|
13
|
+
|
14
|
+
spec = Gem::Specification.new do |s|
|
15
|
+
s.name = 'developergarden_sdk'
|
16
|
+
s.version = '0.0.8'
|
17
|
+
s.homepage = 'http://www.developergarden.com'
|
18
|
+
s.has_rdoc = true
|
19
|
+
s.extra_rdoc_files = ['README', 'LICENSE']
|
20
|
+
s.summary = 'Offers a ruby client for the open development services such as send SMS, voice call and quota management of the Deutsche Telekom AG. See also http://www.developergarden.com.'
|
21
|
+
s.description = s.summary
|
22
|
+
s.author = 'Julian Fischer / Aperto move GmbH'
|
23
|
+
s.email = 'ruby@developergarden.com'
|
24
|
+
# s.executables = ['your_executable_here']
|
25
|
+
|
26
|
+
# GEM dependencies
|
27
|
+
s.add_dependency 'httpclient', '= 2.1.4'
|
28
|
+
s.add_dependency 'nokogiri', '>= 1.3.1'
|
29
|
+
s.add_dependency 'troelskn-handsoap', '= 0.2.8'
|
30
|
+
s.add_dependency 'htmlentities', '>= 4.0.0'
|
31
|
+
|
32
|
+
s.files = %w(LICENSE README Rakefile) + Dir.glob("{bin,lib,spec}/**/*")
|
33
|
+
s.require_path = "lib"
|
34
|
+
s.bindir = "bin"
|
35
|
+
end
|
36
|
+
|
37
|
+
Rake::GemPackageTask.new(spec) do |p|
|
38
|
+
p.gem_spec = spec
|
39
|
+
p.need_tar = true
|
40
|
+
p.need_zip = true
|
41
|
+
end
|
42
|
+
|
43
|
+
Rake::RDocTask.new do |rdoc|
|
44
|
+
files =['README', 'LICENSE', 'lib/**/*.rb']
|
45
|
+
rdoc.rdoc_files.add(files)
|
46
|
+
rdoc.main = "README" # page to start on
|
47
|
+
rdoc.title = "developergarden_sdk Docs"
|
48
|
+
rdoc.rdoc_dir = 'doc/rdoc' # rdoc output folder
|
49
|
+
rdoc.options << '--line-numbers'
|
50
|
+
rdoc.options << '--all'
|
51
|
+
rdoc.options << '--charset=UTF-8'
|
52
|
+
end
|
53
|
+
|
54
|
+
Rake::TestTask.new do |t|
|
55
|
+
t.test_files = FileList['test/**/*.rb']
|
56
|
+
end
|
57
|
+
|
58
|
+
desc "update_plugin"
|
59
|
+
task :update_plugin do
|
60
|
+
sh %{ cp -R lib/* plugin/developergarden_sdk/lib/ }
|
61
|
+
sh %{ cp -R test/* plugin/developergarden_sdk/test/ }
|
62
|
+
end
|
63
|
+
|
@@ -0,0 +1,30 @@
|
|
1
|
+
require File.dirname(__FILE__) + '/basic_service'
|
2
|
+
require File.dirname(__FILE__) + '/token_service/token_service'
|
3
|
+
|
4
|
+
# Base service for all services demanding a security token.
|
5
|
+
class AuthenticatedService < BasicService
|
6
|
+
|
7
|
+
def initialize(username, password)
|
8
|
+
super(username, password)
|
9
|
+
|
10
|
+
@token_service = TokenService::TokenService.new(@username, @password)
|
11
|
+
end
|
12
|
+
|
13
|
+
# Invokes the given action and also adds the security token to the SOAP header.
|
14
|
+
# Using this method authentication is totally hidden from the rest of the application.
|
15
|
+
def invoke_authenticated(action, &block)
|
16
|
+
|
17
|
+
security_token = @token_service.get_security_token
|
18
|
+
|
19
|
+
response = invoke(action) do |message|
|
20
|
+
doc = message.document
|
21
|
+
|
22
|
+
# Build the login header
|
23
|
+
build_service_header(doc, security_token)
|
24
|
+
|
25
|
+
yield(message, doc)
|
26
|
+
end
|
27
|
+
|
28
|
+
return response
|
29
|
+
end
|
30
|
+
end
|
@@ -0,0 +1,45 @@
|
|
1
|
+
require File.dirname(__FILE__) + '/service_exception'
|
2
|
+
|
3
|
+
# Base class for service responses.
|
4
|
+
class BasicResponse
|
5
|
+
attr_accessor :error_code, :error_message
|
6
|
+
|
7
|
+
# Constructor
|
8
|
+
def inizialize
|
9
|
+
end
|
10
|
+
|
11
|
+
# Constructor.
|
12
|
+
# ===Parameters
|
13
|
+
# <tt>response_xml</tt>:: Xml as returned by a <tt>status</tt>-method call.
|
14
|
+
# <tt>raise_exception_on_error</tt>:: Xml as returned by a <tt>status</tt>-method call.
|
15
|
+
def initialize(response_xml, raise_exception_on_error = true)
|
16
|
+
doc = response_xml.document
|
17
|
+
|
18
|
+
@error_code = doc.xpath("//errorCode").text
|
19
|
+
@error_message = doc.xpath("//errorMessage").text
|
20
|
+
|
21
|
+
raise_on_error(response_xml) if raise_exception_on_error
|
22
|
+
end
|
23
|
+
|
24
|
+
# Returns <tt>self.inspect</tt>. Good for debugging purposes.
|
25
|
+
def to_s
|
26
|
+
return self.inspect
|
27
|
+
end
|
28
|
+
|
29
|
+
# Raises an exception if the response is an error.
|
30
|
+
# Since in some response types the error code is not named "errorCode" it is not possible
|
31
|
+
# to call this method only in the constructur of this base class.
|
32
|
+
# This is sufficient for services using the BaseResponse directly but subclasses of BaseResponse
|
33
|
+
# need to call this method at the end of their constructure <tt>initialize</tt>.
|
34
|
+
def raise_on_error(response_xml)
|
35
|
+
if @error_code && !@error_code.empty? && @error_code != "0000" then
|
36
|
+
|
37
|
+
# It is important to create the exception with self.class.new and not only BasicResponse.new
|
38
|
+
# This is because this method can be also invoked from a subclass. If a VoiceCallResponse object for example
|
39
|
+
# raises an exception you will receive "VoiceCallResponse" from self.class. This is very important because
|
40
|
+
# only the VoiceCallResponse knows that in this case the response code is called <tt>status</tt>.
|
41
|
+
# This is because there is an inconsistency within the different service responses.
|
42
|
+
raise(ServiceException.new( self.class.new(response_xml, false) ), "The developer garden service you invoked responded with an error: " + @error_message.to_s)
|
43
|
+
end
|
44
|
+
end
|
45
|
+
end
|
@@ -0,0 +1,88 @@
|
|
1
|
+
require 'rubygems'
|
2
|
+
gem 'troelskn-handsoap'
|
3
|
+
|
4
|
+
require 'handsoap'
|
5
|
+
require File.dirname(__FILE__) + '/common/xml_tools'
|
6
|
+
require File.dirname(__FILE__) + '/service_environment'
|
7
|
+
|
8
|
+
# Implements basic logic used by developer garden ruby service implementations.
|
9
|
+
class BasicService < Handsoap::Service
|
10
|
+
|
11
|
+
@@SERVICE_ID = "https://odg.t-online.de"
|
12
|
+
|
13
|
+
# Create some namespaces
|
14
|
+
on_create_document do |doc|
|
15
|
+
doc.alias 'ns1', "http://sts.idm.telekom.com/schema/"
|
16
|
+
doc.alias 'xmlns:ns2', "Security"
|
17
|
+
end
|
18
|
+
|
19
|
+
# Constructor
|
20
|
+
# ===Parameters
|
21
|
+
# <tt>username</tt>:: Username, such as myuser@t-online.de
|
22
|
+
# <tt>password</tt>:: Password
|
23
|
+
# <tt>environment</tt>:: Service environment as defined in ServiceEnvironment
|
24
|
+
def initialize(username, password, environment = ServiceEnvironment.SANDBOX)
|
25
|
+
@username = username
|
26
|
+
@password = password
|
27
|
+
@environment = environment
|
28
|
+
end
|
29
|
+
|
30
|
+
protected
|
31
|
+
|
32
|
+
# After being successfully authenticated service calls need to performed including the security token(s) in its soap
|
33
|
+
# headers. This method builds such a header.
|
34
|
+
#
|
35
|
+
# The header of the given document will be enhanced so there is no need to
|
36
|
+
# process the returning value.
|
37
|
+
#
|
38
|
+
# ===Parameters
|
39
|
+
# <tt>doc</tt>:: Request XmlMason document.
|
40
|
+
# <tt>security_token</tt>:: Security tokens as plain text gathered using the TokenService.
|
41
|
+
def build_service_header(doc, security_token)
|
42
|
+
header = build_security_header_common(doc)
|
43
|
+
security = header.find("Security")
|
44
|
+
security.set_value( security_token, :raw)
|
45
|
+
return header
|
46
|
+
end
|
47
|
+
|
48
|
+
# Regardless to whether it is a <tt>login</tt>, <tt>getTokens</tt> or a regular service call there always
|
49
|
+
# has to be a security header. This method provides the structure which is in common to all these method calls.
|
50
|
+
#
|
51
|
+
# The header of the given document will be enhanced so there is no need to
|
52
|
+
# process the returning value.
|
53
|
+
# ===Parameters
|
54
|
+
# <tt>doc</tt>:: Request XmlMason document.
|
55
|
+
def build_security_header_common(doc)
|
56
|
+
|
57
|
+
# Get the header element
|
58
|
+
header = doc.find('Header')
|
59
|
+
|
60
|
+
# Add plain security element
|
61
|
+
header.add('Security')
|
62
|
+
|
63
|
+
# Find security element for further enhancement
|
64
|
+
security = header.find('Security')
|
65
|
+
|
66
|
+
# Set namespace
|
67
|
+
security.set_attr("xmlns", "http://docs.oasis-open.org/wss/2004/01/oasis-200401-wss-wssecurity-secext-1.0.xsd")
|
68
|
+
security.set_attr("env:mustUnderstand", "1")
|
69
|
+
return header
|
70
|
+
end
|
71
|
+
|
72
|
+
|
73
|
+
# Extracts any token from the response and returns it.
|
74
|
+
# ===Parameters
|
75
|
+
# <tt>response</tt>:: Response as returned from a <tt>getTokens</tt> call, for example.
|
76
|
+
#
|
77
|
+
# ==Return
|
78
|
+
# Returns the security token as plain text to be inserted into a security header build with <tt>build_security_header_common</tt>.
|
79
|
+
def get_token_data_from_response(response)
|
80
|
+
|
81
|
+
# nokogiri document. Unfortunately it is unable to parse the returning xml completely.
|
82
|
+
# Especially the body is not parsed completely.
|
83
|
+
doc = response.document
|
84
|
+
intermediate_token = doc.xpath("//schema:tokenData", "schema" => 'http://sts.idm.telekom.com/schema/').inner_text
|
85
|
+
|
86
|
+
return intermediate_token
|
87
|
+
end
|
88
|
+
end
|
@@ -0,0 +1,25 @@
|
|
1
|
+
module Common
|
2
|
+
|
3
|
+
# Some tools facilitating xml processing.
|
4
|
+
class XmlTools
|
5
|
+
|
6
|
+
# Get rid of surrounding cdata sections.
|
7
|
+
# Attention: This method will modify the given string itself.
|
8
|
+
# ===Parameter
|
9
|
+
# <tt>xml_with_cdata</tt>:: Some xml string with a cdata section.
|
10
|
+
def self.strip_cdata!(xml_with_cdata)
|
11
|
+
xml_with_cdata.gsub!('<![CDATA[', '')
|
12
|
+
xml_with_cdata.gsub!(']]>', '')
|
13
|
+
return xml_with_cdata
|
14
|
+
end
|
15
|
+
|
16
|
+
# Get rid of surrounding cdata sections.
|
17
|
+
# ===Parameter
|
18
|
+
# <tt>xml_with_cdata</tt>:: Some xml string with a cdata section.
|
19
|
+
def self.strip_cdata(xml_with_cdata)
|
20
|
+
xml_with_cdata.gsub('<![CDATA[', '')
|
21
|
+
xml_with_cdata.gsub(']]>', '')
|
22
|
+
return xml_with_cdata
|
23
|
+
end
|
24
|
+
end
|
25
|
+
end
|
@@ -0,0 +1,36 @@
|
|
1
|
+
require File.dirname(__FILE__) + '/../basic_response'
|
2
|
+
|
3
|
+
module QuotaService
|
4
|
+
|
5
|
+
# Representing the response of a <tt>get_quota_information</tt>-Call.
|
6
|
+
class QuotaInformation < BasicResponse
|
7
|
+
attr_accessor :error_code, :error_message, :max_quota, :max_user_quota, :quota_level
|
8
|
+
|
9
|
+
# Constructor.
|
10
|
+
# ===Parameters
|
11
|
+
# <tt>response_xml</tt>:: Xml as returned by a <tt>call_status</tt>-method call.
|
12
|
+
# <tt>raise_exception_on_error</tt>:: Xml as returned by a <tt>call_status</tt>-method call.
|
13
|
+
def initialize(response_xml, raise_exception_on_error = true)
|
14
|
+
super(response_xml)
|
15
|
+
|
16
|
+
doc = response_xml.document
|
17
|
+
@max_quota = doc.xpath("//maxQuota").text
|
18
|
+
@max_user_quota = doc.xpath("//maxUserQuota").text
|
19
|
+
@quota_level = doc.xpath("//quotaLevel").text
|
20
|
+
|
21
|
+
raise_on_error(response_xml) if raise_exception_on_error
|
22
|
+
end
|
23
|
+
|
24
|
+
def max_quota
|
25
|
+
@max_quota.to_i
|
26
|
+
end
|
27
|
+
|
28
|
+
def max_user_quota
|
29
|
+
@max_user_quota.to_i
|
30
|
+
end
|
31
|
+
|
32
|
+
def quota_level
|
33
|
+
@quota_level.to_i
|
34
|
+
end
|
35
|
+
end
|
36
|
+
end
|
@@ -0,0 +1,53 @@
|
|
1
|
+
require File.dirname(__FILE__) + '/../authenticated_service'
|
2
|
+
require File.dirname(__FILE__) + '/../quota_service/quota_information'
|
3
|
+
|
4
|
+
Handsoap.http_driver = :httpclient
|
5
|
+
|
6
|
+
# Print http and soap requests and reponses if ruby has been started with -d option.
|
7
|
+
Handsoap::Service.logger = $stdout if $DEBUG
|
8
|
+
|
9
|
+
module QuotaService
|
10
|
+
|
11
|
+
# Client to access the developer garden quota service.
|
12
|
+
#
|
13
|
+
# See also:
|
14
|
+
# * https://www.developergarden.com/openapi/dokumentation/uebergreifende_informationen#2.5.
|
15
|
+
# * https://www.developergarden.com/openapi/dokumentation/services#4.2.6.
|
16
|
+
class QuotaService < AuthenticatedService
|
17
|
+
|
18
|
+
@@QUOTA_SERVICE_ENDPOINT = {
|
19
|
+
:uri => "https://gateway.developer.telekom.com/p3gw-mod-odg-admin/services/ODGBaseUserService",
|
20
|
+
:version => 1
|
21
|
+
}
|
22
|
+
|
23
|
+
endpoint @@QUOTA_SERVICE_ENDPOINT
|
24
|
+
|
25
|
+
# Get the amount of remaining quota points.
|
26
|
+
# ===Parameters
|
27
|
+
# <tt>module_id</tt>:: module_id of the service for which a quota request to be made, such as "VoiceButlerProduction"
|
28
|
+
def get_quota_information(module_id = "VoiceButlerSandbox")
|
29
|
+
|
30
|
+
response = invoke_authenticated("getQuotaInformation") do |message, doc|
|
31
|
+
message.add('moduleId', module_id)
|
32
|
+
end
|
33
|
+
|
34
|
+
quota_info = QuotaInformation.new(response)
|
35
|
+
|
36
|
+
return quota_info
|
37
|
+
end
|
38
|
+
|
39
|
+
# Changes the quota for a particular service
|
40
|
+
# ===Parameters
|
41
|
+
# <tt>module_id</tt>:: module_id of the service for which a quota request to be made, such as "VoiceButlerProduction"
|
42
|
+
# <tt>quota_max</tt>:: Quota limit to be set
|
43
|
+
def change_quota_pool(module_id = "VoiceButlerSandbox", quota_max = 100)
|
44
|
+
|
45
|
+
response = invoke_authenticated("changeQuotaPool") do |message, doc|
|
46
|
+
message.add('moduleId', module_id)
|
47
|
+
message.add('quotaMax', quota_max)
|
48
|
+
end
|
49
|
+
|
50
|
+
return BasicResponse.new(response)
|
51
|
+
end
|
52
|
+
end
|
53
|
+
end
|
@@ -0,0 +1,21 @@
|
|
1
|
+
# Possible environment variables to choose a specific service environment.
|
2
|
+
#
|
3
|
+
# See also: https://www.developergarden.com/openapi/dokumentation/ansprache_der_services_ueber_webservice_schnittstellen#A.1.
|
4
|
+
class ServiceEnvironment
|
5
|
+
|
6
|
+
# Production environment constant
|
7
|
+
def self.PRODUCTION
|
8
|
+
@@PRODUCTION = 1
|
9
|
+
end
|
10
|
+
|
11
|
+
# Sandbox environment constant
|
12
|
+
def self.SANDBOX
|
13
|
+
|
14
|
+
@@SANDBOX = 2
|
15
|
+
end
|
16
|
+
|
17
|
+
# Mock environment constant
|
18
|
+
def self.MOCK
|
19
|
+
@@MOCK = 3
|
20
|
+
end
|
21
|
+
end
|
@@ -0,0 +1,19 @@
|
|
1
|
+
require File.dirname(__FILE__) + '/../basic_response'
|
2
|
+
|
3
|
+
# Representing a response from the <tt>SmsService</tt>.
|
4
|
+
class SmsResponse < BasicResponse
|
5
|
+
|
6
|
+
# Constructor.
|
7
|
+
# ===Parameters
|
8
|
+
# <tt>response_xml</tt>:: Xml as returned by a <tt>sms_status</tt>-method call.
|
9
|
+
# <tt>raise_exception_on_error</tt>:: Xml as returned by a <tt>sms_status</tt>-method call.
|
10
|
+
def initialize(response_xml, raise_exception_on_error = true)
|
11
|
+
doc = response_xml.document
|
12
|
+
|
13
|
+
@error_code = doc.xpath("//status").text
|
14
|
+
@error_message = doc.xpath("//description").text
|
15
|
+
|
16
|
+
raise_on_error(response_xml) if raise_exception_on_error
|
17
|
+
end
|
18
|
+
|
19
|
+
end
|
@@ -0,0 +1,86 @@
|
|
1
|
+
require File.dirname(__FILE__) + '/../authenticated_service'
|
2
|
+
require File.dirname(__FILE__) + '/../sms_service/sms_response'
|
3
|
+
|
4
|
+
Handsoap.http_driver = :httpclient
|
5
|
+
|
6
|
+
# Print http and soap requests and reponses if ruby has been started with -d option.
|
7
|
+
Handsoap::Service.logger = $stdout if $DEBUG
|
8
|
+
|
9
|
+
module SmsService
|
10
|
+
|
11
|
+
# Client to the developer garden sms service.
|
12
|
+
# Can be used to send sms and flash sms.
|
13
|
+
#
|
14
|
+
# See also:
|
15
|
+
# * https://www.developergarden.com/openapi/dokumentation/services#4.2.3.
|
16
|
+
class SmsService < AuthenticatedService
|
17
|
+
|
18
|
+
@@SMS_SERVICE_ENDPOINT = {
|
19
|
+
:uri => "https://gateway.developer.telekom.com/p3gw-mod-odg-sms/services/SmsService",
|
20
|
+
:version => 1
|
21
|
+
}
|
22
|
+
|
23
|
+
endpoint @@SMS_SERVICE_ENDPOINT
|
24
|
+
|
25
|
+
# Send a sms.
|
26
|
+
# Detailed information about sending of sms can be found under:
|
27
|
+
# * https://www.developergarden.com/openapi/dokumentation/services#4.2.3.
|
28
|
+
# ===Parameters
|
29
|
+
# <tt>numbers</tt>:: Up to 10 receivers can be specified separated by commas (",").
|
30
|
+
# <tt>sms_message</tt>:: Actual message. Can be up to 765 characters. A sms will be charged for each 153 chars.
|
31
|
+
# <tt>originator</tt>:: String to be displayed as the originator of the message.
|
32
|
+
# Max. 11 characters. Further chars will be cut of. Allowed chars are [a-zA-Z0-9].
|
33
|
+
# <tt>environment</tt>:: Service environment as defined in ServiceEnvironment.
|
34
|
+
# <tt>account</tt>:: Currently unused
|
35
|
+
def send_sms(numbers, sms_message, originator, environment = 2, account = "")
|
36
|
+
return send_sms_common("sendSMS", numbers, sms_message, originator, environment, account)
|
37
|
+
end
|
38
|
+
|
39
|
+
# Send a flasg sms. A flash sms goes directly to the handy screen.
|
40
|
+
# Detailed information about sending of sms can be found under:
|
41
|
+
# * https://www.developergarden.com/openapi/dokumentation/services#4.2.3.
|
42
|
+
# ===Parameters
|
43
|
+
# <tt>numbers</tt>:: Up to 10 receivers can be specified separated by commas (",").
|
44
|
+
# <tt>sms_message</tt>:: Actual message. Can be up to 765 characters. A sms will be charged for each 153 chars.
|
45
|
+
# <tt>originator</tt>:: String to be displayed as the originator of the message.
|
46
|
+
# Max. 11 characters. Further chars will be cut of. Allowed chars are [a-zA-Z0-9].
|
47
|
+
# At least one letter needs to be present.
|
48
|
+
# <tt>environment</tt>:: Service environment as defined in ServiceEnvironment.
|
49
|
+
# <tt>account</tt>:: Currently unused
|
50
|
+
def send_flash_sms(numbers, sms_message, originator, environment = 2, account = "")
|
51
|
+
return send_sms_common("sendFlashSMS", numbers, sms_message, originator, environment, account)
|
52
|
+
end
|
53
|
+
|
54
|
+
|
55
|
+
protected
|
56
|
+
|
57
|
+
# Methods sendSMS and sendFlashSMS have identical arguments. They only differ in their action name.
|
58
|
+
# ===Parameters
|
59
|
+
# <tt>numbers</tt>:: Up to 10 receivers can be specified separated by commas (",").
|
60
|
+
# <tt>sms_message</tt>:: Actual message. Can be up to 765 characters. A sms will be charged for each 153 chars.
|
61
|
+
# <tt>originator</tt>:: String to be displayed as the originator of the message.
|
62
|
+
# Max. 11 characters. Further chars will be cut of. Allowed chars are [a-zA-Z0-9].
|
63
|
+
# <tt>environment</tt>:: Service environment as defined in ServiceEnvironment.
|
64
|
+
# <tt>account</tt>:: Currently unused
|
65
|
+
def send_sms_common(action_name, numbers, sms_message, originator, environment = 2, account = "")
|
66
|
+
|
67
|
+
# Cut originator down to 11 characters
|
68
|
+
originator = originator[0, 11]
|
69
|
+
|
70
|
+
response = invoke_authenticated(action_name) do |message, doc|
|
71
|
+
message.add("request")
|
72
|
+
request = message.find("request")
|
73
|
+
request.add('environment', environment)
|
74
|
+
request.add('number', numbers)
|
75
|
+
request.add('message', sms_message)
|
76
|
+
request.add('originator', originator)
|
77
|
+
request.add('account', account)
|
78
|
+
end
|
79
|
+
|
80
|
+
return SmsResponse.new(response)
|
81
|
+
end
|
82
|
+
|
83
|
+
|
84
|
+
end
|
85
|
+
|
86
|
+
end
|
data/lib/telekom_sdk.rb
ADDED
@@ -0,0 +1,15 @@
|
|
1
|
+
$:.unshift(File.dirname(__FILE__)) unless
|
2
|
+
$:.include?(File.dirname(__FILE__)) || $:.include?(File.expand_path(File.dirname(__FILE__)))
|
3
|
+
|
4
|
+
require File.dirname(__FILE__) + '/quota_service/quota_service'
|
5
|
+
require File.dirname(__FILE__) + '/voice_call_service/voice_call_service'
|
6
|
+
require File.dirname(__FILE__) + '/sms_service/sms_service'
|
7
|
+
|
8
|
+
module QuotaService
|
9
|
+
end
|
10
|
+
|
11
|
+
module SmsService
|
12
|
+
end
|
13
|
+
|
14
|
+
module VoiceCallService
|
15
|
+
end
|
@@ -0,0 +1,46 @@
|
|
1
|
+
require 'nokogiri'
|
2
|
+
|
3
|
+
module TokenService
|
4
|
+
|
5
|
+
# Verifies the timestamp of a security token to determine whether the token
|
6
|
+
# is yet or still valid.
|
7
|
+
# This is done to avoid unnecessary
|
8
|
+
class SecurityTokenValidator
|
9
|
+
|
10
|
+
# Verifies the timestamp of a security token to determine whether the token
|
11
|
+
# is yet or still valid.
|
12
|
+
# This is done to avoid unnecessary
|
13
|
+
# === Parameters
|
14
|
+
# <tt>security_token_xml</tt>:: Security token as plain xml.
|
15
|
+
# === Returns
|
16
|
+
# Boolean indicating whether the security token is yet or still valid.
|
17
|
+
def self.token_valid?(security_token_xml)
|
18
|
+
doc = Nokogiri.XML( security_token_xml )
|
19
|
+
conditions_node_set = doc.xpath("//schema:Conditions", "schema" => 'urn:oasis:names:tc:SAML:2.0:assertion')
|
20
|
+
conditions_elment = conditions_node_set.first
|
21
|
+
not_before = conditions_elment.get_attribute('NotBefore')
|
22
|
+
not_on_or_after = conditions_elment.get_attribute('NotOnOrAfter')
|
23
|
+
|
24
|
+
date_not_before = DateTime.parse(not_before)
|
25
|
+
date_not_on_or_after = DateTime.parse(not_on_or_after)
|
26
|
+
|
27
|
+
# Should be: date_not_before =< now < date_not_on_or_after
|
28
|
+
ret = DateTime.now.between?(date_not_before, date_not_on_or_after)
|
29
|
+
|
30
|
+
return ret
|
31
|
+
end
|
32
|
+
|
33
|
+
# Verifies the timestamp of a security token to determine whether the token
|
34
|
+
# is yet or still valid.
|
35
|
+
# This is done to avoid unnecessary
|
36
|
+
# === Parameters
|
37
|
+
# <tt>security_token_xml</tt>:: Security token as plain xml.
|
38
|
+
# === Returns
|
39
|
+
# (logical) not token_valid?(security_token_xml)
|
40
|
+
# Returns true if the security token is not valid!
|
41
|
+
def self.token_invalid?(security_token_xml)
|
42
|
+
return !(self.token_valid?(security_token_xml))
|
43
|
+
end
|
44
|
+
end
|
45
|
+
|
46
|
+
end
|
@@ -0,0 +1,162 @@
|
|
1
|
+
require File.dirname(__FILE__) + '/../basic_service'
|
2
|
+
require File.dirname(__FILE__) + '/../token_service/security_token_validator'
|
3
|
+
|
4
|
+
Handsoap.http_driver = :httpclient
|
5
|
+
|
6
|
+
# Print http and soap requests and reponses if ruby has been started with -d option.
|
7
|
+
Handsoap::Service.logger = $stdout if $DEBUG
|
8
|
+
|
9
|
+
# Module defining a client to access the security token service.
|
10
|
+
module TokenService
|
11
|
+
|
12
|
+
# TokenService client to perform authentication against the security token service.
|
13
|
+
# Authentication is performed in two steps:
|
14
|
+
# 1. Call <tt>login</tt> to gather an intermediate token
|
15
|
+
# 2. Call <tt>getTokens</tt> to gather one or more security token(s).
|
16
|
+
# 3. Call any service method passing the security token(s) along the soap header.
|
17
|
+
# The security token service is an implementation of the OASIS WSS specification.
|
18
|
+
# See also: http://www.oasis-open.org/committees/wss/.
|
19
|
+
#
|
20
|
+
# Be aware that all security information is provided in the soap header not in the soap body.
|
21
|
+
# This is why a wss enabled service does not provide a separate method parameter to pass the security tokens.
|
22
|
+
# As mentioned before security is passed in the soap header, instead.
|
23
|
+
#
|
24
|
+
class TokenService < BasicService
|
25
|
+
|
26
|
+
@@TOKEN_SERVICE_ENDPOINT = {
|
27
|
+
:uri => 'https://sts.idm.telekom.com/TokenService',
|
28
|
+
:version => 1
|
29
|
+
}
|
30
|
+
|
31
|
+
endpoint @@TOKEN_SERVICE_ENDPOINT
|
32
|
+
|
33
|
+
# This is disabled per default because client time and server time need to be in sync
|
34
|
+
# to use this function. Otherwise local token verification might fail even on valid tokens.
|
35
|
+
# This would imply an unnecessary call to the token service.
|
36
|
+
@@PERFORM_LOCAL_TOKEN_CHECKS = false
|
37
|
+
|
38
|
+
# Create some namespace attributes
|
39
|
+
on_create_document do |doc|
|
40
|
+
|
41
|
+
# doc is of type XmlMason::Document
|
42
|
+
doc.alias 'ns1', "http://stss.idm.telekom.com/schema/"
|
43
|
+
doc.alias 'xmlns:ns2', "Security"
|
44
|
+
end
|
45
|
+
|
46
|
+
# Call the the security token service to gather an intermediate token.
|
47
|
+
def login
|
48
|
+
response = invoke("login") do |message|
|
49
|
+
doc = message.document
|
50
|
+
|
51
|
+
# Build the login header
|
52
|
+
build_login_header(doc)
|
53
|
+
end
|
54
|
+
|
55
|
+
intermediate_token = get_token_data_from_response(response)
|
56
|
+
|
57
|
+
return intermediate_token
|
58
|
+
end
|
59
|
+
|
60
|
+
#### Composite methods
|
61
|
+
|
62
|
+
# Check whether there is a security token. Authenticate if not.
|
63
|
+
# Reauthenticates if the security token has expired.
|
64
|
+
# ===Returns
|
65
|
+
# Security token as plain text/xml.
|
66
|
+
def get_security_token
|
67
|
+
|
68
|
+
# Reauthenticates if the security token has expired.
|
69
|
+
if @security_token.nil? then
|
70
|
+
authenticate
|
71
|
+
end
|
72
|
+
|
73
|
+
# Look at the validity dates of the token and locally check whether the token is still valid.
|
74
|
+
if @@PERFORM_LOCAL_TOKEN_CHECKS && SecurityTokenValidator.token_invalid?(@security_token) then
|
75
|
+
authenticate
|
76
|
+
end
|
77
|
+
|
78
|
+
return @security_token
|
79
|
+
end
|
80
|
+
|
81
|
+
protected
|
82
|
+
|
83
|
+
# Performs a two step authentication gathering an intermediate token and then the actual security token.
|
84
|
+
# The security token is used to make further service calls.
|
85
|
+
# ===Returns
|
86
|
+
# Security token as plain text/xml.
|
87
|
+
def authenticate
|
88
|
+
intermediate_token = login
|
89
|
+
@security_token = get_tokens(intermediate_token)
|
90
|
+
|
91
|
+
return @security_token
|
92
|
+
end
|
93
|
+
|
94
|
+
# Invokes the getTokens method using an intermediate token to gather security token(s).
|
95
|
+
# Security tokens are needed to perform further service calls.
|
96
|
+
# ===Parameters
|
97
|
+
# <tt>intermediate_token</tt>:: Intermediate token gathered by invoking the <tt>login</tt>-Method
|
98
|
+
def get_tokens(intermediate_token)
|
99
|
+
response = invoke("getTokens") do |message|
|
100
|
+
doc = message.document
|
101
|
+
|
102
|
+
# Build the login header
|
103
|
+
build_get_tokens_header(doc, intermediate_token)
|
104
|
+
|
105
|
+
message.add('ns1:serviceId', @@SERVICE_ID)
|
106
|
+
end
|
107
|
+
|
108
|
+
security_token = get_token_data_from_response(response)
|
109
|
+
|
110
|
+
return security_token
|
111
|
+
end
|
112
|
+
|
113
|
+
# Builds the header including the username/password token
|
114
|
+
# to call the login method in order to gather an intermediate token.
|
115
|
+
#
|
116
|
+
# The header of the given document will be enhanced so there is no need to
|
117
|
+
# process the returning value.
|
118
|
+
# ===Parameters
|
119
|
+
# <tt>doc</tt>:: Request XmlMason document.
|
120
|
+
def build_login_header(doc)
|
121
|
+
|
122
|
+
# Get the header element
|
123
|
+
header = build_security_header_common(doc)
|
124
|
+
|
125
|
+
security = header.find('Security')
|
126
|
+
security.add("UsernameToken")
|
127
|
+
|
128
|
+
# Create username section
|
129
|
+
username_token = security.find("UsernameToken")
|
130
|
+
username_token.add("Username")
|
131
|
+
username = username_token.find("Username")
|
132
|
+
username.set_value(@username)
|
133
|
+
|
134
|
+
# Create password section
|
135
|
+
username_token.add("Password")
|
136
|
+
password = username_token.find("Password")
|
137
|
+
password.set_attr("Type", "http://docs.oasis-open.org/wss/2004/01/oasis-200401-wss-username-token-profile-1.0#PasswordText")
|
138
|
+
password.set_value(@password)
|
139
|
+
|
140
|
+
return header
|
141
|
+
end
|
142
|
+
|
143
|
+
# Build the header using the intermediate_token to gather the security token(s).
|
144
|
+
# This is part of the authentication process.
|
145
|
+
#
|
146
|
+
# The header of the given document will be enhanced so there is no need to
|
147
|
+
# process the returning value.
|
148
|
+
# ==Parameter
|
149
|
+
# <tt>doc</tt>:: Request XmlMason document.
|
150
|
+
# <tt>intermediate_token</tt>:: Intermediate token gathered by invoking the <tt>login</tt>-Method
|
151
|
+
def build_get_tokens_header(doc, intermediate_token)
|
152
|
+
|
153
|
+
# Get the header element
|
154
|
+
header = build_security_header_common(doc)
|
155
|
+
security = header.find("Security")
|
156
|
+
security.set_value( intermediate_token, :raw )
|
157
|
+
|
158
|
+
return header
|
159
|
+
end
|
160
|
+
|
161
|
+
end
|
162
|
+
end
|
@@ -0,0 +1,31 @@
|
|
1
|
+
require File.dirname(__FILE__) + '/../basic_response'
|
2
|
+
|
3
|
+
# Represents a response for a voice call operation, such as <tt>new_call</tt> ot the
|
4
|
+
# VoiceCallService.
|
5
|
+
class CallStatusResponse < BasicResponse
|
6
|
+
|
7
|
+
attr_accessor :connection_time_a, :connection_time_b, :description_a, :description_b, :reason_a, :reason_b
|
8
|
+
attr_accessor :state_a, :state_b
|
9
|
+
|
10
|
+
# Constructor.
|
11
|
+
# ===Parameters
|
12
|
+
# <tt>response_xml</tt>:: Xml as returned by a <tt>call_status</tt>-method call.
|
13
|
+
# <tt>raise_exception_on_error</tt>:: Xml as returned by a <tt>call_status</tt>-method call.
|
14
|
+
def initialize(response_xml, raise_exception_on_error = true)
|
15
|
+
doc = response_xml.document
|
16
|
+
|
17
|
+
@error_code = doc.xpath("//status").text
|
18
|
+
@error_message = doc.xpath("//err_msg").text
|
19
|
+
@session_id = doc.xpath("//sessionId").text
|
20
|
+
@connection_time_a = doc.xpath("//connectiontimea").text
|
21
|
+
@connection_time_b = doc.xpath("//connectiontimeb").text
|
22
|
+
@description_a = doc.xpath("//descriptiona").text
|
23
|
+
@description_b = doc.xpath("//descriptionb").text
|
24
|
+
@reason_a = doc.xpath("//reasona").text
|
25
|
+
@reason_b = doc.xpath("//reasonb").text
|
26
|
+
@state_a = doc.xpath("//statea").text
|
27
|
+
@state_b = doc.xpath("//stateb").text
|
28
|
+
|
29
|
+
raise_on_error(response_xml) if raise_exception_on_error
|
30
|
+
end
|
31
|
+
end
|
@@ -0,0 +1,22 @@
|
|
1
|
+
require File.dirname(__FILE__) + '/../basic_response'
|
2
|
+
|
3
|
+
# Represents a response for a voice call operation, such as <tt>new_call</tt> ot the
|
4
|
+
# VoiceCallService.
|
5
|
+
class VoiceCallResponse < BasicResponse
|
6
|
+
|
7
|
+
attr_accessor :session_id
|
8
|
+
|
9
|
+
# Constructor.
|
10
|
+
# ===Parameters
|
11
|
+
# <tt>response_xml</tt>:: Xml as returned by a <tt>call_status</tt>-method call.
|
12
|
+
# <tt>raise_exception_on_error</tt>:: Xml as returned by a <tt>call_status</tt>-method call.
|
13
|
+
def initialize(response_xml, raise_exception_on_error = true)
|
14
|
+
doc = response_xml.document
|
15
|
+
|
16
|
+
@error_code = doc.xpath("//status").text
|
17
|
+
@error_message = doc.xpath("//err_msg").text
|
18
|
+
@session_id = doc.xpath("//sessionId").text
|
19
|
+
|
20
|
+
raise_on_error(response_xml) if raise_exception_on_error
|
21
|
+
end
|
22
|
+
end
|
@@ -0,0 +1,137 @@
|
|
1
|
+
require File.dirname(__FILE__) + '/../authenticated_service'
|
2
|
+
require File.dirname(__FILE__) + '/../service_environment'
|
3
|
+
require File.dirname(__FILE__) + '/../voice_call_service/voice_call_response'
|
4
|
+
require File.dirname(__FILE__) + '/../voice_call_service/call_status_response'
|
5
|
+
|
6
|
+
Handsoap.http_driver = :httpclient
|
7
|
+
|
8
|
+
# Print http and soap requests and reponses if ruby has been started with -d option.
|
9
|
+
Handsoap::Service.logger = $stdout if $DEBUG
|
10
|
+
|
11
|
+
module VoiceCallService
|
12
|
+
|
13
|
+
# Establish voice calls between two participants
|
14
|
+
# See also: http://www.developergarden.com/openapi/dokumentation/services#4.2.1.
|
15
|
+
class VoiceCallService < AuthenticatedService
|
16
|
+
@@VOICE_CALL_SERVICE_ENDPOINT = {
|
17
|
+
:uri => "https://gateway.developer.telekom.com/p3gw-mod-odg-voicebutler/services/VoiceButlerService",
|
18
|
+
:version => 1
|
19
|
+
}
|
20
|
+
|
21
|
+
endpoint @@VOICE_CALL_SERVICE_ENDPOINT
|
22
|
+
|
23
|
+
# Establish a voice call between two participants.
|
24
|
+
# After a connection to the first participant has been successfully established the seccond particiant is called.
|
25
|
+
# The call is established after the 2nd participant has picked up.
|
26
|
+
#
|
27
|
+
# ===Parameters
|
28
|
+
# <tt>a_number</tt>:: Phone number of participant a.
|
29
|
+
# <tt>b_number</tt>:: Phone number of participant b.
|
30
|
+
# <tt>expiration</tt>:: Nr of seconds until the call will be canceled if no <tt>call_status</tt> call is received.
|
31
|
+
# <tt>max_duration</tt>:: Maximum duration of the call in secons. In addition to this the system limit is applied.
|
32
|
+
# <tt>environment</tt>:: Service environment as defined in ServiceLevel.
|
33
|
+
# <tt>privacy_a</tt>:: Whether to show the phone number of participant a.
|
34
|
+
# <tt>privacy_b</tt>:: Whether to show the phone number of participant b.
|
35
|
+
# <tt>greeter</tt>:: Currently unused
|
36
|
+
# <tt>account</tt>:: Currently unused
|
37
|
+
def new_call(a_number, b_number, expiration, max_duration, environment = ServiceEnvironment.MOCK, privacy_a = false, privacy_b = false, greeter = "", account = "")
|
38
|
+
response = invoke_authenticated("newCall") do |message, doc|
|
39
|
+
message.add("request")
|
40
|
+
request = message.find("request")
|
41
|
+
request.add('environment', environment)
|
42
|
+
request.add('aNumber', a_number)
|
43
|
+
request.add('bNumber', b_number)
|
44
|
+
request.add('privacyA', privacy_a.to_s)
|
45
|
+
request.add('privacyB', privacy_b.to_s)
|
46
|
+
request.add('expiration', expiration)
|
47
|
+
request.add('maxDuration', max_duration)
|
48
|
+
request.add('greeter', greeter)
|
49
|
+
request.add('account', account)
|
50
|
+
end
|
51
|
+
|
52
|
+
return VoiceCallResponse.new(response)
|
53
|
+
end
|
54
|
+
|
55
|
+
# Retrieve information about a specific call.
|
56
|
+
# ===Parameters
|
57
|
+
# <tt>session_id</tt>:: Session id of the call of interest.
|
58
|
+
# <tt>environment</tt>:: Service environment as defined in ServiceEnvironment.
|
59
|
+
# <tt>keep_alive</tt>:: Prevent an expiration of the call by calling <tt>call_status</tt> with <tt>keep_alive = 1</tt>.
|
60
|
+
def call_status(session_id, environment = ServiceEnvironment.MOCK, keep_alive = 1)
|
61
|
+
response = invoke_authenticated("callStatus") do |message, doc|
|
62
|
+
message.add("request")
|
63
|
+
request = message.find("request")
|
64
|
+
request.add('environment', environment)
|
65
|
+
request.add('keepAlive', keep_alive)
|
66
|
+
request.add('sessionId', session_id)
|
67
|
+
end
|
68
|
+
|
69
|
+
return CallStatusResponse.new(response)
|
70
|
+
end
|
71
|
+
|
72
|
+
# Cancels an ongoing call.
|
73
|
+
# ===Parameters
|
74
|
+
# <tt>session_id</tt>::
|
75
|
+
# <tt>environment</tt>:: Service environment as defined in ServiceEnvironment.
|
76
|
+
def teardown_call(session_id, environment = ServiceEnvironment.MOCK)
|
77
|
+
response = invoke_authenticated("tearDownCall") do |message, doc|
|
78
|
+
|
79
|
+
# Add namespace
|
80
|
+
tdc = message.find("tearDownCall")
|
81
|
+
tdc.set_attr("xmlns", "http://webservice.voicebutler.odg.tonline.de")
|
82
|
+
|
83
|
+
message.add("request")
|
84
|
+
request = message.find("request")
|
85
|
+
request.add('environment', environment)
|
86
|
+
request.add('sessionId', session_id)
|
87
|
+
end
|
88
|
+
|
89
|
+
return CallStatusResponse.new(response)
|
90
|
+
end
|
91
|
+
|
92
|
+
# Establishes a voice call similar to <tt>newCall</tt>. <tt>b_number</tt> can be an array of numbers.
|
93
|
+
# The service will call participants listed in <tt>b_number</tt> in sequence until sb. picks up.
|
94
|
+
# ===Parameters
|
95
|
+
# <tt>a_number</tt>:: Phone number of participant a.
|
96
|
+
# <tt>b_number</tt>:: Phone number(s) of participant b. <tt>b_number</tt> can be an array of strings
|
97
|
+
# representing numbers or a single string representing a single number.
|
98
|
+
# <tt>expiration</tt>:: Nr of seconds until the call will be canceled if no <tt>call_status</tt> with keepalive=true call is received.
|
99
|
+
# <tt>max_duration</tt>:: Maximum duration of the call in secons. In addition to this the system limit is applied.
|
100
|
+
# <tt>environment</tt>:: Service environment as defined in ServiceEnvironment.
|
101
|
+
# <tt>privacy_a</tt>:: Whether to show the phone number of participant a.
|
102
|
+
# <tt>privacy_b</tt>:: Whether to show the phone number of participant b.
|
103
|
+
# <tt>max_wait</tt>:: Call the next participant after max_wait seconds.
|
104
|
+
# <tt>greeter</tt>:: Currently unused.
|
105
|
+
# <tt>account</tt>:: Currently unused.
|
106
|
+
def new_call_sequenced(a_number, b_number, expiration, max_duration, environment = ServiceEnvironment.MOCK, privacy_a = false, privacy_b = false, max_wait = 60, greeter = "", account = "")
|
107
|
+
response = invoke_authenticated("newCallSequenced") do |message, doc|
|
108
|
+
message.add("request")
|
109
|
+
request = message.find("request")
|
110
|
+
request.add('environment', environment)
|
111
|
+
request.add('aNumber', a_number)
|
112
|
+
|
113
|
+
# b_number can be an array of strings representing numbers or a single string representing a single number.
|
114
|
+
if b_number.is_a? Array then
|
115
|
+
# It's an array
|
116
|
+
for bn in b_number do
|
117
|
+
request.add('bNumber', bn)
|
118
|
+
end
|
119
|
+
else
|
120
|
+
|
121
|
+
# We assume its a string
|
122
|
+
request.add('bNumber', b_number)
|
123
|
+
end
|
124
|
+
|
125
|
+
request.add('privacyA', privacy_a.to_s)
|
126
|
+
request.add('privacyB', privacy_b.to_s)
|
127
|
+
request.add('expiration', expiration)
|
128
|
+
request.add('maxDuration', max_duration)
|
129
|
+
request.add('maxWait', max_wait)
|
130
|
+
request.add('greeter', greeter)
|
131
|
+
request.add('account', account)
|
132
|
+
end
|
133
|
+
|
134
|
+
return VoiceCallResponse.new(response)
|
135
|
+
end
|
136
|
+
end
|
137
|
+
end
|
metadata
ADDED
@@ -0,0 +1,116 @@
|
|
1
|
+
--- !ruby/object:Gem::Specification
|
2
|
+
name: developergarden_sdk
|
3
|
+
version: !ruby/object:Gem::Version
|
4
|
+
version: 0.0.8
|
5
|
+
platform: ruby
|
6
|
+
authors:
|
7
|
+
- Julian Fischer / Aperto move GmbH
|
8
|
+
autorequire:
|
9
|
+
bindir: bin
|
10
|
+
cert_chain: []
|
11
|
+
|
12
|
+
date: 2009-08-04 00:00:00 +02:00
|
13
|
+
default_executable:
|
14
|
+
dependencies:
|
15
|
+
- !ruby/object:Gem::Dependency
|
16
|
+
name: httpclient
|
17
|
+
type: :runtime
|
18
|
+
version_requirement:
|
19
|
+
version_requirements: !ruby/object:Gem::Requirement
|
20
|
+
requirements:
|
21
|
+
- - "="
|
22
|
+
- !ruby/object:Gem::Version
|
23
|
+
version: 2.1.4
|
24
|
+
version:
|
25
|
+
- !ruby/object:Gem::Dependency
|
26
|
+
name: nokogiri
|
27
|
+
type: :runtime
|
28
|
+
version_requirement:
|
29
|
+
version_requirements: !ruby/object:Gem::Requirement
|
30
|
+
requirements:
|
31
|
+
- - ">="
|
32
|
+
- !ruby/object:Gem::Version
|
33
|
+
version: 1.3.1
|
34
|
+
version:
|
35
|
+
- !ruby/object:Gem::Dependency
|
36
|
+
name: troelskn-handsoap
|
37
|
+
type: :runtime
|
38
|
+
version_requirement:
|
39
|
+
version_requirements: !ruby/object:Gem::Requirement
|
40
|
+
requirements:
|
41
|
+
- - "="
|
42
|
+
- !ruby/object:Gem::Version
|
43
|
+
version: 0.2.8
|
44
|
+
version:
|
45
|
+
- !ruby/object:Gem::Dependency
|
46
|
+
name: htmlentities
|
47
|
+
type: :runtime
|
48
|
+
version_requirement:
|
49
|
+
version_requirements: !ruby/object:Gem::Requirement
|
50
|
+
requirements:
|
51
|
+
- - ">="
|
52
|
+
- !ruby/object:Gem::Version
|
53
|
+
version: 4.0.0
|
54
|
+
version:
|
55
|
+
description: Offers a ruby client for the open development services such as send SMS, voice call and quota management of the Deutsche Telekom AG. See also http://www.developergarden.com.
|
56
|
+
email: ruby@developergarden.com
|
57
|
+
executables: []
|
58
|
+
|
59
|
+
extensions: []
|
60
|
+
|
61
|
+
extra_rdoc_files:
|
62
|
+
- README
|
63
|
+
- LICENSE
|
64
|
+
files:
|
65
|
+
- LICENSE
|
66
|
+
- README
|
67
|
+
- Rakefile
|
68
|
+
- lib/authenticated_service.rb
|
69
|
+
- lib/basic_response.rb
|
70
|
+
- lib/basic_service.rb
|
71
|
+
- lib/common
|
72
|
+
- lib/common/xml_tools.rb
|
73
|
+
- lib/quota_service
|
74
|
+
- lib/quota_service/quota_information.rb
|
75
|
+
- lib/quota_service/quota_service.rb
|
76
|
+
- lib/service_environment.rb
|
77
|
+
- lib/service_exception.rb
|
78
|
+
- lib/sms_service
|
79
|
+
- lib/sms_service/sms_response.rb
|
80
|
+
- lib/sms_service/sms_service.rb
|
81
|
+
- lib/telekom_sdk.rb
|
82
|
+
- lib/token_service
|
83
|
+
- lib/token_service/security_token_validator.rb
|
84
|
+
- lib/token_service/token_service.rb
|
85
|
+
- lib/voice_call_service
|
86
|
+
- lib/voice_call_service/call_status_response.rb
|
87
|
+
- lib/voice_call_service/voice_call_response.rb
|
88
|
+
- lib/voice_call_service/voice_call_service.rb
|
89
|
+
has_rdoc: true
|
90
|
+
homepage: http://www.developergarden.com
|
91
|
+
post_install_message:
|
92
|
+
rdoc_options: []
|
93
|
+
|
94
|
+
require_paths:
|
95
|
+
- lib
|
96
|
+
required_ruby_version: !ruby/object:Gem::Requirement
|
97
|
+
requirements:
|
98
|
+
- - ">="
|
99
|
+
- !ruby/object:Gem::Version
|
100
|
+
version: "0"
|
101
|
+
version:
|
102
|
+
required_rubygems_version: !ruby/object:Gem::Requirement
|
103
|
+
requirements:
|
104
|
+
- - ">="
|
105
|
+
- !ruby/object:Gem::Version
|
106
|
+
version: "0"
|
107
|
+
version:
|
108
|
+
requirements: []
|
109
|
+
|
110
|
+
rubyforge_project:
|
111
|
+
rubygems_version: 1.3.1
|
112
|
+
signing_key:
|
113
|
+
specification_version: 2
|
114
|
+
summary: Offers a ruby client for the open development services such as send SMS, voice call and quota management of the Deutsche Telekom AG. See also http://www.developergarden.com.
|
115
|
+
test_files: []
|
116
|
+
|