vonage 7.9.0 → 7.11.0

Sign up to get free protection for your applications and to get access to all the features.
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