nexmo 6.0.1 → 7.1.0
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/LICENSE.txt +1 -1
- data/README.md +24 -4
- data/lib/nexmo.rb +12 -14
- data/lib/nexmo/abstract_authentication.rb +2 -0
- data/lib/nexmo/account.rb +6 -1
- data/lib/nexmo/alerts.rb +6 -1
- data/lib/nexmo/applications.rb +24 -3
- data/lib/nexmo/applications/list_response.rb +2 -0
- data/lib/nexmo/authentication_error.rb +2 -0
- data/lib/nexmo/basic.rb +2 -0
- data/lib/nexmo/bearer_token.rb +1 -0
- data/lib/nexmo/client.rb +46 -23
- data/lib/nexmo/client_error.rb +2 -0
- data/lib/nexmo/config.rb +52 -9
- data/lib/nexmo/conversations.rb +24 -0
- data/lib/nexmo/conversations/events.rb +1 -0
- data/lib/nexmo/conversations/legs.rb +1 -0
- data/lib/nexmo/conversations/members.rb +1 -0
- data/lib/nexmo/conversations/users.rb +1 -0
- data/lib/nexmo/conversions.rb +4 -0
- data/lib/nexmo/entity.rb +5 -3
- data/lib/nexmo/error.rb +2 -0
- data/lib/nexmo/errors.rb +10 -0
- data/lib/nexmo/files.rb +7 -2
- data/lib/nexmo/form_data.rb +2 -0
- data/lib/nexmo/gsm7.rb +2 -0
- data/lib/nexmo/http.rb +12 -3
- data/lib/nexmo/json.rb +4 -0
- data/lib/nexmo/jwt.rb +6 -2
- data/lib/nexmo/key_secret_params.rb +10 -2
- data/lib/nexmo/keys.rb +7 -1
- data/lib/nexmo/logger.rb +14 -4
- data/lib/nexmo/messages.rb +7 -1
- data/lib/nexmo/namespace.rb +15 -18
- data/lib/nexmo/number_insight.rb +21 -6
- data/lib/nexmo/numbers.rb +24 -20
- data/lib/nexmo/numbers/list_response.rb +2 -0
- data/lib/nexmo/numbers/response.rb +1 -0
- data/lib/nexmo/params.rb +1 -0
- data/lib/nexmo/pricing.rb +2 -1
- data/lib/nexmo/pricing_types.rb +1 -0
- data/lib/nexmo/redact.rb +2 -1
- data/lib/nexmo/response.rb +2 -0
- data/lib/nexmo/secrets.rb +1 -0
- data/lib/nexmo/secrets/list_response.rb +2 -0
- data/lib/nexmo/server_error.rb +2 -0
- data/lib/nexmo/signature.rb +19 -13
- data/lib/nexmo/sms.rb +16 -10
- data/lib/nexmo/tfa.rb +2 -1
- data/lib/nexmo/user_agent.rb +1 -0
- data/lib/nexmo/verify.rb +93 -17
- data/lib/nexmo/version.rb +3 -1
- data/lib/nexmo/{calls.rb → voice.rb} +12 -11
- data/lib/nexmo/{calls → voice}/dtmf.rb +2 -1
- data/lib/nexmo/{calls → voice}/list_response.rb +3 -1
- data/lib/nexmo/{calls → voice}/stream.rb +2 -1
- data/lib/nexmo/{calls → voice}/talk.rb +2 -1
- data/nexmo.gemspec +2 -7
- metadata +17 -85
- data/lib/nexmo/key_secret_query.rb +0 -20
- data/lib/nexmo/number_insight/response.rb +0 -5
- data/lib/nexmo/sms/response.rb +0 -7
- data/lib/nexmo/verify/response.rb +0 -5
data/lib/nexmo/pricing_types.rb
CHANGED
data/lib/nexmo/redact.rb
CHANGED
data/lib/nexmo/response.rb
CHANGED
data/lib/nexmo/secrets.rb
CHANGED
data/lib/nexmo/server_error.rb
CHANGED
data/lib/nexmo/signature.rb
CHANGED
@@ -1,16 +1,21 @@
|
|
1
|
+
# typed: true
|
2
|
+
# frozen_string_literal: true
|
3
|
+
require 'openssl'
|
1
4
|
require 'digest/md5'
|
2
5
|
require 'jwt'
|
3
6
|
|
4
7
|
module Nexmo
|
5
8
|
class Signature
|
6
|
-
def initialize(
|
7
|
-
@
|
9
|
+
def initialize(config)
|
10
|
+
@config = config
|
8
11
|
end
|
9
12
|
|
10
13
|
# Check webhook request signature.
|
11
14
|
#
|
12
15
|
# @example
|
13
|
-
# client = Nexmo::Client.new
|
16
|
+
# client = Nexmo::Client.new
|
17
|
+
# client.config.signature_secret = 'secret'
|
18
|
+
# client.config.signature_method = 'sha512'
|
14
19
|
#
|
15
20
|
# if client.signature.check(request.GET)
|
16
21
|
# # valid signature
|
@@ -22,26 +27,27 @@ module Nexmo
|
|
22
27
|
#
|
23
28
|
# @see https://developer.nexmo.com/concepts/guides/signing-messages
|
24
29
|
#
|
25
|
-
def check(params)
|
30
|
+
def check(params, signature_method: @config.signature_method)
|
26
31
|
params = params.dup
|
27
32
|
|
28
33
|
signature = params.delete('sig')
|
29
34
|
|
30
|
-
::JWT::SecurityUtils.secure_compare(signature, digest(params))
|
35
|
+
::JWT::SecurityUtils.secure_compare(signature, digest(params, signature_method))
|
31
36
|
end
|
32
37
|
|
33
38
|
private
|
34
39
|
|
35
|
-
def digest(params)
|
36
|
-
|
40
|
+
def digest(params, signature_method)
|
41
|
+
digest_string = params.sort.map { |k, v| "&#{k}=#{v.tr('&=', '_')}" }.join
|
37
42
|
|
38
|
-
|
39
|
-
|
43
|
+
case signature_method
|
44
|
+
when 'md5', 'sha1', 'sha256', 'sha512'
|
45
|
+
OpenSSL::HMAC.hexdigest(signature_method, @config.signature_secret, digest_string).upcase
|
46
|
+
when 'md5hash'
|
47
|
+
Digest::MD5.hexdigest("#{digest_string}#{@config.signature_secret}")
|
48
|
+
else
|
49
|
+
raise ArgumentError, "Unknown signature algorithm: #{signature_method}. Expected: md5hash, md5, sha1, sha256, or sha512."
|
40
50
|
end
|
41
|
-
|
42
|
-
md5.update(@secret)
|
43
|
-
|
44
|
-
md5.hexdigest
|
45
51
|
end
|
46
52
|
end
|
47
53
|
end
|
data/lib/nexmo/sms.rb
CHANGED
@@ -1,21 +1,19 @@
|
|
1
|
+
# typed: strict
|
1
2
|
# frozen_string_literal: true
|
2
3
|
|
3
4
|
module Nexmo
|
4
5
|
class SMS < Namespace
|
6
|
+
extend T::Sig
|
5
7
|
include Keys
|
6
8
|
|
7
|
-
self.host =
|
9
|
+
self.host = :rest_host
|
8
10
|
|
9
11
|
# Send an outbound SMS from your Nexmo account.
|
10
12
|
#
|
11
13
|
# @example
|
12
14
|
# response = client.sms.send(from: 'Ruby', to: '447700900000', text: 'Hello world')
|
13
15
|
#
|
14
|
-
#
|
15
|
-
# puts "Sent message id=#{response.messages.first.message_id}"
|
16
|
-
# else
|
17
|
-
# puts "Error: #{response.messages.first.error_text}"
|
18
|
-
# end
|
16
|
+
# puts "Sent message id=#{response.messages.first.message_id}"
|
19
17
|
#
|
20
18
|
# @option params [required, String] :from
|
21
19
|
# The name or number the message should be sent from.
|
@@ -94,22 +92,30 @@ module Nexmo
|
|
94
92
|
#
|
95
93
|
# @see https://developer.nexmo.com/api/sms#send-an-sms
|
96
94
|
#
|
95
|
+
sig { params(params: T::Hash[Symbol, T.untyped]).returns(Nexmo::Response) }
|
97
96
|
def send(params)
|
98
|
-
if unicode?(params
|
97
|
+
if unicode?(params.fetch(:text)) && params[:type] != 'unicode'
|
99
98
|
message = 'Sending unicode text SMS without setting the type parameter to "unicode". ' \
|
100
99
|
'See https://developer.nexmo.com/messaging/sms for details, ' \
|
101
100
|
'or email support@nexmo.com if you have any questions.'
|
102
101
|
|
103
|
-
|
102
|
+
logger.warn(message)
|
104
103
|
end
|
105
104
|
|
106
|
-
request('/sms/json', params: hyphenate(params), type: Post
|
105
|
+
response = request('/sms/json', params: hyphenate(params), type: Post)
|
106
|
+
|
107
|
+
unless response.messages.first.status == '0'
|
108
|
+
raise Error, response.messages.first[:error_text]
|
109
|
+
end
|
110
|
+
|
111
|
+
response
|
107
112
|
end
|
108
113
|
|
109
114
|
private
|
110
115
|
|
116
|
+
sig { params(text: String).returns(T::Boolean) }
|
111
117
|
def unicode?(text)
|
112
|
-
!GSM7.encoded?(text)
|
118
|
+
!Nexmo::GSM7Test::GSM7.encoded?(text)
|
113
119
|
end
|
114
120
|
end
|
115
121
|
end
|
data/lib/nexmo/tfa.rb
CHANGED
data/lib/nexmo/user_agent.rb
CHANGED
data/lib/nexmo/verify.rb
CHANGED
@@ -1,13 +1,13 @@
|
|
1
|
+
# typed: strict
|
1
2
|
# frozen_string_literal: true
|
2
3
|
|
3
4
|
module Nexmo
|
4
5
|
class Verify < Namespace
|
6
|
+
extend T::Sig
|
5
7
|
alias_method :http_request, :request
|
6
8
|
|
7
9
|
private :http_request
|
8
10
|
|
9
|
-
self.response_class = Response
|
10
|
-
|
11
11
|
# Generate and send a PIN to your user.
|
12
12
|
#
|
13
13
|
# @note You can make a maximum of one Verify request per second.
|
@@ -15,11 +15,7 @@ module Nexmo
|
|
15
15
|
# @example
|
16
16
|
# response = client.verify.request(number: '447700900000', brand: 'Acme Inc')
|
17
17
|
#
|
18
|
-
#
|
19
|
-
# puts "Started verification request_id=#{response.request_id}"
|
20
|
-
# else
|
21
|
-
# puts "Error: #{response.error_text}"
|
22
|
-
# end
|
18
|
+
# puts "Started verification request_id=#{response.request_id}"
|
23
19
|
#
|
24
20
|
# @option params [required, String] :number
|
25
21
|
# The mobile or landline phone number to verify.
|
@@ -64,8 +60,13 @@ module Nexmo
|
|
64
60
|
#
|
65
61
|
# @see https://developer.nexmo.com/api/verify#verifyRequest
|
66
62
|
#
|
67
|
-
|
68
|
-
|
63
|
+
sig { params(params: T.untyped, uri: T.untyped).returns(T.untyped) }
|
64
|
+
def request(params, uri = '/verify/json')
|
65
|
+
response = http_request(uri, params: params, type: Post)
|
66
|
+
|
67
|
+
raise Error, response[:error_text] if error?(response)
|
68
|
+
|
69
|
+
response
|
69
70
|
end
|
70
71
|
|
71
72
|
# Confirm that the PIN you received from your user matches the one sent by Nexmo in your verification request.
|
@@ -73,11 +74,7 @@ module Nexmo
|
|
73
74
|
# @example
|
74
75
|
# response = client.verify.check(request_id: request_id, code: '1234')
|
75
76
|
#
|
76
|
-
#
|
77
|
-
# puts "Verification complete, event_id=#{response.event_id}"
|
78
|
-
# else
|
79
|
-
# puts "Error: #{response.error_text}"
|
80
|
-
# end
|
77
|
+
# puts "Verification complete, event_id=#{response.event_id}"
|
81
78
|
#
|
82
79
|
# @option params [required, String] :request_id
|
83
80
|
# The Verify request to check.
|
@@ -96,8 +93,13 @@ module Nexmo
|
|
96
93
|
#
|
97
94
|
# @see https://developer.nexmo.com/api/verify#verifyCheck
|
98
95
|
#
|
96
|
+
sig { params(params: T::Hash[Symbol, T.untyped]).returns(Nexmo::Response) }
|
99
97
|
def check(params)
|
100
|
-
http_request('/verify/check/json', params: params, type: Post)
|
98
|
+
response = http_request('/verify/check/json', params: params, type: Post)
|
99
|
+
|
100
|
+
raise Error, response[:error_text] if error?(response)
|
101
|
+
|
102
|
+
response
|
101
103
|
end
|
102
104
|
|
103
105
|
# Check the status of past or current verification requests.
|
@@ -118,8 +120,13 @@ module Nexmo
|
|
118
120
|
#
|
119
121
|
# @see https://developer.nexmo.com/api/verify#verifySearch
|
120
122
|
#
|
123
|
+
sig { params(params: T::Hash[Symbol, T.untyped]).returns(T.any(T::Hash[Symbol, T.untyped], Nexmo::Response)) }
|
121
124
|
def search(params)
|
122
|
-
http_request('/verify/search/json', params: params)
|
125
|
+
response = http_request('/verify/search/json', params: params)
|
126
|
+
|
127
|
+
raise Error, response[:error_text] if error?(response)
|
128
|
+
|
129
|
+
response
|
123
130
|
end
|
124
131
|
|
125
132
|
# Control the progress of your verification requests.
|
@@ -140,8 +147,13 @@ module Nexmo
|
|
140
147
|
#
|
141
148
|
# @see https://developer.nexmo.com/api/verify#verifyControl
|
142
149
|
#
|
150
|
+
sig { params(params: T::Hash[Symbol, T.untyped]).returns(T.untyped) }
|
143
151
|
def control(params)
|
144
|
-
http_request('/verify/control/json', params: params, type: Post)
|
152
|
+
response = http_request('/verify/control/json', params: params, type: Post)
|
153
|
+
|
154
|
+
raise Error, response[:error_text] if error?(response)
|
155
|
+
|
156
|
+
response
|
145
157
|
end
|
146
158
|
|
147
159
|
# Cancel an existing verification request.
|
@@ -155,6 +167,7 @@ module Nexmo
|
|
155
167
|
#
|
156
168
|
# @see https://developer.nexmo.com/api/verify#verifyControl
|
157
169
|
#
|
170
|
+
sig { params(id: String).returns(Nexmo::Response) }
|
158
171
|
def cancel(id)
|
159
172
|
control(request_id: id, cmd: 'cancel')
|
160
173
|
end
|
@@ -170,8 +183,71 @@ module Nexmo
|
|
170
183
|
#
|
171
184
|
# @see https://developer.nexmo.com/api/verify#verifyControl
|
172
185
|
#
|
186
|
+
sig { params(id: String).returns(Nexmo::Response) }
|
173
187
|
def trigger_next_event(id)
|
174
188
|
control(request_id: id, cmd: 'trigger_next_event')
|
175
189
|
end
|
190
|
+
|
191
|
+
# Send a PSD2-compliant payment token to a user for payment authorization
|
192
|
+
#
|
193
|
+
# @example
|
194
|
+
# response = client.verify.psd2(number: '447700900000', payee: 'Acme Inc', amount: 48.00)
|
195
|
+
#
|
196
|
+
# @option params [required, String] :number
|
197
|
+
# The mobile or landline phone number to verify.
|
198
|
+
# Unless you are setting **:country** explicitly, this number must be in E.164 format.
|
199
|
+
#
|
200
|
+
# @option params [String] :country
|
201
|
+
# If you do not provide **:number** in international format or you are not sure if **:number** is correctly formatted, specify the two-character country code in **:country**.
|
202
|
+
# Verify will then format the number for you.
|
203
|
+
#
|
204
|
+
# @option params [required, String] :payee
|
205
|
+
# An alphanumeric string to indicate to the user the name of the recipient that they are confirming a payment to.
|
206
|
+
#
|
207
|
+
# @option params [required, Float] :amount
|
208
|
+
# The decimal amount of the payment to be confirmed, in Euros
|
209
|
+
#
|
210
|
+
# @option params [Integer] :code_length
|
211
|
+
# The length of the verification code.
|
212
|
+
#
|
213
|
+
# @option params [String] :lg
|
214
|
+
# By default, the SMS or text-to-speech (TTS) message is generated in the locale that matches the **:number**.
|
215
|
+
# For example, the text message or TTS message for a `33*` number is sent in French.
|
216
|
+
# Use this parameter to explicitly control the language, accent and gender used for the Verify request.
|
217
|
+
#
|
218
|
+
# @option params [Integer] :pin_expiry
|
219
|
+
# How log the generated verification code is valid for, in seconds.
|
220
|
+
# When you specify both **:pin_expiry** and **:next_event_wait** then **:pin_expiry** must be an integer multiple of **:next_event_wait** otherwise **:pin_expiry** is defaulted to equal **:next_event_wait**.
|
221
|
+
# See [changing the event timings](https://developer.nexmo.com/verify/guides/changing-default-timings).
|
222
|
+
#
|
223
|
+
# @option params [Integer] :next_event_wait
|
224
|
+
# Specifies the wait time in seconds between attempts to deliver the verification code.
|
225
|
+
#
|
226
|
+
# @option params [Integer] :workflow_id
|
227
|
+
# Selects the predefined sequence of SMS and TTS (Text To Speech) actions to use in order to convey the PIN to your user.
|
228
|
+
# For example, an id of 1 identifies the workflow SMS - TTS - TTS.
|
229
|
+
# For a list of all workflows and their associated ids, please visit the [developer portal](https://developer.nexmo.com/verify/guides/workflows-and-events).
|
230
|
+
#
|
231
|
+
# @param [Hash] params
|
232
|
+
#
|
233
|
+
# @return [Response]
|
234
|
+
#
|
235
|
+
# @see https://developer.nexmo.com/api/verify#verifyRequestWithPSD2
|
236
|
+
#
|
237
|
+
sig { params(params: T.untyped, uri: T.untyped).returns(T.any(Nexmo::Error, Nexmo::Response)) }
|
238
|
+
def psd2(params, uri = '/verify/psd2/json')
|
239
|
+
response = http_request(uri, params: params, type: Post)
|
240
|
+
|
241
|
+
raise Error, response[:error_text] if error?(response)
|
242
|
+
|
243
|
+
response
|
244
|
+
end
|
245
|
+
|
246
|
+
private
|
247
|
+
|
248
|
+
sig { params(response: T.untyped).returns(T::Boolean) }
|
249
|
+
def error?(response)
|
250
|
+
response.respond_to?(:error_text)
|
251
|
+
end
|
176
252
|
end
|
177
253
|
end
|
data/lib/nexmo/version.rb
CHANGED
@@ -1,7 +1,8 @@
|
|
1
|
+
# typed: true
|
1
2
|
# frozen_string_literal: true
|
2
3
|
|
3
4
|
module Nexmo
|
4
|
-
class
|
5
|
+
class Voice < Namespace
|
5
6
|
self.authentication = BearerToken
|
6
7
|
|
7
8
|
self.request_body = JSON
|
@@ -9,7 +10,7 @@ module Nexmo
|
|
9
10
|
# Create an outbound Call.
|
10
11
|
#
|
11
12
|
# @example
|
12
|
-
# response = client.
|
13
|
+
# response = client.voice.create({
|
13
14
|
# to: [{type: 'phone', number: '14843331234'}],
|
14
15
|
# from: {type: 'phone', number: '14843335555'},
|
15
16
|
# answer_url: ['https://example.com/answer']
|
@@ -60,7 +61,7 @@ module Nexmo
|
|
60
61
|
# Get details of your calls.
|
61
62
|
#
|
62
63
|
# @example
|
63
|
-
# response = client.
|
64
|
+
# response = client.voice.list
|
64
65
|
# response.each do |item|
|
65
66
|
# puts "#{item.uuid} #{item.direction} #{item.status}"
|
66
67
|
# end
|
@@ -99,7 +100,7 @@ module Nexmo
|
|
99
100
|
# Get detail of a specific call.
|
100
101
|
#
|
101
102
|
# @example
|
102
|
-
# response = client.
|
103
|
+
# response = client.voice.get(id)
|
103
104
|
#
|
104
105
|
# @param [String] id
|
105
106
|
#
|
@@ -114,7 +115,7 @@ module Nexmo
|
|
114
115
|
# Modify an in progress call.
|
115
116
|
#
|
116
117
|
# @example
|
117
|
-
# response = client.
|
118
|
+
# response = client.voice.update(id, action: 'hangup')
|
118
119
|
#
|
119
120
|
# @option params [required, String] :action
|
120
121
|
#
|
@@ -135,7 +136,7 @@ module Nexmo
|
|
135
136
|
# Hangup an in progress call.
|
136
137
|
#
|
137
138
|
# @example
|
138
|
-
# response = client.
|
139
|
+
# response = client.voice.hangup(id)
|
139
140
|
#
|
140
141
|
# @param [String] id
|
141
142
|
#
|
@@ -150,7 +151,7 @@ module Nexmo
|
|
150
151
|
# Mute an in progress call.
|
151
152
|
#
|
152
153
|
# @example
|
153
|
-
# response = client.
|
154
|
+
# response = client.voice.mute(id)
|
154
155
|
#
|
155
156
|
# @param [String] id
|
156
157
|
#
|
@@ -165,7 +166,7 @@ module Nexmo
|
|
165
166
|
# Unmute an in progress call.
|
166
167
|
#
|
167
168
|
# @example
|
168
|
-
# response = client.
|
169
|
+
# response = client.voice.unmute(id)
|
169
170
|
#
|
170
171
|
# @param [String] id
|
171
172
|
#
|
@@ -180,7 +181,7 @@ module Nexmo
|
|
180
181
|
# Earmuff an in progress call.
|
181
182
|
#
|
182
183
|
# @example
|
183
|
-
# response = client.
|
184
|
+
# response = client.voice.earmuff(id)
|
184
185
|
#
|
185
186
|
# @param [String] id
|
186
187
|
#
|
@@ -195,7 +196,7 @@ module Nexmo
|
|
195
196
|
# Unearmuff an in progress call.
|
196
197
|
#
|
197
198
|
# @example
|
198
|
-
# response = client.
|
199
|
+
# response = client.voice.unearmuff(id)
|
199
200
|
#
|
200
201
|
# @param [String] id
|
201
202
|
#
|
@@ -215,7 +216,7 @@ module Nexmo
|
|
215
216
|
# url: ['https://example.com/ncco.json']
|
216
217
|
# }
|
217
218
|
#
|
218
|
-
# response = client.
|
219
|
+
# response = client.voice.transfer(id, destination: destination)
|
219
220
|
#
|
220
221
|
# @param [String] id
|
221
222
|
# @param [Hash] destination
|