cpaas-sdk 1.0.0
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +7 -0
- data/.gitignore +11 -0
- data/.rspec +3 -0
- data/.travis.yml +7 -0
- data/CHANGELOG.md +11 -0
- data/Gemfile +4 -0
- data/LICENSE.md +1 -0
- data/README.md +25 -0
- data/Rakefile +6 -0
- data/bin/console +14 -0
- data/bin/setup +8 -0
- data/cpaas-sdk.gemspec +32 -0
- data/docs/Cpaas.html +446 -0
- data/docs/Cpaas/Conversation.html +1742 -0
- data/docs/Cpaas/Notification.html +301 -0
- data/docs/Cpaas/TwoFactor.html +908 -0
- data/docs/_index.html +146 -0
- data/docs/_index.md +21 -0
- data/docs/class_list.html +51 -0
- data/docs/css/common.css +1 -0
- data/docs/css/full_list.css +58 -0
- data/docs/css/style.css +496 -0
- data/docs/file.README.html +102 -0
- data/docs/file._index.html +94 -0
- data/docs/file_list.html +56 -0
- data/docs/frames.html +17 -0
- data/docs/index.html +94 -0
- data/docs/js/app.js +303 -0
- data/docs/js/full_list.js +216 -0
- data/docs/js/jquery.js +4 -0
- data/docs/method_list.html +251 -0
- data/docs/mv_index.html +102 -0
- data/docs/top-level-namespace.html +663 -0
- data/examples/2fa/.env.example +6 -0
- data/examples/2fa/.gitignore +159 -0
- data/examples/2fa/.ruby-gemset +1 -0
- data/examples/2fa/.ruby-version +1 -0
- data/examples/2fa/Gemfile +8 -0
- data/examples/2fa/README.md +34 -0
- data/examples/2fa/app.rb +134 -0
- data/examples/2fa/config.ru +10 -0
- data/examples/2fa/helper.rb +37 -0
- data/examples/2fa/public/stylesheets/forms.css +28 -0
- data/examples/2fa/public/stylesheets/global.css +7 -0
- data/examples/2fa/public/stylesheets/layout.css +45 -0
- data/examples/2fa/public/stylesheets/main.css +3 -0
- data/examples/2fa/views/alert.erb +5 -0
- data/examples/2fa/views/dashboard.erb +4 -0
- data/examples/2fa/views/index.erb +17 -0
- data/examples/2fa/views/login.erb +13 -0
- data/examples/2fa/views/verify.erb +8 -0
- data/examples/sms/.env.example +4 -0
- data/examples/sms/.gitignore +159 -0
- data/examples/sms/.ruby-gemset +1 -0
- data/examples/sms/.ruby-version +1 -0
- data/examples/sms/Gemfile +8 -0
- data/examples/sms/README.md +80 -0
- data/examples/sms/app.rb +87 -0
- data/examples/sms/config.ru +10 -0
- data/examples/sms/helper.rb +33 -0
- data/examples/sms/public/scripts/notification.js +46 -0
- data/examples/sms/public/stylesheets/forms.css +28 -0
- data/examples/sms/public/stylesheets/global.css +7 -0
- data/examples/sms/public/stylesheets/layout.css +74 -0
- data/examples/sms/public/stylesheets/main.css +3 -0
- data/examples/sms/views/alert.erb +5 -0
- data/examples/sms/views/index.erb +48 -0
- data/lib/cpaas-sdk.rb +30 -0
- data/lib/cpaas-sdk/api.rb +139 -0
- data/lib/cpaas-sdk/config.rb +9 -0
- data/lib/cpaas-sdk/resources.rb +4 -0
- data/lib/cpaas-sdk/resources/conversation.rb +268 -0
- data/lib/cpaas-sdk/resources/notification.rb +62 -0
- data/lib/cpaas-sdk/resources/notification_channel.rb +39 -0
- data/lib/cpaas-sdk/resources/twofactor.rb +136 -0
- data/lib/cpaas-sdk/util.rb +93 -0
- data/lib/cpaas-sdk/version.rb +3 -0
- data/tutorials/2FA.md +109 -0
- data/tutorials/2fa-flow.png +0 -0
- data/tutorials/GetStarted.md +86 -0
- data/tutorials/SMSMessaging.md +132 -0
- data/tutorials/index.html +86 -0
- data/tutorials/quickstarts.yml +15 -0
- metadata +238 -0
@@ -0,0 +1,46 @@
|
|
1
|
+
(function (window) {
|
2
|
+
function syntaxHighlight (obj) {
|
3
|
+
let json = JSON.stringify(obj, undefined, 4)
|
4
|
+
json = json.replace(/&/g, '&').replace(/</g, '<').replace(/>/g, '>')
|
5
|
+
|
6
|
+
return json.replace(/("(\\u[a-zA-Z0-9]{4}|\\[^u]|[^\\"])*"(\s*:)?|\b(true|false|null)\b|-?\d+(?:\.\d*)?(?:[eE][+-]?\d+)?)/g, function (match) {
|
7
|
+
var cls = 'number'
|
8
|
+
if (/^"/.test(match)) {
|
9
|
+
if (/:$/.test(match)) {
|
10
|
+
cls = 'key'
|
11
|
+
} else {
|
12
|
+
cls = 'string'
|
13
|
+
}
|
14
|
+
} else if (/true|false/.test(match)) {
|
15
|
+
cls = 'boolean'
|
16
|
+
} else if (/null/.test(match)) {
|
17
|
+
cls = 'null'
|
18
|
+
}
|
19
|
+
return '<span class="' + cls + '">' + match + '</span>'
|
20
|
+
})
|
21
|
+
}
|
22
|
+
|
23
|
+
function render () {
|
24
|
+
const { host, protocol } = window.location
|
25
|
+
|
26
|
+
window.fetch(`${protocol}//${host}/notifications`)
|
27
|
+
.then(res => res.json().then(data => ({ status: res.status, body: data })))
|
28
|
+
.then((res) => {
|
29
|
+
if (res.status === 200 && res.body && res.body.length) {
|
30
|
+
const notifications = res.body
|
31
|
+
const notificationWrapper = document.getElementById('notification')
|
32
|
+
let html = ''
|
33
|
+
|
34
|
+
for (let i in notifications) {
|
35
|
+
html += '<pre class="notification">' + syntaxHighlight(notifications[i]) + '</pre>'
|
36
|
+
}
|
37
|
+
|
38
|
+
notificationWrapper.innerHTML = html
|
39
|
+
}
|
40
|
+
})
|
41
|
+
}
|
42
|
+
|
43
|
+
window.smsNotification = {
|
44
|
+
render
|
45
|
+
}
|
46
|
+
})(window)
|
@@ -0,0 +1,28 @@
|
|
1
|
+
.input-group {
|
2
|
+
display: flex;
|
3
|
+
flex-direction: column;
|
4
|
+
}
|
5
|
+
|
6
|
+
input[type=text],
|
7
|
+
input[type=password] {
|
8
|
+
border-radius: 4px;
|
9
|
+
border: 1px solid #ccc;
|
10
|
+
box-sizing: border-box;
|
11
|
+
display: inline-block;
|
12
|
+
font-size: 14px;
|
13
|
+
margin: 8px 0;
|
14
|
+
padding: 12px 20px;
|
15
|
+
width: 100%;
|
16
|
+
}
|
17
|
+
|
18
|
+
button {
|
19
|
+
background-color: #4CAF50;
|
20
|
+
border-radius: 5px;
|
21
|
+
border: none;
|
22
|
+
color: white;
|
23
|
+
cursor: pointer;
|
24
|
+
font-size: 14px;
|
25
|
+
margin: 8px 0;
|
26
|
+
padding: 14px 20px;
|
27
|
+
width: 100%;
|
28
|
+
}
|
@@ -0,0 +1,74 @@
|
|
1
|
+
.container {
|
2
|
+
display: flex;
|
3
|
+
align-items: center;
|
4
|
+
justify-content: space-around;
|
5
|
+
height: 100vh;
|
6
|
+
}
|
7
|
+
|
8
|
+
.box {
|
9
|
+
border-radius: 5px;
|
10
|
+
border: 1px black solid;
|
11
|
+
height: 450px;
|
12
|
+
padding: 40px;
|
13
|
+
width: 350px;
|
14
|
+
display: flex;
|
15
|
+
flex-direction: column;
|
16
|
+
}
|
17
|
+
|
18
|
+
.vertically-center {
|
19
|
+
justify-content: center;
|
20
|
+
}
|
21
|
+
|
22
|
+
.notification-box {
|
23
|
+
overflow-y: auto;
|
24
|
+
}
|
25
|
+
|
26
|
+
.solid-background {
|
27
|
+
background-color: #f2f2f2;
|
28
|
+
}
|
29
|
+
|
30
|
+
.text-center {
|
31
|
+
text-align: center;
|
32
|
+
}
|
33
|
+
|
34
|
+
.alert {
|
35
|
+
align-items: center;
|
36
|
+
border-radius: 5px;
|
37
|
+
border: 1px solid transparent;
|
38
|
+
display: flex;
|
39
|
+
height: 30px;
|
40
|
+
justify-content: center;
|
41
|
+
left: 10%;
|
42
|
+
padding: 10px 20px;
|
43
|
+
position: absolute;
|
44
|
+
top: 10px;
|
45
|
+
width: 80%;
|
46
|
+
}
|
47
|
+
|
48
|
+
.alert-error {
|
49
|
+
color: #721c24;
|
50
|
+
background-color: #f8d7da;
|
51
|
+
border-color: #f5c6cb;
|
52
|
+
}
|
53
|
+
|
54
|
+
.alert-success {
|
55
|
+
color: #155724;
|
56
|
+
background-color: #d4edda;
|
57
|
+
border-color: #c3e6cb;
|
58
|
+
}
|
59
|
+
|
60
|
+
.notification-box {
|
61
|
+
display: flex;
|
62
|
+
flex-direction: column;
|
63
|
+
}
|
64
|
+
|
65
|
+
pre {
|
66
|
+
outline: 1px solid #ccc;
|
67
|
+
padding: 5px;
|
68
|
+
margin: 5px auto;
|
69
|
+
}
|
70
|
+
.string { color: green; }
|
71
|
+
.number { color: darkorange; }
|
72
|
+
.boolean { color: blue; }
|
73
|
+
.null { color: magenta; }
|
74
|
+
.key { color: red; }
|
@@ -0,0 +1,48 @@
|
|
1
|
+
<!DOCTYPE html>
|
2
|
+
<html lang="en">
|
3
|
+
<head>
|
4
|
+
<meta charset="UTF-8">
|
5
|
+
<meta name="viewport" content="width=device-width, initial-scale=1.0">
|
6
|
+
<meta http-equiv="X-UA-Compatible" content="ie=edge">
|
7
|
+
<title>SMS | Home</title>
|
8
|
+
|
9
|
+
<link rel="stylesheet" type="text/css" href="stylesheets/main.css">
|
10
|
+
<script src="scripts/notification.js"></script>
|
11
|
+
</head>
|
12
|
+
<body>
|
13
|
+
<%= erb :alert, locals: locals %>
|
14
|
+
<div class="container">
|
15
|
+
<div class="box solid-background vertically-center">
|
16
|
+
<h2 class="text-center">Send SMS</h2>
|
17
|
+
<form action="/send" method="post">
|
18
|
+
<div class="input-group">
|
19
|
+
<label for="number">Phone number (E164 format)</label>
|
20
|
+
<input type="text" name="number" id="number" placeholder="+12223334444"/>
|
21
|
+
</div>
|
22
|
+
<div class="input-group">
|
23
|
+
<label>Message</label>
|
24
|
+
<input type="text" name="message" id="message" />
|
25
|
+
</div>
|
26
|
+
<button type="submit">Send</button>
|
27
|
+
</form>
|
28
|
+
</div>
|
29
|
+
<div class="box">
|
30
|
+
<form action="/subscribe" method="post">
|
31
|
+
<div class="input-group">
|
32
|
+
<label for="webhook">Webhook host URL(Ref. README for details)</label>
|
33
|
+
<input type="text" name="webhook" id="webhook" />
|
34
|
+
</div>
|
35
|
+
<button type="submit">Subscribe</button>
|
36
|
+
</form>
|
37
|
+
<h2 class="text-center">SMS Notification</h2>
|
38
|
+
<div id="notification" class="notification-box"></div>
|
39
|
+
</div>
|
40
|
+
</div>
|
41
|
+
<script>
|
42
|
+
if (window.smsNotification) {
|
43
|
+
window.smsNotification.render()
|
44
|
+
setInterval(window.smsNotification.render, 5000)
|
45
|
+
}
|
46
|
+
</script>
|
47
|
+
</body>
|
48
|
+
</html>
|
data/lib/cpaas-sdk.rb
ADDED
@@ -0,0 +1,30 @@
|
|
1
|
+
require 'cpaas-sdk/api'
|
2
|
+
require 'cpaas-sdk/config'
|
3
|
+
require 'cpaas-sdk/resources'
|
4
|
+
require 'cpaas-sdk/version'
|
5
|
+
|
6
|
+
module Cpaas
|
7
|
+
class << self
|
8
|
+
attr_accessor :config, :api
|
9
|
+
end
|
10
|
+
|
11
|
+
#
|
12
|
+
# Configure the SDK with client_id and client_secret.
|
13
|
+
#
|
14
|
+
# @param client_id [String] Private project secret
|
15
|
+
# @param client_secret [String] Private project secret
|
16
|
+
# @param base_url [String] JSON URL of the server to be used.
|
17
|
+
#
|
18
|
+
# @example
|
19
|
+
# Cpaas.configure do |config|
|
20
|
+
# config.client_id: '<private project key>',
|
21
|
+
# config.client_secret: '<private project secret>',
|
22
|
+
# config.base_url: '<base url>'
|
23
|
+
# end
|
24
|
+
#
|
25
|
+
def self.configure
|
26
|
+
yield self.config = Cpaas::Config.new
|
27
|
+
|
28
|
+
self.api = Cpaas::Api.new(config)
|
29
|
+
end
|
30
|
+
end
|
@@ -0,0 +1,139 @@
|
|
1
|
+
require 'httparty'
|
2
|
+
require 'jwt'
|
3
|
+
|
4
|
+
require 'cpaas-sdk/util'
|
5
|
+
|
6
|
+
module Cpaas
|
7
|
+
# @private
|
8
|
+
class Api
|
9
|
+
include HTTParty
|
10
|
+
format :json
|
11
|
+
|
12
|
+
attr_accessor :user_id, :client_correlator
|
13
|
+
|
14
|
+
def initialize(config)
|
15
|
+
@client_id = config.client_id
|
16
|
+
@client_secret = config.client_secret
|
17
|
+
@id_token_parsed = nil
|
18
|
+
@access_token = nil
|
19
|
+
self.user_id = nil
|
20
|
+
self.client_correlator = "#{config.client_id}-ruby"
|
21
|
+
|
22
|
+
self.class.base_uri config.base_url
|
23
|
+
|
24
|
+
auth_token
|
25
|
+
end
|
26
|
+
|
27
|
+
def send_request(url, options = {}, verb = :get, with_token = true)
|
28
|
+
body = recursive_compact(options[:body]) if options[:body]
|
29
|
+
options[:headers] = headers(options[:headers] || {}, with_token)
|
30
|
+
options[:body] = body.to_json if options[:headers]['Content-Type'] == 'application/json'
|
31
|
+
options[:query] = options[:query] if options.has_key? :query
|
32
|
+
|
33
|
+
case verb
|
34
|
+
when :get
|
35
|
+
response = self.class.get(url, options)
|
36
|
+
when :post
|
37
|
+
response = self.class.post(url, options)
|
38
|
+
when :put
|
39
|
+
response = self.class.put(url, options)
|
40
|
+
when :delete
|
41
|
+
response = self.class.delete(url, options)
|
42
|
+
else
|
43
|
+
raise 'Invalid Verb'
|
44
|
+
end
|
45
|
+
|
46
|
+
handle_response(response)
|
47
|
+
end
|
48
|
+
|
49
|
+
def handle_response(response)
|
50
|
+
@parsed_response = begin
|
51
|
+
res = convert_hash_keys(response.parsed_response)
|
52
|
+
|
53
|
+
if response.code >= 400 && !res.nil?
|
54
|
+
compose_error_from(res)
|
55
|
+
else
|
56
|
+
res || { status_code: response.code, response: response }
|
57
|
+
end
|
58
|
+
rescue JSON::ParserError => e
|
59
|
+
response.success? ? { message: response.body } : { error: response.body }
|
60
|
+
end
|
61
|
+
end
|
62
|
+
|
63
|
+
def headers(request_headers = {}, with_token = false)
|
64
|
+
base_headers = {
|
65
|
+
'X-Cpaas-Agent' => "ruby-sdk/#{Cpaas::VERSION}",
|
66
|
+
'Content-Type' => 'application/json',
|
67
|
+
'Accept' => '*/*',
|
68
|
+
}.merge(request_headers)
|
69
|
+
|
70
|
+
return base_headers.merge(auth_headers) if with_token
|
71
|
+
|
72
|
+
base_headers
|
73
|
+
end
|
74
|
+
|
75
|
+
def auth_headers
|
76
|
+
{
|
77
|
+
'Authorization' => "Bearer #{auth_token}"
|
78
|
+
}
|
79
|
+
end
|
80
|
+
|
81
|
+
def auth_token
|
82
|
+
set_tokens(get_auth_token) if token_expired
|
83
|
+
|
84
|
+
@access_token
|
85
|
+
end
|
86
|
+
|
87
|
+
def get_auth_token
|
88
|
+
options = {
|
89
|
+
body: {
|
90
|
+
grant_type: 'client_credentials',
|
91
|
+
client_id: @client_id,
|
92
|
+
client_secret: @client_secret,
|
93
|
+
scope: 'openid'
|
94
|
+
},
|
95
|
+
headers: {
|
96
|
+
'Content-Type' => 'application/x-www-form-urlencoded'
|
97
|
+
}
|
98
|
+
}
|
99
|
+
|
100
|
+
response = send_request('/cpaas/auth/v1/token', options, :post , false)
|
101
|
+
|
102
|
+
process_response(response, false)
|
103
|
+
end
|
104
|
+
|
105
|
+
def token_expired
|
106
|
+
return true if @access_token.nil?
|
107
|
+
|
108
|
+
min_buffer = (@token_parsed['exp'] - @token_parsed['iat']) / 2
|
109
|
+
expires_in = @token_parsed['exp'] - Time.now.to_i - min_buffer
|
110
|
+
|
111
|
+
expires_in < 0
|
112
|
+
end
|
113
|
+
|
114
|
+
def set_tokens(tokens)
|
115
|
+
if tokens[:access_token].nil?
|
116
|
+
@access_token = nil
|
117
|
+
@id_token = nil
|
118
|
+
@id_token_parsed = nil
|
119
|
+
@self.user_id = nil
|
120
|
+
else
|
121
|
+
@access_token = tokens[:access_token]
|
122
|
+
@id_token = tokens[:id_token]
|
123
|
+
@id_token_parsed = JWT.decode(tokens[:id_token], nil, false).first
|
124
|
+
@token_parsed = JWT.decode(tokens[:access_token], nil, false).first
|
125
|
+
self.user_id = @id_token_parsed['preferred_username']
|
126
|
+
end
|
127
|
+
end
|
128
|
+
|
129
|
+
def recursive_compact(hash_or_array)
|
130
|
+
p = proc do |*args|
|
131
|
+
v = args.last
|
132
|
+
v.delete_if(&p) if v.respond_to? :delete_if
|
133
|
+
v.nil? || v.respond_to?(:"empty?") && v.empty?
|
134
|
+
end
|
135
|
+
|
136
|
+
hash_or_array.delete_if(&p)
|
137
|
+
end
|
138
|
+
end
|
139
|
+
end
|
@@ -0,0 +1,268 @@
|
|
1
|
+
require 'cpaas-sdk/util'
|
2
|
+
|
3
|
+
module Cpaas
|
4
|
+
|
5
|
+
#
|
6
|
+
# CPaaS conversation.
|
7
|
+
#
|
8
|
+
class Conversation
|
9
|
+
#
|
10
|
+
# Send a new outbound message
|
11
|
+
#
|
12
|
+
# @param params [Hash]
|
13
|
+
# @option params [String] :type Type of conversation. Possible values - 'sms'. Check Conversation.types for more options
|
14
|
+
# @option params [String] :sender_address Sender address information, basically the from address. E164 formatted DID number passed as a value, which is owned by the user. If the user wants to let CPaaS uses the default assigned DID number, this field can either has "default" value or the same value as the userId.
|
15
|
+
# @option params [Array[string]|String] :destination_address
|
16
|
+
# @option params [String] :message text message
|
17
|
+
#
|
18
|
+
def self.create_message(params)
|
19
|
+
if params[:type] == types[:SMS]
|
20
|
+
address = (params[:destination_address].is_a? String) ? [ params[:destination_address] ] : params[:destination_address]
|
21
|
+
|
22
|
+
options = {
|
23
|
+
body: {
|
24
|
+
outboundSMSMessageRequest: {
|
25
|
+
address: address,
|
26
|
+
clientCorrelator: Cpaas.api.client_correlator,
|
27
|
+
outboundSMSTextMessage: {
|
28
|
+
message: params[:message]
|
29
|
+
}
|
30
|
+
}
|
31
|
+
}
|
32
|
+
}
|
33
|
+
|
34
|
+
response = Cpaas.api.send_request("#{base_url}/outbound/#{params[:sender_address]}/requests", options, :post)
|
35
|
+
process_response(response) do |res|
|
36
|
+
outboundSMS = res.dig(:outbound_sms_message_request)
|
37
|
+
|
38
|
+
{
|
39
|
+
message: outboundSMS.dig(:outbound_sms_text_message, :message),
|
40
|
+
senderAddress: outboundSMS.dig(:sender_address),
|
41
|
+
deliveryInfo: outboundSMS.dig(:delivery_info_list, :delivery_info)
|
42
|
+
}
|
43
|
+
end
|
44
|
+
end
|
45
|
+
end
|
46
|
+
|
47
|
+
#
|
48
|
+
# Gets all messages.
|
49
|
+
#
|
50
|
+
# @param params [Hash]
|
51
|
+
# @option params [String] :type Type of conversation. Possible values - 'sms'. Check Conversation.types for more options
|
52
|
+
# @option params [String] :remote_address +optional+ Remote address information while retrieving the conversation history, basically the destination telephone number that user exchanged message before. E164 formatted DID number passed as a value.
|
53
|
+
# @option params [String] :local_address +optional+ Local address information while retrieving the conversation history, basically the source telephone number that user exchanged message before.
|
54
|
+
# @option params [String] :query[:name] +optional+ - Performs search operation on firstName and lastName fields.
|
55
|
+
# @option params [String] :query[:first_name] +optional+ - Performs search for the first_name field of the directory items.
|
56
|
+
# @option params [String] :query[:last_name] +optional+ - Performs search for the last_name field of the directory items.
|
57
|
+
# @option params [String] :query[:user_name] +optional+ - Performs search for the user_name field of the directory items.
|
58
|
+
# @option params [String] :query[:phone_number] +optional+ - Performs search for the fields containing a phone number, like businessPhoneNumber, homePhoneNumber, mobile, pager, fax.
|
59
|
+
# @option params [String] :query[:order] +optional+ - Ordering the contact results based on the requested sortBy value, order query parameter should be accompanied by sortBy query parameter.
|
60
|
+
# @option params [String] :query[:sort_by] +optional+ - sort_by value is used to detect sorting the contact results based on which attribute. If order is not provided with that, ascending order is used.
|
61
|
+
# @option params [Number] :query[:max] +optional+ - Maximum number of contact results that has been requested from CPaaS for this query.
|
62
|
+
# @option params [String] :query[:next] +optional+ - Pointer for the next chunk of contacts, should be gathered from the previous query results.
|
63
|
+
#
|
64
|
+
def self.get_messages(params)
|
65
|
+
if params[:type] == types[:SMS]
|
66
|
+
options = {
|
67
|
+
query: params[:query]
|
68
|
+
}
|
69
|
+
|
70
|
+
url = "#{base_url}/remoteAddresses"
|
71
|
+
url += "/#{params[:remote_address]}" if params[:remote_address]
|
72
|
+
url += "/localAddresses/#{params[:local_address]}" if params[:local_address]
|
73
|
+
|
74
|
+
response = Cpaas.api.send_request(url, options)
|
75
|
+
|
76
|
+
process_response(response) do |res|
|
77
|
+
if params[:local_address]
|
78
|
+
res.dig(:sms_thread_list, :sms_thread)
|
79
|
+
.map { |i| reject(l, :resource_url) }
|
80
|
+
else
|
81
|
+
message = res.dig(:sms_thread)
|
82
|
+
reject(message, :resource_url)
|
83
|
+
end
|
84
|
+
end
|
85
|
+
end
|
86
|
+
end
|
87
|
+
|
88
|
+
#
|
89
|
+
# Delete conversation message
|
90
|
+
#
|
91
|
+
# @param params [Hash]
|
92
|
+
# @option params [String] :type Type of conversation. Possible values - 'sms'. Check Conversation.types for more options
|
93
|
+
# @option params [String] :remote_address Remote address information while retrieving the conversation history, basically the destination telephone number that user exchanged message before. E164 formatted DID number passed as a value.
|
94
|
+
# @option params [String] :local_address Local address information while retrieving the conversation history, basically the source telephone number that user exchanged message before.
|
95
|
+
# @option params [String] :message_id +optional+ Identification of the message. If messeageId is not passsed then the conversation thread is deleted with all messages.
|
96
|
+
#
|
97
|
+
def self.delete_message(params)
|
98
|
+
if params[:type] == types[:SMS]
|
99
|
+
url = "#{base_url}/remoteAddresses/#{params[:remote_address]}/localAddresses/#{params[:local_address]}"
|
100
|
+
|
101
|
+
url += "/messages/#{params[:message_id]}" if params[:message_id]
|
102
|
+
|
103
|
+
Cpaas.api.send_request(url, {}, :delete)
|
104
|
+
end
|
105
|
+
end
|
106
|
+
|
107
|
+
#
|
108
|
+
# Read all messages in a thread
|
109
|
+
#
|
110
|
+
# @param params [Hash]
|
111
|
+
# @option params [String] :type Type of conversation. Possible values - 'sms'. Check Conversation.types for more options
|
112
|
+
# @option params [String] :remote_address Remote address information while retrieving the conversation history, basically the destination telephone number that user exchanged message before. E164 formatted DID number passed as a value.
|
113
|
+
# @option params [String] :local_address Local address information while retrieving the conversation history, basically the source telephone number that user exchanged message before.
|
114
|
+
# @option params [String] :query[:next] +optional+ - Pointer for the next page to retrieve for the messages, provided by CPaaS in previous GET response.
|
115
|
+
# @option params [String] :query[:max] +optional+ - Number of messages that is requested from CPaaS.
|
116
|
+
# @option params [String] :query[:new] +optional+ - Filters the messages or threads having messages that are not received by the user yet.
|
117
|
+
# @option params [String] :query[:last_Message_Time] +optional+ - Filters the messages or threads having messages that are sent/received after provided Epoch time
|
118
|
+
#
|
119
|
+
def self.get_messages_in_thread(params)
|
120
|
+
if params[:type] == types[:SMS]
|
121
|
+
options = {
|
122
|
+
query: params[:query]
|
123
|
+
}
|
124
|
+
|
125
|
+
response = Cpaas.api.send_request("#{base_url}/remoteAddresses/#{params[:remote_address]}/localAddresses/#{params[:local_address]}/messages", options)
|
126
|
+
|
127
|
+
process_response(response) do |res|
|
128
|
+
res.dig(:sms_message_list, :sms_message)
|
129
|
+
.map { |m| reject(m, :resource_url) }
|
130
|
+
end
|
131
|
+
end
|
132
|
+
end
|
133
|
+
|
134
|
+
#
|
135
|
+
# Read a conversation message status
|
136
|
+
#
|
137
|
+
# @param params [Hash]
|
138
|
+
# @option params [String] :type Type of conversation. Possible values - 'sms'. Check Conversation.types for more options
|
139
|
+
# @option params [String] :remote_address Remote address information while retrieving the conversation history, basically the destination telephone number that user exchanged message before. E164 formatted DID number passed as a value.
|
140
|
+
# @option params [String] :local_address Local address information while retrieving the conversation history, basically the source telephone number that user exchanged message before.
|
141
|
+
# @option params [String] :message_id Identification of the message. If messeageId is not passsed then the conversation thread is deleted with all messages.
|
142
|
+
#
|
143
|
+
def self.get_status(params)
|
144
|
+
if params[:type] == types[:SMS]
|
145
|
+
Cpaas.api.send_request("#{base_url}/remoteAddresses/#{params[:remote_address]}/localAddresses/#{params[:local_address]}/messages/#{params[:message_id]}/status")
|
146
|
+
end
|
147
|
+
end
|
148
|
+
|
149
|
+
#
|
150
|
+
# Read all active subscriptions
|
151
|
+
#
|
152
|
+
# @option params [String] :type Type of conversation. Possible values - 'sms'. Check Conversation.types for more options
|
153
|
+
#
|
154
|
+
|
155
|
+
def self.get_subscriptions(params)
|
156
|
+
if params[:type] == types[:SMS]
|
157
|
+
response = Cpaas.api.send_request("#{base_url}/inbound/subscriptions")
|
158
|
+
|
159
|
+
process_response(response) do |res|
|
160
|
+
res.dig(:subscription_list, :subscription)
|
161
|
+
.map do |subscriptions|
|
162
|
+
{
|
163
|
+
notify_url: subscription.dig(:callback_reference, :notify_url),
|
164
|
+
destination_address: subscription.dig(:destination_address),
|
165
|
+
subscription_id: id_from(subscription.dig(:resource_url))
|
166
|
+
}
|
167
|
+
end
|
168
|
+
end
|
169
|
+
end
|
170
|
+
end
|
171
|
+
|
172
|
+
#
|
173
|
+
# Read active subscription
|
174
|
+
#
|
175
|
+
# @param params [Hash]
|
176
|
+
# @option params [String] :type Type of conversation. Possible values - 'sms'. Check Conversation.types for more options
|
177
|
+
# @option params [String] :subscription_id Resource ID of the subscription
|
178
|
+
#
|
179
|
+
def self.get_subscription(params)
|
180
|
+
if params[:type] == types[:SMS]
|
181
|
+
response = Cpaas.api.send_request("#{base_url}/inbound/subscriptions/#{params[:subscription_id]}")
|
182
|
+
|
183
|
+
process_response(response) do |res|
|
184
|
+
subscription = res.dig(:subscription)
|
185
|
+
|
186
|
+
{
|
187
|
+
notify_url: subscription.dig(:callback_reference, :notify_url),
|
188
|
+
destination_address: subscription.dig(:destination_address),
|
189
|
+
subscription_id: id_from(subscription.dig(:resource_url))
|
190
|
+
}
|
191
|
+
end
|
192
|
+
end
|
193
|
+
end
|
194
|
+
|
195
|
+
#
|
196
|
+
# Create a new subscription
|
197
|
+
#
|
198
|
+
# @param params [Hash]
|
199
|
+
# @option params [String] :type Type of conversation. Possible values - 'sms'. Check Conversation.types for more options
|
200
|
+
# @option params [String] :webhook_url The notification channel ID that has been acquired during /notificationchannel API subscription, either websockets, mobile push or webhooks type, which the incoming notifications supposed to be sent to.
|
201
|
+
# @option params [String] :destination_address +optional+ The address that incoming messages are received for this subscription. If does not exist, CPaaS uses the default assigned DID number to subscribe against. It is suggested to provide the intended E164 formatted DID number within this parameter.
|
202
|
+
#
|
203
|
+
|
204
|
+
def self.subscribe(params)
|
205
|
+
if params[:type] == types[:SMS]
|
206
|
+
channel = Cpaas::NotificationChannel.create_channel(webhook_url: params[:webhook_url])
|
207
|
+
|
208
|
+
return channel if !channel.dig(:exception_id).nil?
|
209
|
+
|
210
|
+
options = {
|
211
|
+
body: {
|
212
|
+
subscription: {
|
213
|
+
callbackReference: {
|
214
|
+
notifyURL: channel[:channel_id]
|
215
|
+
},
|
216
|
+
clientCorrelator: Cpaas.api.client_correlator,
|
217
|
+
destinationAddress: params[:destination_address]
|
218
|
+
}
|
219
|
+
}
|
220
|
+
}
|
221
|
+
|
222
|
+
response = Cpaas.api.send_request("#{base_url}/inbound/subscriptions", options, :post)
|
223
|
+
|
224
|
+
process_response(response) do |res|
|
225
|
+
{
|
226
|
+
webhook_url: params[:webhook_url],
|
227
|
+
destination_address: response.dig(:subscription, :destination_address),
|
228
|
+
subscription_id: id_from(response.dig(:subscription, :resource_url))
|
229
|
+
}
|
230
|
+
end
|
231
|
+
end
|
232
|
+
end
|
233
|
+
|
234
|
+
#
|
235
|
+
# Unsubscription from conversation notification
|
236
|
+
#
|
237
|
+
# @param params [Hash]
|
238
|
+
# @option params [String] :subscription_id Resource ID of the subscription.
|
239
|
+
#
|
240
|
+
|
241
|
+
def self.unsubscribe(params = {})
|
242
|
+
if params[:type] == types[:SMS]
|
243
|
+
response = Cpaas.api.send_request("#{base_url}/inbound/subscriptions/#{params[:subscription_id]}", {}, :delete)
|
244
|
+
|
245
|
+
process_response(response) do |res|
|
246
|
+
{
|
247
|
+
subscription_id: params[:subscription_id],
|
248
|
+
success: true,
|
249
|
+
message: "Unsubscribed from #{params[:type]} conversation notification"
|
250
|
+
}
|
251
|
+
end
|
252
|
+
end
|
253
|
+
end
|
254
|
+
|
255
|
+
# @private
|
256
|
+
def self.types
|
257
|
+
{
|
258
|
+
SMS: 'sms'
|
259
|
+
}
|
260
|
+
end
|
261
|
+
|
262
|
+
private
|
263
|
+
|
264
|
+
def self.base_url
|
265
|
+
"/cpaas/smsmessaging/v1/#{Cpaas.api.user_id}"
|
266
|
+
end
|
267
|
+
end
|
268
|
+
end
|