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
metadata
CHANGED
@@ -1,47 +1,161 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: africastalking-ruby
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version:
|
5
|
-
prerelease:
|
4
|
+
version: 2.0.0
|
6
5
|
platform: ruby
|
7
6
|
authors:
|
8
|
-
-
|
7
|
+
- Michael Mwirigi
|
9
8
|
autorequire:
|
10
|
-
bindir:
|
9
|
+
bindir: exe
|
11
10
|
cert_chain: []
|
12
|
-
date:
|
13
|
-
dependencies:
|
14
|
-
|
11
|
+
date: 2018-07-02 00:00:00.000000000 Z
|
12
|
+
dependencies:
|
13
|
+
- !ruby/object:Gem::Dependency
|
14
|
+
name: bundler
|
15
|
+
requirement: !ruby/object:Gem::Requirement
|
16
|
+
requirements:
|
17
|
+
- - "~>"
|
18
|
+
- !ruby/object:Gem::Version
|
19
|
+
version: '1.16'
|
20
|
+
type: :development
|
21
|
+
prerelease: false
|
22
|
+
version_requirements: !ruby/object:Gem::Requirement
|
23
|
+
requirements:
|
24
|
+
- - "~>"
|
25
|
+
- !ruby/object:Gem::Version
|
26
|
+
version: '1.16'
|
27
|
+
- !ruby/object:Gem::Dependency
|
28
|
+
name: rake
|
29
|
+
requirement: !ruby/object:Gem::Requirement
|
30
|
+
requirements:
|
31
|
+
- - "~>"
|
32
|
+
- !ruby/object:Gem::Version
|
33
|
+
version: '10.0'
|
34
|
+
type: :development
|
35
|
+
prerelease: false
|
36
|
+
version_requirements: !ruby/object:Gem::Requirement
|
37
|
+
requirements:
|
38
|
+
- - "~>"
|
39
|
+
- !ruby/object:Gem::Version
|
40
|
+
version: '10.0'
|
41
|
+
- !ruby/object:Gem::Dependency
|
42
|
+
name: rspec
|
43
|
+
requirement: !ruby/object:Gem::Requirement
|
44
|
+
requirements:
|
45
|
+
- - "~>"
|
46
|
+
- !ruby/object:Gem::Version
|
47
|
+
version: '3.0'
|
48
|
+
type: :development
|
49
|
+
prerelease: false
|
50
|
+
version_requirements: !ruby/object:Gem::Requirement
|
51
|
+
requirements:
|
52
|
+
- - "~>"
|
53
|
+
- !ruby/object:Gem::Version
|
54
|
+
version: '3.0'
|
55
|
+
- !ruby/object:Gem::Dependency
|
56
|
+
name: rspec-rails
|
57
|
+
requirement: !ruby/object:Gem::Requirement
|
58
|
+
requirements:
|
59
|
+
- - "~>"
|
60
|
+
- !ruby/object:Gem::Version
|
61
|
+
version: 3.7.2
|
62
|
+
type: :development
|
63
|
+
prerelease: false
|
64
|
+
version_requirements: !ruby/object:Gem::Requirement
|
65
|
+
requirements:
|
66
|
+
- - "~>"
|
67
|
+
- !ruby/object:Gem::Version
|
68
|
+
version: 3.7.2
|
69
|
+
- !ruby/object:Gem::Dependency
|
70
|
+
name: rubocop
|
71
|
+
requirement: !ruby/object:Gem::Requirement
|
72
|
+
requirements:
|
73
|
+
- - "~>"
|
74
|
+
- !ruby/object:Gem::Version
|
75
|
+
version: 0.54.0
|
76
|
+
type: :development
|
77
|
+
prerelease: false
|
78
|
+
version_requirements: !ruby/object:Gem::Requirement
|
79
|
+
requirements:
|
80
|
+
- - "~>"
|
81
|
+
- !ruby/object:Gem::Version
|
82
|
+
version: 0.54.0
|
83
|
+
- !ruby/object:Gem::Dependency
|
84
|
+
name: pry
|
85
|
+
requirement: !ruby/object:Gem::Requirement
|
86
|
+
requirements:
|
87
|
+
- - "~>"
|
88
|
+
- !ruby/object:Gem::Version
|
89
|
+
version: '0'
|
90
|
+
type: :development
|
91
|
+
prerelease: false
|
92
|
+
version_requirements: !ruby/object:Gem::Requirement
|
93
|
+
requirements:
|
94
|
+
- - "~>"
|
95
|
+
- !ruby/object:Gem::Version
|
96
|
+
version: '0'
|
97
|
+
- !ruby/object:Gem::Dependency
|
98
|
+
name: httparty
|
99
|
+
requirement: !ruby/object:Gem::Requirement
|
100
|
+
requirements:
|
101
|
+
- - '='
|
102
|
+
- !ruby/object:Gem::Version
|
103
|
+
version: 0.16.1
|
104
|
+
type: :runtime
|
105
|
+
prerelease: false
|
106
|
+
version_requirements: !ruby/object:Gem::Requirement
|
107
|
+
requirements:
|
108
|
+
- - '='
|
109
|
+
- !ruby/object:Gem::Version
|
110
|
+
version: 0.16.1
|
111
|
+
description: ''
|
15
112
|
email:
|
16
|
-
-
|
113
|
+
- mmwirigi@africastalking.com
|
17
114
|
executables: []
|
18
115
|
extensions: []
|
19
116
|
extra_rdoc_files: []
|
20
117
|
files:
|
21
|
-
-
|
22
|
-
|
118
|
+
- ".gitignore"
|
119
|
+
- ".rspec"
|
120
|
+
- CODE_OF_CONDUCT.md
|
121
|
+
- Gemfile
|
122
|
+
- Gemfile.lock
|
123
|
+
- LICENSE.txt
|
124
|
+
- README.md
|
125
|
+
- Rakefile
|
126
|
+
- africastalking-ruby.gemspec
|
127
|
+
- bin/console
|
128
|
+
- bin/setup
|
129
|
+
- lib/AfricasTalking.rb
|
130
|
+
- lib/AfricasTalking/Airtime.rb
|
131
|
+
- lib/AfricasTalking/Application.rb
|
132
|
+
- lib/AfricasTalking/Payments.rb
|
133
|
+
- lib/AfricasTalking/Sms.rb
|
134
|
+
- lib/AfricasTalking/Token.rb
|
135
|
+
- lib/AfricasTalking/Voice.rb
|
136
|
+
- lib/AfricasTalking/version.rb
|
137
|
+
homepage: https://africastalking.com
|
23
138
|
licenses:
|
24
139
|
- MIT
|
140
|
+
metadata: {}
|
25
141
|
post_install_message:
|
26
142
|
rdoc_options: []
|
27
143
|
require_paths:
|
28
144
|
- lib
|
29
145
|
required_ruby_version: !ruby/object:Gem::Requirement
|
30
|
-
none: false
|
31
146
|
requirements:
|
32
|
-
- -
|
147
|
+
- - ">="
|
33
148
|
- !ruby/object:Gem::Version
|
34
149
|
version: '0'
|
35
150
|
required_rubygems_version: !ruby/object:Gem::Requirement
|
36
|
-
none: false
|
37
151
|
requirements:
|
38
|
-
- -
|
152
|
+
- - ">="
|
39
153
|
- !ruby/object:Gem::Version
|
40
154
|
version: '0'
|
41
155
|
requirements: []
|
42
156
|
rubyforge_project:
|
43
|
-
rubygems_version:
|
157
|
+
rubygems_version: 2.7.3
|
44
158
|
signing_key:
|
45
|
-
specification_version:
|
46
|
-
summary:
|
159
|
+
specification_version: 4
|
160
|
+
summary: Simple gem that helps you build integrations with AfricasTalking
|
47
161
|
test_files: []
|
@@ -1,340 +0,0 @@
|
|
1
|
-
require 'rubygems'
|
2
|
-
require 'net/http'
|
3
|
-
require 'uri'
|
4
|
-
require 'json'
|
5
|
-
|
6
|
-
class AfricasTalkingGatewayException < Exception
|
7
|
-
end
|
8
|
-
|
9
|
-
class SMSMessages
|
10
|
-
attr_accessor :id, :text, :from, :to, :linkId, :date
|
11
|
-
|
12
|
-
def initialize(id_, text_, from_, to_, linkId_, date_)
|
13
|
-
@id = id_
|
14
|
-
@text = text_
|
15
|
-
@from = from_
|
16
|
-
@to = to_
|
17
|
-
@linkId = linkId_
|
18
|
-
@date = date_
|
19
|
-
end
|
20
|
-
end
|
21
|
-
|
22
|
-
class StatusReport
|
23
|
-
attr_accessor :number, :status, :cost, :messageId
|
24
|
-
|
25
|
-
def initialize(number_, status_, cost_,messageId_)
|
26
|
-
@number = number_
|
27
|
-
@status = status_
|
28
|
-
@cost = cost_
|
29
|
-
@messageId = messageId_
|
30
|
-
end
|
31
|
-
end
|
32
|
-
|
33
|
-
class PremiumSubscriptionNumbers
|
34
|
-
attr_accessor :phoneNumber, :id
|
35
|
-
|
36
|
-
def initialize(number_, id_)
|
37
|
-
@phoneNumber = number_
|
38
|
-
@id = id_
|
39
|
-
end
|
40
|
-
end
|
41
|
-
|
42
|
-
class AirtimeResult
|
43
|
-
attr_accessor :amount, :phoneNumber, :requestId, :status, :errorMessage, :discount
|
44
|
-
|
45
|
-
def initialize(status_, number_, amount_, requestId_, errorMessage_, discount_)
|
46
|
-
@status = status_
|
47
|
-
@phoneNumber = number_
|
48
|
-
@amount = amount_
|
49
|
-
@requestId = requestId_
|
50
|
-
@errorMessage = errorMessage_
|
51
|
-
@discount = discount_
|
52
|
-
end
|
53
|
-
end
|
54
|
-
|
55
|
-
class CallResponse
|
56
|
-
attr_accessor :phoneNumber, :status
|
57
|
-
|
58
|
-
def initialize(status_, number_)
|
59
|
-
@status = status_
|
60
|
-
@phoneNumber = number_
|
61
|
-
end
|
62
|
-
end
|
63
|
-
|
64
|
-
class QueuedCalls
|
65
|
-
attr_accessor :numCalls, :phoneNumber, :queueName
|
66
|
-
|
67
|
-
def initialize(number_, numCalls_, queueName_)
|
68
|
-
@phoneNumber = number_
|
69
|
-
@numCalls = numCalls_
|
70
|
-
@queueName = queueName_
|
71
|
-
end
|
72
|
-
end
|
73
|
-
|
74
|
-
class AfricasTalkingGateway
|
75
|
-
|
76
|
-
SMS_URL = 'https://api.africastalking.com/version1/messaging'
|
77
|
-
VOICE_URL = 'https://voice.africastalking.com'
|
78
|
-
SUBSCRIPTION_URL = 'https://api.africastalking.com/version1/subscription'
|
79
|
-
USERDATA_URL = 'https://api.africastalking.com/version1/user'
|
80
|
-
AIRTIME_URL = 'https://api.africastalking.com/version1/airtime'
|
81
|
-
|
82
|
-
HTTP_CREATED = 201
|
83
|
-
HTTP_OK = 200
|
84
|
-
|
85
|
-
#Set debug flag to to true to view response body
|
86
|
-
DEBUG = false
|
87
|
-
|
88
|
-
|
89
|
-
def initialize(user_name,api_key)
|
90
|
-
@user_name = user_name
|
91
|
-
@api_key = api_key
|
92
|
-
|
93
|
-
@response_code = nil
|
94
|
-
end
|
95
|
-
|
96
|
-
def sendMessage(recipients_, message_, from_ = nil, bulkSMSMode_ = 1, enqueue_ = 0, keyword_ = nil, linkId_ = nil, retryDurationInHours_ = nil)
|
97
|
-
post_body = {
|
98
|
-
'username' => @user_name,
|
99
|
-
'message' => message_,
|
100
|
-
'to' => recipients_,
|
101
|
-
'bulkSMSMode' => bulkSMSMode_
|
102
|
-
}
|
103
|
-
if (from_ != nil)
|
104
|
-
post_body['from'] = from_
|
105
|
-
end
|
106
|
-
|
107
|
-
if (enqueue_ > 0)
|
108
|
-
post_body['enqueue'] = enqueue_
|
109
|
-
end
|
110
|
-
|
111
|
-
if (keyword_ != nil)
|
112
|
-
post_body['keyword'] = keyword_
|
113
|
-
end
|
114
|
-
|
115
|
-
if (linkId_ != nil)
|
116
|
-
post_body['linkId'] = linkId_
|
117
|
-
end
|
118
|
-
|
119
|
-
if (retryDurationInHours_ != nil)
|
120
|
-
post_body['retryDurationInHours'] = retryDurationInHours_
|
121
|
-
end
|
122
|
-
|
123
|
-
response = executePost(SMS_URL, post_body)
|
124
|
-
if @response_code == HTTP_CREATED
|
125
|
-
messageData = JSON.parse(response,:quirks_mode=>true)["SMSMessageData"]
|
126
|
-
recipients = messageData["Recipients"]
|
127
|
-
|
128
|
-
if recipients.length > 0
|
129
|
-
reports = recipients.collect { |entry|
|
130
|
-
StatusReport.new entry["number"], entry["status"], entry["cost"], entry["messageId"]
|
131
|
-
}
|
132
|
-
return reports
|
133
|
-
end
|
134
|
-
|
135
|
-
raise AfricasTalkingGatewayException, messageData["Message"]
|
136
|
-
|
137
|
-
else
|
138
|
-
raise AfricasTalkingGatewayException, response
|
139
|
-
end
|
140
|
-
end
|
141
|
-
|
142
|
-
def fetchMessages(last_received_id_)
|
143
|
-
url = "#{SMS_URL}?username=#{@user_name}&lastReceivedId=#{last_received_id_}"
|
144
|
-
response = executePost(url)
|
145
|
-
if @response_code == HTTP_OK
|
146
|
-
messages = JSON.parse(response, :quirky_mode => true)["SMSMessageData"]["Messages"].collect { |msg|
|
147
|
-
SMSMessage.new msg["id"], msg["text"], msg["from"] , msg["to"], msg["linkId"], msg["date"]
|
148
|
-
}
|
149
|
-
return messages
|
150
|
-
else
|
151
|
-
raise AfricasTalkingGatewayException, response
|
152
|
-
end
|
153
|
-
end
|
154
|
-
|
155
|
-
def createSubcription(phone_number_, short_code_, keyword_)
|
156
|
-
if(phone_number_.length == 0 || short_code.length == 0 || keyword_.length == 0)
|
157
|
-
raise AfricasTalkingGatewayException, "Please supply phone number, short code and keyword"
|
158
|
-
end
|
159
|
-
|
160
|
-
post_body = {
|
161
|
-
'username' => @user_name,
|
162
|
-
'phoneNumber' => phone_number_,
|
163
|
-
'shortCode' => short_code_,
|
164
|
-
'keyword' => keyword_
|
165
|
-
}
|
166
|
-
url = "#{SUBSCRIPTION_URL}/create"
|
167
|
-
response = executePost(url, post_body)
|
168
|
-
if(@response_code == HTTP_CREATED)
|
169
|
-
return JSON.parse(response, :quirky_mode => true)
|
170
|
-
else
|
171
|
-
raise AfricasTalkingGatewayException, response
|
172
|
-
end
|
173
|
-
end
|
174
|
-
|
175
|
-
def deleteSubcription(phone_number_, short_code_, keyword_)
|
176
|
-
if(phone_number_.length == 0 || short_code.length == 0 || keyword_.length == 0)
|
177
|
-
raise AfricasTalkingGatewayException, "Please supply phone number, short code and keyword"
|
178
|
-
end
|
179
|
-
|
180
|
-
post_body = {
|
181
|
-
'username' => @user_name,
|
182
|
-
'phoneNumber' => phone_number_,
|
183
|
-
'shortCode' => short_code_,
|
184
|
-
'keyword' => keyword_
|
185
|
-
}
|
186
|
-
url = "#{SUBSCRIPTION_URL}/delete"
|
187
|
-
|
188
|
-
response = executePost(url, post_body)
|
189
|
-
|
190
|
-
if(@response_code == HTTP_CREATED)
|
191
|
-
return JSON.parse(response, :quirky_mode => true)
|
192
|
-
else
|
193
|
-
raise AfricasTalkingGatewayException, response
|
194
|
-
end
|
195
|
-
end
|
196
|
-
|
197
|
-
def fetchPremiumSubscriptions(short_code_, keyword_, last_received_id_ = 0)
|
198
|
-
if(short_code_.length == 0 || keyword_.length == 0)
|
199
|
-
raise AfricasTalkingGatewayException, "Please supply the short code and keyword"
|
200
|
-
end
|
201
|
-
|
202
|
-
url = "#{SUBSCRIPTION_URL}?username=#{@user_name}&shortCode=#{short_code_}&keyword=#{keyword_}&lastReceivedId=#{last_received_id_}"
|
203
|
-
|
204
|
-
response = executePost(url)
|
205
|
-
|
206
|
-
if(@response_code == HTTP_OK)
|
207
|
-
subscriptions = JSON.parse(response)['responses'].collect{ |subscriber|
|
208
|
-
PremiumSubscriptionNumbers.new subscriber['phoneNumber'], subscriber['id']
|
209
|
-
}
|
210
|
-
return subscriptions
|
211
|
-
else
|
212
|
-
raise AfricasTalkingGatewayException, response
|
213
|
-
end
|
214
|
-
end
|
215
|
-
|
216
|
-
def call(from_, to_)
|
217
|
-
post_body = {
|
218
|
-
'username' => @user_name,
|
219
|
-
'from' => from_,
|
220
|
-
'to' => to_
|
221
|
-
}
|
222
|
-
response = executePost("#{VOICE_URL}/call", post_body)
|
223
|
-
if(@response_code == HTTP_OK || @response_code == HTTP_CREATED)
|
224
|
-
jObject = JSON.parse(response, :quirky_mode => true)
|
225
|
-
|
226
|
-
if (jObject['errorMessage'] == "None")
|
227
|
-
results = jObject['entries'].collect{|result|
|
228
|
-
CallResponse.new result['status'], result['phoneNumber']
|
229
|
-
}
|
230
|
-
return results
|
231
|
-
end
|
232
|
-
|
233
|
-
raise AfricasTalkingGatewayException, jObject['errorMessage']
|
234
|
-
end
|
235
|
-
|
236
|
-
raise AfricasTalkingGatewayException, response
|
237
|
-
end
|
238
|
-
|
239
|
-
def getNumQueuedCalls(phone_number_, queue_name_ = nil)
|
240
|
-
post_body = {
|
241
|
-
'username' => @user_name,
|
242
|
-
'phoneNumbers' => phone_number_,
|
243
|
-
}
|
244
|
-
if (queue_name_ != nil)
|
245
|
-
post_body['queueName'] = queue_name_
|
246
|
-
end
|
247
|
-
url = "#{VOICE_URL}/queueStatus"
|
248
|
-
response = executePost(url, post_body)
|
249
|
-
|
250
|
-
jsObject = JSON.parse(response, :quirky_mode => true)
|
251
|
-
|
252
|
-
if(@response_code == HTTP_OK || @response_code == HTTP_CREATED)
|
253
|
-
if (jsObject['errorMessage'] == "None")
|
254
|
-
results = jsObject['entries'].collect{|result|
|
255
|
-
QueuedCalls.new result['phoneNumber'], result['numCalls'], result['queueName']
|
256
|
-
}
|
257
|
-
return results
|
258
|
-
end
|
259
|
-
|
260
|
-
raise AfricasTalkingGatewayException, jsObject['errorMessage']
|
261
|
-
end
|
262
|
-
|
263
|
-
raise AfricasTalkingGatewayException, response
|
264
|
-
end
|
265
|
-
|
266
|
-
def uploadMediaFile(url_string_)
|
267
|
-
post_body = {
|
268
|
-
'username' => @user_name,
|
269
|
-
'url' => url_string_
|
270
|
-
}
|
271
|
-
url = "#{VOICE_URL}/mediaUpload"
|
272
|
-
response = executePost(url, post_body)
|
273
|
-
|
274
|
-
jsObject = JSON.parse(response, :quirky_mode => true)
|
275
|
-
|
276
|
-
raise AfricasTalkingGatewayException, jsObject['errorMessage'] if jsObject['errorMessage'] != "None"
|
277
|
-
end
|
278
|
-
|
279
|
-
def sendAirtime(recipients_)
|
280
|
-
recipients = recipients_.to_json
|
281
|
-
post_body = {
|
282
|
-
'username' => @user_name,
|
283
|
-
'recipients' => recipients
|
284
|
-
}
|
285
|
-
url = "#{AIRTIME_URL}/send"
|
286
|
-
response = executePost(url, post_body)
|
287
|
-
if (@response_code == HTTP_CREATED)
|
288
|
-
responses = JSON.parse(response)['responses']
|
289
|
-
if (responses.length > 0)
|
290
|
-
results = responses.collect{ |result|
|
291
|
-
AirtimeResult.new result['status'], result['phoneNumber'],result['amount'],result['requestId'], result['errorMessage'], result['discount']
|
292
|
-
}
|
293
|
-
return results
|
294
|
-
else
|
295
|
-
raise AfricasTalkingGatewayException, response['errorMessage']
|
296
|
-
end
|
297
|
-
else
|
298
|
-
raise AfricasTalkingGatewayException, response
|
299
|
-
end
|
300
|
-
|
301
|
-
end
|
302
|
-
|
303
|
-
def getUserData()
|
304
|
-
url = "#{USERDATA_URL}?username=#{@user_name}"
|
305
|
-
response = executePost(url)
|
306
|
-
if (@response_code == HTTP_OK)
|
307
|
-
result = JSON.parse(response, :quirky_mode =>true)['UserData']
|
308
|
-
return result
|
309
|
-
else
|
310
|
-
raise AfricasTalkingGatewayException, response
|
311
|
-
end
|
312
|
-
end
|
313
|
-
|
314
|
-
def executePost(url_, data_ = nil)
|
315
|
-
uri = URI.parse(url_)
|
316
|
-
http = Net::HTTP.new(uri.host, uri.port)
|
317
|
-
http.use_ssl = true
|
318
|
-
headers = {
|
319
|
-
"apikey" => @api_key,
|
320
|
-
"Accept" => "application/json"
|
321
|
-
}
|
322
|
-
if(data_ != nil)
|
323
|
-
request = Net::HTTP::Post.new(uri.request_uri)
|
324
|
-
request.set_form_data(data_)
|
325
|
-
else
|
326
|
-
request = Net::HTTP::Get.new(uri.request_uri)
|
327
|
-
end
|
328
|
-
request["apikey"] = @api_key
|
329
|
-
request["Accept"] = "application/json"
|
330
|
-
|
331
|
-
response = http.request(request)
|
332
|
-
|
333
|
-
if (DEBUG)
|
334
|
-
puts "Full response #{response.body}"
|
335
|
-
end
|
336
|
-
|
337
|
-
@response_code = response.code.to_i
|
338
|
-
return response.body
|
339
|
-
end
|
340
|
-
end
|