developergarden_sdk 0.0.8
Sign up to get free protection for your applications and to get access to all the features.
- 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
|
+
|