smart-mobile 0.0.1
Sign up to get free protection for your applications and to get access to all the features.
- data/.DS_Store +0 -0
- data/.gitignore +20 -0
- data/Gemfile +5 -0
- data/README.md +12 -0
- data/Rakefile +8 -0
- data/lib/smart-mobile.rb +13 -0
- data/lib/smart/rest/client.rb +81 -0
- data/lib/smart/rest/config.rb +22 -0
- data/lib/smart/rest/response.rb +95 -0
- data/lib/smart/rest/sms.rb +8 -0
- data/lib/smart/support.rb +30 -0
- data/lib/smart/version.rb +3 -0
- data/smart-mobile.gemspec +22 -0
- data/test/.DS_Store +0 -0
- data/test/test_helper.rb +9 -0
- data/test/test_smart.rb +52 -0
- data/travis.yml +3 -0
- metadata +75 -0
data/.DS_Store
ADDED
Binary file
|
data/.gitignore
ADDED
data/Gemfile
ADDED
data/README.md
ADDED
@@ -0,0 +1,12 @@
|
|
1
|
+
smart-mobile
|
2
|
+
============
|
3
|
+
|
4
|
+
Smart Mobile API
|
5
|
+
|
6
|
+
## MIT Open Source License
|
7
|
+
|
8
|
+
Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions:
|
9
|
+
|
10
|
+
The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software.
|
11
|
+
|
12
|
+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
data/Rakefile
ADDED
data/lib/smart-mobile.rb
ADDED
@@ -0,0 +1,13 @@
|
|
1
|
+
require 'rubygems'
|
2
|
+
|
3
|
+
require 'nokogiri'
|
4
|
+
require 'net/https'
|
5
|
+
require 'uri'
|
6
|
+
require 'json'
|
7
|
+
|
8
|
+
require_relative 'smart/support'
|
9
|
+
require_relative 'smart/version'
|
10
|
+
require_relative 'smart/rest/config'
|
11
|
+
require_relative 'smart/rest/response'
|
12
|
+
require_relative 'smart/rest/client'
|
13
|
+
require_relative 'smart/rest/sms'
|
@@ -0,0 +1,81 @@
|
|
1
|
+
module Smart
|
2
|
+
module REST
|
3
|
+
class Client
|
4
|
+
include ClassSupportMixin
|
5
|
+
include Smart::REST::Configuration
|
6
|
+
|
7
|
+
HTTP_HEADERS = {
|
8
|
+
'Content-Type' => 'application/json',
|
9
|
+
'Accept' => 'application/json',
|
10
|
+
'Authorization' => 'WSSE realm="SDP",profile="UsernameToken"'
|
11
|
+
}
|
12
|
+
|
13
|
+
set_attributes :host => 'npwifi.smart.com.ph',
|
14
|
+
:port => 443,
|
15
|
+
:timeout => 30,
|
16
|
+
:retry_limit => 1,
|
17
|
+
:sp_id => '',
|
18
|
+
:sp_password => '',
|
19
|
+
:service_id => '',
|
20
|
+
:nonce => '',
|
21
|
+
:creation_time => '',
|
22
|
+
:trans_id => '',
|
23
|
+
:access_code => '',
|
24
|
+
:mobile_number => '',
|
25
|
+
:path_to_cert => '',
|
26
|
+
:mobile_number => '',
|
27
|
+
:message => ''
|
28
|
+
|
29
|
+
|
30
|
+
attr_reader :sp_id, :sp_password, :sp_service_id, :nonce, :creation_time, :trans_id, :access_code, :mobile_number, :path_to_cert
|
31
|
+
|
32
|
+
def headers
|
33
|
+
HTTP_HEADERS.merge! ({
|
34
|
+
'X-WSSE' => %{ "UsernameToken Username="#{self.sp_id}",PasswordDigest="#{self.sp_password}",Nonce="#{self.nonce}", Created="#{self.creation_time}"},
|
35
|
+
'X-RequestHeader' => %{ "request TransId="",ServiceId="#{self.service_id}" }
|
36
|
+
})
|
37
|
+
end
|
38
|
+
|
39
|
+
def send_sms(args = {})
|
40
|
+
request = setup_connection(args)
|
41
|
+
response = connect(request)
|
42
|
+
end
|
43
|
+
|
44
|
+
private
|
45
|
+
|
46
|
+
def setup_sms_outbound_endpoint
|
47
|
+
"https://#{self.host}/1/smsmessaging/outbound/#{self.access_code}/requests"
|
48
|
+
end
|
49
|
+
|
50
|
+
def setup_connection(args)
|
51
|
+
uri = URI.parse(setup_sms_outbound_endpoint)
|
52
|
+
@http = Net::HTTP.new(uri.host, uri.port)
|
53
|
+
@http.use_ssl = true
|
54
|
+
@http.verify_mode = OpenSSL::SSL::VERIFY_NONE
|
55
|
+
@http.open_timeout = 3 # in seconds
|
56
|
+
@http.read_timeout = 3 # in seconds
|
57
|
+
|
58
|
+
store = OpenSSL::X509::Store.new
|
59
|
+
store.add_cert(OpenSSL::X509::Certificate.new(File.read(self.path_to_cert)))
|
60
|
+
@http.cert_store = store
|
61
|
+
|
62
|
+
request = Net::HTTP::Post.new(uri.request_uri, initheader = headers)
|
63
|
+
request.body = args.to_json
|
64
|
+
request
|
65
|
+
end
|
66
|
+
|
67
|
+
def connect(request)
|
68
|
+
response = @http.request(request)
|
69
|
+
|
70
|
+
if response.body and !response.body.empty?
|
71
|
+
object = JSON.parse(response.body)
|
72
|
+
end
|
73
|
+
if response.kind_of? Net::HTTPClientError
|
74
|
+
error = Smart::REST::Response.new(object["requestError"]["serviceException"]["messageId"])
|
75
|
+
raise error.to_s
|
76
|
+
end
|
77
|
+
response
|
78
|
+
end
|
79
|
+
end
|
80
|
+
end
|
81
|
+
end
|
@@ -0,0 +1,22 @@
|
|
1
|
+
module Smart
|
2
|
+
module REST
|
3
|
+
module Configuration
|
4
|
+
def self.included(base)
|
5
|
+
base.extend ClassMethods
|
6
|
+
end
|
7
|
+
|
8
|
+
module ClassMethods
|
9
|
+
def configure(&block)
|
10
|
+
config = self.new
|
11
|
+
raise ArgumentError, "Please provide configuration block" unless block_given?
|
12
|
+
yield config
|
13
|
+
|
14
|
+
[:sp_id, :sp_password, :service_id, :access_code, :path_to_cert].each do |required|
|
15
|
+
raise "#{required} is required" unless config.send(required)
|
16
|
+
end
|
17
|
+
config
|
18
|
+
end
|
19
|
+
end
|
20
|
+
end
|
21
|
+
end
|
22
|
+
end
|
@@ -0,0 +1,95 @@
|
|
1
|
+
module Smart
|
2
|
+
module REST
|
3
|
+
class Response
|
4
|
+
attr_reader :response_code
|
5
|
+
#TODO:
|
6
|
+
# Service Exception Extension
|
7
|
+
# Policy Exceptions
|
8
|
+
# Policy Exception Extension
|
9
|
+
@@error_map = {
|
10
|
+
:condition_not_met? => 304,
|
11
|
+
:invalid_request_parameters? => 400,
|
12
|
+
:authentication_failed? => 401,
|
13
|
+
:not_permitted? => 403,
|
14
|
+
:not_found? => 404,
|
15
|
+
:method_not_allowed? => 405,
|
16
|
+
:conflict? => 409,
|
17
|
+
:content_length_required? => 411,
|
18
|
+
:precondition_failed? => 412,
|
19
|
+
:request_body_too_large? => 413,
|
20
|
+
:invalid_range? => 416,
|
21
|
+
:internal_server_error? => 500,
|
22
|
+
:server_busy? => 503,
|
23
|
+
:service_error? => 'SVC0001',
|
24
|
+
:invalid_input_value? => 'SVC0002',
|
25
|
+
:invalid_input_value_with_valid_values? => 'SVC0003',
|
26
|
+
:no_valid_address? => 'SVC0004',
|
27
|
+
:duplicate_correlator? => 'SVC0005',
|
28
|
+
:invalid_group? => 'SVC0006',
|
29
|
+
:invalid_charging_info? => 'SVC0007',
|
30
|
+
:overlapping_criteria? => 'SVC0008',
|
31
|
+
:success? => 200,
|
32
|
+
:created? => 201,
|
33
|
+
:no_content? => 204,
|
34
|
+
:password_not_accepted? => 'SVC0901'
|
35
|
+
}
|
36
|
+
|
37
|
+
@@status_messages = {
|
38
|
+
304 => "ConditionNotMet - Not Modified: The condition specified in the conditional header(s) was not met for a read operation.",
|
39
|
+
400 => "Invalid parameters in the request",
|
40
|
+
401 => "Authentication failure",
|
41
|
+
403 => "Application does not have permissions to access resource due to the policy constraints (request rate limit, etc)",
|
42
|
+
404 => "Not Found - The specified resource does not exist.",
|
43
|
+
405 => "Method not allowed by the resource",
|
44
|
+
409 => "Conflict",
|
45
|
+
411 => "Length Required: The Content-Length header was not specified.",
|
46
|
+
412 => "Precondition Failed: The condition specified in the conditional header(s) was not met for a write operation.",
|
47
|
+
413 => "RequestBodyTooLarge - Request Entity Too Large: The size of the request body exceeds the maximum size permitted.",
|
48
|
+
416 => "InvalidRange - Requested Range Not Satisfiable: The range specified is invalid for the current size of the resource.",
|
49
|
+
500 => "Internal server error",
|
50
|
+
503 => "ServerBusy - Service Unavailable: The server is currently unable to receive requests. Please retry your request.",
|
51
|
+
"SVC0001" => "Service Error",
|
52
|
+
"SVC0002" => "Invalid input value",
|
53
|
+
"SVC0003" => "Invalid input value with list of valid values",
|
54
|
+
"SVC0004" => "No valid addresses",
|
55
|
+
"SVC0005" => "Duplicate correlator",
|
56
|
+
"SVC0006" => "Invalid group",
|
57
|
+
"SVC0007" => "Invalid charging information",
|
58
|
+
"SVC0008" => "Overlapping Criteria",
|
59
|
+
"SVC0901" => "Sp password is not accepted!",
|
60
|
+
200 => "Success",
|
61
|
+
201 => "Created",
|
62
|
+
204 => "No Content"
|
63
|
+
}
|
64
|
+
|
65
|
+
def initialize(code)
|
66
|
+
@response_code = code
|
67
|
+
end
|
68
|
+
|
69
|
+
def valid?
|
70
|
+
[200, 201].include?(self.response_code)
|
71
|
+
end
|
72
|
+
|
73
|
+
def to_s
|
74
|
+
#"#{self.response_code} - #{msg}"
|
75
|
+
msg
|
76
|
+
end
|
77
|
+
|
78
|
+
def msg(code = self.response_code)
|
79
|
+
if msg = @@status_messages[code]
|
80
|
+
msg
|
81
|
+
else
|
82
|
+
raise ArgumentError, "#{code} - undefined response code"
|
83
|
+
end
|
84
|
+
end
|
85
|
+
|
86
|
+
def method_missing(method_id)
|
87
|
+
if code = @@error_map[method_id.to_sym]
|
88
|
+
self.response_code == code
|
89
|
+
else
|
90
|
+
raise NoMethodError
|
91
|
+
end
|
92
|
+
end
|
93
|
+
end
|
94
|
+
end
|
95
|
+
end
|
@@ -0,0 +1,30 @@
|
|
1
|
+
module ClassSupportMixin
|
2
|
+
def self.included(base)
|
3
|
+
base.send(:include, InstanceMethods)
|
4
|
+
base.extend ClassMethods
|
5
|
+
end
|
6
|
+
|
7
|
+
module ClassMethods
|
8
|
+
def set_attributes(attrs)
|
9
|
+
attr_accessor *attrs.keys
|
10
|
+
define_method(:default_attributes) { attrs }
|
11
|
+
end
|
12
|
+
end
|
13
|
+
|
14
|
+
module InstanceMethods
|
15
|
+
def initialize(options={})
|
16
|
+
init = if self.respond_to?(:default_attributes)
|
17
|
+
self.default_attributes.merge(options)
|
18
|
+
else
|
19
|
+
options
|
20
|
+
end
|
21
|
+
init.each { |k, v| self.send("#{k}=", v) if self.respond_to?(k) }
|
22
|
+
end
|
23
|
+
|
24
|
+
def attributes
|
25
|
+
attrs = {}
|
26
|
+
self.default_attributes.keys.each {|k| attrs[k] = self.send(k) if self.respond_to?(k)}
|
27
|
+
attrs
|
28
|
+
end
|
29
|
+
end
|
30
|
+
end
|
@@ -0,0 +1,22 @@
|
|
1
|
+
# -*- encoding: utf-8 -*-
|
2
|
+
lib = File.expand_path('../lib', __FILE__)
|
3
|
+
|
4
|
+
Gem::Specification.new do |s|
|
5
|
+
s.name = 'smart-mobile'
|
6
|
+
s.version = '0.0.1'
|
7
|
+
s.date = '2012-11-24'
|
8
|
+
s.email = 'me@iantusil.com'
|
9
|
+
|
10
|
+
s.summary = "A gem for consuming Smart Mobile API"
|
11
|
+
s.description = "A gem for consuming Smart Mobile API (currently supports SMS only)."
|
12
|
+
s.author = "Ian Bert Tusil"
|
13
|
+
s.homepage = 'http://www.smart.com.ph/developer'
|
14
|
+
s.license = 'MIT'
|
15
|
+
|
16
|
+
s.platform = Gem::Platform::RUBY
|
17
|
+
s.require_paths = %w[lib]
|
18
|
+
s.files = `git ls-files`.split("\n")
|
19
|
+
s.test_files = Dir['test/*.rb']
|
20
|
+
|
21
|
+
s.add_development_dependency 'minitest', '~> 4.3.3'
|
22
|
+
end
|
data/test/.DS_Store
ADDED
Binary file
|
data/test/test_helper.rb
ADDED
data/test/test_smart.rb
ADDED
@@ -0,0 +1,52 @@
|
|
1
|
+
require_relative 'test_helper'
|
2
|
+
require_relative '../lib/smart-mobile'
|
3
|
+
|
4
|
+
describe Smart do
|
5
|
+
|
6
|
+
before do
|
7
|
+
@sms = Smart::REST::SMS.new
|
8
|
+
end
|
9
|
+
|
10
|
+
def valid_sms_data
|
11
|
+
{"outboundSMSMessageRequest" =>
|
12
|
+
{"address" => ["tel:+639176230655"],
|
13
|
+
"senderAddress" => config_file['access_code'].to_s,
|
14
|
+
"outboundSMSTextMessage" => {
|
15
|
+
"message" => "Test Message"
|
16
|
+
}
|
17
|
+
}
|
18
|
+
}
|
19
|
+
end
|
20
|
+
|
21
|
+
def client
|
22
|
+
@client ||= initialize_rest_client
|
23
|
+
end
|
24
|
+
|
25
|
+
def initialize_rest_client
|
26
|
+
Smart::REST::Client.configure do |config|
|
27
|
+
config.sp_id = config_file['sp_id']
|
28
|
+
config.sp_password = config_file['sp_password'].to_s
|
29
|
+
config.service_id = config_file['service_id']
|
30
|
+
config.access_code = config_file['access_code'].to_s
|
31
|
+
config.path_to_cert = config_file['path_to_cert']
|
32
|
+
config.creation_time = config_file['creation_time']
|
33
|
+
config.nonce = config_file['nonce']
|
34
|
+
end
|
35
|
+
end
|
36
|
+
|
37
|
+
it 'should not allow for invalid sp_password' do
|
38
|
+
begin
|
39
|
+
response = client.send_sms(valid_sms_data)
|
40
|
+
rescue Exception => e
|
41
|
+
e.message.must_equal Smart::REST::Response.new('SVC0901').to_s
|
42
|
+
end
|
43
|
+
end
|
44
|
+
|
45
|
+
it 'should have a valid certificate' do
|
46
|
+
|
47
|
+
end
|
48
|
+
|
49
|
+
it 'should try to retry up to the max number of retry limited' do
|
50
|
+
end
|
51
|
+
|
52
|
+
end
|
data/travis.yml
ADDED
metadata
ADDED
@@ -0,0 +1,75 @@
|
|
1
|
+
--- !ruby/object:Gem::Specification
|
2
|
+
name: smart-mobile
|
3
|
+
version: !ruby/object:Gem::Version
|
4
|
+
version: 0.0.1
|
5
|
+
prerelease:
|
6
|
+
platform: ruby
|
7
|
+
authors:
|
8
|
+
- Ian Bert Tusil
|
9
|
+
autorequire:
|
10
|
+
bindir: bin
|
11
|
+
cert_chain: []
|
12
|
+
date: 2012-11-24 00:00:00.000000000Z
|
13
|
+
dependencies:
|
14
|
+
- !ruby/object:Gem::Dependency
|
15
|
+
name: minitest
|
16
|
+
requirement: &319130 !ruby/object:Gem::Requirement
|
17
|
+
none: false
|
18
|
+
requirements:
|
19
|
+
- - ~>
|
20
|
+
- !ruby/object:Gem::Version
|
21
|
+
version: 4.3.3
|
22
|
+
type: :development
|
23
|
+
prerelease: false
|
24
|
+
version_requirements: *319130
|
25
|
+
description: A gem for consuming Smart Mobile API (currently supports SMS only).
|
26
|
+
email: me@iantusil.com
|
27
|
+
executables: []
|
28
|
+
extensions: []
|
29
|
+
extra_rdoc_files: []
|
30
|
+
files:
|
31
|
+
- .DS_Store
|
32
|
+
- .gitignore
|
33
|
+
- Gemfile
|
34
|
+
- README.md
|
35
|
+
- Rakefile
|
36
|
+
- lib/smart-mobile.rb
|
37
|
+
- lib/smart/rest/client.rb
|
38
|
+
- lib/smart/rest/config.rb
|
39
|
+
- lib/smart/rest/response.rb
|
40
|
+
- lib/smart/rest/sms.rb
|
41
|
+
- lib/smart/support.rb
|
42
|
+
- lib/smart/version.rb
|
43
|
+
- smart-mobile.gemspec
|
44
|
+
- test/.DS_Store
|
45
|
+
- test/test_helper.rb
|
46
|
+
- test/test_smart.rb
|
47
|
+
- travis.yml
|
48
|
+
homepage: http://www.smart.com.ph/developer
|
49
|
+
licenses:
|
50
|
+
- MIT
|
51
|
+
post_install_message:
|
52
|
+
rdoc_options: []
|
53
|
+
require_paths:
|
54
|
+
- lib
|
55
|
+
required_ruby_version: !ruby/object:Gem::Requirement
|
56
|
+
none: false
|
57
|
+
requirements:
|
58
|
+
- - ! '>='
|
59
|
+
- !ruby/object:Gem::Version
|
60
|
+
version: '0'
|
61
|
+
required_rubygems_version: !ruby/object:Gem::Requirement
|
62
|
+
none: false
|
63
|
+
requirements:
|
64
|
+
- - ! '>='
|
65
|
+
- !ruby/object:Gem::Version
|
66
|
+
version: '0'
|
67
|
+
requirements: []
|
68
|
+
rubyforge_project:
|
69
|
+
rubygems_version: 1.8.17
|
70
|
+
signing_key:
|
71
|
+
specification_version: 3
|
72
|
+
summary: A gem for consuming Smart Mobile API
|
73
|
+
test_files:
|
74
|
+
- test/test_helper.rb
|
75
|
+
- test/test_smart.rb
|