africastalking-ruby 1.0.0 → 2.0.0
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.
- checksums.yaml +7 -0
- data/.gitignore +11 -0
- data/.rspec +3 -0
- data/CODE_OF_CONDUCT.md +74 -0
- data/Gemfile +6 -0
- data/Gemfile.lock +119 -0
- data/LICENSE.txt +21 -0
- data/README.md +332 -0
- data/Rakefile +6 -0
- data/africastalking-ruby.gemspec +40 -0
- data/bin/console +14 -0
- data/bin/setup +8 -0
- data/lib/AfricasTalking/Airtime.rb +72 -0
- data/lib/AfricasTalking/Application.rb +43 -0
- data/lib/AfricasTalking/Payments.rb +436 -0
- data/lib/AfricasTalking/Sms.rb +242 -0
- data/lib/AfricasTalking/Token.rb +66 -0
- data/lib/AfricasTalking/Voice.rb +141 -0
- data/lib/AfricasTalking/version.rb +3 -0
- data/lib/AfricasTalking.rb +118 -0
- metadata +131 -17
- data/lib/AfricasTalkingGateway.rb +0 -340
@@ -0,0 +1,242 @@
|
|
1
|
+
class Sms
|
2
|
+
include AfricasTalking
|
3
|
+
|
4
|
+
HTTP_CREATED = 201
|
5
|
+
HTTP_OK = 200
|
6
|
+
|
7
|
+
#Set debug flag to to true to view response body
|
8
|
+
|
9
|
+
def initialize username, apikey
|
10
|
+
@username = username
|
11
|
+
@apikey = apikey
|
12
|
+
end
|
13
|
+
|
14
|
+
# def initialize
|
15
|
+
# super
|
16
|
+
# end
|
17
|
+
|
18
|
+
|
19
|
+
def send options
|
20
|
+
#
|
21
|
+
post_body = {
|
22
|
+
|
23
|
+
'username' => @username,
|
24
|
+
'message' => options['message'],
|
25
|
+
'to' => options['to']
|
26
|
+
}
|
27
|
+
if options['from'] != nil
|
28
|
+
post_body['from'] = options['from']
|
29
|
+
end
|
30
|
+
if options['enqueue'] != nil
|
31
|
+
post_body['enqueue'] = options['enqueue']
|
32
|
+
end
|
33
|
+
if options['bulkSMSMode'] != nil
|
34
|
+
post_body['bulkSMSMode'] = options['bulkSMSMode']
|
35
|
+
end
|
36
|
+
if options['retryDurationInHours'] != nil
|
37
|
+
post_body['retryDurationInHours'] = options['retryDurationInHours']
|
38
|
+
end
|
39
|
+
#
|
40
|
+
if validateParamsPresence?(options, ['message', 'to'])
|
41
|
+
response = sendNormalRequest(getSmsUrl(), post_body)
|
42
|
+
end
|
43
|
+
if @response_code == HTTP_CREATED
|
44
|
+
messageData = JSON.parse(response,:quirks_mode=>true)["SMSMessageData"]
|
45
|
+
recipients = messageData["Recipients"]
|
46
|
+
|
47
|
+
if recipients.length > 0
|
48
|
+
reports = recipients.collect { |entry|
|
49
|
+
StatusReport.new entry["number"], entry["status"], entry["cost"], entry["messageId"]
|
50
|
+
}
|
51
|
+
#
|
52
|
+
return reports
|
53
|
+
end
|
54
|
+
|
55
|
+
raise AfricasTalkingException, messageData["Message"]
|
56
|
+
|
57
|
+
else
|
58
|
+
raise AfricasTalkingException, response
|
59
|
+
end
|
60
|
+
end
|
61
|
+
|
62
|
+
def sendPremium options
|
63
|
+
post_body = {
|
64
|
+
'username' => @username,
|
65
|
+
'message' => options['message'],
|
66
|
+
'to' => options['to'],
|
67
|
+
'keyword' => options['keyword'],
|
68
|
+
'linkId' => options['linkId'],
|
69
|
+
}
|
70
|
+
if options['retryDurationInHours'] != nil
|
71
|
+
post_body['retryDurationInHours'] = options['retryDurationInHours']
|
72
|
+
end
|
73
|
+
if options['bulkSMSMode'] != nil
|
74
|
+
post_body['bulkSMSMode'] = options['bulkSMSMode']
|
75
|
+
end
|
76
|
+
if options['enqueue'] != nil
|
77
|
+
post_body['enqueue'] = options['enqueue']
|
78
|
+
end
|
79
|
+
if options['from'] != nil
|
80
|
+
post_body['from'] = options['from']
|
81
|
+
end
|
82
|
+
#
|
83
|
+
if validateParamsPresence?(options, ['message', 'to', 'keyword', 'linkId'])
|
84
|
+
response = sendNormalRequest(getSmsUrl(), post_body)
|
85
|
+
end
|
86
|
+
|
87
|
+
#
|
88
|
+
if @response_code == HTTP_CREATED
|
89
|
+
messageData = JSON.parse(response,:quirks_mode=>true)["SMSMessageData"]
|
90
|
+
recipients = messageData["Recipients"]
|
91
|
+
|
92
|
+
if recipients.length > 0
|
93
|
+
reports = recipients.collect { |entry|
|
94
|
+
StatusReport.new entry["number"], entry["status"], entry["cost"], entry["messageId"]
|
95
|
+
}
|
96
|
+
return SendPremiumMessagesResponse.new reports, messageData["Message"]
|
97
|
+
end
|
98
|
+
|
99
|
+
raise AfricasTalkingException, messageData["Message"]
|
100
|
+
|
101
|
+
else
|
102
|
+
raise AfricasTalkingException, response
|
103
|
+
end
|
104
|
+
|
105
|
+
#
|
106
|
+
end
|
107
|
+
|
108
|
+
def fetchMessages options
|
109
|
+
url = getSmsUrl() + "?username=#{@username}&lastReceivedId=#{options['last_received_id']}"
|
110
|
+
response = sendNormalRequest(url)
|
111
|
+
if @response_code == HTTP_OK
|
112
|
+
messages = JSON.parse(response, :quirky_mode => true)["SMSMessageData"]["Messages"].collect { |msg|
|
113
|
+
SMSMessages.new msg["id"], msg["text"], msg["from"] , msg["to"], msg["linkId"], msg["date"]
|
114
|
+
}
|
115
|
+
# messages
|
116
|
+
|
117
|
+
return FetchMessagesResponse.new messages
|
118
|
+
|
119
|
+
else
|
120
|
+
raise AfricasTalkingException, response
|
121
|
+
end
|
122
|
+
end
|
123
|
+
|
124
|
+
def fetchSubscriptions options
|
125
|
+
if validateParamsPresence?(options, ['shortCode', 'keyword'])
|
126
|
+
url = getSmsSubscriptionUrl() + "?username=#{@username}&shortCode=#{options['shortCode']}&keyword=#{options['keyword']}&lastReceivedId=#{options['lastReceivedId']}"
|
127
|
+
response = sendNormalRequest(url)
|
128
|
+
end
|
129
|
+
if(@response_code == HTTP_OK)
|
130
|
+
#
|
131
|
+
subscriptions = JSON.parse(response)['responses'].collect{ |subscriber|
|
132
|
+
PremiumSubscriptionNumbers.new subscriber['phoneNumber'], subscriber['id'], subscriber['date']
|
133
|
+
}
|
134
|
+
#
|
135
|
+
return subscriptions
|
136
|
+
else
|
137
|
+
raise AfricasTalkingException, response
|
138
|
+
end
|
139
|
+
end
|
140
|
+
|
141
|
+
def createSubcription options
|
142
|
+
post_body = {
|
143
|
+
'username' => @username,
|
144
|
+
'phoneNumber' => options['phoneNumber'],
|
145
|
+
'shortCode' => options['shortCode'],
|
146
|
+
'keyword' => options['keyword']
|
147
|
+
}
|
148
|
+
if options['checkoutToken'] != nil
|
149
|
+
post_body['checkoutToken'] = options['checkoutToken']
|
150
|
+
end
|
151
|
+
url = getSmsSubscriptionUrl() + "/create"
|
152
|
+
if validateParamsPresence?(options, ['shortCode', 'keyword', 'phoneNumber'])
|
153
|
+
response = sendNormalRequest(url, post_body)
|
154
|
+
end
|
155
|
+
if(@response_code == HTTP_CREATED)
|
156
|
+
r = JSON.parse(response, :quirky_mode => true)
|
157
|
+
return CreateSubscriptionResponse.new r['status'], r['description']
|
158
|
+
else
|
159
|
+
raise AfricasTalkingException, response
|
160
|
+
end
|
161
|
+
end
|
162
|
+
|
163
|
+
private
|
164
|
+
|
165
|
+
def getSmsUrl()
|
166
|
+
return getApiHost() + "/version1/messaging"
|
167
|
+
end
|
168
|
+
|
169
|
+
def getSmsSubscriptionUrl()
|
170
|
+
return getApiHost() + "/version1/subscription"
|
171
|
+
end
|
172
|
+
|
173
|
+
def getApiHost()
|
174
|
+
if(@username == "sandbox")
|
175
|
+
return "https://api.sandbox.africastalking.com"
|
176
|
+
else
|
177
|
+
return "https://api.africastalking.com"
|
178
|
+
end
|
179
|
+
end
|
180
|
+
end
|
181
|
+
# ////////////////////////
|
182
|
+
|
183
|
+
class StatusReport
|
184
|
+
attr_reader :number, :status, :cost, :messageId
|
185
|
+
|
186
|
+
def initialize(number_, status_, cost_,messageId_)
|
187
|
+
@number = number_
|
188
|
+
@status = status_
|
189
|
+
@cost = cost_
|
190
|
+
@messageId = messageId_
|
191
|
+
end
|
192
|
+
end
|
193
|
+
|
194
|
+
class PremiumSubscriptionNumbers
|
195
|
+
attr_reader :phoneNumber, :id, :date
|
196
|
+
|
197
|
+
def initialize number_, id_, date_
|
198
|
+
@phoneNumber = number_
|
199
|
+
@id = id_
|
200
|
+
@date = date_
|
201
|
+
end
|
202
|
+
end
|
203
|
+
|
204
|
+
|
205
|
+
class FetchMessagesResponse
|
206
|
+
attr_reader :responses, :status
|
207
|
+
def initialize responses_, status_= nil
|
208
|
+
@responses = responses_
|
209
|
+
@status = status_
|
210
|
+
end
|
211
|
+
end
|
212
|
+
|
213
|
+
class CreateSubscriptionResponse
|
214
|
+
attr_reader :status, :description
|
215
|
+
def initialize status_, description_
|
216
|
+
@description = description_
|
217
|
+
@status = status_
|
218
|
+
end
|
219
|
+
end
|
220
|
+
|
221
|
+
|
222
|
+
class SendPremiumMessagesResponse
|
223
|
+
attr_reader :recipients, :overview
|
224
|
+
def initialize recipients_, overview_
|
225
|
+
@recipients = recipients_
|
226
|
+
@overview = overview_
|
227
|
+
end
|
228
|
+
end
|
229
|
+
|
230
|
+
class SMSMessages
|
231
|
+
attr_reader :id, :text, :from, :to, :linkId, :date
|
232
|
+
|
233
|
+
def initialize(id_, text_, from_, to_, linkId_, date_)
|
234
|
+
@id = id_
|
235
|
+
@text = text_
|
236
|
+
@from = from_
|
237
|
+
@to = to_
|
238
|
+
@linkId = linkId_
|
239
|
+
@date = date_
|
240
|
+
end
|
241
|
+
end
|
242
|
+
|
@@ -0,0 +1,66 @@
|
|
1
|
+
class Token
|
2
|
+
include AfricasTalking
|
3
|
+
HTTP_CREATED = 201
|
4
|
+
HTTP_OK = 200
|
5
|
+
|
6
|
+
#Set debug flag to to true to view response body
|
7
|
+
def initialize username, apikey
|
8
|
+
@username = username
|
9
|
+
@apikey = apikey
|
10
|
+
end
|
11
|
+
|
12
|
+
def generateAuthToken
|
13
|
+
post_body = {
|
14
|
+
'username' => @username
|
15
|
+
}
|
16
|
+
url = getApiHost() + "/auth-token/generate"
|
17
|
+
response = sendJSONRequest(url, post_body)
|
18
|
+
#
|
19
|
+
if(@response_code == HTTP_CREATED)
|
20
|
+
r=JSON.parse(response, :quirky_mode => true)
|
21
|
+
return AuthTokenResponse.new r["token"], r["lifetimeInSeconds"]
|
22
|
+
else
|
23
|
+
raise AfricasTalkingException, response
|
24
|
+
end
|
25
|
+
end
|
26
|
+
|
27
|
+
def createCheckoutToken options
|
28
|
+
post_body = {
|
29
|
+
'phoneNumber' => options['phoneNumber']
|
30
|
+
}
|
31
|
+
url = getApiHost() + "/checkout/token/create"
|
32
|
+
response = sendNormalRequest(url, post_body)
|
33
|
+
#
|
34
|
+
if(@response_code == HTTP_CREATED)
|
35
|
+
r= JSON.parse(response, :quirky_mode => true)
|
36
|
+
return CheckoutTokenResponse.new r['token'], r['description']
|
37
|
+
else
|
38
|
+
raise AfricasTalkingException, response
|
39
|
+
end
|
40
|
+
end
|
41
|
+
|
42
|
+
private
|
43
|
+
|
44
|
+
def getApiHost()
|
45
|
+
if(@username == "sandbox")
|
46
|
+
return "https://api.sandbox.africastalking.com"
|
47
|
+
else
|
48
|
+
return "https://api.africastalking.com"
|
49
|
+
end
|
50
|
+
end
|
51
|
+
end
|
52
|
+
|
53
|
+
class AuthTokenResponse
|
54
|
+
attr_accessor :token, :lifetimeInSeconds
|
55
|
+
def initialize token_, lifetimeInSeconds_
|
56
|
+
@token = token_
|
57
|
+
@lifetimeInSeconds = lifetimeInSeconds_
|
58
|
+
end
|
59
|
+
end
|
60
|
+
class CheckoutTokenResponse
|
61
|
+
attr_accessor :token, :description
|
62
|
+
def initialize token_, description_
|
63
|
+
@token = token_
|
64
|
+
@description = description_
|
65
|
+
end
|
66
|
+
end
|
@@ -0,0 +1,141 @@
|
|
1
|
+
class Voice
|
2
|
+
include AfricasTalking
|
3
|
+
HTTP_CREATED = 201
|
4
|
+
HTTP_OK = 200
|
5
|
+
|
6
|
+
#Set debug flag to to true to view response body
|
7
|
+
|
8
|
+
def initialize username, apikey
|
9
|
+
@username = username
|
10
|
+
@apikey = apikey
|
11
|
+
end
|
12
|
+
|
13
|
+
def call options
|
14
|
+
if validateParamsPresence?(options, ['from', 'to'])
|
15
|
+
post_body = {
|
16
|
+
'username' => @username,
|
17
|
+
'from' => options['from'],
|
18
|
+
'to' => options['to']
|
19
|
+
}
|
20
|
+
#
|
21
|
+
response = sendNormalRequest(getVoiceHost() + "/call", post_body)
|
22
|
+
end
|
23
|
+
if(@response_code == HTTP_OK || @response_code == HTTP_CREATED)
|
24
|
+
ob = JSON.parse(response, :quirky_mode => true)
|
25
|
+
#
|
26
|
+
if (ob['entries'].length > 0)
|
27
|
+
results = ob['entries'].collect{|result|
|
28
|
+
CallEntries.new result['status'], result['phoneNumber']
|
29
|
+
}
|
30
|
+
end
|
31
|
+
return CallResponse.new results, ob['errorMessage']
|
32
|
+
#
|
33
|
+
else
|
34
|
+
raise AfricasTalkingException, response
|
35
|
+
end
|
36
|
+
end
|
37
|
+
|
38
|
+
def fetchQueuedCalls options
|
39
|
+
if validateParamsPresence?(options, ['phoneNumber'])
|
40
|
+
post_body = {
|
41
|
+
'username' => @username,
|
42
|
+
'phoneNumbers' => options['phoneNumber'],
|
43
|
+
}
|
44
|
+
|
45
|
+
url = getVoiceHost() + "/queueStatus"
|
46
|
+
response = sendNormalRequest(url, post_body)
|
47
|
+
end
|
48
|
+
#
|
49
|
+
if(@response_code == HTTP_OK || @response_code == HTTP_CREATED)
|
50
|
+
ob = JSON.parse(response, :quirky_mode => true)
|
51
|
+
results = []
|
52
|
+
if (ob['entries'].length > 0)
|
53
|
+
results = ob['entries'].collect{|result|
|
54
|
+
QueuedCalls.new result['phoneNumber'], result['numCalls'], result['queueName']
|
55
|
+
}
|
56
|
+
end
|
57
|
+
#
|
58
|
+
return QueuedCallsResponse.new ob['status'], ob['errorMessage'], results
|
59
|
+
end
|
60
|
+
|
61
|
+
raise AfricasTalkingException, response
|
62
|
+
|
63
|
+
end
|
64
|
+
|
65
|
+
def uploadMediaFile options
|
66
|
+
if validateParamsPresence?(options, ['url','phoneNumber'])
|
67
|
+
|
68
|
+
post_body = {
|
69
|
+
'username' => @username,
|
70
|
+
'url' => options['url'],
|
71
|
+
'phoneNumber' => options['phoneNumber']
|
72
|
+
}
|
73
|
+
url = getVoiceHost() + "/mediaUpload"
|
74
|
+
#
|
75
|
+
response = sendNormalRequest(url, post_body)
|
76
|
+
end
|
77
|
+
if(@response_code == HTTP_OK || @response_code == HTTP_CREATED)
|
78
|
+
return UploadMediaResponse.new response
|
79
|
+
end
|
80
|
+
#
|
81
|
+
raise AfricasTalkingException, response
|
82
|
+
end
|
83
|
+
|
84
|
+
|
85
|
+
private
|
86
|
+
def getVoiceHost()
|
87
|
+
if(@username == "sandbox")
|
88
|
+
return "https://voice.sandbox.africastalking.com"
|
89
|
+
else
|
90
|
+
return "https://voice.africastalking.com"
|
91
|
+
end
|
92
|
+
end
|
93
|
+
|
94
|
+
end
|
95
|
+
|
96
|
+
|
97
|
+
class CallResponse
|
98
|
+
attr_reader :errorMessage, :entries
|
99
|
+
|
100
|
+
def initialize(entries_, errorMessage_)
|
101
|
+
@errorMessage = errorMessage_
|
102
|
+
@entries = entries_
|
103
|
+
end
|
104
|
+
end
|
105
|
+
|
106
|
+
class CallEntries
|
107
|
+
attr_reader :status, :phoneNumber
|
108
|
+
|
109
|
+
def initialize(status_, number_)
|
110
|
+
@status = status_
|
111
|
+
@phoneNumber = number_
|
112
|
+
end
|
113
|
+
end
|
114
|
+
|
115
|
+
class QueuedCalls
|
116
|
+
attr_reader :numCalls, :phoneNumber, :queueName
|
117
|
+
|
118
|
+
def initialize(number_, numCalls_, queueName_)
|
119
|
+
@phoneNumber = number_
|
120
|
+
@numCalls = numCalls_
|
121
|
+
@queueName = queueName_
|
122
|
+
end
|
123
|
+
end
|
124
|
+
|
125
|
+
class QueuedCallsResponse
|
126
|
+
attr_reader :status, :errorMessage, :entries
|
127
|
+
|
128
|
+
def initialize(status_, errorMessage_, entries_)
|
129
|
+
@status = status_
|
130
|
+
@errorMessage = errorMessage_
|
131
|
+
@entries = entries_
|
132
|
+
end
|
133
|
+
end
|
134
|
+
|
135
|
+
class UploadMediaResponse
|
136
|
+
attr_reader :status
|
137
|
+
def initialize status
|
138
|
+
@status = status
|
139
|
+
end
|
140
|
+
end
|
141
|
+
|
@@ -0,0 +1,118 @@
|
|
1
|
+
require "AfricasTalking/version"
|
2
|
+
require 'httparty'
|
3
|
+
require "AfricasTalking/Sms"
|
4
|
+
require "AfricasTalking/Airtime"
|
5
|
+
require "AfricasTalking/Payments"
|
6
|
+
require "AfricasTalking/Voice"
|
7
|
+
require "AfricasTalking/Token"
|
8
|
+
require "AfricasTalking/Application"
|
9
|
+
|
10
|
+
module AfricasTalking
|
11
|
+
DEBUG = false
|
12
|
+
@username = nil
|
13
|
+
@apikey = nil
|
14
|
+
@response_code = nil
|
15
|
+
|
16
|
+
class Initialize
|
17
|
+
attr_accessor :username, :apikey
|
18
|
+
def initialize username, apikey
|
19
|
+
@username = username
|
20
|
+
@apikey = apikey
|
21
|
+
end
|
22
|
+
|
23
|
+
def sms
|
24
|
+
return Sms.new @username, @apikey
|
25
|
+
end
|
26
|
+
|
27
|
+
def payments
|
28
|
+
return Payments.new @username, @apikey
|
29
|
+
end
|
30
|
+
|
31
|
+
def airtime
|
32
|
+
return Airtime.new @username, @apikey
|
33
|
+
end
|
34
|
+
|
35
|
+
def voice
|
36
|
+
return Voice.new @username, @apikey
|
37
|
+
end
|
38
|
+
|
39
|
+
def token
|
40
|
+
return Token.new @username, @apikey
|
41
|
+
end
|
42
|
+
|
43
|
+
def application
|
44
|
+
return Application.new @username, @apikey
|
45
|
+
end
|
46
|
+
end
|
47
|
+
|
48
|
+
class AfricasTalkingException < Exception
|
49
|
+
# error handling appear here
|
50
|
+
# def initialize(msg="My default message")
|
51
|
+
# super
|
52
|
+
# end
|
53
|
+
|
54
|
+
end
|
55
|
+
|
56
|
+
|
57
|
+
private
|
58
|
+
|
59
|
+
def sendNormalRequest url_, data_ = nil
|
60
|
+
uri = URI.parse(url_)
|
61
|
+
http = Net::HTTP.new(uri.host, uri.port)
|
62
|
+
http.use_ssl = true
|
63
|
+
headers = {
|
64
|
+
"apikey" => @apikey,
|
65
|
+
"Accept" => "application/json"
|
66
|
+
}
|
67
|
+
if(data_ != nil)
|
68
|
+
request = Net::HTTP::Post.new(uri.request_uri)
|
69
|
+
request.set_form_data(data_)
|
70
|
+
else
|
71
|
+
request = Net::HTTP::Get.new(uri.request_uri)
|
72
|
+
end
|
73
|
+
request["apikey"] = @apikey
|
74
|
+
request["Accept"] = "application/json"
|
75
|
+
response = http.request(request)
|
76
|
+
|
77
|
+
if (DEBUG)
|
78
|
+
puts "Full response #{response.body}"
|
79
|
+
end
|
80
|
+
|
81
|
+
@response_code = response.code.to_i
|
82
|
+
return response.body
|
83
|
+
end
|
84
|
+
|
85
|
+
def sendJSONRequest (url_, data_)
|
86
|
+
uri = URI.parse(url_)
|
87
|
+
http = Net::HTTP.new(uri.host, uri.port)
|
88
|
+
http.use_ssl = true
|
89
|
+
req = Net::HTTP::Post.new(uri.request_uri, 'Content-Type'=>"application/json")
|
90
|
+
|
91
|
+
req["apikey"] = @apikey
|
92
|
+
req["Accept"] = "application/json"
|
93
|
+
|
94
|
+
req.body = data_.to_json
|
95
|
+
|
96
|
+
response = http.request(req)
|
97
|
+
|
98
|
+
if (DEBUG)
|
99
|
+
puts "Full response #{response.body}"
|
100
|
+
end
|
101
|
+
|
102
|
+
@response_code = response.code.to_i
|
103
|
+
return response.body
|
104
|
+
end
|
105
|
+
|
106
|
+
def validateParamsPresence? params, values
|
107
|
+
status = values.each{ |v|
|
108
|
+
if !params.key?(v)
|
109
|
+
raise AfricasTalkingException, "Please make sure your params has key #{v}"
|
110
|
+
elsif v.empty?
|
111
|
+
raise AfricasTalkingException, "Please make sure your key #{v} is not empty"
|
112
|
+
end
|
113
|
+
}
|
114
|
+
return true
|
115
|
+
|
116
|
+
end
|
117
|
+
|
118
|
+
end
|