action_sms_gateways 0.0.6 → 0.0.7
Sign up to get free protection for your applications and to get access to all the features.
- data/README.markdown +143 -8
- data/Rakefile +1 -0
- data/VERSION +1 -1
- data/action_sms_gateways.gemspec +8 -2
- data/lib/action_sms_gateways/connection_adapters/sms_global.rb +19 -7
- data/lib/action_sms_gateways/connection_adapters/test_helpers/sms_global.rb +40 -0
- data/lib/action_sms_gateways/connection_adapters/test_helpers/tropo.rb +68 -0
- data/lib/action_sms_gateways/connection_adapters/tropo.rb +82 -0
- metadata +22 -5
data/README.markdown
CHANGED
@@ -1,22 +1,157 @@
|
|
1
1
|
# action_sms_gateways
|
2
|
+
|
2
3
|
A collection of SMS Gateway Adapters for [action_sms](http://github.com/dwilkie/action_sms)
|
3
4
|
|
4
5
|
## Current SMS Adapters
|
6
|
+
|
5
7
|
* [SMSGlobal](http://www.smsglobal.com)
|
8
|
+
* [Tropo](http://www.tropo.com)
|
9
|
+
|
10
|
+
## Configuration
|
11
|
+
|
12
|
+
* [SMSGlobal](http://github.com/dwilkie/action_sms_gateways/wiki/SMSGlobal)
|
13
|
+
* [Tropo](http://github.com/dwilkie/action_sms_gateways/wiki/Tropo)
|
14
|
+
|
15
|
+
## Usage
|
16
|
+
|
17
|
+
### Send an SMS and check if it was successful
|
18
|
+
|
19
|
+
class SMS
|
20
|
+
def recipient
|
21
|
+
"617198378843"
|
22
|
+
end
|
23
|
+
|
24
|
+
def body
|
25
|
+
"Hello world"
|
26
|
+
end
|
27
|
+
|
28
|
+
def from
|
29
|
+
end
|
30
|
+
end
|
31
|
+
|
32
|
+
sms_gateway = ActionSms::Base.connection
|
33
|
+
response = sms_gateway.deliver(SMS.new)
|
34
|
+
success = sms_gateway.delivery_request_successful?(response)
|
35
|
+
|
36
|
+
### Receive an SMS
|
37
|
+
|
38
|
+
# Assume 'params' has the data posted back to your server
|
39
|
+
|
40
|
+
sms_gateway = ActionSms::Base.connection
|
41
|
+
|
42
|
+
# get sender
|
43
|
+
sender = sms_gateway.sender(params)
|
44
|
+
|
45
|
+
# get message text
|
46
|
+
message_text = sms_gateway.message_text(params)
|
47
|
+
|
48
|
+
### Delivery receipts
|
49
|
+
|
50
|
+
# Assume 'receipt' has the data posted back to your server as the delivery receipt
|
51
|
+
|
52
|
+
sms_gateway = ActionSms::Base.connection
|
53
|
+
|
54
|
+
# get status
|
55
|
+
status = sms_gateway.status(receipt)
|
56
|
+
|
57
|
+
# get message id
|
58
|
+
message_id = sms_gateway.message_id(receipt)
|
59
|
+
|
60
|
+
### Authentication
|
61
|
+
|
62
|
+
ActionSms::Base.establish_connection(
|
63
|
+
:authentication_key => "my secret",
|
64
|
+
:use_ssl => true
|
65
|
+
)
|
66
|
+
|
67
|
+
If you set up an: `authentication_key` in the configuration, your key will be passed back to your listener url. Using an authentication key in conjunction with a secure connection `use_ssl => true` helps protect you against someone faking incoming messages to your server. You can authenticate an incoming message as follows:
|
6
68
|
|
7
|
-
|
8
|
-
Take a look at the source under `lib/action_sms_gateways/connection_adapters/sms_global.rb` and use it as a template for your own adapter. Then why not share it for all to use...
|
69
|
+
# Assume 'params' has the data posted back to your server
|
9
70
|
|
10
|
-
|
11
|
-
|
12
|
-
|
13
|
-
|
14
|
-
|
15
|
-
|
71
|
+
sms_gateway = ActionSms::Base.connection
|
72
|
+
|
73
|
+
# Removes the authentication key from 'params' and returns true or false
|
74
|
+
sms_gateway.authenticate(params)
|
75
|
+
|
76
|
+
### Service url
|
77
|
+
|
78
|
+
# gets the gateway's api url
|
79
|
+
# ActionSms::Base.connection.service_url
|
80
|
+
|
81
|
+
## Testing
|
82
|
+
|
83
|
+
When you set: `:environment => "test"` in your configuration, you get some additional test helpers.
|
84
|
+
|
85
|
+
ActionSms::Base.establish_connection(
|
86
|
+
:environment => "test"
|
87
|
+
)
|
88
|
+
|
89
|
+
sms_gateway = ActionSms::Base.connection
|
90
|
+
|
91
|
+
# get sample incoming SMS params
|
92
|
+
sms_gateway.sample_incoming_sms
|
93
|
+
|
94
|
+
# get customized sample incoming SMS
|
95
|
+
sms_gateway.sample_incoming_sms(
|
96
|
+
:message => "hello",
|
97
|
+
:to => "6128392323",
|
98
|
+
:from => "61289339432",
|
99
|
+
:date => Time.now,
|
100
|
+
:authentic => false # see configuration
|
101
|
+
)
|
102
|
+
|
103
|
+
# get sample delivery response
|
104
|
+
sms_gateway.sample_delivery_response
|
105
|
+
|
106
|
+
# get sample delivery response (failed)
|
107
|
+
sms_gateway.sample_delivery_response(:failed => true)
|
108
|
+
|
109
|
+
# get sample message id
|
110
|
+
sms_gateway.sample_message_id
|
111
|
+
|
112
|
+
# get sample delivery receipt
|
113
|
+
sms_gateway.sample_delivery_receipt
|
114
|
+
|
115
|
+
# get customized sample delivery receipt
|
116
|
+
sms_gateway.sample_delivery_receipt(
|
117
|
+
:message_id => "12345",
|
118
|
+
:status => "delivered",
|
119
|
+
:error => "some error",
|
120
|
+
:date => Time.now
|
121
|
+
)
|
122
|
+
|
123
|
+
## Creating your own adapter
|
124
|
+
|
125
|
+
To create your own adapter all you need to do is open up the ActionSms::Base class
|
126
|
+
and add a class method named: `my_adapter_connection` which takes a single hash argument of configuration details and returns an instance of your adapter class. For example, let's create an adapter for clickatell:
|
127
|
+
|
128
|
+
# clickatell.rb
|
129
|
+
require 'action_sms/connection_adapters/abstract_adapter'
|
130
|
+
|
131
|
+
module ActionSms
|
132
|
+
class Base
|
133
|
+
def self.clickatell_connection(config)
|
134
|
+
ConnectionAdapters::ClickatellAdapter.new(config)
|
135
|
+
end
|
136
|
+
end
|
137
|
+
end
|
138
|
+
|
139
|
+
module ConnectionAdapters
|
140
|
+
class ClickatellAdapter < AbstractAdapter
|
141
|
+
# define your adapter here ...
|
142
|
+
def initialize(config)
|
143
|
+
end
|
144
|
+
end
|
145
|
+
end
|
146
|
+
|
147
|
+
Take a look at the [source](http://github.com/dwilkie/action_sms_gateways/tree/master/lib/action_sms_gateways/connection_adapters/) for more details
|
16
148
|
|
17
149
|
## Installation
|
150
|
+
|
18
151
|
gem install action_sms_gateways
|
152
|
+
|
19
153
|
### Rails
|
154
|
+
|
20
155
|
Place the following in your Gemfile:
|
21
156
|
|
22
157
|
gem action_sms_gateways
|
data/Rakefile
CHANGED
@@ -22,6 +22,7 @@ begin
|
|
22
22
|
gemspec.email = "dwilkie@gmail.com"
|
23
23
|
gemspec.homepage = "http://github.com/dwilkie/action_sms_gateways"
|
24
24
|
gemspec.authors = ["David Wilkie"]
|
25
|
+
gemspec.add_runtime_dependency "tropo_message", ">=0.0.4"
|
25
26
|
end
|
26
27
|
rescue LoadError
|
27
28
|
puts "Jeweler not available. Install it with: gem install jeweler"
|
data/VERSION
CHANGED
@@ -1 +1 @@
|
|
1
|
-
0.0.
|
1
|
+
0.0.7
|
data/action_sms_gateways.gemspec
CHANGED
@@ -5,11 +5,11 @@
|
|
5
5
|
|
6
6
|
Gem::Specification.new do |s|
|
7
7
|
s.name = %q{action_sms_gateways}
|
8
|
-
s.version = "0.0.
|
8
|
+
s.version = "0.0.7"
|
9
9
|
|
10
10
|
s.required_rubygems_version = Gem::Requirement.new(">= 0") if s.respond_to? :required_rubygems_version=
|
11
11
|
s.authors = ["David Wilkie"]
|
12
|
-
s.date = %q{2010-10-
|
12
|
+
s.date = %q{2010-10-14}
|
13
13
|
s.email = %q{dwilkie@gmail.com}
|
14
14
|
s.extra_rdoc_files = [
|
15
15
|
"README.markdown"
|
@@ -24,6 +24,9 @@ Gem::Specification.new do |s|
|
|
24
24
|
"lib/action_sms_gateways.rb",
|
25
25
|
"lib/action_sms_gateways/connection_adapters.rb",
|
26
26
|
"lib/action_sms_gateways/connection_adapters/sms_global.rb",
|
27
|
+
"lib/action_sms_gateways/connection_adapters/test_helpers/sms_global.rb",
|
28
|
+
"lib/action_sms_gateways/connection_adapters/test_helpers/tropo.rb",
|
29
|
+
"lib/action_sms_gateways/connection_adapters/tropo.rb",
|
27
30
|
"todo"
|
28
31
|
]
|
29
32
|
s.homepage = %q{http://github.com/dwilkie/action_sms_gateways}
|
@@ -37,9 +40,12 @@ Gem::Specification.new do |s|
|
|
37
40
|
s.specification_version = 3
|
38
41
|
|
39
42
|
if Gem::Version.new(Gem::VERSION) >= Gem::Version.new('1.2.0') then
|
43
|
+
s.add_runtime_dependency(%q<tropo_message>, [">= 0.0.4"])
|
40
44
|
else
|
45
|
+
s.add_dependency(%q<tropo_message>, [">= 0.0.4"])
|
41
46
|
end
|
42
47
|
else
|
48
|
+
s.add_dependency(%q<tropo_message>, [">= 0.0.4"])
|
43
49
|
end
|
44
50
|
end
|
45
51
|
|
@@ -1,10 +1,18 @@
|
|
1
1
|
require 'action_sms/connection_adapters/abstract_adapter'
|
2
|
-
require 'uri'
|
3
2
|
|
4
3
|
module ActionSms
|
5
4
|
class Base
|
6
5
|
def self.sms_global_connection(config) #:nodoc:
|
7
|
-
|
6
|
+
if config[:environment].to_s == "test"
|
7
|
+
test_helper = File.expand_path(File.dirname(__FILE__) + '/test_helpers/sms_global')
|
8
|
+
if File.exists?("#{test_helper}.rb")
|
9
|
+
require test_helper
|
10
|
+
ConnectionAdapters::SMSGlobalAdapter.class_eval do
|
11
|
+
include TestHelpers::SMSGlobal
|
12
|
+
end
|
13
|
+
end
|
14
|
+
end
|
15
|
+
ConnectionAdapters::SMSGlobalAdapter.new(config)
|
8
16
|
end
|
9
17
|
end
|
10
18
|
|
@@ -13,14 +21,18 @@ module ActionSms
|
|
13
21
|
# class. You can use this interface directly by borrowing the gateway
|
14
22
|
# connection from the Base with Base.connection.
|
15
23
|
class SMSGlobalAdapter < AbstractAdapter
|
24
|
+
require 'uri'
|
25
|
+
|
16
26
|
SERVICE_HOST = "http://smsglobal.com.au"
|
17
27
|
SERVICE_PATH = "http-api.php"
|
18
28
|
|
19
|
-
|
20
|
-
|
29
|
+
attr_reader :service_url
|
30
|
+
|
31
|
+
def initialize(config = {}) #:nodoc:
|
21
32
|
@config = config.dup
|
22
|
-
|
23
|
-
|
33
|
+
service_uri = URI.join(SERVICE_HOST, SERVICE_PATH)
|
34
|
+
service_uri.scheme = config[:use_ssl] ? "https" : "http"
|
35
|
+
@service_url = service_uri.to_s
|
24
36
|
end
|
25
37
|
|
26
38
|
def message_id(data)
|
@@ -72,7 +84,7 @@ module ActionSms
|
|
72
84
|
params.merge!(
|
73
85
|
:userfield => userfield
|
74
86
|
) if userfield
|
75
|
-
send_http_request(@service_url
|
87
|
+
send_http_request(@service_url, params)
|
76
88
|
end
|
77
89
|
end
|
78
90
|
end
|
@@ -0,0 +1,40 @@
|
|
1
|
+
module TestHelpers
|
2
|
+
module SMSGlobal
|
3
|
+
def sample_incoming_sms(options = {})
|
4
|
+
options[:message] ||= "Endia kasdf ofeao"
|
5
|
+
options[:to] ||= "61447100308"
|
6
|
+
options[:from] ||= "61447100399"
|
7
|
+
options[:date] ||= "2010-05-13 23:59:11"
|
8
|
+
params = {
|
9
|
+
"to" => options[:to],
|
10
|
+
"from" => options[:from],
|
11
|
+
"msg"=> options[:message],
|
12
|
+
"date" => options[:date]
|
13
|
+
}
|
14
|
+
params.merge!("userfield" => @config[:authentication_key]) unless options[:authentic] == false
|
15
|
+
params
|
16
|
+
end
|
17
|
+
|
18
|
+
def sample_delivery_response(options = {})
|
19
|
+
options[:failed] ? "ERROR: No action requested" : "OK: 0; Sent queued message ID: 86b1a945370734f4 SMSGlobalMsgID:6942744494999745"
|
20
|
+
end
|
21
|
+
|
22
|
+
def sample_message_id
|
23
|
+
"SMSGlobalMsgID:6942744494999745"
|
24
|
+
end
|
25
|
+
|
26
|
+
def sample_delivery_receipt(options = {})
|
27
|
+
options[:message_id] ||= "6942744494999745"
|
28
|
+
options[:status] ||= "DELIVRD"
|
29
|
+
options[:error] ||= "000"
|
30
|
+
options[:date] ||= "1005132312"
|
31
|
+
{
|
32
|
+
"msgid"=> options[:message_id],
|
33
|
+
"dlrstatus"=> options[:status],
|
34
|
+
"dlr_err"=> options[:error],
|
35
|
+
"donedate"=> options[:date]
|
36
|
+
}
|
37
|
+
end
|
38
|
+
end
|
39
|
+
end
|
40
|
+
|
@@ -0,0 +1,68 @@
|
|
1
|
+
module TestHelpers
|
2
|
+
module Tropo
|
3
|
+
def sample_incoming_sms(options = {})
|
4
|
+
options[:message] ||= "Endia kasdf ofeao"
|
5
|
+
options[:to] ||= "61447100308"
|
6
|
+
options[:from] ||= "61447100399"
|
7
|
+
options[:date] ||= "Mon Oct 11 09:21:38 UTC 2010"
|
8
|
+
params = {
|
9
|
+
"session" => {
|
10
|
+
"id"=>"12349516546e59746d6a89a990466789",
|
11
|
+
"account_id"=>"12345",
|
12
|
+
"timestamp"=> options[:date],
|
13
|
+
"user_type"=>"HUMAN",
|
14
|
+
"initial_text"=> options[:message],
|
15
|
+
"call_id"=>"123e71195545ad204bdd99f2070a7d86",
|
16
|
+
"to"=>{
|
17
|
+
"id"=> options[:to],
|
18
|
+
"name"=>"unknown",
|
19
|
+
"channel"=>"TEXT",
|
20
|
+
"network"=>"SMS"
|
21
|
+
},
|
22
|
+
"from" => {
|
23
|
+
"id"=> options[:from],
|
24
|
+
"name"=>"unknown",
|
25
|
+
"channel"=>"TEXT",
|
26
|
+
"network"=>"SMS"
|
27
|
+
},
|
28
|
+
"headers" => {
|
29
|
+
"_max-_forwards"=>"70",
|
30
|
+
"_content-_length"=>"124",
|
31
|
+
"_contact"=>"<sip:11.8.93.101:5066;transport=udp>",
|
32
|
+
"_to"=>"<sip:1231454582@10.6.69.203:5061;to=#{options[:to]}>",
|
33
|
+
"_c_seq"=>"1 INVITE",
|
34
|
+
"_via"=>"SIP/2.0/UDP 11.8.93.101:5066;branch=h0hG4bKk5sy1e",
|
35
|
+
"_call-_i_d"=>"ieeg18",
|
36
|
+
"_content-_type"=>"application/sdp",
|
37
|
+
|
38
|
+
"_from"=>"<sip:15EB6BAB-99DF-44C2-871DFBA75C319776@11.8.93.201;channel=private;user=#{options[:to]};msg=#{options[:message]};network=SMS;step=1>;tag=zm13kt"
|
39
|
+
}
|
40
|
+
}
|
41
|
+
}
|
42
|
+
params.merge!("authentication_key" => @config[:authentication_key]) unless options[:authentic] == false
|
43
|
+
params
|
44
|
+
end
|
45
|
+
|
46
|
+
def sample_delivery_response(options = {})
|
47
|
+
options[:failure] ? "<session><success>false</success><token></token><reason>FAILED TO ROUTE TOKEN</reason></session>" : "<session><success>true</success></session>"
|
48
|
+
end
|
49
|
+
|
50
|
+
def sample_message_id
|
51
|
+
"123e71195545ad204bdd99f2070a7d86"
|
52
|
+
end
|
53
|
+
|
54
|
+
# This is here simply so the current tests pass
|
55
|
+
# Tropo does not *yet* send delivery receipts
|
56
|
+
def sample_delivery_receipt(options = {})
|
57
|
+
options[:message_id] ||= "123e71195545ad204bdd99f2070a7d86"
|
58
|
+
options[:status] ||= "delivered"
|
59
|
+
options[:date] ||= "Mon Oct 11 09:21:38 UTC 2010"
|
60
|
+
{
|
61
|
+
"message_id"=> options[:message_id],
|
62
|
+
"status"=> options[:status],
|
63
|
+
"delivered_at"=> options[:date]
|
64
|
+
}
|
65
|
+
end
|
66
|
+
end
|
67
|
+
end
|
68
|
+
|
@@ -0,0 +1,82 @@
|
|
1
|
+
require 'action_sms/connection_adapters/abstract_adapter'
|
2
|
+
|
3
|
+
module ActionSms
|
4
|
+
class Base
|
5
|
+
def self.tropo_connection(config) #:nodoc:
|
6
|
+
if config[:environment].to_s == "test"
|
7
|
+
test_helper = File.expand_path(File.dirname(__FILE__) + '/test_helpers/tropo')
|
8
|
+
if File.exists?("#{test_helper}.rb")
|
9
|
+
require test_helper
|
10
|
+
ConnectionAdapters::TropoAdapter.class_eval do
|
11
|
+
include TestHelpers::Tropo
|
12
|
+
end
|
13
|
+
end
|
14
|
+
end
|
15
|
+
ConnectionAdapters::TropoAdapter.new(config)
|
16
|
+
end
|
17
|
+
end
|
18
|
+
|
19
|
+
module ConnectionAdapters
|
20
|
+
# All the concrete gateway adapters follow the interface laid down in this
|
21
|
+
# class. You can use this interface directly by borrowing the gateway
|
22
|
+
# connection from the Base with Base.connection.
|
23
|
+
class TropoAdapter < AbstractAdapter
|
24
|
+
require 'uri'
|
25
|
+
require 'tropo_message'
|
26
|
+
|
27
|
+
attr_reader :service_url
|
28
|
+
|
29
|
+
SERVICE_HOST = "http://api.tropo.com/1.0"
|
30
|
+
SERVICE_PATH = "sessions"
|
31
|
+
|
32
|
+
def initialize(config = {}) #:nodoc:
|
33
|
+
@config = config.dup
|
34
|
+
service_uri = URI.join(SERVICE_HOST, SERVICE_PATH)
|
35
|
+
service_uri.scheme = config[:use_ssl] ? "https" : "http"
|
36
|
+
@service_url = service_uri.to_s
|
37
|
+
end
|
38
|
+
|
39
|
+
# message_id and status are for text message delivery receipts only
|
40
|
+
# Tropo does not *yet* send text message delivery receipts, so these
|
41
|
+
# two methods are here for testing purposes
|
42
|
+
def message_id(data)
|
43
|
+
data.is_a?(Hash) ? data["message_id"] : data
|
44
|
+
end
|
45
|
+
|
46
|
+
def status(delivery_receipt)
|
47
|
+
delivery_receipt["status"]
|
48
|
+
end
|
49
|
+
|
50
|
+
def delivery_request_successful?(gateway_response)
|
51
|
+
gateway_response =~ /\<success\>true\<\/success\>/
|
52
|
+
end
|
53
|
+
|
54
|
+
def message_text(params)
|
55
|
+
session(params)["initial_text"]
|
56
|
+
end
|
57
|
+
|
58
|
+
def sender(params)
|
59
|
+
session(params)["from"]["id"]
|
60
|
+
end
|
61
|
+
|
62
|
+
def authenticate(params)
|
63
|
+
params.delete("authentication_key") == @config[:authentication_key]
|
64
|
+
end
|
65
|
+
|
66
|
+
def deliver(sms)
|
67
|
+
tropo_message = Tropo::Message.new
|
68
|
+
tropo_message.to = sms.recipient
|
69
|
+
tropo_message.text = sms.body || ""
|
70
|
+
tropo_message.from = sms.from if sms.respond_to?(:from)
|
71
|
+
tropo_message.token = @config[:outgoing_token]
|
72
|
+
send_http_request(@service_url, tropo_message.request_xml)
|
73
|
+
end
|
74
|
+
|
75
|
+
private
|
76
|
+
def session(params)
|
77
|
+
params["session"]
|
78
|
+
end
|
79
|
+
end
|
80
|
+
end
|
81
|
+
end
|
82
|
+
|
metadata
CHANGED
@@ -5,8 +5,8 @@ version: !ruby/object:Gem::Version
|
|
5
5
|
segments:
|
6
6
|
- 0
|
7
7
|
- 0
|
8
|
-
-
|
9
|
-
version: 0.0.
|
8
|
+
- 7
|
9
|
+
version: 0.0.7
|
10
10
|
platform: ruby
|
11
11
|
authors:
|
12
12
|
- David Wilkie
|
@@ -14,10 +14,24 @@ autorequire:
|
|
14
14
|
bindir: bin
|
15
15
|
cert_chain: []
|
16
16
|
|
17
|
-
date: 2010-10-
|
17
|
+
date: 2010-10-14 00:00:00 +07:00
|
18
18
|
default_executable:
|
19
|
-
dependencies:
|
20
|
-
|
19
|
+
dependencies:
|
20
|
+
- !ruby/object:Gem::Dependency
|
21
|
+
name: tropo_message
|
22
|
+
prerelease: false
|
23
|
+
requirement: &id001 !ruby/object:Gem::Requirement
|
24
|
+
none: false
|
25
|
+
requirements:
|
26
|
+
- - ">="
|
27
|
+
- !ruby/object:Gem::Version
|
28
|
+
segments:
|
29
|
+
- 0
|
30
|
+
- 0
|
31
|
+
- 4
|
32
|
+
version: 0.0.4
|
33
|
+
type: :runtime
|
34
|
+
version_requirements: *id001
|
21
35
|
description:
|
22
36
|
email: dwilkie@gmail.com
|
23
37
|
executables: []
|
@@ -36,6 +50,9 @@ files:
|
|
36
50
|
- lib/action_sms_gateways.rb
|
37
51
|
- lib/action_sms_gateways/connection_adapters.rb
|
38
52
|
- lib/action_sms_gateways/connection_adapters/sms_global.rb
|
53
|
+
- lib/action_sms_gateways/connection_adapters/test_helpers/sms_global.rb
|
54
|
+
- lib/action_sms_gateways/connection_adapters/test_helpers/tropo.rb
|
55
|
+
- lib/action_sms_gateways/connection_adapters/tropo.rb
|
39
56
|
- todo
|
40
57
|
has_rdoc: true
|
41
58
|
homepage: http://github.com/dwilkie/action_sms_gateways
|