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.
Files changed (130) hide show
  1. checksums.yaml +4 -4
  2. data/README.md +880 -87
  3. data/lib/vonage/account.rb +2 -0
  4. data/lib/vonage/api_error.rb +33 -0
  5. data/lib/vonage/applications.rb +12 -4
  6. data/lib/vonage/basic.rb +1 -1
  7. data/lib/vonage/basic_and_bearer_token.rb +18 -0
  8. data/lib/vonage/basic_and_signature.rb +22 -0
  9. data/lib/vonage/bearer_token.rb +1 -1
  10. data/lib/vonage/client.rb +79 -0
  11. data/lib/vonage/client_error.rb +1 -1
  12. data/lib/vonage/config.rb +11 -1
  13. data/lib/vonage/conversation/event/list_response.rb +11 -0
  14. data/lib/vonage/conversation/event.rb +108 -0
  15. data/lib/vonage/conversation/list_response.rb +11 -0
  16. data/lib/vonage/conversation/member/list_response.rb +11 -0
  17. data/lib/vonage/conversation/member.rb +134 -0
  18. data/lib/vonage/conversation/user/conversations_list_response.rb +11 -0
  19. data/lib/vonage/conversation/user/sessions_list_response.rb +11 -0
  20. data/lib/vonage/conversation/user.rb +67 -0
  21. data/lib/vonage/conversation.rb +164 -0
  22. data/lib/vonage/conversations/events.rb +12 -0
  23. data/lib/vonage/conversations/legs.rb +6 -0
  24. data/lib/vonage/conversations/members.rb +15 -0
  25. data/lib/vonage/conversations/users.rb +15 -0
  26. data/lib/vonage/conversations.rb +30 -0
  27. data/lib/vonage/conversions.rb +2 -0
  28. data/lib/vonage/errors.rb +37 -20
  29. data/lib/vonage/http.rb +3 -3
  30. data/lib/vonage/identity_insights/insights_builder.rb +75 -0
  31. data/lib/vonage/identity_insights.rb +75 -0
  32. data/lib/vonage/jwt.rb +17 -0
  33. data/lib/vonage/key_secret_params.rb +3 -2
  34. data/lib/vonage/keys.rb +24 -1
  35. data/lib/vonage/logger.rb +0 -3
  36. data/lib/vonage/meetings/applications.rb +28 -0
  37. data/lib/vonage/meetings/dial_in_numbers/list_response.rb +11 -0
  38. data/lib/vonage/meetings/dial_in_numbers.rb +26 -0
  39. data/lib/vonage/meetings/recordings.rb +42 -0
  40. data/lib/vonage/meetings/rooms/list_response.rb +11 -0
  41. data/lib/vonage/meetings/rooms.rb +167 -0
  42. data/lib/vonage/meetings/sessions/list_response.rb +11 -0
  43. data/lib/vonage/meetings/sessions.rb +31 -0
  44. data/lib/vonage/meetings/themes/list_response.rb +11 -0
  45. data/lib/vonage/meetings/themes.rb +239 -0
  46. data/lib/vonage/meetings.rb +50 -0
  47. data/lib/vonage/messaging/channels/messenger.rb +2 -0
  48. data/lib/vonage/messaging/channels/mms.rb +13 -3
  49. data/lib/vonage/messaging/channels/rcs.rb +44 -0
  50. data/lib/vonage/messaging/channels/sms.rb +2 -0
  51. data/lib/vonage/messaging/channels/viber.rb +11 -2
  52. data/lib/vonage/messaging/channels/whats_app.rb +5 -1
  53. data/lib/vonage/messaging/message.rb +4 -1
  54. data/lib/vonage/messaging.rb +43 -4
  55. data/lib/vonage/namespace.rb +152 -69
  56. data/lib/vonage/network_authentication/client_authentication.rb +39 -0
  57. data/lib/vonage/network_authentication/server_authentication.rb +47 -0
  58. data/lib/vonage/network_authentication.rb +22 -0
  59. data/lib/vonage/network_number_verification.rb +92 -0
  60. data/lib/vonage/network_sim_swap.rb +84 -0
  61. data/lib/vonage/number_insight.rb +1 -0
  62. data/lib/vonage/number_insight_2.rb +21 -0
  63. data/lib/vonage/numbers.rb +40 -17
  64. data/lib/vonage/proactive_connect/events/list_response.rb +11 -0
  65. data/lib/vonage/proactive_connect/events.rb +71 -0
  66. data/lib/vonage/proactive_connect/item.rb +116 -0
  67. data/lib/vonage/proactive_connect/items/file_response.rb +32 -0
  68. data/lib/vonage/proactive_connect/items/list_response.rb +11 -0
  69. data/lib/vonage/proactive_connect/items.rb +116 -0
  70. data/lib/vonage/proactive_connect/list.rb +186 -0
  71. data/lib/vonage/proactive_connect/lists/list_response.rb +11 -0
  72. data/lib/vonage/proactive_connect/lists.rb +38 -0
  73. data/lib/vonage/proactive_connect.rb +43 -0
  74. data/lib/vonage/server_error.rb +1 -1
  75. data/lib/vonage/signature.rb +29 -6
  76. data/lib/vonage/sms.rb +25 -0
  77. data/lib/vonage/subaccounts/balance_transfers/list_response.rb +11 -0
  78. data/lib/vonage/subaccounts/credit_transfers/list_response.rb +11 -0
  79. data/lib/vonage/subaccounts/list_response.rb +15 -0
  80. data/lib/vonage/subaccounts.rb +203 -0
  81. data/lib/vonage/users/list_response.rb +11 -0
  82. data/lib/vonage/users.rb +156 -0
  83. data/lib/vonage/verify.rb +2 -0
  84. data/lib/vonage/verify2/channels/email.rb +36 -0
  85. data/lib/vonage/verify2/channels/silent_auth.rb +46 -0
  86. data/lib/vonage/verify2/channels/sms.rb +63 -0
  87. data/lib/vonage/verify2/channels/voice.rb +32 -0
  88. data/lib/vonage/verify2/channels/whats_app.rb +45 -0
  89. data/lib/vonage/verify2/channels/whats_app_interactive.rb +32 -0
  90. data/lib/vonage/verify2/start_verification_options.rb +63 -0
  91. data/lib/vonage/verify2/template_fragments/list_response.rb +11 -0
  92. data/lib/vonage/verify2/template_fragments.rb +125 -0
  93. data/lib/vonage/verify2/templates/list_response.rb +11 -0
  94. data/lib/vonage/verify2/templates.rb +86 -0
  95. data/lib/vonage/verify2/workflow.rb +39 -0
  96. data/lib/vonage/verify2/workflow_builder.rb +25 -0
  97. data/lib/vonage/verify2.rb +112 -0
  98. data/lib/vonage/version.rb +1 -1
  99. data/lib/vonage/video/archives/list_response.rb +11 -0
  100. data/lib/vonage/video/archives.rb +164 -0
  101. data/lib/vonage/video/broadcasts/list_response.rb +11 -0
  102. data/lib/vonage/video/broadcasts.rb +75 -0
  103. data/lib/vonage/video/captions.rb +67 -0
  104. data/lib/vonage/video/connections/list_response.rb +11 -0
  105. data/lib/vonage/video/connections.rb +29 -0
  106. data/lib/vonage/video/moderation.rb +58 -0
  107. data/lib/vonage/video/renders/list_response.rb +11 -0
  108. data/lib/vonage/video/renders.rb +107 -0
  109. data/lib/vonage/video/signals.rb +50 -0
  110. data/lib/vonage/video/sip.rb +48 -0
  111. data/lib/vonage/video/streams/list_response.rb +11 -0
  112. data/lib/vonage/video/streams.rb +70 -0
  113. data/lib/vonage/video/web_socket.rb +68 -0
  114. data/lib/vonage/video.rb +134 -0
  115. data/lib/vonage/voice/actions/connect.rb +45 -9
  116. data/lib/vonage/voice/actions/conversation.rb +10 -4
  117. data/lib/vonage/voice/actions/input.rb +26 -3
  118. data/lib/vonage/voice/actions/notify.rb +8 -3
  119. data/lib/vonage/voice/actions/record.rb +52 -4
  120. data/lib/vonage/voice/actions/stream.rb +7 -3
  121. data/lib/vonage/voice/actions/talk.rb +29 -4
  122. data/lib/vonage/voice/actions/transfer.rb +83 -0
  123. data/lib/vonage/voice/actions/wait.rb +43 -0
  124. data/lib/vonage/voice/ncco.rb +3 -1
  125. data/lib/vonage/voice/talk.rb +11 -1
  126. data/lib/vonage/voice.rb +24 -0
  127. data/lib/vonage.rb +4 -0
  128. data/vonage.gemspec +3 -1
  129. metadata +119 -9
  130. data/lib/vonage/voice/actions/pay.rb +0 -107
@@ -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 = self.class.host == :api_host ? @config.api_host : @config.rest_host
14
+ @host = set_host
12
15
 
13
- @http = Net::HTTP.new(@host, Net::HTTP.https_default_port, p_addr = nil)
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 host == :rest_host
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('https://' + @host + path)
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['User-Agent'] = UserAgent.string(@config.app_name, @config.app_version)
74
- request['Accept'] = 'application/json'
75
- self.class.request_headers.each do |key, value|
76
- request[key] = value
77
- end
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 BearerToken if needed
80
- authentication.update(request)
80
+ # Set Authorization header if needed
81
+ authentication.update(request, auth_data)
81
82
 
82
83
  # set body
83
- self.class.request_body.update(request, params) if type.const_get(:REQUEST_HAS_BODY)
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
- response = @http.request(request, &block)
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 = !params.nil? && params.key?(:auto_advance) ? params[:auto_advance] : false
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 = params.tap { |params| params.delete(:auto_advance) } if !params.nil? && params.key?(:auto_advance)
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(path, response: response, response_class: response_class, params: params, &block)
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['page_size'] }
127
-
128
- if json_response['record_index'] && json_response['record_index'] == 0
129
- params[:record_index] = json_response['page_size']
130
- elsif json_response['record_index'] && json_response['record_index'] != 0
131
- params[:record_index] = (json_response['record_index'] + json_response['page_size'])
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['total_pages']
135
- params[:page] = json_response['page'] + 1
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?('_embedded')
147
- collection_name = collection_name(response['_embedded'])
148
- response['_embedded'][collection_name].push(*next_response['_embedded'][collection_name])
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(*next_response[collection_name(next_response)])
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?('total_pages')
159
- params['total_pages'] - params['page']
160
- elsif params.key?('count')
161
- params['count'] - (params['record_index'] == 0 ? params['page_size'] : (params['record_index'] + params['page_size']))
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 ||= case
169
- when params.respond_to?('calls')
170
- 'calls'
171
- when params.respond_to?('users')
172
- 'users'
173
- when params.respond_to?('legs')
174
- 'legs'
175
- when params.respond_to?('data')
176
- 'data'
177
- when params.respond_to?('conversations')
178
- 'conversations'
179
- when params.respond_to?('applications')
180
- 'applications'
181
- when params.respond_to?('records')
182
- 'records'
183
- when params.respond_to?('reports')
184
- 'reports'
185
- when params.respond_to?('networks')
186
- 'networks'
187
- when params.respond_to?('countries')
188
- 'countries'
189
- when params.respond_to?('media')
190
- 'media'
191
- when params.respond_to?('numbers')
192
- 'numbers'
193
- when params.respond_to?('events')
194
- 'events'
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
@@ -3,6 +3,7 @@
3
3
 
4
4
  module Vonage
5
5
  class NumberInsight < Namespace
6
+ self.authentication = Basic
6
7
  # Provides basic number insight information about a number.
7
8
  #
8
9
  # @example
@@ -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