vonage 7.8.2 → 7.36.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 +4 -4
- data/README.md +880 -87
- data/lib/vonage/account.rb +2 -0
- data/lib/vonage/api_error.rb +33 -0
- data/lib/vonage/applications.rb +12 -4
- data/lib/vonage/basic.rb +1 -1
- data/lib/vonage/basic_and_bearer_token.rb +18 -0
- data/lib/vonage/basic_and_signature.rb +22 -0
- data/lib/vonage/bearer_token.rb +1 -1
- data/lib/vonage/client.rb +79 -0
- data/lib/vonage/client_error.rb +1 -1
- data/lib/vonage/config.rb +11 -1
- data/lib/vonage/conversation/event/list_response.rb +11 -0
- data/lib/vonage/conversation/event.rb +108 -0
- data/lib/vonage/conversation/list_response.rb +11 -0
- data/lib/vonage/conversation/member/list_response.rb +11 -0
- data/lib/vonage/conversation/member.rb +134 -0
- data/lib/vonage/conversation/user/conversations_list_response.rb +11 -0
- data/lib/vonage/conversation/user/sessions_list_response.rb +11 -0
- data/lib/vonage/conversation/user.rb +67 -0
- data/lib/vonage/conversation.rb +164 -0
- data/lib/vonage/conversations/events.rb +12 -0
- data/lib/vonage/conversations/legs.rb +6 -0
- data/lib/vonage/conversations/members.rb +15 -0
- data/lib/vonage/conversations/users.rb +15 -0
- data/lib/vonage/conversations.rb +30 -0
- data/lib/vonage/conversions.rb +2 -0
- data/lib/vonage/errors.rb +37 -20
- data/lib/vonage/http.rb +3 -3
- data/lib/vonage/identity_insights/insights_builder.rb +75 -0
- data/lib/vonage/identity_insights.rb +75 -0
- data/lib/vonage/jwt.rb +17 -0
- data/lib/vonage/key_secret_params.rb +3 -2
- data/lib/vonage/keys.rb +24 -1
- data/lib/vonage/logger.rb +0 -3
- data/lib/vonage/meetings/applications.rb +28 -0
- data/lib/vonage/meetings/dial_in_numbers/list_response.rb +11 -0
- data/lib/vonage/meetings/dial_in_numbers.rb +26 -0
- data/lib/vonage/meetings/recordings.rb +42 -0
- data/lib/vonage/meetings/rooms/list_response.rb +11 -0
- data/lib/vonage/meetings/rooms.rb +167 -0
- data/lib/vonage/meetings/sessions/list_response.rb +11 -0
- data/lib/vonage/meetings/sessions.rb +31 -0
- data/lib/vonage/meetings/themes/list_response.rb +11 -0
- data/lib/vonage/meetings/themes.rb +239 -0
- data/lib/vonage/meetings.rb +50 -0
- data/lib/vonage/messaging/channels/messenger.rb +2 -0
- data/lib/vonage/messaging/channels/mms.rb +13 -3
- data/lib/vonage/messaging/channels/rcs.rb +44 -0
- data/lib/vonage/messaging/channels/sms.rb +2 -0
- data/lib/vonage/messaging/channels/viber.rb +11 -2
- data/lib/vonage/messaging/channels/whats_app.rb +5 -1
- data/lib/vonage/messaging/message.rb +4 -1
- data/lib/vonage/messaging.rb +43 -4
- data/lib/vonage/namespace.rb +152 -69
- data/lib/vonage/network_authentication/client_authentication.rb +39 -0
- data/lib/vonage/network_authentication/server_authentication.rb +47 -0
- data/lib/vonage/network_authentication.rb +22 -0
- data/lib/vonage/network_number_verification.rb +92 -0
- data/lib/vonage/network_sim_swap.rb +84 -0
- data/lib/vonage/number_insight.rb +1 -0
- data/lib/vonage/number_insight_2.rb +21 -0
- data/lib/vonage/numbers.rb +40 -17
- data/lib/vonage/proactive_connect/events/list_response.rb +11 -0
- data/lib/vonage/proactive_connect/events.rb +71 -0
- data/lib/vonage/proactive_connect/item.rb +116 -0
- data/lib/vonage/proactive_connect/items/file_response.rb +32 -0
- data/lib/vonage/proactive_connect/items/list_response.rb +11 -0
- data/lib/vonage/proactive_connect/items.rb +116 -0
- data/lib/vonage/proactive_connect/list.rb +186 -0
- data/lib/vonage/proactive_connect/lists/list_response.rb +11 -0
- data/lib/vonage/proactive_connect/lists.rb +38 -0
- data/lib/vonage/proactive_connect.rb +43 -0
- data/lib/vonage/server_error.rb +1 -1
- data/lib/vonage/signature.rb +29 -6
- data/lib/vonage/sms.rb +25 -0
- data/lib/vonage/subaccounts/balance_transfers/list_response.rb +11 -0
- data/lib/vonage/subaccounts/credit_transfers/list_response.rb +11 -0
- data/lib/vonage/subaccounts/list_response.rb +15 -0
- data/lib/vonage/subaccounts.rb +203 -0
- data/lib/vonage/users/list_response.rb +11 -0
- data/lib/vonage/users.rb +156 -0
- data/lib/vonage/verify.rb +2 -0
- data/lib/vonage/verify2/channels/email.rb +36 -0
- data/lib/vonage/verify2/channels/silent_auth.rb +46 -0
- data/lib/vonage/verify2/channels/sms.rb +63 -0
- data/lib/vonage/verify2/channels/voice.rb +32 -0
- data/lib/vonage/verify2/channels/whats_app.rb +45 -0
- data/lib/vonage/verify2/channels/whats_app_interactive.rb +32 -0
- data/lib/vonage/verify2/start_verification_options.rb +63 -0
- data/lib/vonage/verify2/template_fragments/list_response.rb +11 -0
- data/lib/vonage/verify2/template_fragments.rb +125 -0
- data/lib/vonage/verify2/templates/list_response.rb +11 -0
- data/lib/vonage/verify2/templates.rb +86 -0
- data/lib/vonage/verify2/workflow.rb +39 -0
- data/lib/vonage/verify2/workflow_builder.rb +25 -0
- data/lib/vonage/verify2.rb +112 -0
- data/lib/vonage/version.rb +1 -1
- data/lib/vonage/video/archives/list_response.rb +11 -0
- data/lib/vonage/video/archives.rb +164 -0
- data/lib/vonage/video/broadcasts/list_response.rb +11 -0
- data/lib/vonage/video/broadcasts.rb +75 -0
- data/lib/vonage/video/captions.rb +67 -0
- data/lib/vonage/video/connections/list_response.rb +11 -0
- data/lib/vonage/video/connections.rb +29 -0
- data/lib/vonage/video/moderation.rb +58 -0
- data/lib/vonage/video/renders/list_response.rb +11 -0
- data/lib/vonage/video/renders.rb +107 -0
- data/lib/vonage/video/signals.rb +50 -0
- data/lib/vonage/video/sip.rb +48 -0
- data/lib/vonage/video/streams/list_response.rb +11 -0
- data/lib/vonage/video/streams.rb +70 -0
- data/lib/vonage/video/web_socket.rb +68 -0
- data/lib/vonage/video.rb +134 -0
- data/lib/vonage/voice/actions/connect.rb +45 -9
- data/lib/vonage/voice/actions/conversation.rb +10 -4
- data/lib/vonage/voice/actions/input.rb +26 -3
- data/lib/vonage/voice/actions/notify.rb +8 -3
- data/lib/vonage/voice/actions/record.rb +52 -4
- data/lib/vonage/voice/actions/stream.rb +7 -3
- data/lib/vonage/voice/actions/talk.rb +29 -4
- data/lib/vonage/voice/actions/transfer.rb +83 -0
- data/lib/vonage/voice/actions/wait.rb +43 -0
- data/lib/vonage/voice/ncco.rb +3 -1
- data/lib/vonage/voice/talk.rb +11 -1
- data/lib/vonage/voice.rb +24 -0
- data/lib/vonage.rb +4 -0
- data/vonage.gemspec +3 -1
- metadata +119 -9
- data/lib/vonage/voice/actions/pay.rb +0 -107
data/lib/vonage/namespace.rb
CHANGED
|
@@ -1,6 +1,9 @@
|
|
|
1
1
|
# typed: true
|
|
2
2
|
# frozen_string_literal: true
|
|
3
|
+
|
|
3
4
|
require 'net/http'
|
|
5
|
+
require 'net/http/persistent'
|
|
6
|
+
require 'net/http/post/multipart'
|
|
4
7
|
require 'json'
|
|
5
8
|
|
|
6
9
|
module Vonage
|
|
@@ -8,10 +11,9 @@ module Vonage
|
|
|
8
11
|
def initialize(config)
|
|
9
12
|
@config = config
|
|
10
13
|
|
|
11
|
-
@host =
|
|
14
|
+
@host = set_host
|
|
12
15
|
|
|
13
|
-
@http = Net::HTTP.new
|
|
14
|
-
@http.use_ssl = true
|
|
16
|
+
@http = Net::HTTP::Persistent.new
|
|
15
17
|
|
|
16
18
|
@config.http.set(@http) unless @config.http.nil?
|
|
17
19
|
end
|
|
@@ -21,8 +23,7 @@ module Vonage
|
|
|
21
23
|
end
|
|
22
24
|
|
|
23
25
|
def self.host=(host)
|
|
24
|
-
raise ArgumentError unless
|
|
25
|
-
|
|
26
|
+
raise ArgumentError unless %i[rest_host video_host vonage_host].include?(host)
|
|
26
27
|
@host = host
|
|
27
28
|
end
|
|
28
29
|
|
|
@@ -47,40 +48,42 @@ module Vonage
|
|
|
47
48
|
end
|
|
48
49
|
|
|
49
50
|
protected
|
|
51
|
+
|
|
50
52
|
# :nocov:
|
|
51
53
|
|
|
52
54
|
Get = Net::HTTP::Get
|
|
53
55
|
Put = Net::HTTP::Put
|
|
56
|
+
Patch = Net::HTTP::Patch
|
|
54
57
|
Post = Net::HTTP::Post
|
|
55
58
|
Delete = Net::HTTP::Delete
|
|
56
59
|
|
|
57
|
-
def build_request(path:, type: Get, params: {})
|
|
60
|
+
def build_request(path:, type: Get, params: {}, auth_data: nil)
|
|
58
61
|
authentication = self.class.authentication.new(@config)
|
|
59
|
-
authentication.update(params)
|
|
62
|
+
authentication.update(params, auth_data)
|
|
60
63
|
|
|
61
|
-
uri = URI(
|
|
64
|
+
uri = URI("https://" + @host + path)
|
|
62
65
|
unless type.const_get(:REQUEST_HAS_BODY) || params.empty?
|
|
63
66
|
uri.query = Params.encode(params)
|
|
64
67
|
end
|
|
65
68
|
|
|
66
|
-
# Set BasicAuth if neeeded
|
|
67
|
-
authentication.update(uri)
|
|
68
|
-
|
|
69
69
|
# instantiate request
|
|
70
70
|
request = type.new(uri)
|
|
71
71
|
|
|
72
72
|
# set headers
|
|
73
|
-
request[
|
|
74
|
-
|
|
75
|
-
|
|
76
|
-
|
|
77
|
-
|
|
73
|
+
request["User-Agent"] = UserAgent.string(
|
|
74
|
+
@config.app_name,
|
|
75
|
+
@config.app_version
|
|
76
|
+
)
|
|
77
|
+
request["Accept"] = "application/json"
|
|
78
|
+
self.class.request_headers.each { |key, value| request[key] = value }
|
|
78
79
|
|
|
79
|
-
# Set
|
|
80
|
-
authentication.update(request)
|
|
80
|
+
# Set Authorization header if needed
|
|
81
|
+
authentication.update(request, auth_data)
|
|
81
82
|
|
|
82
83
|
# set body
|
|
83
|
-
|
|
84
|
+
if type.const_get(:REQUEST_HAS_BODY)
|
|
85
|
+
self.class.request_body.update(request, params)
|
|
86
|
+
end
|
|
84
87
|
|
|
85
88
|
request
|
|
86
89
|
end
|
|
@@ -88,7 +91,8 @@ module Vonage
|
|
|
88
91
|
def make_request!(request, &block)
|
|
89
92
|
logger.log_request_info(request)
|
|
90
93
|
|
|
91
|
-
|
|
94
|
+
uri = URI("https://" + @host + request.path)
|
|
95
|
+
response = @http.request(uri, request, &block)
|
|
92
96
|
|
|
93
97
|
logger.log_response_info(response, @host)
|
|
94
98
|
|
|
@@ -99,17 +103,32 @@ module Vonage
|
|
|
99
103
|
response
|
|
100
104
|
end
|
|
101
105
|
|
|
102
|
-
def request(path, params: nil, type: Get, response_class: Response, &block)
|
|
103
|
-
auto_advance =
|
|
106
|
+
def request(path, params: nil, type: Get, response_class: Response, auth_data: nil, &block)
|
|
107
|
+
auto_advance =
|
|
108
|
+
(
|
|
109
|
+
if !params.nil? && params.key?(:auto_advance)
|
|
110
|
+
params[:auto_advance]
|
|
111
|
+
else
|
|
112
|
+
false
|
|
113
|
+
end
|
|
114
|
+
)
|
|
104
115
|
|
|
105
|
-
params =
|
|
116
|
+
params =
|
|
117
|
+
params.tap { |params| params.delete(:auto_advance) } if !params.nil? &&
|
|
118
|
+
params.key?(:auto_advance)
|
|
106
119
|
|
|
107
|
-
request = build_request(path: path, params: params || {}, type: type)
|
|
120
|
+
request = build_request(path: path, params: params || {}, type: type, auth_data: auth_data)
|
|
108
121
|
|
|
109
122
|
response = make_request!(request, &block)
|
|
110
123
|
|
|
111
124
|
if auto_advance
|
|
112
|
-
iterable_request(
|
|
125
|
+
iterable_request(
|
|
126
|
+
path,
|
|
127
|
+
response: response,
|
|
128
|
+
response_class: response_class,
|
|
129
|
+
params: params,
|
|
130
|
+
&block
|
|
131
|
+
)
|
|
113
132
|
else
|
|
114
133
|
return if block
|
|
115
134
|
|
|
@@ -117,22 +136,59 @@ module Vonage
|
|
|
117
136
|
end
|
|
118
137
|
end
|
|
119
138
|
|
|
139
|
+
def multipart_post_request(path, filepath:, file_name:, mime_type:, params: {}, override_uri: nil, no_auth: false, response_class: Response, auth_data: nil, &block)
|
|
140
|
+
authentication = self.class.authentication.new(@config) unless no_auth
|
|
141
|
+
|
|
142
|
+
uri = override_uri ? URI(override_uri) : URI('https://' + @host + path)
|
|
143
|
+
|
|
144
|
+
http = Net::HTTP.new(uri.host, Net::HTTP.https_default_port, p_addr = nil)
|
|
145
|
+
http.use_ssl = true
|
|
146
|
+
http.set_debug_output($stdout)
|
|
147
|
+
|
|
148
|
+
response = File.open(filepath) do |file|
|
|
149
|
+
request = Net::HTTP::Post::Multipart.new(
|
|
150
|
+
uri,
|
|
151
|
+
params.merge(file: Multipart::Post::UploadIO.new(file, mime_type, file_name))
|
|
152
|
+
)
|
|
153
|
+
|
|
154
|
+
request['User-Agent'] = UserAgent.string(@config.app_name, @config.app_version)
|
|
155
|
+
|
|
156
|
+
# Set Authorization header if needed
|
|
157
|
+
authentication.update(request, auth_data) unless no_auth
|
|
158
|
+
|
|
159
|
+
logger.log_request_info(request)
|
|
160
|
+
|
|
161
|
+
http.request(request, &block)
|
|
162
|
+
end
|
|
163
|
+
|
|
164
|
+
logger.log_response_info(response, @host)
|
|
165
|
+
|
|
166
|
+
return if block
|
|
167
|
+
|
|
168
|
+
logger.debug(response.body) if response.body
|
|
169
|
+
|
|
170
|
+
parse(response, response_class)
|
|
171
|
+
end
|
|
172
|
+
|
|
120
173
|
def iterable_request(path, response: nil, response_class: nil, params: {}, &block)
|
|
121
174
|
json_response = ::JSON.parse(response.body)
|
|
122
175
|
response = parse(response, response_class)
|
|
123
176
|
remainder = remaining_count(json_response)
|
|
124
177
|
|
|
125
178
|
while remainder > 0
|
|
126
|
-
params = { page_size: json_response[
|
|
127
|
-
|
|
128
|
-
if json_response[
|
|
129
|
-
params[:record_index] = json_response[
|
|
130
|
-
elsif json_response[
|
|
131
|
-
|
|
179
|
+
params = { page_size: json_response["page_size"] }
|
|
180
|
+
|
|
181
|
+
if json_response["record_index"] && json_response["record_index"] == 0
|
|
182
|
+
params[:record_index] = json_response["page_size"]
|
|
183
|
+
elsif json_response["record_index"] &&
|
|
184
|
+
json_response["record_index"] != 0
|
|
185
|
+
params[:record_index] = (
|
|
186
|
+
json_response["record_index"] + json_response["page_size"]
|
|
187
|
+
)
|
|
132
188
|
end
|
|
133
189
|
|
|
134
|
-
if json_response[
|
|
135
|
-
params[:page] = json_response[
|
|
190
|
+
if json_response["total_pages"]
|
|
191
|
+
params[:page] = json_response["page"] + 1
|
|
136
192
|
end
|
|
137
193
|
|
|
138
194
|
request = build_request(path: path, type: Get, params: params)
|
|
@@ -143,11 +199,15 @@ module Vonage
|
|
|
143
199
|
json_response = ::JSON.parse(paginated_response.body)
|
|
144
200
|
remainder = remaining_count(json_response)
|
|
145
201
|
|
|
146
|
-
if response.respond_to?(
|
|
147
|
-
collection_name = collection_name(response[
|
|
148
|
-
response[
|
|
202
|
+
if response.respond_to?("_embedded")
|
|
203
|
+
collection_name = collection_name(response["_embedded"])
|
|
204
|
+
response["_embedded"][collection_name].push(
|
|
205
|
+
*next_response["_embedded"][collection_name]
|
|
206
|
+
)
|
|
149
207
|
else
|
|
150
|
-
response[collection_name(response)].push(
|
|
208
|
+
response[collection_name(response)].push(
|
|
209
|
+
*next_response[collection_name(next_response)]
|
|
210
|
+
)
|
|
151
211
|
end
|
|
152
212
|
end
|
|
153
213
|
|
|
@@ -155,43 +215,51 @@ module Vonage
|
|
|
155
215
|
end
|
|
156
216
|
|
|
157
217
|
def remaining_count(params)
|
|
158
|
-
if params.key?(
|
|
159
|
-
params[
|
|
160
|
-
elsif params.key?(
|
|
161
|
-
params[
|
|
218
|
+
if params.key?("total_pages")
|
|
219
|
+
params["total_pages"] - params["page"]
|
|
220
|
+
elsif params.key?("count")
|
|
221
|
+
params["count"] -
|
|
222
|
+
(
|
|
223
|
+
if params["record_index"] == 0
|
|
224
|
+
params["page_size"]
|
|
225
|
+
else
|
|
226
|
+
(params["record_index"] + params["page_size"])
|
|
227
|
+
end
|
|
228
|
+
)
|
|
162
229
|
else
|
|
163
230
|
0
|
|
164
231
|
end
|
|
165
232
|
end
|
|
166
233
|
|
|
167
234
|
def collection_name(params)
|
|
168
|
-
@collection_name ||=
|
|
169
|
-
|
|
170
|
-
|
|
171
|
-
|
|
172
|
-
|
|
173
|
-
|
|
174
|
-
|
|
175
|
-
|
|
176
|
-
|
|
177
|
-
|
|
178
|
-
|
|
179
|
-
|
|
180
|
-
|
|
181
|
-
|
|
182
|
-
|
|
183
|
-
|
|
184
|
-
|
|
185
|
-
|
|
186
|
-
|
|
187
|
-
|
|
188
|
-
|
|
189
|
-
|
|
190
|
-
|
|
191
|
-
|
|
192
|
-
|
|
193
|
-
|
|
194
|
-
|
|
235
|
+
@collection_name ||=
|
|
236
|
+
case
|
|
237
|
+
when params.respond_to?("calls")
|
|
238
|
+
"calls"
|
|
239
|
+
when params.respond_to?("users")
|
|
240
|
+
"users"
|
|
241
|
+
when params.respond_to?("legs")
|
|
242
|
+
"legs"
|
|
243
|
+
when params.respond_to?("data")
|
|
244
|
+
"data"
|
|
245
|
+
when params.respond_to?("conversations")
|
|
246
|
+
"conversations"
|
|
247
|
+
when params.respond_to?("applications")
|
|
248
|
+
"applications"
|
|
249
|
+
when params.respond_to?("records")
|
|
250
|
+
"records"
|
|
251
|
+
when params.respond_to?("reports")
|
|
252
|
+
"reports"
|
|
253
|
+
when params.respond_to?("networks")
|
|
254
|
+
"networks"
|
|
255
|
+
when params.respond_to?("countries")
|
|
256
|
+
"countries"
|
|
257
|
+
when params.respond_to?("media")
|
|
258
|
+
"media"
|
|
259
|
+
when params.respond_to?("numbers")
|
|
260
|
+
"numbers"
|
|
261
|
+
when params.respond_to?("events")
|
|
262
|
+
"events"
|
|
195
263
|
else
|
|
196
264
|
params.entity.attributes.keys[0].to_s
|
|
197
265
|
end
|
|
@@ -202,7 +270,7 @@ module Vonage
|
|
|
202
270
|
when Net::HTTPNoContent
|
|
203
271
|
response_class.new(nil, response)
|
|
204
272
|
when Net::HTTPSuccess
|
|
205
|
-
if response['Content-Type'].split(';').first == 'application/json'
|
|
273
|
+
if response['Content-Type'] && response['Content-Type'].split(';').first == 'application/json' && !response.body.empty?
|
|
206
274
|
entity = ::JSON.parse(response.body, object_class: Vonage::Entity)
|
|
207
275
|
|
|
208
276
|
response_class.new(entity, response)
|
|
@@ -217,6 +285,21 @@ module Vonage
|
|
|
217
285
|
def logger
|
|
218
286
|
@config.logger
|
|
219
287
|
end
|
|
288
|
+
|
|
289
|
+
private
|
|
290
|
+
|
|
291
|
+
def set_host
|
|
292
|
+
case self.class.host
|
|
293
|
+
when :rest_host
|
|
294
|
+
@config.rest_host
|
|
295
|
+
when :video_host
|
|
296
|
+
@config.video_host
|
|
297
|
+
when :vonage_host
|
|
298
|
+
@config.vonage_host
|
|
299
|
+
else
|
|
300
|
+
@config.api_host
|
|
301
|
+
end
|
|
302
|
+
end
|
|
220
303
|
end
|
|
221
304
|
|
|
222
305
|
private_constant :Namespace
|
|
@@ -0,0 +1,39 @@
|
|
|
1
|
+
# typed: true
|
|
2
|
+
# frozen_string_literal: true
|
|
3
|
+
|
|
4
|
+
module Vonage
|
|
5
|
+
class NetworkAuthentication::ClientAuthentication < Namespace
|
|
6
|
+
extend T::Sig
|
|
7
|
+
|
|
8
|
+
self.authentication = BearerToken
|
|
9
|
+
|
|
10
|
+
self.host = :vonage_host
|
|
11
|
+
|
|
12
|
+
self.request_headers['Content-Type'] = 'application/x-www-form-urlencoded'
|
|
13
|
+
|
|
14
|
+
def token(oidc_auth_code:, redirect_uri:, **params)
|
|
15
|
+
request(
|
|
16
|
+
'/oauth2/token',
|
|
17
|
+
params: {
|
|
18
|
+
grant_type: 'authorization_code',
|
|
19
|
+
code: oidc_auth_code,
|
|
20
|
+
redirect_uri: redirect_uri
|
|
21
|
+
},
|
|
22
|
+
type: Post
|
|
23
|
+
).access_token
|
|
24
|
+
end
|
|
25
|
+
|
|
26
|
+
def generate_oidc_uri(purpose:, api_scope:, login_hint:, redirect_uri:, state:)
|
|
27
|
+
scope = "openid%20dpv:#{purpose}%23#{api_scope}"
|
|
28
|
+
uri = "https://oidc.idp.vonage.com/oauth2/auth?" +
|
|
29
|
+
"client_id=#{@config.application_id}" +
|
|
30
|
+
"&response_type=code" +
|
|
31
|
+
"&scope=#{scope}" +
|
|
32
|
+
"&login_hint=#{login_hint}" +
|
|
33
|
+
"&redirect_uri=#{redirect_uri}" +
|
|
34
|
+
"&state=#{state}"
|
|
35
|
+
|
|
36
|
+
uri
|
|
37
|
+
end
|
|
38
|
+
end
|
|
39
|
+
end
|
|
@@ -0,0 +1,47 @@
|
|
|
1
|
+
# typed: true
|
|
2
|
+
# frozen_string_literal: true
|
|
3
|
+
|
|
4
|
+
module Vonage
|
|
5
|
+
class NetworkAuthentication::ServerAuthentication < Namespace
|
|
6
|
+
extend T::Sig
|
|
7
|
+
|
|
8
|
+
self.authentication = BearerToken
|
|
9
|
+
|
|
10
|
+
self.host = :vonage_host
|
|
11
|
+
|
|
12
|
+
self.request_headers['Content-Type'] = 'application/x-www-form-urlencoded'
|
|
13
|
+
|
|
14
|
+
def token(purpose:, api_scope:, login_hint:, **params)
|
|
15
|
+
auth_req_id = bc_authorize(
|
|
16
|
+
purpose: purpose,
|
|
17
|
+
api_scope: api_scope,
|
|
18
|
+
login_hint: login_hint
|
|
19
|
+
).auth_req_id
|
|
20
|
+
|
|
21
|
+
request_access_token(auth_req_id: auth_req_id).access_token
|
|
22
|
+
end
|
|
23
|
+
|
|
24
|
+
def bc_authorize(purpose:, api_scope:, login_hint:)
|
|
25
|
+
scope = "openid dpv:#{purpose}##{api_scope}"
|
|
26
|
+
request(
|
|
27
|
+
"/oauth2/bc-authorize",
|
|
28
|
+
params: {
|
|
29
|
+
scope: scope,
|
|
30
|
+
login_hint: login_hint
|
|
31
|
+
},
|
|
32
|
+
type: Post
|
|
33
|
+
)
|
|
34
|
+
end
|
|
35
|
+
|
|
36
|
+
def request_access_token(auth_req_id:)
|
|
37
|
+
request(
|
|
38
|
+
"/oauth2/token",
|
|
39
|
+
params: {
|
|
40
|
+
grant_type: 'urn:openid:params:grant-type:ciba',
|
|
41
|
+
auth_req_id: auth_req_id
|
|
42
|
+
},
|
|
43
|
+
type: Post
|
|
44
|
+
)
|
|
45
|
+
end
|
|
46
|
+
end
|
|
47
|
+
end
|
|
@@ -0,0 +1,22 @@
|
|
|
1
|
+
# typed: true
|
|
2
|
+
# frozen_string_literal: true
|
|
3
|
+
|
|
4
|
+
module Vonage
|
|
5
|
+
class NetworkAuthentication < AbstractAuthentication
|
|
6
|
+
def update(object, data)
|
|
7
|
+
return unless object.is_a?(Net::HTTPRequest)
|
|
8
|
+
|
|
9
|
+
token = self.public_send(data[:auth_flow]).token(**data)
|
|
10
|
+
|
|
11
|
+
object['Authorization'] = 'Bearer ' + token
|
|
12
|
+
end
|
|
13
|
+
|
|
14
|
+
def client_authentication
|
|
15
|
+
@client_authentication ||= ClientAuthentication.new(@config)
|
|
16
|
+
end
|
|
17
|
+
|
|
18
|
+
def server_authentication
|
|
19
|
+
@server_authentication ||= ServerAuthentication.new(@config)
|
|
20
|
+
end
|
|
21
|
+
end
|
|
22
|
+
end
|
|
@@ -0,0 +1,92 @@
|
|
|
1
|
+
# typed: strict
|
|
2
|
+
# frozen_string_literal: true
|
|
3
|
+
require 'phonelib'
|
|
4
|
+
|
|
5
|
+
module Vonage
|
|
6
|
+
class NetworkNumberVerification < Namespace
|
|
7
|
+
extend T::Sig
|
|
8
|
+
include Keys
|
|
9
|
+
|
|
10
|
+
self.authentication = NetworkAuthentication
|
|
11
|
+
|
|
12
|
+
self.host = :vonage_host
|
|
13
|
+
|
|
14
|
+
self.request_body = JSON
|
|
15
|
+
|
|
16
|
+
# Verifies if the specified phone number (plain text or hashed format) matches the one that the user is currently using.
|
|
17
|
+
#
|
|
18
|
+
# @example
|
|
19
|
+
# response = client.network_number_verification.verify(
|
|
20
|
+
# phone_number: '+447900000000',
|
|
21
|
+
# auth_data: {
|
|
22
|
+
# oidc_auth_code: '0dadaeb4-7c79-4d39-b4b0-5a6cc08bf537',
|
|
23
|
+
# redirect_uri: 'https://example.com/callback'
|
|
24
|
+
# }
|
|
25
|
+
# )
|
|
26
|
+
#
|
|
27
|
+
# @param [required, String] :phone_number The phone number to check, in the E.164 format, prepended with a `+`.
|
|
28
|
+
#
|
|
29
|
+
# @param [required, Hash] :auth_data A hash of authentication data required for the client token request. Must contain the following keys:
|
|
30
|
+
# @option auth_data [required, String] :oidc_auth_code The OIDC auth code.
|
|
31
|
+
# @option auth_data [required, String] :redirect_uri The redirect URI.
|
|
32
|
+
# @see https://developer.vonage.com/en/getting-started-network/authentication#client-authentication-flow
|
|
33
|
+
#
|
|
34
|
+
# @return [Response]
|
|
35
|
+
#
|
|
36
|
+
# @see https://developer.vonage.com/en/api/camara/number-verification#verifyNumberVerification
|
|
37
|
+
#
|
|
38
|
+
sig { params(phone_number: String, auth_data: Hash).returns(Vonage::Response) }
|
|
39
|
+
def verify(phone_number:, auth_data:)
|
|
40
|
+
raise ArgumentError.new("`phone_number` must be in E.164 format") unless Phonelib.parse(phone_number).valid?
|
|
41
|
+
raise ArgumentError.new("`phone_number` must be prepended with a `+`") unless phone_number.start_with?('+')
|
|
42
|
+
raise ArgumentError.new("`auth_data` must contain key `:oidc_auth_code`") unless auth_data.has_key?(:oidc_auth_code)
|
|
43
|
+
raise ArgumentError.new("`auth_data[:oidc_auth_code]` must be a String") unless auth_data[:oidc_auth_code].is_a?(String)
|
|
44
|
+
raise ArgumentError.new("`auth_data` must contain key `:redirect_uri`") unless auth_data.has_key?(:redirect_uri)
|
|
45
|
+
raise ArgumentError.new("`auth_data[:redirect_uri]` must be a String") unless auth_data[:redirect_uri].is_a?(String)
|
|
46
|
+
|
|
47
|
+
params = {phone_number: phone_number}
|
|
48
|
+
|
|
49
|
+
request(
|
|
50
|
+
'/camara/number-verification/v031/verify',
|
|
51
|
+
params: camelcase(params),
|
|
52
|
+
type: Post,
|
|
53
|
+
auth_data: {
|
|
54
|
+
oidc_auth_code: auth_data[:oidc_auth_code],
|
|
55
|
+
redirect_uri: auth_data[:redirect_uri],
|
|
56
|
+
auth_flow: :client_authentication
|
|
57
|
+
}
|
|
58
|
+
)
|
|
59
|
+
end
|
|
60
|
+
|
|
61
|
+
# Creates a URL for a client-side OIDC request.
|
|
62
|
+
#
|
|
63
|
+
# @example
|
|
64
|
+
# response = client.network_number_verification.generate_oidc_uri(
|
|
65
|
+
# phone_number: '+447900000000',
|
|
66
|
+
# redirect_uri: 'https://example.com/callback'
|
|
67
|
+
# )
|
|
68
|
+
#
|
|
69
|
+
# @param [required, String] :phone_number The phone number that will be checked during the verification request.
|
|
70
|
+
#
|
|
71
|
+
# @param [required, String] :redirect_uri The URI that will receive the callback containing the OIDC auth code.
|
|
72
|
+
#
|
|
73
|
+
# @param [required, String] :state A string that you can use for tracking.
|
|
74
|
+
# Used to set a unique identifier for each access token you generate.
|
|
75
|
+
#
|
|
76
|
+
# @return [String]
|
|
77
|
+
#
|
|
78
|
+
# @see https://developer.vonage.com/en/getting-started-network/authentication#1-make-an-oidc-request
|
|
79
|
+
sig { params(phone_number: String, redirect_uri: String, state: String).returns(String) }
|
|
80
|
+
def generate_oidc_uri(phone_number:, redirect_uri:, state:)
|
|
81
|
+
params = {
|
|
82
|
+
purpose: 'FraudPreventionAndDetection',
|
|
83
|
+
api_scope: 'number-verification-verify-read',
|
|
84
|
+
login_hint: phone_number,
|
|
85
|
+
redirect_uri: redirect_uri,
|
|
86
|
+
state: state
|
|
87
|
+
}
|
|
88
|
+
|
|
89
|
+
Vonage::NetworkAuthentication::ClientAuthentication.new(@config).generate_oidc_uri(**params)
|
|
90
|
+
end
|
|
91
|
+
end
|
|
92
|
+
end
|
|
@@ -0,0 +1,84 @@
|
|
|
1
|
+
# typed: strict
|
|
2
|
+
# frozen_string_literal: true
|
|
3
|
+
require 'phonelib'
|
|
4
|
+
|
|
5
|
+
module Vonage
|
|
6
|
+
class NetworkSIMSwap < Namespace
|
|
7
|
+
extend T::Sig
|
|
8
|
+
include Keys
|
|
9
|
+
|
|
10
|
+
self.authentication = NetworkAuthentication
|
|
11
|
+
|
|
12
|
+
self.host = :vonage_host
|
|
13
|
+
|
|
14
|
+
self.request_body = JSON
|
|
15
|
+
|
|
16
|
+
# Check if SIM swap has been performed during a past period.
|
|
17
|
+
#
|
|
18
|
+
# @example
|
|
19
|
+
# response = client.network_sim_swap.check(phone_number: '+447900000000')
|
|
20
|
+
#
|
|
21
|
+
# @param [required, String] :phone_number The phone number to check, in the E.164 format, prepended with a `+`.
|
|
22
|
+
#
|
|
23
|
+
# @param [optional, Integer] :max_age Period in hours to be checked for SIM swap
|
|
24
|
+
#
|
|
25
|
+
# @return [Response]
|
|
26
|
+
#
|
|
27
|
+
# @see https://developer.vonage.com/en/api/camara/sim-swap#checkSimSwap
|
|
28
|
+
#
|
|
29
|
+
sig { params(phone_number: String, max_age: T.nilable(Integer)).returns(Vonage::Response) }
|
|
30
|
+
def check(phone_number:, max_age: nil)
|
|
31
|
+
raise ArgumentError.new("`phone_number` must be in E.164 format") unless Phonelib.parse(phone_number).valid?
|
|
32
|
+
raise ArgumentError.new("`phone_number` must be prepended with a `+`") unless phone_number.start_with?('+')
|
|
33
|
+
if max_age
|
|
34
|
+
raise ArgumentError.new("`max_age` must between 1 and 2400") unless max_age.between?(1, 2400)
|
|
35
|
+
end
|
|
36
|
+
|
|
37
|
+
params = {phone_number: phone_number}
|
|
38
|
+
params[:max_age] = max_age if max_age
|
|
39
|
+
|
|
40
|
+
request(
|
|
41
|
+
'/camara/sim-swap/v040/check',
|
|
42
|
+
params: camelcase(params),
|
|
43
|
+
type: Post,
|
|
44
|
+
auth_data: {
|
|
45
|
+
login_hint: phone_number,
|
|
46
|
+
purpose: 'FraudPreventionAndDetection',
|
|
47
|
+
api_scope: 'check-sim-swap',
|
|
48
|
+
auth_flow: :server_authentication
|
|
49
|
+
}
|
|
50
|
+
)
|
|
51
|
+
end
|
|
52
|
+
|
|
53
|
+
# Get timestamp of last MSISDN <-> IMSI pairing change for a mobile user account provided with MSIDN.
|
|
54
|
+
#
|
|
55
|
+
# @example
|
|
56
|
+
# response = client.network_sim_swap.retrieve_date(phone_number: '+447900000000')
|
|
57
|
+
#
|
|
58
|
+
# @param [required, String] :phone_number The phone number to check, in the E.164 format, prepended with a `+`.
|
|
59
|
+
#
|
|
60
|
+
# @return [Response]
|
|
61
|
+
#
|
|
62
|
+
# @see https://developer.vonage.com/en/api/camara/sim-swap#retrieveSimSwapDate
|
|
63
|
+
#
|
|
64
|
+
sig { params(phone_number: String).returns(Vonage::Response) }
|
|
65
|
+
def retrieve_date(phone_number:)
|
|
66
|
+
raise ArgumentError.new("`phone_number` must be in E.164 format") unless Phonelib.parse(phone_number).valid?
|
|
67
|
+
raise ArgumentError.new("`phone_number` must be prepended with a `+`") unless phone_number.start_with?('+')
|
|
68
|
+
|
|
69
|
+
params = {phone_number: phone_number}
|
|
70
|
+
|
|
71
|
+
request(
|
|
72
|
+
'/camara/sim-swap/v040/retrieve-date',
|
|
73
|
+
params: camelcase(params),
|
|
74
|
+
type: Post,
|
|
75
|
+
auth_data: {
|
|
76
|
+
login_hint: phone_number,
|
|
77
|
+
purpose: 'FraudPreventionAndDetection',
|
|
78
|
+
api_scope: 'retrieve-sim-swap-date',
|
|
79
|
+
auth_flow: :server_authentication
|
|
80
|
+
}
|
|
81
|
+
)
|
|
82
|
+
end
|
|
83
|
+
end
|
|
84
|
+
end
|
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
# typed: strict
|
|
2
|
+
# frozen_string_literal: true
|
|
3
|
+
|
|
4
|
+
module Vonage
|
|
5
|
+
class NumberInsight2 < Namespace
|
|
6
|
+
extend T::Sig
|
|
7
|
+
|
|
8
|
+
self.authentication = Basic
|
|
9
|
+
|
|
10
|
+
self.request_body = JSON
|
|
11
|
+
|
|
12
|
+
# @deprecated
|
|
13
|
+
sig { params(type: String, phone: String, insights: T::Array[String]).returns(Vonage::Response) }
|
|
14
|
+
def fraud_check(type:, phone:, insights:)
|
|
15
|
+
logger.info('This method is deprecated and will be removed in a future release.')
|
|
16
|
+
raise ArgumentError.new("`insights` must not be an empty") if insights.empty?
|
|
17
|
+
|
|
18
|
+
request('/v2/ni', params: {type: type, phone: phone, insights: insights}, type: Post)
|
|
19
|
+
end
|
|
20
|
+
end
|
|
21
|
+
end
|