emergent_ussd_gateway 0.1.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/.rspec +3 -0
- data/.rubocop.yml +8 -0
- data/CHANGELOG.md +5 -0
- data/LICENSE.txt +21 -0
- data/README.md +162 -0
- data/Rakefile +12 -0
- data/lib/emergent_ussd_gateway/base_controller.rb +36 -0
- data/lib/emergent_ussd_gateway/request_parser.rb +47 -0
- data/lib/emergent_ussd_gateway/response_builder.rb +26 -0
- data/lib/emergent_ussd_gateway/version.rb +5 -0
- data/lib/emergent_ussd_gateway.rb +8 -0
- data/sig/emergent_ussd_gateway.rbs +4 -0
- metadata +89 -0
checksums.yaml
ADDED
@@ -0,0 +1,7 @@
|
|
1
|
+
---
|
2
|
+
SHA256:
|
3
|
+
metadata.gz: d7c4f42f34ceacd928f0690d665a43221cb3a1c5c6cf3f9c11371250701e2518
|
4
|
+
data.tar.gz: 8fed40fe24a3acf80d23ba4cd97758eb74bc104e0c0770745d9ba52c054dd932
|
5
|
+
SHA512:
|
6
|
+
metadata.gz: 19ea4f6c0cbec6f319bf922b75447c8039c424487bf8f157c31cc3f867281f0f5300f782c7f2bd0b592923d56ea3f5e7d8654ec9462450485e6b441f208d3185
|
7
|
+
data.tar.gz: 7dafeca8caf184e21f6a29239fca05af6d23aff89ffe1d3fade3141cf90a4642c2c1437b65b01401618e4dd8d5ab79358cdfa085d0bc4f657d66394f51d482a6
|
data/.rspec
ADDED
data/.rubocop.yml
ADDED
data/CHANGELOG.md
ADDED
data/LICENSE.txt
ADDED
@@ -0,0 +1,21 @@
|
|
1
|
+
The MIT License (MIT)
|
2
|
+
|
3
|
+
Copyright (c) 2025 Shepherd Yaw Morttey
|
4
|
+
|
5
|
+
Permission is hereby granted, free of charge, to any person obtaining a copy
|
6
|
+
of this software and associated documentation files (the "Software"), to deal
|
7
|
+
in the Software without restriction, including without limitation the rights
|
8
|
+
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
9
|
+
copies of the Software, and to permit persons to whom the Software is
|
10
|
+
furnished to do so, subject to the following conditions:
|
11
|
+
|
12
|
+
The above copyright notice and this permission notice shall be included in
|
13
|
+
all copies or substantial portions of the Software.
|
14
|
+
|
15
|
+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
16
|
+
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
17
|
+
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
18
|
+
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
19
|
+
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
20
|
+
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
|
21
|
+
THE SOFTWARE.
|
data/README.md
ADDED
@@ -0,0 +1,162 @@
|
|
1
|
+
# EmergentUssdGateway
|
2
|
+
|
3
|
+
EmergentUssdGateway is a Ruby gem that simplifies handling USSD requests from the [Emergent Technology USSD Gateway](www.emergentafrica.com). Built for Rails developers, it provides a structured way to parse USSD push requests, manage sessions, and send back valid JSON responses.
|
4
|
+
|
5
|
+
---
|
6
|
+
|
7
|
+
## Features
|
8
|
+
|
9
|
+
- Parse and normalize USSD initiation, response, release, and timeout events
|
10
|
+
- Provide structured response builders for `Response` and `Release`
|
11
|
+
- Easily integrate with any Rails app by subclassing a base controller
|
12
|
+
- Mask input routes when expecting confidential entries like PINs
|
13
|
+
- Optional local session tracking (in-memory, Redis, etc. - future versions)
|
14
|
+
|
15
|
+
---
|
16
|
+
|
17
|
+
## Installation
|
18
|
+
|
19
|
+
Add this line to your Gemfile:
|
20
|
+
|
21
|
+
```ruby
|
22
|
+
gem 'emergent_ussd_gateway'
|
23
|
+
```
|
24
|
+
|
25
|
+
Then run:
|
26
|
+
|
27
|
+
```bash
|
28
|
+
bundle install
|
29
|
+
```
|
30
|
+
|
31
|
+
Or install it directly:
|
32
|
+
|
33
|
+
```bash
|
34
|
+
gem install emergent_ussd_gateway
|
35
|
+
```
|
36
|
+
|
37
|
+
---
|
38
|
+
|
39
|
+
## Usage in Rails
|
40
|
+
|
41
|
+
Create a controller that inherits from the gem’s base controller and implement your USSD logic by overriding `handle_ussd`.
|
42
|
+
|
43
|
+
```ruby
|
44
|
+
# app/controllers/emergent_ussd_controller.rb
|
45
|
+
class EmergentUssdController < EmergentUssdGateway::BaseController
|
46
|
+
private
|
47
|
+
|
48
|
+
def handle_ussd(request)
|
49
|
+
case request.type.downcase
|
50
|
+
when "initiation"
|
51
|
+
EmergentUssdGateway::ResponseBuilder.new(
|
52
|
+
type: "Response",
|
53
|
+
message: "Welcome.\n1. Check Balance 2. Change PIN 3. Request Support."
|
54
|
+
)
|
55
|
+
when "response"
|
56
|
+
case request.message.strip
|
57
|
+
when "1"
|
58
|
+
EmergentUssdGateway::ResponseBuilder.new(
|
59
|
+
type: "Release",
|
60
|
+
message: "Your account balance is GHS 53,743"
|
61
|
+
)
|
62
|
+
when "2"
|
63
|
+
EmergentUssdGateway::ResponseBuilder.new(
|
64
|
+
type: "Response",
|
65
|
+
message: "Enter your new PIN",
|
66
|
+
mask_next_route: true
|
67
|
+
)
|
68
|
+
when "3"
|
69
|
+
EmergentUssdGateway::ResponseBuilder.new(
|
70
|
+
type: "Response",
|
71
|
+
message: "Support: Call 1234 or email support@example.com"
|
72
|
+
)
|
73
|
+
else
|
74
|
+
EmergentUssdGateway::ResponseBuilder.new(
|
75
|
+
type: "Response",
|
76
|
+
message: "Invalid option. 1. Check Balance 2. Change PIN 3. Request Support."
|
77
|
+
)
|
78
|
+
end
|
79
|
+
else
|
80
|
+
EmergentUssdGateway::ResponseBuilder.new(
|
81
|
+
type: "Release",
|
82
|
+
message: "Session ended."
|
83
|
+
)
|
84
|
+
end
|
85
|
+
end
|
86
|
+
end
|
87
|
+
```
|
88
|
+
|
89
|
+
Add a route to your `config/routes.rb`:
|
90
|
+
|
91
|
+
```ruby
|
92
|
+
post "/ussd-app", to: "emergent_ussd#ussd"
|
93
|
+
```
|
94
|
+
|
95
|
+
---
|
96
|
+
|
97
|
+
## Example Payloads
|
98
|
+
|
99
|
+
**Incoming POST from Emergent Gateway**
|
100
|
+
|
101
|
+
```json
|
102
|
+
{
|
103
|
+
"Mobile": "233262183777",
|
104
|
+
"SessionId": "abc123",
|
105
|
+
"ServiceCode": "711",
|
106
|
+
"Type": "initiation",
|
107
|
+
"Message": "*711#",
|
108
|
+
"Operator": "Vodafone"
|
109
|
+
}
|
110
|
+
```
|
111
|
+
|
112
|
+
**Response JSON**
|
113
|
+
|
114
|
+
```json
|
115
|
+
{
|
116
|
+
"Type": "Response",
|
117
|
+
"Message": "Enter your PIN",
|
118
|
+
"MaskNextRoute": true
|
119
|
+
}
|
120
|
+
```
|
121
|
+
|
122
|
+
---
|
123
|
+
|
124
|
+
## Development
|
125
|
+
|
126
|
+
```bash
|
127
|
+
git clone https://github.com/smorttey/emergent_ussd_gateway.git
|
128
|
+
cd emergent_ussd_gateway
|
129
|
+
bin/setup # Install dependencies
|
130
|
+
rake spec # Run tests
|
131
|
+
bin/console # Interactive dev console
|
132
|
+
```
|
133
|
+
|
134
|
+
To install locally:
|
135
|
+
|
136
|
+
```bash
|
137
|
+
bundle exec rake install
|
138
|
+
```
|
139
|
+
|
140
|
+
To release a new version:
|
141
|
+
|
142
|
+
1. Update `lib/emergent_ussd_gateway/version.rb`
|
143
|
+
2. Run:
|
144
|
+
|
145
|
+
```bash
|
146
|
+
bundle exec rake release
|
147
|
+
```
|
148
|
+
|
149
|
+
---
|
150
|
+
|
151
|
+
## Contributing
|
152
|
+
|
153
|
+
Bug reports and pull requests are welcome at:
|
154
|
+
https://github.com/smorttey/emergent_ussd_gateway
|
155
|
+
|
156
|
+
---
|
157
|
+
|
158
|
+
## License
|
159
|
+
|
160
|
+
This gem is available as open source under the terms of the [MIT License](https://opensource.org/licenses/MIT).
|
161
|
+
|
162
|
+
---
|
data/Rakefile
ADDED
@@ -0,0 +1,36 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
require "json"
|
4
|
+
require_relative "request_parser"
|
5
|
+
require_relative "response_builder"
|
6
|
+
|
7
|
+
module EmergentUssdGateway
|
8
|
+
# Base controller for handling Emergent Technology USSD requests in Rails.
|
9
|
+
# Subclass this controller and implement #handle_ussd(request) to provide your logic.
|
10
|
+
# Mount your subclassed controller in your Rails routes.
|
11
|
+
class BaseController < ActionController::API
|
12
|
+
# POST /ussd-app
|
13
|
+
def ussd
|
14
|
+
request_data = EmergentUssdGateway::RequestParser.new(params.to_unsafe_h)
|
15
|
+
response = handle_ussd(request_data)
|
16
|
+
unless response.is_a?(EmergentUssdGateway::ResponseBuilder)
|
17
|
+
raise "handle_ussd must return an EmergentUssdGateway::ResponseBuilder instance"
|
18
|
+
end
|
19
|
+
|
20
|
+
render json: response.to_h
|
21
|
+
rescue ArgumentError => e
|
22
|
+
render json: { error: e.message }, status: :bad_request
|
23
|
+
rescue StandardError => e
|
24
|
+
render json: { error: e.message }, status: :internal_server_error
|
25
|
+
end
|
26
|
+
|
27
|
+
private
|
28
|
+
|
29
|
+
# Subclasses must implement this method.
|
30
|
+
# @param request [EmergentUssdGateway::RequestParser]
|
31
|
+
# @return [EmergentUssdGateway::ResponseBuilder]
|
32
|
+
def handle_ussd(request)
|
33
|
+
raise NotImplementedError, "You must implement handle_ussd(request) in your subclass."
|
34
|
+
end
|
35
|
+
end
|
36
|
+
end
|
@@ -0,0 +1,47 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
module EmergentUssdGateway
|
4
|
+
# Parses and validates incoming USSD JSON requests for the Emergent Technology USSD API.
|
5
|
+
# Ensures all required fields are present and exposes request attributes.
|
6
|
+
# Raises ArgumentError if validation fails.
|
7
|
+
class RequestParser
|
8
|
+
REQUIRED_FIELDS = %w[Type Mobile SessionId ServiceCode Message Operator].freeze
|
9
|
+
|
10
|
+
attr_reader :type, :mobile, :session_id, :service_code, :message, :operator
|
11
|
+
|
12
|
+
def initialize(params)
|
13
|
+
@type = params["Type"] || params["type"]
|
14
|
+
@mobile = params["Mobile"] || params["mobile"]
|
15
|
+
@session_id = params["SessionId"] || params["session_id"]
|
16
|
+
@service_code = params["ServiceCode"] || params["service_code"]
|
17
|
+
@message = params["Message"] || params["message"]
|
18
|
+
@operator = params["Operator"] || params["operator"]
|
19
|
+
validate!
|
20
|
+
end
|
21
|
+
|
22
|
+
def self.from_json(json)
|
23
|
+
new(JSON.parse(json))
|
24
|
+
end
|
25
|
+
|
26
|
+
def validate!
|
27
|
+
missing = missing_fields
|
28
|
+
return if missing.empty?
|
29
|
+
|
30
|
+
raise ArgumentError, "Missing required USSD fields: #{missing.join(", ")}"
|
31
|
+
end
|
32
|
+
|
33
|
+
private
|
34
|
+
|
35
|
+
def missing_fields
|
36
|
+
field_map = {
|
37
|
+
"Type" => @type,
|
38
|
+
"Mobile" => @mobile,
|
39
|
+
"SessionId" => @session_id,
|
40
|
+
"ServiceCode" => @service_code,
|
41
|
+
"Message" => @message,
|
42
|
+
"Operator" => @operator
|
43
|
+
}
|
44
|
+
field_map.select { |_k, v| v.nil? }.keys
|
45
|
+
end
|
46
|
+
end
|
47
|
+
end
|
@@ -0,0 +1,26 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
module EmergentUssdGateway
|
4
|
+
# Builds USSD API responses for the Emergent Technology USSD API.
|
5
|
+
# Allows setting Type, Message, and optional MaskNextRoute fields.
|
6
|
+
# Provides a to_json method for API-compliant output.
|
7
|
+
class ResponseBuilder
|
8
|
+
attr_accessor :type, :message, :mask_next_route
|
9
|
+
|
10
|
+
def initialize(type:, message:, mask_next_route: nil)
|
11
|
+
@type = type
|
12
|
+
@message = message
|
13
|
+
@mask_next_route = mask_next_route
|
14
|
+
end
|
15
|
+
|
16
|
+
def to_h
|
17
|
+
h = { "Type" => type, "Message" => message }
|
18
|
+
h["MaskNextRoute"] = mask_next_route unless mask_next_route.nil?
|
19
|
+
h
|
20
|
+
end
|
21
|
+
|
22
|
+
def to_json(*_args)
|
23
|
+
to_h.to_json
|
24
|
+
end
|
25
|
+
end
|
26
|
+
end
|
metadata
ADDED
@@ -0,0 +1,89 @@
|
|
1
|
+
--- !ruby/object:Gem::Specification
|
2
|
+
name: emergent_ussd_gateway
|
3
|
+
version: !ruby/object:Gem::Version
|
4
|
+
version: 0.1.0
|
5
|
+
platform: ruby
|
6
|
+
authors:
|
7
|
+
- Shepherd Yaw Morttey
|
8
|
+
autorequire:
|
9
|
+
bindir: exe
|
10
|
+
cert_chain: []
|
11
|
+
date: 2025-07-17 00:00:00.000000000 Z
|
12
|
+
dependencies:
|
13
|
+
- !ruby/object:Gem::Dependency
|
14
|
+
name: rails
|
15
|
+
requirement: !ruby/object:Gem::Requirement
|
16
|
+
requirements:
|
17
|
+
- - ">="
|
18
|
+
- !ruby/object:Gem::Version
|
19
|
+
version: '6.0'
|
20
|
+
type: :runtime
|
21
|
+
prerelease: false
|
22
|
+
version_requirements: !ruby/object:Gem::Requirement
|
23
|
+
requirements:
|
24
|
+
- - ">="
|
25
|
+
- !ruby/object:Gem::Version
|
26
|
+
version: '6.0'
|
27
|
+
- !ruby/object:Gem::Dependency
|
28
|
+
name: rspec
|
29
|
+
requirement: !ruby/object:Gem::Requirement
|
30
|
+
requirements:
|
31
|
+
- - ">="
|
32
|
+
- !ruby/object:Gem::Version
|
33
|
+
version: '0'
|
34
|
+
type: :development
|
35
|
+
prerelease: false
|
36
|
+
version_requirements: !ruby/object:Gem::Requirement
|
37
|
+
requirements:
|
38
|
+
- - ">="
|
39
|
+
- !ruby/object:Gem::Version
|
40
|
+
version: '0'
|
41
|
+
description: This gem simplifies the integration of Emergent Technology's USSD Gateway
|
42
|
+
into Ruby on Rails applications. It provides request parsers, response builders,
|
43
|
+
and a base controller for clean USSD session handling.
|
44
|
+
email:
|
45
|
+
- shepherd@mfidie.com
|
46
|
+
executables: []
|
47
|
+
extensions: []
|
48
|
+
extra_rdoc_files: []
|
49
|
+
files:
|
50
|
+
- ".rspec"
|
51
|
+
- ".rubocop.yml"
|
52
|
+
- CHANGELOG.md
|
53
|
+
- LICENSE.txt
|
54
|
+
- README.md
|
55
|
+
- Rakefile
|
56
|
+
- lib/emergent_ussd_gateway.rb
|
57
|
+
- lib/emergent_ussd_gateway/base_controller.rb
|
58
|
+
- lib/emergent_ussd_gateway/request_parser.rb
|
59
|
+
- lib/emergent_ussd_gateway/response_builder.rb
|
60
|
+
- lib/emergent_ussd_gateway/version.rb
|
61
|
+
- sig/emergent_ussd_gateway.rbs
|
62
|
+
homepage: https://github.com/smorttey/emergent_ussd_gateway
|
63
|
+
licenses:
|
64
|
+
- MIT
|
65
|
+
metadata:
|
66
|
+
allowed_push_host: https://rubygems.org
|
67
|
+
homepage_uri: https://github.com/smorttey/emergent_ussd_gateway
|
68
|
+
source_code_uri: https://github.com/smorttey/emergent_ussd_gateway
|
69
|
+
changelog_uri: https://github.com/smorttey/emergent_ussd_gateway/blob/main/CHANGELOG.md
|
70
|
+
post_install_message:
|
71
|
+
rdoc_options: []
|
72
|
+
require_paths:
|
73
|
+
- lib
|
74
|
+
required_ruby_version: !ruby/object:Gem::Requirement
|
75
|
+
requirements:
|
76
|
+
- - ">="
|
77
|
+
- !ruby/object:Gem::Version
|
78
|
+
version: 3.0.0
|
79
|
+
required_rubygems_version: !ruby/object:Gem::Requirement
|
80
|
+
requirements:
|
81
|
+
- - ">="
|
82
|
+
- !ruby/object:Gem::Version
|
83
|
+
version: '0'
|
84
|
+
requirements: []
|
85
|
+
rubygems_version: 3.5.22
|
86
|
+
signing_key:
|
87
|
+
specification_version: 4
|
88
|
+
summary: Rails-friendly gem to handle USSD requests from Emergent Technology
|
89
|
+
test_files: []
|