termii_ruby 0.1.0 → 0.1.1
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 +4 -4
- data/.rubocop.yml +3 -0
- data/Gemfile +3 -0
- data/Gemfile.lock +12 -1
- data/README.md +4 -4
- data/lib/termii_ruby/abstract_client.rb +15 -1
- data/lib/termii_ruby/client.rb +11 -6
- data/lib/termii_ruby/insight.rb +30 -0
- data/lib/termii_ruby/sender.rb +18 -0
- data/lib/termii_ruby/termii.rb +40 -3
- data/lib/termii_ruby/token.rb +45 -2
- data/lib/termii_ruby/version.rb +1 -1
- data/lib/termii_ruby.rb +3 -0
- metadata +2 -2
checksums.yaml
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
---
|
|
2
2
|
SHA256:
|
|
3
|
-
metadata.gz:
|
|
4
|
-
data.tar.gz:
|
|
3
|
+
metadata.gz: 845e38ac1d73b88056bd65863f81b0d46d252d773decdf6326711014db0bac10
|
|
4
|
+
data.tar.gz: fe3813e56c0eead5056e5546d10ba9fa67977551003950fc48e93f216540a488
|
|
5
5
|
SHA512:
|
|
6
|
-
metadata.gz:
|
|
7
|
-
data.tar.gz:
|
|
6
|
+
metadata.gz: 8b8f959a635d3f0e35a19a91b38b14e30464dcc1419af766d8c4c89dbf79156d58ba0599a769d580c497255fbbc5e6683fed69281e809375bae198bec3f1b53d
|
|
7
|
+
data.tar.gz: 6b21733a176c75782c23541f78ea5ba6d066e4ad200ed616f80b27ff91c1e3d030f3d57b411d1832930a43a953d119d1c81943f6a06c2be100aa8d2425249cef
|
data/.rubocop.yml
CHANGED
data/Gemfile
CHANGED
data/Gemfile.lock
CHANGED
|
@@ -1,12 +1,16 @@
|
|
|
1
1
|
PATH
|
|
2
2
|
remote: .
|
|
3
3
|
specs:
|
|
4
|
-
termii_ruby (0.1.
|
|
4
|
+
termii_ruby (0.1.1)
|
|
5
5
|
|
|
6
6
|
GEM
|
|
7
7
|
remote: https://rubygems.org/
|
|
8
8
|
specs:
|
|
9
|
+
addressable (2.8.4)
|
|
10
|
+
public_suffix (>= 2.0.2, < 6.0)
|
|
9
11
|
ast (2.4.2)
|
|
12
|
+
crack (0.4.5)
|
|
13
|
+
rexml
|
|
10
14
|
diff-lcs (1.5.0)
|
|
11
15
|
faraday (2.7.4)
|
|
12
16
|
faraday-net_http (>= 2.0, < 3.1)
|
|
@@ -14,10 +18,12 @@ GEM
|
|
|
14
18
|
faraday-net_http (3.0.2)
|
|
15
19
|
faraday-retry (2.1.0)
|
|
16
20
|
faraday (~> 2.0)
|
|
21
|
+
hashdiff (1.0.1)
|
|
17
22
|
json (2.6.3)
|
|
18
23
|
parallel (1.23.0)
|
|
19
24
|
parser (3.2.2.1)
|
|
20
25
|
ast (~> 2.4.1)
|
|
26
|
+
public_suffix (5.0.1)
|
|
21
27
|
rainbow (3.1.1)
|
|
22
28
|
rake (13.0.6)
|
|
23
29
|
regexp_parser (2.8.0)
|
|
@@ -50,6 +56,10 @@ GEM
|
|
|
50
56
|
ruby-progressbar (1.13.0)
|
|
51
57
|
ruby2_keywords (0.0.5)
|
|
52
58
|
unicode-display_width (2.4.2)
|
|
59
|
+
webmock (3.18.1)
|
|
60
|
+
addressable (>= 2.8.0)
|
|
61
|
+
crack (>= 0.3.2)
|
|
62
|
+
hashdiff (>= 0.4.0, < 2.0.0)
|
|
53
63
|
|
|
54
64
|
PLATFORMS
|
|
55
65
|
x86_64-linux
|
|
@@ -61,6 +71,7 @@ DEPENDENCIES
|
|
|
61
71
|
rspec (~> 3.0)
|
|
62
72
|
rubocop (~> 1.21)
|
|
63
73
|
termii_ruby!
|
|
74
|
+
webmock (~> 3.18, >= 3.18.1)
|
|
64
75
|
|
|
65
76
|
BUNDLED WITH
|
|
66
77
|
2.3.5
|
data/README.md
CHANGED
|
@@ -9,7 +9,7 @@ TODO: Delete this and the text above, and describe your gem
|
|
|
9
9
|
Add this line to your application's Gemfile:
|
|
10
10
|
|
|
11
11
|
```ruby
|
|
12
|
-
gem 'termii_ruby'
|
|
12
|
+
gem 'termii_ruby', '~> 0.1.0'
|
|
13
13
|
```
|
|
14
14
|
|
|
15
15
|
And then execute:
|
|
@@ -22,7 +22,7 @@ Or install it yourself as:
|
|
|
22
22
|
|
|
23
23
|
## Usage
|
|
24
24
|
|
|
25
|
-
|
|
25
|
+
|
|
26
26
|
|
|
27
27
|
## Development
|
|
28
28
|
|
|
@@ -32,7 +32,7 @@ To install this gem onto your local machine, run `bundle exec rake install`. To
|
|
|
32
32
|
|
|
33
33
|
## Contributing
|
|
34
34
|
|
|
35
|
-
Bug reports and pull requests are welcome on GitHub at https://github.com/
|
|
35
|
+
Bug reports and pull requests are welcome on GitHub at https://github.com/collinsugwu/termii_ruby. This project is intended to be a safe, welcoming space for collaboration, and contributors are expected to adhere to the [code of conduct](https://github.com/collinsugwu/termii_ruby/blob/master/CODE_OF_CONDUCT.md).
|
|
36
36
|
|
|
37
37
|
## License
|
|
38
38
|
|
|
@@ -40,4 +40,4 @@ The gem is available as open source under the terms of the [MIT License](https:/
|
|
|
40
40
|
|
|
41
41
|
## Code of Conduct
|
|
42
42
|
|
|
43
|
-
Everyone interacting in the TermiiRuby project's codebases, issue trackers, chat rooms and mailing lists is expected to follow the [code of conduct](https://github.com/
|
|
43
|
+
Everyone interacting in the TermiiRuby project's codebases, issue trackers, chat rooms and mailing lists is expected to follow the [code of conduct](https://github.com/collinsugwu/termii_ruby/blob/master/CODE_OF_CONDUCT.md).
|
|
@@ -1,12 +1,26 @@
|
|
|
1
1
|
# frozen_string_literal: true
|
|
2
2
|
|
|
3
|
-
|
|
4
3
|
module TermiiRuby
|
|
4
|
+
#
|
|
5
|
+
# @author Collins
|
|
6
|
+
# A class to enforce the request methods
|
|
7
|
+
# @abstract
|
|
8
|
+
#
|
|
5
9
|
class AbstractClient
|
|
10
|
+
#
|
|
11
|
+
# Ensure the subclass implements the make_get_request method
|
|
12
|
+
#
|
|
13
|
+
# @return [Object] NotImplementedError
|
|
14
|
+
#
|
|
6
15
|
def make_get_request
|
|
7
16
|
raise NotImplementedError, "Subclasses must implement the make_get_request method"
|
|
8
17
|
end
|
|
9
18
|
|
|
19
|
+
#
|
|
20
|
+
# Ensure the subclass implements the make_post_request method
|
|
21
|
+
#
|
|
22
|
+
# @return [Object] NotImplementedError
|
|
23
|
+
#
|
|
10
24
|
def make_post_request
|
|
11
25
|
raise NotImplementedError, "Subclasses must implement the make_post_request method"
|
|
12
26
|
end
|
data/lib/termii_ruby/client.rb
CHANGED
|
@@ -6,6 +6,10 @@ require "faraday/retry"
|
|
|
6
6
|
require_relative "abstract_client"
|
|
7
7
|
|
|
8
8
|
module TermiiRuby
|
|
9
|
+
#
|
|
10
|
+
# @author Collins Ugwu
|
|
11
|
+
# Client class to make request to Termii endpoints
|
|
12
|
+
#
|
|
9
13
|
class Client < TermiiRuby::AbstractClient
|
|
10
14
|
def initialize(api_key)
|
|
11
15
|
@api_key = api_key
|
|
@@ -24,10 +28,7 @@ module TermiiRuby
|
|
|
24
28
|
end
|
|
25
29
|
end
|
|
26
30
|
|
|
27
|
-
|
|
28
|
-
status: response.status,
|
|
29
|
-
data: response.body
|
|
30
|
-
}
|
|
31
|
+
request_response(response)
|
|
31
32
|
end
|
|
32
33
|
|
|
33
34
|
def make_post_request(endpoint, args = {})
|
|
@@ -38,14 +39,18 @@ module TermiiRuby
|
|
|
38
39
|
req.body = args.to_json
|
|
39
40
|
end
|
|
40
41
|
|
|
42
|
+
request_response(response)
|
|
43
|
+
end
|
|
44
|
+
|
|
45
|
+
private
|
|
46
|
+
|
|
47
|
+
def request_response(response)
|
|
41
48
|
{
|
|
42
49
|
status: response.status,
|
|
43
50
|
data: response.body
|
|
44
51
|
}
|
|
45
52
|
end
|
|
46
53
|
|
|
47
|
-
private
|
|
48
|
-
|
|
49
54
|
def request_url(endpoint)
|
|
50
55
|
"#{base_url}/#{endpoint}"
|
|
51
56
|
end
|
data/lib/termii_ruby/insight.rb
CHANGED
|
@@ -5,6 +5,10 @@ require_relative "termii"
|
|
|
5
5
|
require_relative "client"
|
|
6
6
|
|
|
7
7
|
module TermiiRuby
|
|
8
|
+
#
|
|
9
|
+
# @author Collins Ugwu
|
|
10
|
+
# Retrieve real-time delivery report of messages sent to customers as well as the status of their contacts
|
|
11
|
+
#
|
|
8
12
|
class Insight < TermiiRuby::Termii
|
|
9
13
|
QUERY = "phone_number"
|
|
10
14
|
|
|
@@ -15,10 +19,23 @@ module TermiiRuby
|
|
|
15
19
|
|
|
16
20
|
def verify; end
|
|
17
21
|
|
|
22
|
+
#
|
|
23
|
+
# The Balance API returns your total balance and balance information from your wallet, such as currency.
|
|
24
|
+
#
|
|
25
|
+
# @return [JSON] JSON object
|
|
26
|
+
#
|
|
18
27
|
def balance
|
|
19
28
|
@client.make_get_request(GET_BALANCE)
|
|
20
29
|
end
|
|
21
30
|
|
|
31
|
+
#
|
|
32
|
+
# The search API allows businesses verify phone numbers and automatically detect their status as well as current network
|
|
33
|
+
#
|
|
34
|
+
# @param [String] phone_number Represents the phone number to be verified. Phone number must be in the international format (Example: 23490126727)
|
|
35
|
+
# @param [Hash] query Hash of the query params
|
|
36
|
+
#
|
|
37
|
+
# @return [JSON] JSON object
|
|
38
|
+
#
|
|
22
39
|
def search(phone_number, query = {})
|
|
23
40
|
if query.empty?
|
|
24
41
|
query = {
|
|
@@ -29,6 +46,14 @@ module TermiiRuby
|
|
|
29
46
|
@client.make_get_request(SEARCH, query)
|
|
30
47
|
end
|
|
31
48
|
|
|
49
|
+
#
|
|
50
|
+
# The status API allows businesses to detect if a number is fake or has ported to a new network.
|
|
51
|
+
#
|
|
52
|
+
# @param [<Type>] phone_number Represents the phone number to be verified. Phone number must be in the international format (Example: 2348753243651)
|
|
53
|
+
# @param [Hash] query Hash of the query params
|
|
54
|
+
#
|
|
55
|
+
# @return [JSON] JSON object
|
|
56
|
+
#
|
|
32
57
|
def status(phone_number, query = {})
|
|
33
58
|
if query.empty?
|
|
34
59
|
query = {
|
|
@@ -39,6 +64,11 @@ module TermiiRuby
|
|
|
39
64
|
@client.make_get_request(STATUS, query)
|
|
40
65
|
end
|
|
41
66
|
|
|
67
|
+
#
|
|
68
|
+
# This Inbox API returns reports for messages sent across the sms, voice & whatsapp channels. Reports can either display all messages on termii or a single message.
|
|
69
|
+
#
|
|
70
|
+
# @return [JSON] JSON object
|
|
71
|
+
#
|
|
42
72
|
def history
|
|
43
73
|
@client.make_get_request(HISTORY)
|
|
44
74
|
end
|
data/lib/termii_ruby/sender.rb
CHANGED
|
@@ -5,12 +5,25 @@ require_relative "termii"
|
|
|
5
5
|
require_relative "client"
|
|
6
6
|
|
|
7
7
|
module TermiiRuby
|
|
8
|
+
#
|
|
9
|
+
# @author Collins Ugwu
|
|
10
|
+
# Sender Class for creating and fetching the sender ID
|
|
11
|
+
#
|
|
8
12
|
class Sender < TermiiRuby::Termii
|
|
9
13
|
def initialize(api_key)
|
|
10
14
|
super()
|
|
11
15
|
@client = TermiiRuby::Client.new(api_key)
|
|
12
16
|
end
|
|
13
17
|
|
|
18
|
+
#
|
|
19
|
+
# Create a Sender ID
|
|
20
|
+
#
|
|
21
|
+
# @param [String] sender_id Represents the ID of the sender which can be alphanumeric or numeric
|
|
22
|
+
# @param [String] usecase A sample of the type of message sent.
|
|
23
|
+
# @param [String] company Represents the name of the company with the sender ID.
|
|
24
|
+
#
|
|
25
|
+
# @return [JSON] JSON object
|
|
26
|
+
#
|
|
14
27
|
def create_sender(sender_id, usecase, company)
|
|
15
28
|
data = {
|
|
16
29
|
sender_id: sender_id,
|
|
@@ -20,6 +33,11 @@ module TermiiRuby
|
|
|
20
33
|
@client.make_post_request(CREATE_SENDER, data)
|
|
21
34
|
end
|
|
22
35
|
|
|
36
|
+
#
|
|
37
|
+
# A Sender ID is the name or number that identifies the sender of an SMS message.
|
|
38
|
+
#
|
|
39
|
+
# @return [JSON] JSON object
|
|
40
|
+
#
|
|
23
41
|
def fetch_senders
|
|
24
42
|
@client.make_get_request(FETCH_SENDER)
|
|
25
43
|
end
|
data/lib/termii_ruby/termii.rb
CHANGED
|
@@ -1,13 +1,38 @@
|
|
|
1
1
|
# frozen_string_literal: true
|
|
2
2
|
|
|
3
|
-
# Base Class
|
|
4
|
-
|
|
5
3
|
require_relative "mixins/endpoints"
|
|
6
4
|
|
|
7
5
|
module TermiiRuby
|
|
6
|
+
#
|
|
7
|
+
# @author Collins Ugwu
|
|
8
|
+
# Base Termii Class
|
|
9
|
+
#
|
|
8
10
|
class Termii
|
|
9
11
|
include TermiiRuby::Mixins::Endpoints
|
|
10
|
-
|
|
12
|
+
|
|
13
|
+
# @return [Stiring] Enum: "NUMERIC" "ALPHANUMERIC" Type of message that will be generated and sent as part of the OTP message. You can set message type to numeric or alphanumeric
|
|
14
|
+
attr_accessor :message_type
|
|
15
|
+
|
|
16
|
+
# @return [String] "NUMERIC"
|
|
17
|
+
attr_accessor :pin_type
|
|
18
|
+
|
|
19
|
+
# @return [String] This is the route through which the message is sent. It is either dnd, WhatsApp, or generic or email
|
|
20
|
+
attr_accessor :channel
|
|
21
|
+
|
|
22
|
+
# @return [Integer] Example: 3 Represents the number of times the PIN can be attempted before expiration. It has a minimum of one attempt
|
|
23
|
+
attr_accessor :pin_attempts
|
|
24
|
+
|
|
25
|
+
# @return [Integer] The length of the PIN code.It has a minimum of 4 and maximum of 8.
|
|
26
|
+
attr_accessor :pin_length
|
|
27
|
+
|
|
28
|
+
# @return [Interger] Represents how long the PIN is valid before expiration. The time is in minutes. The minimum time value is 0 and the maximum time value is 60
|
|
29
|
+
attr_accessor :pin_time_to_live
|
|
30
|
+
|
|
31
|
+
# @return [String] Example: "< 1234 >" PIN placeholder. Right before sending the message, PIN code placeholder will be replaced with generate PIN code.
|
|
32
|
+
attr_accessor :pin_placeholder
|
|
33
|
+
|
|
34
|
+
# @return [String] Represents short alphabetic codes developed to represent countries
|
|
35
|
+
attr_accessor :country_code
|
|
11
36
|
|
|
12
37
|
def initialize
|
|
13
38
|
@message_type = "NUMERIC"
|
|
@@ -20,10 +45,22 @@ module TermiiRuby
|
|
|
20
45
|
@country_code = "NG"
|
|
21
46
|
end
|
|
22
47
|
|
|
48
|
+
#
|
|
49
|
+
# Subclasses must implement the verify method
|
|
50
|
+
#
|
|
51
|
+
# @return [Object] NotImplementedError
|
|
52
|
+
#
|
|
23
53
|
def verify
|
|
24
54
|
raise NotImplementedError, "Subclasses must implement the verify method"
|
|
25
55
|
end
|
|
26
56
|
|
|
57
|
+
#
|
|
58
|
+
# <Description>
|
|
59
|
+
#
|
|
60
|
+
# @param [<Type>] attrs <description>
|
|
61
|
+
#
|
|
62
|
+
# @return [<Type>] <description>
|
|
63
|
+
#
|
|
27
64
|
def update_attributes(attrs)
|
|
28
65
|
attrs.each do |key, value|
|
|
29
66
|
self[key.to_s] = value
|
data/lib/termii_ruby/token.rb
CHANGED
|
@@ -5,12 +5,25 @@ require_relative "termii"
|
|
|
5
5
|
require_relative "client"
|
|
6
6
|
|
|
7
7
|
module TermiiRuby
|
|
8
|
+
#
|
|
9
|
+
# @author Collins Ugwu
|
|
10
|
+
# Token allows businesses generate, send and verify one-time-passwords.
|
|
11
|
+
#
|
|
8
12
|
class Token < TermiiRuby::Termii
|
|
9
13
|
def initialize(api_key)
|
|
10
14
|
super()
|
|
11
15
|
@client = TermiiRuby::Client.new(api_key)
|
|
12
16
|
end
|
|
13
17
|
|
|
18
|
+
#
|
|
19
|
+
# The send token API allows businesses trigger one-time-passwords (OTP) across any available messaging channel on Termii. One-time-passwords created are generated randomly and there's an option to set an expiry time.
|
|
20
|
+
#
|
|
21
|
+
# @param [string] to Represents the email address if the channel is set to email (Example: testshola@termii.com). It represents the destination phone number if other channels are selected. Phone number must be in the international format (Example: 23490126727)
|
|
22
|
+
# @param [string] from Represents the configuration ID if the channel is set to email (Example: 0a53c416-uocj-95af-ab3c306aellc). It can be found on your Termii dashboard. If other channels are selected, it represents a sender ID which can be alphanumeric or numeric. Alphanumeric sender ID length should be between 3 and 11 characters (Example:CompanyName)
|
|
23
|
+
# @param [string] message_text Text of a message that would be sent to the destination phone number
|
|
24
|
+
#
|
|
25
|
+
# @return [JSON] JSON object
|
|
26
|
+
#
|
|
14
27
|
def send_otp_token(to, from, message_text)
|
|
15
28
|
data = {
|
|
16
29
|
to: to,
|
|
@@ -27,6 +40,13 @@ module TermiiRuby
|
|
|
27
40
|
@client.make_post_request(SEND_OTP_TOKEN, data)
|
|
28
41
|
end
|
|
29
42
|
|
|
43
|
+
#
|
|
44
|
+
# The voice token API enables you to generate and trigger one-time passwords (OTP) through the voice channel to a phone number. OTPs are generated and sent to the phone number and can only be verified using our Verify Token API .
|
|
45
|
+
#
|
|
46
|
+
# @param [string] phone_number The destination phone number. Phone number must be in the international format (Example: 23490126727)
|
|
47
|
+
#
|
|
48
|
+
# @return [JSON] JSON object
|
|
49
|
+
#
|
|
30
50
|
def send_voice_token(phone_number)
|
|
31
51
|
data = {
|
|
32
52
|
phone_number: phone_number,
|
|
@@ -37,6 +57,14 @@ module TermiiRuby
|
|
|
37
57
|
@client.make_post_request(SEND_VOICE_TOKEN, data)
|
|
38
58
|
end
|
|
39
59
|
|
|
60
|
+
#
|
|
61
|
+
# The voice call API enables you to send messages from your application through our voice channel to a phone number. Only one-time-passwords (OTP) are allowed for now and these OTPs can not be verified using our Verify Token API.
|
|
62
|
+
#
|
|
63
|
+
# @param [String] phone_number The destination phone number. Phone number must be in the international format (Example: 23490126727)
|
|
64
|
+
# @param [Numeric] code Example: 3344, The code you want your users to receive. It has to be numeric and length must be between 4 and 8 digits.
|
|
65
|
+
#
|
|
66
|
+
# @return [JSON] JSON object
|
|
67
|
+
#
|
|
40
68
|
def send_voice_call(phone_number, code)
|
|
41
69
|
data = {
|
|
42
70
|
phone_number: phone_number,
|
|
@@ -46,6 +74,13 @@ module TermiiRuby
|
|
|
46
74
|
@client.make_post_request(SEND_VOICE_CALL, data)
|
|
47
75
|
end
|
|
48
76
|
|
|
77
|
+
#
|
|
78
|
+
# This API returns OTP codes in JSON format which can be used within any web or mobile app.
|
|
79
|
+
#
|
|
80
|
+
# @param [String] phone_number Represents the destination phone number.Phone number must be in the international format (Example: 23490126727)
|
|
81
|
+
#
|
|
82
|
+
# @return [JSON] JSON object
|
|
83
|
+
#
|
|
49
84
|
def send_in_app_token(phone_number)
|
|
50
85
|
data = {
|
|
51
86
|
phone_number: phone_number,
|
|
@@ -57,10 +92,18 @@ module TermiiRuby
|
|
|
57
92
|
@client.make_post_request(SEND_IN_APP_TOKEN, data)
|
|
58
93
|
end
|
|
59
94
|
|
|
60
|
-
|
|
95
|
+
#
|
|
96
|
+
# Verify token API, checks tokens sent to customers and returns a response confirming the status of the token. A token can either be confirmed as verified or expired based on the timer set for the token.
|
|
97
|
+
#
|
|
98
|
+
# @param [string] pin_id ID of the PIN sent (Example: "c8dcd048-5e7f-4347-8c89-4470c3af0b")
|
|
99
|
+
# @param [string] token The PIN code (Example: "195558")
|
|
100
|
+
#
|
|
101
|
+
# @return [JSON] JSON object
|
|
102
|
+
#
|
|
103
|
+
def verify(pin_id, token)
|
|
61
104
|
data = {
|
|
62
105
|
pin_id: pin_id,
|
|
63
|
-
pin:
|
|
106
|
+
pin: token
|
|
64
107
|
}
|
|
65
108
|
@client.make_post_request(VERIFY_TOKEN, data)
|
|
66
109
|
end
|
data/lib/termii_ruby/version.rb
CHANGED
data/lib/termii_ruby.rb
CHANGED
metadata
CHANGED
|
@@ -1,14 +1,14 @@
|
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
|
2
2
|
name: termii_ruby
|
|
3
3
|
version: !ruby/object:Gem::Version
|
|
4
|
-
version: 0.1.
|
|
4
|
+
version: 0.1.1
|
|
5
5
|
platform: ruby
|
|
6
6
|
authors:
|
|
7
7
|
- Collins Ugwu
|
|
8
8
|
autorequire:
|
|
9
9
|
bindir: exe
|
|
10
10
|
cert_chain: []
|
|
11
|
-
date: 2023-05
|
|
11
|
+
date: 2023-06-05 00:00:00.000000000 Z
|
|
12
12
|
dependencies: []
|
|
13
13
|
description: A Ruby gem for integrating Termii messaging API
|
|
14
14
|
email:
|