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 +4 -4
- data/README.md +129 -1
- data/lib/vonage/client.rb +7 -0
- data/lib/vonage/namespace.rb +1 -1
- data/lib/vonage/verify2/channels/email.rb +38 -0
- data/lib/vonage/verify2/channels/silent_auth.rb +32 -0
- data/lib/vonage/verify2/channels/sms.rb +39 -0
- data/lib/vonage/verify2/channels/voice.rb +32 -0
- data/lib/vonage/verify2/channels/whats_app.rb +38 -0
- data/lib/vonage/verify2/channels/whats_app_interactive.rb +32 -0
- data/lib/vonage/verify2/start_verification_options.rb +71 -0
- data/lib/vonage/verify2/workflow.rb +39 -0
- data/lib/vonage/verify2/workflow_builder.rb +25 -0
- data/lib/vonage/verify2.rb +93 -0
- data/lib/vonage/version.rb +1 -1
- data/lib/vonage/voice/actions/connect.rb +27 -3
- data/lib/vonage/voice/actions/talk.rb +11 -2
- data/lib/vonage/voice/talk.rb +11 -1
- data/lib/vonage/voice.rb +11 -0
- metadata +12 -3
- data/lib/vonage/voice/actions/pay.rb +0 -107
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA256:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 95210747eb477199b15e3e5349e2bddfe7650928e8caae6a0275dde92381b835
|
4
|
+
data.tar.gz: '00917603bc90d21275328916969cd1af6b5925e6d034aa557705027ae514f7f8'
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
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/
|
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)) }
|
data/lib/vonage/namespace.rb
CHANGED
@@ -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
|
data/lib/vonage/version.rb
CHANGED
@@ -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
|
data/lib/vonage/voice/talk.rb
CHANGED
@@ -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.
|
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-
|
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
|