vonage 7.9.0 → 7.11.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 CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: 9d8620ac3418486f818675d3b75efdf29a572c38100d00aeb8f36ab36aae4fb0
4
- data.tar.gz: 7c1f845f11ba6b1eb625cdf20b703c2b19af2f789dd41e5368ce99465eab2d05
3
+ metadata.gz: 95210747eb477199b15e3e5349e2bddfe7650928e8caae6a0275dde92381b835
4
+ data.tar.gz: '00917603bc90d21275328916969cd1af6b5925e6d034aa557705027ae514f7f8'
5
5
  SHA512:
6
- metadata.gz: 04e95b2647f1d19323fa512b803de87baa245379957fa051c3b13cb12571bf5cb93e735aa28ef332b47f5cf1ccaded503f628b88ee73856ab1e94ee09573d175
7
- data.tar.gz: 37ae894d0413c3b72d4c9d8d65462fcb5853740cd8bfcc254f4701fd1529dc3fc3a66fed0888db1e8b0de2ea28461cb4822d7e7e3f06ba5a5db53fce202c4ab3
6
+ metadata.gz: 523f1f2cb099dfe781a065eb538fd45fd5d06bdb1b71156f10e119c3d4890f1df1c86ce29bfa17a3fb28231d8906deec0a2a66d41b8780e1fe5a892be6bea5b8
7
+ data.tar.gz: ecbfe4149f794e02ab6835de0fee165bc708036cb8ff4e672d77437e94bda0a4a1fef836eddc4ba0583b6058a2f8cc7ee81a5c29b0f28dad84416ccd8b694e09
data/README.md CHANGED
@@ -17,6 +17,8 @@ need a Vonage account. Sign up [for free at vonage.com][signup].
17
17
  * [Webhook signatures](#webhook-signatures)
18
18
  * [Pagination](#pagination)
19
19
  * [NCCO Builder](#ncco-builder)
20
+ * [Messages API](#messages-api)
21
+ * [Verify API v2](#verify-api-v2)
20
22
  * [Documentation](#documentation)
21
23
  * [Frequently Asked Questions](#frequently-asked-questions)
22
24
  * [Supported APIs](#supported-apis)
@@ -220,11 +222,136 @@ Once the message data is created, you can then send the message.
220
222
  response = client.messaging.send(to: "447700900000", from: "447700900001", **message)
221
223
  ```
222
224
 
225
+ ## Verify API v2
226
+
227
+ The [Vonage Verify API v2](https://developer.vonage.com/en/verify/verify-v2/overview) allows you to manage 2FA verification workflows over a number of different channels such as SMS, WhatsApp, WhatsApp Interactive, Voice, Email, and Silent Authentication, either individually or in combination with each other. See the Vonage Developer Documentation for a [complete API reference](https://developer.vonage.com/en/api/verify.v2) listing all the channels, verification options, and callback types.
228
+
229
+ The Ruby SDK provides two methods for interacting with the Verify v2 API:
230
+
231
+ - `Verify2#start_verification`: starts a new verification request. Here you can specify options for the request and the workflow to be used.
232
+ - `Verify2#check_code`: for channels where the end-user is sent a one-time code, this method is used to verify the code against the `request_id` of the verification request created by the `start_verification` method.
233
+
234
+ ### Creating a Verify2 Object
235
+
236
+ ```ruby
237
+ verify = client.verify2
238
+ ```
239
+
240
+ ### Making a verification request
241
+
242
+ For simple requests, you may prefer to manually set the value for `workflow` (an array of one or more hashes containing the settings for a particular channel) and any optional params.
243
+
244
+ Example with the required `:brand` and `:workflow` arguments:
245
+
246
+ ```ruby
247
+ verification_request = verify.start_verification(
248
+ brand: 'Acme',
249
+ workflow: [{channel: 'sms', to: '447000000000'}]
250
+ )
251
+ ```
252
+
253
+ Example with the required `:brand` and `:workflow` arguments, and an optional `code_length`:
254
+
255
+ ```ruby
256
+ verification_request = verify.start_verification(
257
+ brand: 'Acme',
258
+ workflow: [{channel: 'sms', to: '447000000000'}],
259
+ code_length: 6
260
+ )
261
+ ```
262
+
263
+ For more complex requests (e.g. with mutliple workflow channels or addtional options), or to take advantage of built-in input validation, you can use the `StartVerificationOptions` object and the `Workflow` and various channel objects or the `WorkflowBuilder`:
264
+
265
+ #### Create options using StartVerificationOptions object
266
+
267
+ ```ruby
268
+ opts = verify.start_verification_options(
269
+ locale: 'fr-fr',
270
+ code_length: 6,
271
+ client_ref: 'abc-123'
272
+ ).to_h
273
+
274
+ verification_request = verify.start_verification(
275
+ brand: 'Acme',
276
+ workflow: [{channel: 'email', to: 'alice.example.com'}],
277
+ **opts
278
+ )
279
+ ```
280
+
281
+ #### Create workflow using Workflow and Channel objects
282
+
283
+ ```ruby
284
+ # Instantiate a Workflow object
285
+ workflow = verify.workflow
286
+
287
+ # Add channels to the workflow
288
+ workflow << workflow.sms(to: '447000000000')
289
+ workflow << workflow.email(to: 'alice.example.com')
290
+
291
+ # Channel data is encpsulated in channel objects stored in the Workflow list array
292
+ workflow.list
293
+ # => [ #<Vonage::Verify2::Channels::SMS:0x0000561474a74778 @channel="sms", @to="447000000000">,
294
+ #<Vonage::Verify2::Channels::Email:0x0000561474c51a28 @channel="email", @to="alice.example.com">]
295
+
296
+ # To use the list as the value for `:workflow` in a `start_verification` request call,
297
+ # the objects must be hashified
298
+ workflow_list = workflow.hashified_list
299
+ # => [{:channel=>"sms", :to=>"447000000000"}, {:channel=>"email", :to=>"alice.example.com"}]
300
+
301
+ verification_request = verify.start_verification(brand: 'Acme', workflow: workflow_list)
302
+ ```
303
+
304
+ #### Create a workflow using the WorkflowBuilder
305
+
306
+ ```ruby
307
+ workflow = verify.workflow_builder.build do |builder|
308
+ builder.add_voice(to: '447000000001')
309
+ builder.add_whatsapp(to: '447000000000')
310
+ end
311
+
312
+ workflow_list = workflow.hashified_list
313
+ # => [{:channel=>"voice", :to=>"447000000001"}, {:channel=>"whatsapp", :to=>"447000000000"}]
314
+
315
+ verification_request = verify.start_verification(brand: 'Acme', workflow: workflow_list)
316
+ ```
317
+
318
+ ### Cancelling a request
319
+
320
+ You can cancel in in-progress verification request
321
+
322
+ ```ruby
323
+ # Get the `request_id` from the Vonage#Response object returned by the `start_verification` method call
324
+ request_id = verification_request.request_id
325
+
326
+ verify.cancel_verification_request(request_id: request_id)
327
+ ```
328
+
329
+ ### Checking a code
330
+
331
+ ```ruby
332
+ # Get the `request_id` from the Vonage#Response object returned by the `start_verification` method call
333
+ request_id = verification_request.request_id
334
+
335
+ # Get the one-time code via user input
336
+ # e.g. from params in a route handler or controller action for a form input
337
+ code = params[:code]
338
+
339
+ begin
340
+ code_check = verify.check_code(request_id: request_id, code: code)
341
+ rescue => error
342
+ # an invalid code will raise an exception of type Vonage::ClientError
343
+ end
344
+
345
+ if code_check.http_response.code == '200'
346
+ # code is valid
347
+ end
348
+ ```
349
+
223
350
  ## Documentation
224
351
 
225
352
  Vonage Ruby documentation: https://www.rubydoc.info/github/Vonage/vonage-ruby-sdk
226
353
 
227
- Vonage Ruby code examples: https://github.com/Nexmo/nexmo-ruby-code-snippets
354
+ Vonage Ruby code examples: https://github.com/Vonage/vonage-ruby-code-snippets
228
355
 
229
356
  Vonage APIs API reference: https://developer.nexmo.com/api
230
357
 
@@ -252,6 +379,7 @@ The following is a list of Vonage APIs and whether the Ruby SDK provides support
252
379
  | Reports API | Beta |❌|
253
380
  | SMS API | General Availability |✅|
254
381
  | Verify API | General Availability |✅|
382
+ | Verify API v2 | General Availability |✅|
255
383
  | Voice API | General Availability |✅|
256
384
 
257
385
  ## License
data/lib/vonage/client.rb CHANGED
@@ -131,6 +131,13 @@ module Vonage
131
131
  @verify ||= T.let(Verify.new(config), T.nilable(Vonage::Verify))
132
132
  end
133
133
 
134
+ # @return [Verify2]
135
+ #
136
+ sig { returns(T.nilable(Vonage::Verify2)) }
137
+ def verify2
138
+ @verify2 ||= T.let(Verify2.new(config), T.nilable(Vonage::Verify2))
139
+ end
140
+
134
141
  # @return [Voice]
135
142
  #
136
143
  sig { returns(T.nilable(Vonage::Voice)) }
@@ -202,7 +202,7 @@ module Vonage
202
202
  when Net::HTTPNoContent
203
203
  response_class.new(nil, response)
204
204
  when Net::HTTPSuccess
205
- if response['Content-Type'].split(';').first == 'application/json'
205
+ if response['Content-Type'] && response['Content-Type'].split(';').first == 'application/json'
206
206
  entity = ::JSON.parse(response.body, object_class: Vonage::Entity)
207
207
 
208
208
  response_class.new(entity, response)
@@ -0,0 +1,38 @@
1
+ # typed: true
2
+ # frozen_string_literal: true
3
+ require 'phonelib'
4
+
5
+ module Vonage
6
+ class Verify2::Channels::Email
7
+
8
+ attr_reader :channel, :to, :from
9
+
10
+ def initialize(to:, from: nil)
11
+ self.channel = 'email'
12
+ self.to = to
13
+ self.from = from if from
14
+ end
15
+
16
+ def to=(to)
17
+ # TODO: add validation
18
+ @to = to
19
+ end
20
+
21
+ def from=(from)
22
+ # TODO: add validation
23
+ @from = from
24
+ end
25
+
26
+ def to_h
27
+ hash = Hash.new
28
+ self.instance_variables.each do |ivar|
29
+ hash[ivar.to_s.delete("@").to_sym] = self.instance_variable_get(ivar)
30
+ end
31
+ hash
32
+ end
33
+
34
+ private
35
+
36
+ attr_writer :channel
37
+ end
38
+ end
@@ -0,0 +1,32 @@
1
+ # typed: true
2
+ # frozen_string_literal: true
3
+ require 'phonelib'
4
+
5
+ module Vonage
6
+ class Verify2::Channels::SilentAuth
7
+
8
+ attr_reader :channel, :to
9
+
10
+ def initialize(to:)
11
+ self.channel = 'silent_auth'
12
+ self.to = to
13
+ end
14
+
15
+ def to=(to)
16
+ raise ArgumentError, "Invalid 'to' value #{to}. Expected to be in E.164 format" unless Phonelib.parse(to.to_i).valid?
17
+ @to = to
18
+ end
19
+
20
+ def to_h
21
+ hash = Hash.new
22
+ self.instance_variables.each do |ivar|
23
+ hash[ivar.to_s.delete("@").to_sym] = self.instance_variable_get(ivar)
24
+ end
25
+ hash
26
+ end
27
+
28
+ private
29
+
30
+ attr_writer :channel
31
+ end
32
+ end
@@ -0,0 +1,39 @@
1
+ # typed: true
2
+ # frozen_string_literal: true
3
+ require 'phonelib'
4
+
5
+ module Vonage
6
+ class Verify2::Channels::SMS
7
+ APP_HASH_LENGTH = 11
8
+
9
+ attr_reader :channel, :to, :app_hash
10
+
11
+ def initialize(to:, app_hash: nil)
12
+ self.channel = 'sms'
13
+ self.to = to
14
+ self.app_hash = app_hash if app_hash
15
+ end
16
+
17
+ def to=(to)
18
+ raise ArgumentError, "Invalid 'to' value #{to}. Expected to be in E.164 format" unless Phonelib.parse(to).valid?
19
+ @to = to
20
+ end
21
+
22
+ def app_hash=(app_hash)
23
+ raise ArgumentError, "Invalid 'app_hash' value #{app_hash}. Length must be #{APP_HASH_LENGTH}" unless app_hash.length == APP_HASH_LENGTH
24
+ @app_hash = app_hash
25
+ end
26
+
27
+ def to_h
28
+ hash = Hash.new
29
+ self.instance_variables.each do |ivar|
30
+ hash[ivar.to_s.delete("@").to_sym] = self.instance_variable_get(ivar)
31
+ end
32
+ hash
33
+ end
34
+
35
+ private
36
+
37
+ attr_writer :channel
38
+ end
39
+ end
@@ -0,0 +1,32 @@
1
+ # typed: true
2
+ # frozen_string_literal: true
3
+ require 'phonelib'
4
+
5
+ module Vonage
6
+ class Verify2::Channels::Voice
7
+
8
+ attr_reader :channel, :to
9
+
10
+ def initialize(to:)
11
+ self.channel = 'voice'
12
+ self.to = to
13
+ end
14
+
15
+ def to=(to)
16
+ raise ArgumentError, "Invalid 'to' value #{to}. Expected to be in E.164 format" unless Phonelib.parse(to.to_i).valid?
17
+ @to = to
18
+ end
19
+
20
+ def to_h
21
+ hash = Hash.new
22
+ self.instance_variables.each do |ivar|
23
+ hash[ivar.to_s.delete("@").to_sym] = self.instance_variable_get(ivar)
24
+ end
25
+ hash
26
+ end
27
+
28
+ private
29
+
30
+ attr_writer :channel
31
+ end
32
+ end
@@ -0,0 +1,38 @@
1
+ # typed: true
2
+ # frozen_string_literal: true
3
+ require 'phonelib'
4
+
5
+ module Vonage
6
+ class Verify2::Channels::WhatsApp
7
+
8
+ attr_reader :channel, :to, :from
9
+
10
+ def initialize(to:, from: nil)
11
+ self.channel = 'whatsapp'
12
+ self.to = to
13
+ self.from = from if from
14
+ end
15
+
16
+ def to=(to)
17
+ raise ArgumentError, "Invalid 'to' value #{to}. Expected to be in E.164 format" unless Phonelib.parse(to.to_i).valid?
18
+ @to = to
19
+ end
20
+
21
+ def from=(from)
22
+ raise ArgumentError, "Invalid 'from' value #{from}. Expected to be in E.164 format" unless Phonelib.parse(from.to_i).valid?
23
+ @from = from
24
+ end
25
+
26
+ def to_h
27
+ hash = Hash.new
28
+ self.instance_variables.each do |ivar|
29
+ hash[ivar.to_s.delete("@").to_sym] = self.instance_variable_get(ivar)
30
+ end
31
+ hash
32
+ end
33
+
34
+ private
35
+
36
+ attr_writer :channel
37
+ end
38
+ end
@@ -0,0 +1,32 @@
1
+ # typed: true
2
+ # frozen_string_literal: true
3
+ require 'phonelib'
4
+
5
+ module Vonage
6
+ class Verify2::Channels::WhatsAppInteractive
7
+
8
+ attr_reader :channel, :to
9
+
10
+ def initialize(to:)
11
+ self.channel = 'whatsapp_interactive'
12
+ self.to = to
13
+ end
14
+
15
+ def to=(to)
16
+ raise ArgumentError, "Invalid 'to' value #{to}. Expected to be in E.164 format" unless Phonelib.parse(to.to_i).valid?
17
+ @to = to
18
+ end
19
+
20
+ def to_h
21
+ hash = Hash.new
22
+ self.instance_variables.each do |ivar|
23
+ hash[ivar.to_s.delete("@").to_sym] = self.instance_variable_get(ivar)
24
+ end
25
+ hash
26
+ end
27
+
28
+ private
29
+
30
+ attr_writer :channel
31
+ end
32
+ end
@@ -0,0 +1,71 @@
1
+ # typed: true
2
+ # frozen_string_literal: true
3
+
4
+ module Vonage
5
+ class Verify2::StartVerificationOptions
6
+ VALID_OPTS = [:locale, :channel_timeout, :client_ref, :code_length, :code, :fraud_check].freeze
7
+
8
+ VALID_LOCALES = [
9
+ 'en-us', 'en-gb', 'es-es', 'es-mx', 'es-us', 'it-it', 'fr-fr',
10
+ 'de-de', 'ru-ru', 'hi-in', 'pt-br', 'pt-pt', 'id-id'
11
+ ].freeze
12
+
13
+ MIN_CHANNEL_TIMEOUT, MAX_CHANNEL_TIMEOUT = [60, 900]
14
+
15
+ MIN_CODE_LENGTH, MAX_CODE_LENGTH = [4, 10]
16
+
17
+ attr_reader(*VALID_OPTS)
18
+
19
+ def initialize(**opts)
20
+ VALID_OPTS.each do |opt|
21
+ send("#{opt}=", opts[opt]) unless opts[opt].nil?
22
+ end
23
+ end
24
+
25
+ def locale=(locale)
26
+ unless VALID_LOCALES.include?(locale)
27
+ raise ArgumentError, "Invalid 'locale' #{locale}. Please choose from the following #{VALID_LOCALES}"
28
+ end
29
+
30
+ @locale = locale
31
+ end
32
+
33
+ def channel_timeout=(channel_timeout)
34
+ unless channel_timeout.between?(MIN_CHANNEL_TIMEOUT, MAX_CHANNEL_TIMEOUT)
35
+ raise ArgumentError, "Invalid 'channel_timeout' #{channel_timeout}. Must be between #{MIN_CHANNEL_TIMEOUT} and #{MAX_CHANNEL_TIMEOUT} (inclusive)"
36
+ end
37
+
38
+ @channel_timeout = channel_timeout
39
+ end
40
+
41
+ def client_ref=(client_ref)
42
+ @client_ref = client_ref
43
+ end
44
+
45
+ def code_length=(code_length)
46
+ unless code_length.between?(MIN_CODE_LENGTH, MAX_CODE_LENGTH)
47
+ raise ArgumentError, "Invalid 'code_length' #{code_length}. Must be between #{MIN_CODE_LENGTH} and #{MAX_CODE_LENGTH} (inclusive)"
48
+ end
49
+
50
+ @code_length = code_length
51
+ end
52
+
53
+ def code=(code)
54
+ @code = code
55
+ end
56
+
57
+ def fraud_check=(fraud_check)
58
+ raise ArgumentError, "Invalid 'fraud_check' #{fraud_check}. Must be `false`" unless fraud_check == false
59
+
60
+ @fraud_check = fraud_check
61
+ end
62
+
63
+ def to_h
64
+ hash = Hash.new
65
+ self.instance_variables.each do |ivar|
66
+ hash[ivar.to_s.delete("@").to_sym] = self.instance_variable_get(ivar)
67
+ end
68
+ hash
69
+ end
70
+ end
71
+ end
@@ -0,0 +1,39 @@
1
+ # typed: true
2
+ # frozen_string_literal: true
3
+
4
+ module Vonage
5
+ class Verify2::Workflow
6
+ CHANNELS = {
7
+ sms: Verify2::Channels::SMS,
8
+ whatsapp: Verify2::Channels::WhatsApp,
9
+ whatsapp_interactive: Verify2::Channels::WhatsAppInteractive,
10
+ voice: Verify2::Channels::Voice,
11
+ email: Verify2::Channels::Email,
12
+ silent_auth: Verify2::Channels::SilentAuth
13
+ }
14
+
15
+ CHANNELS.keys.each do |method|
16
+ define_method method do |attributes|
17
+ CHANNELS[method].new(**attributes)
18
+ end
19
+ end
20
+
21
+ def self.method_missing(method)
22
+ raise ClientError.new("Workflow channel must be one of the valid options. Please refer to https://developer.vonage.com/en/api/verify.v2#newRequest for a complete list.")
23
+ end
24
+
25
+ attr_reader :list
26
+
27
+ def initialize
28
+ @list = []
29
+ end
30
+
31
+ def <<(workflow)
32
+ list << workflow
33
+ end
34
+
35
+ def hashified_list
36
+ list.map(&:to_h)
37
+ end
38
+ end
39
+ end
@@ -0,0 +1,25 @@
1
+ # typed: true
2
+ # frozen_string_literal: true
3
+
4
+ module Vonage
5
+ class Verify2::WorkflowBuilder
6
+
7
+ def self.build
8
+ builder = self.new
9
+ yield builder if block_given?
10
+ builder.workflow
11
+ end
12
+
13
+ attr_reader :workflow
14
+
15
+ def initialize
16
+ @workflow = Vonage::Verify2::Workflow.new
17
+ end
18
+
19
+ Vonage::Verify2::Workflow::CHANNELS.keys.each do |channel|
20
+ define_method "add_#{channel.to_s}" do |args|
21
+ workflow << workflow.send(channel, **args)
22
+ end
23
+ end
24
+ end
25
+ end
@@ -0,0 +1,93 @@
1
+ # typed: true
2
+ # frozen_string_literal: true
3
+
4
+ module Vonage
5
+ class Verify2 < Namespace
6
+ self.authentication = BearerToken
7
+
8
+ self.request_body = JSON
9
+
10
+ # Request a verification be sent to a user.
11
+ #
12
+ # @example
13
+ # verification_request = verify.start_verification(
14
+ # brand: 'Acme',
15
+ # workflow: [{channel: 'sms', to: '447000000000'}],
16
+ # code_length: 6
17
+ # )
18
+ #
19
+ # @param [required, String] :brand The brand that is sending the verification request
20
+ #
21
+ # @param [required, Array<Hash>] :workflow An array of hashes for channels in the workflow
22
+ #
23
+ # @param [optional, Hash] opts the options for the verification request.
24
+ # @option opts [Integer] :code_length The length of the one-time code provided to the end-user
25
+ # @option opts [String] :code An optional alphanumeric custom code to use instead of an auto-generated code
26
+ # @option opts [String] :locale The language to use for the verification message (where applicable)
27
+ # @option opts [Integer] :channel_timeout Wait time in seconds before trying the next channel in the workflow
28
+ # @option opts [String] :client_ref Reference to be included in callbacks
29
+ # @option opts [Boolean] If used, must be set to `false`. Will bypass a network block for a single Verify V2 request
30
+ #
31
+ # @return Vomage::Response
32
+ # @see https://developer.vonage.com/en/api/verify.v2#newRequest
33
+ #
34
+ def start_verification(brand:, workflow:, **opts)
35
+ raise ArgumentError, ':workflow must be an Array' unless workflow.is_a?(Array)
36
+ raise ArgumentError, ':workflow must not be empty' if workflow.empty?
37
+
38
+ request('/v2/verify/', params: opts.merge(brand: brand, workflow: workflow), type: Post)
39
+ end
40
+
41
+ # Check a supplied code against a request to see if it is valid.
42
+ #
43
+ # @example
44
+ # code_check = verify.check_code(request_id: '7e8c5965-0a3f-44df-8a14-f1486209d8a2', code: '1234')
45
+ #
46
+ # @param [required, String] :request_id The request_id of the verification request being checked
47
+ #
48
+ # @param [required, String] :code The code supplied to the end-user by the verification request
49
+ #
50
+ # @see https://developer.vonage.com/en/api/verify.v2#checkCode
51
+ #
52
+ def check_code(request_id:, code:)
53
+ request('/v2/verify/' + request_id, params: {code: code}, type: Post)
54
+ end
55
+
56
+ # Cancel a verifiction. If a verification request is still active, calling this method aborts the workflow.
57
+ #
58
+ # @example
59
+ # verify.cancel_verification_request(request_id: '7e8c5965-0a3f-44df-8a14-f1486209d8a2')
60
+ #
61
+ # @param [required, String] :request_id The request_id of the verification request to be cancelled
62
+ #
63
+ # @see https://developer.vonage.com/en/api/verify.v2#cancelRequest
64
+ #
65
+ def cancel_verification_request(request_id:)
66
+ request('/v2/verify/' + request_id, type: Delete)
67
+ end
68
+
69
+ # Instantiate a new Vonage::Verify2::StartVerificationOptions object
70
+ #
71
+ # @param [optional, Hash] opts the options for the verification request.
72
+ # @option opts [Integer] :code_length The length of the one-time code provided to the end-user
73
+ # @option opts [String] :code An optional alphanumeric custom code to use instead of an auto-generated code
74
+ # @option opts [String] :locale The language to use for the verification message (where applicable)
75
+ # @option opts [Integer] :channel_timeout Wait time in seconds before trying the next channel in the workflow
76
+ # @option opts [String] :client_ref Reference to be included in callbacks
77
+ # @option opts [Boolean] If used, must be set to `false`. Will bypass a network block for a single Verify V2 request
78
+ #
79
+ def start_verification_options(**opts)
80
+ StartVerificationOptions.new(**opts)
81
+ end
82
+
83
+ # Instantiate a new Vonage::Verify2::Workflow object
84
+ def workflow
85
+ Workflow.new
86
+ end
87
+
88
+ # Return the Vonage::Verify2::WorkflowBuilder class
89
+ def workflow_builder
90
+ WorkflowBuilder.itself
91
+ end
92
+ end
93
+ end
@@ -1,5 +1,5 @@
1
1
  # typed: strong
2
2
 
3
3
  module Vonage
4
- VERSION = "7.9.0"
4
+ VERSION = "7.11.0"
5
5
  end
@@ -2,9 +2,9 @@
2
2
  # frozen_string_literal: true
3
3
  require 'phonelib'
4
4
 
5
- module Vonage
5
+ module Vonage
6
6
  class Voice::Actions::Connect
7
- attr_accessor :endpoint, :from, :eventType, :timeout, :limit, :machineDetection, :eventUrl, :eventMethod, :ringbackTone
7
+ attr_accessor :endpoint, :from, :eventType, :timeout, :limit, :machineDetection, :advanced_machine_detection, :eventUrl, :eventMethod, :ringbackTone
8
8
 
9
9
  def initialize(attributes = {})
10
10
  @endpoint = attributes.fetch(:endpoint)
@@ -13,6 +13,7 @@ module Vonage
13
13
  @timeout = attributes.fetch(:timeout, nil)
14
14
  @limit = attributes.fetch(:limit, nil)
15
15
  @machineDetection = attributes.fetch(:machineDetection, nil)
16
+ @advanced_machine_detection = attributes.fetch(:advanced_machine_detection, nil)
16
17
  @eventUrl = attributes.fetch(:eventUrl, nil)
17
18
  @eventMethod = attributes.fetch(:eventMethod, nil)
18
19
  @ringbackTone = attributes.fetch(:ringbackTone, nil)
@@ -39,6 +40,10 @@ module Vonage
39
40
  verify_machine_detection
40
41
  end
41
42
 
43
+ if self.advanced_machine_detection
44
+ verify_advanced_machine_detection
45
+ end
46
+
42
47
  if self.eventUrl
43
48
  verify_event_url
44
49
  end
@@ -82,6 +87,25 @@ module Vonage
82
87
  raise ClientError.new("Invalid 'machineDetection' value, must be either: 'continue' or 'hangup' if defined") unless self.machineDetection == 'continue' || self.machineDetection == 'hangup'
83
88
  end
84
89
 
90
+ def verify_advanced_machine_detection
91
+ raise ClientError.new("Invalid 'advanced_machine_detection' value, must be a Hash") unless self.advanced_machine_detection.is_a?(Hash)
92
+ verify_advanced_machine_detection_behavior if self.advanced_machine_detection[:behavior]
93
+ verify_advanced_machine_detection_mode if self.advanced_machine_detection[:mode]
94
+ verify_advanced_machine_detection_beep_timeout if self.advanced_machine_detection[:beep_timeout]
95
+ end
96
+
97
+ def verify_advanced_machine_detection_behavior
98
+ raise ClientError.new("Invalid 'advanced_machine_detection[:behavior]' value, must be a `continue` or `hangup`") unless ['continue', 'hangup'].include?(self.advanced_machine_detection[:behavior])
99
+ end
100
+
101
+ def verify_advanced_machine_detection_mode
102
+ raise ClientError.new("Invalid 'advanced_machine_detection[:mode]' value, must be a `detect` or `detect_beep`") unless ['detect', 'detect_beep'].include?(self.advanced_machine_detection[:mode])
103
+ end
104
+
105
+ def verify_advanced_machine_detection_beep_timeout
106
+ raise ClientError.new("Invalid 'advanced_machine_detection[:beep_timeout]' value, must be between 45 and 120") unless self.advanced_machine_detection[:beep_timeout].between?(45, 120)
107
+ end
108
+
85
109
  def verify_event_url
86
110
  uri = URI.parse(self.eventUrl)
87
111
 
@@ -196,4 +220,4 @@ module Vonage
196
220
  }
197
221
  end
198
222
  end
199
- end
223
+ end
@@ -2,7 +2,7 @@
2
2
  # frozen_string_literal: true
3
3
  module Vonage
4
4
  class Voice::Actions::Talk
5
- attr_accessor :text, :bargeIn, :loop, :level, :language, :style
5
+ attr_accessor :text, :bargeIn, :loop, :level, :language, :style, :premium
6
6
 
7
7
  def initialize(attributes= {})
8
8
  @text = attributes.fetch(:text)
@@ -11,6 +11,7 @@ module Vonage
11
11
  @level = attributes.fetch(:level, nil)
12
12
  @language = attributes.fetch(:language, nil)
13
13
  @style = attributes.fetch(:style, nil)
14
+ @premium = attributes.fetch(:premium, nil)
14
15
 
15
16
  after_initialize!
16
17
  end
@@ -31,6 +32,10 @@ module Vonage
31
32
  if self.style
32
33
  verify_style
33
34
  end
35
+
36
+ if self.premium
37
+ verify_premium
38
+ end
34
39
  end
35
40
 
36
41
  def verify_barge_in
@@ -49,6 +54,10 @@ module Vonage
49
54
  raise ClientError.new("Expected 'style' value to be an Integer") unless self.style.is_a?(Integer)
50
55
  end
51
56
 
57
+ def verify_premium
58
+ raise ClientError.new("Expected 'premium' value to be a Boolean") unless self.premium == true || self.premium == false
59
+ end
60
+
52
61
  def action
53
62
  create_talk!(self)
54
63
  end
@@ -70,4 +79,4 @@ module Vonage
70
79
  ncco
71
80
  end
72
81
  end
73
- end
82
+ end
@@ -12,8 +12,18 @@ module Vonage
12
12
  # @option params [required, String] :text
13
13
  # The text to read.
14
14
  #
15
+ # @option params [String] :language
16
+ # The language to use. See {https://developer.vonage.com/en/api/voice#startTalk-req-body} for a list of valid language codes.
17
+ #
18
+ # @option params [Integer] :style
19
+ # The vocal style, as identified by an assigned integer.
20
+ # See {https://developer.vonage.com/en/voice/voice-api/concepts/text-to-speech#supported-languages} for a list of available styles.
21
+ #
22
+ # @option params [Boolean] :premium
23
+ # Set to `true` to use the premium version of the specified style if available, otherwise the standard version will be used.
24
+ #
15
25
  # @option params [String] :voice_name
16
- # The voice & language to use.
26
+ # The voice & language to use. [DEPRECATED: use `language` and `style` instead].
17
27
  #
18
28
  # @option params [Integer] :loop
19
29
  # The number of times to repeat the text the file, 0 for infinite.
data/lib/vonage/voice.rb CHANGED
@@ -48,6 +48,17 @@ module Vonage
48
48
  # @option params [String] :machine_detection
49
49
  # Configure the behavior when Vonage detects that the call is answered by voicemail.
50
50
  #
51
+ # @option params [Hash] :advanced_machine_detection
52
+ # Configure the behavior of Vonage's advanced machine detection. Overrides machine_detection if both are set.
53
+ # Hash with three possible properties:
54
+ # - :behavior [String]: Must be one of `continue` or `hangup`. When hangup is used, the call will be terminated if a
55
+ # machine is detected. When continue is used, the call will continue even if a machine is detected.
56
+ # - :mode [String]: Must be one of `detect` or `detect_beep`. Detect if machine answered and sends a human or
57
+ # machine status in the webhook payload. When set to `detect_beep`, the system also attempts to detect
58
+ # voice mail beep and sends an additional parameter `sub_state` in the webhook with the value `beep_start`.
59
+ # - :beep_timeout [Integer]: Min: 45, Max: 120. Maximum time in seconds Vonage should wait for a machine beep
60
+ # to be detected. A machine event with `sub_state` set to `beep_timeout` will be sent if the timeout is exceeded.
61
+ #
51
62
  # @option params [Integer] :length_timer
52
63
  # Set the number of seconds that elapse before Vonage hangs up after the call state changes to in_progress.
53
64
  #
metadata CHANGED
@@ -1,14 +1,14 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: vonage
3
3
  version: !ruby/object:Gem::Version
4
- version: 7.9.0
4
+ version: 7.11.0
5
5
  platform: ruby
6
6
  authors:
7
7
  - Vonage
8
8
  autorequire:
9
9
  bindir: bin
10
10
  cert_chain: []
11
- date: 2023-04-19 00:00:00.000000000 Z
11
+ date: 2023-06-16 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: vonage-jwt
@@ -152,13 +152,22 @@ files:
152
152
  - lib/vonage/tfa.rb
153
153
  - lib/vonage/user_agent.rb
154
154
  - lib/vonage/verify.rb
155
+ - lib/vonage/verify2.rb
156
+ - lib/vonage/verify2/channels/email.rb
157
+ - lib/vonage/verify2/channels/silent_auth.rb
158
+ - lib/vonage/verify2/channels/sms.rb
159
+ - lib/vonage/verify2/channels/voice.rb
160
+ - lib/vonage/verify2/channels/whats_app.rb
161
+ - lib/vonage/verify2/channels/whats_app_interactive.rb
162
+ - lib/vonage/verify2/start_verification_options.rb
163
+ - lib/vonage/verify2/workflow.rb
164
+ - lib/vonage/verify2/workflow_builder.rb
155
165
  - lib/vonage/version.rb
156
166
  - lib/vonage/voice.rb
157
167
  - lib/vonage/voice/actions/connect.rb
158
168
  - lib/vonage/voice/actions/conversation.rb
159
169
  - lib/vonage/voice/actions/input.rb
160
170
  - lib/vonage/voice/actions/notify.rb
161
- - lib/vonage/voice/actions/pay.rb
162
171
  - lib/vonage/voice/actions/record.rb
163
172
  - lib/vonage/voice/actions/stream.rb
164
173
  - lib/vonage/voice/actions/talk.rb
@@ -1,107 +0,0 @@
1
- # typed: true
2
- # frozen_string_literal: true
3
- module Vonage
4
- class Voice::Actions::Pay
5
- attr_accessor :amount, :currency, :eventUrl, :prompts, :voice
6
-
7
- def initialize(attributes= {})
8
- @amount = attributes.fetch(:amount)
9
- @currency = attributes.fetch(:currency, nil)
10
- @eventUrl = attributes.fetch(:eventUrl, nil)
11
- @prompts = attributes.fetch(:prompts, nil)
12
- @voice = attributes.fetch(:voice, nil)
13
-
14
- after_initialize!
15
- end
16
-
17
- def action
18
- create_pay!(self)
19
- end
20
-
21
- def create_pay!(builder)
22
- ncco = [
23
- {
24
- action: 'pay',
25
- amount: builder.amount
26
- }
27
- ]
28
-
29
- ncco[0].merge!(currency: builder.currency) if builder.currency
30
- ncco[0].merge!(eventUrl: builder.eventUrl) if builder.eventUrl
31
- ncco[0].merge!(prompts: builder.prompts) if builder.prompts
32
- ncco[0].merge!(voice: builder.voice) if builder.voice
33
-
34
- ncco
35
- end
36
-
37
- private
38
-
39
- def after_initialize!
40
- verify_amount
41
-
42
- if self.eventUrl
43
- verify_event_url
44
- end
45
-
46
- if self.prompts
47
- verify_prompts
48
- end
49
-
50
- if self.voice
51
- verify_voice
52
- end
53
- end
54
-
55
- def verify_amount
56
- verify_amount_class
57
- verify_amount_value
58
- end
59
-
60
- def verify_event_url
61
- raise ClientError.new("Expected 'eventUrl' parameter to be an Array containing a single string item") unless self.eventUrl.is_a?(Array)
62
-
63
- uri = URI.parse(self.eventUrl[0])
64
-
65
- raise ClientError.new("Invalid 'eventUrl' value, must be a valid URL") unless uri.kind_of?(URI::HTTP) || uri.kind_of?(URI::HTTPS)
66
- end
67
-
68
- def verify_prompts
69
- verify_prompts_structure
70
- verify_prompts_values
71
- end
72
-
73
- def verify_voice
74
- verify_voice_structure
75
- verify_voice_style if self.voice[:style]
76
- end
77
-
78
- def verify_amount_class
79
- raise ClientError.new("Invalid 'amount' value, must be a float") unless self.amount.is_a?(Float)
80
- end
81
-
82
- def verify_amount_value
83
- raise ClientError.new("Invalid 'amount' value, must be greater than 0") unless self.amount > 0
84
- end
85
-
86
- def verify_prompts_structure
87
- raise ClientError.new("Invalid 'prompt', must be an array of at least one hash") unless self.prompts.is_a?(Array) && !self.prompts.empty? && self.prompts.all?(Hash)
88
- end
89
-
90
- def verify_prompts_values
91
- self.prompts.each do |prompt|
92
- prompt_keys = prompt.keys
93
- [:type, :text, :errors].each do |key|
94
- raise ClientError.new("Invalid 'prompt', '#{key}' is required") unless prompt_keys.include?(key)
95
- end
96
- end
97
- end
98
-
99
- def verify_voice_structure
100
- raise ClientError.new("Expected 'voice' value to be a Hash") unless self.voice.is_a?(Hash)
101
- end
102
-
103
- def verify_voice_style
104
- raise ClientError.new("Expected 'style' value to be an Integer") unless self.voice[:style].is_a?(Integer)
105
- end
106
- end
107
- end