infobipapi 0.5.0

Sign up to get free protection for your applications and to get access to all the features.
checksums.yaml ADDED
@@ -0,0 +1,7 @@
1
+ ---
2
+ SHA1:
3
+ metadata.gz: 5408b6cf03a955f7d2b6ccff2c966f35f46a27cb
4
+ data.tar.gz: 3c2ccc52b0abf714eaae7a5f6cacf34798503374
5
+ SHA512:
6
+ metadata.gz: 633f8626eee9419a045246575fa143a9ec76eff7d256b0f1e972685be4f5ba5a19f5165cfb00ac1c1f2b554324617641a62bbd99e1dbd2f2a1f27c79a8851e8b
7
+ data.tar.gz: 46ba2eb544776043b0c636c801ae47e9025c1ac65dd6a74f30a82fab603902513f750db2ec4589ab424fd017ce019ac0eaf069e837bd9a5da3657676d85ca4bf
data/.gitignore ADDED
@@ -0,0 +1,24 @@
1
+ *.gem
2
+ *.rbc
3
+ .bundle
4
+ .config
5
+ .yardoc
6
+ Gemfile.lock
7
+ InstalledFiles
8
+ _yardoc
9
+ coverage
10
+ doc/
11
+ lib/bundler/man
12
+ pkg
13
+ rdoc
14
+ spec/reports
15
+ test/tmp
16
+ test/version_tmp
17
+ tmp
18
+ pkg
19
+ *.iml
20
+ *.ipr
21
+ *.iws
22
+ .idea
23
+ test-numbers.txt
24
+ vendor/bundle
data/Gemfile ADDED
@@ -0,0 +1,4 @@
1
+ source 'https://rubygems.org'
2
+
3
+ # Specify your gem's dependencies in infobip.gemspec
4
+ gemspec
data/LICENSE.txt ADDED
@@ -0,0 +1,202 @@
1
+
2
+ Apache License
3
+ Version 2.0, January 2004
4
+ http://www.apache.org/licenses/
5
+
6
+ TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION
7
+
8
+ 1. Definitions.
9
+
10
+ "License" shall mean the terms and conditions for use, reproduction,
11
+ and distribution as defined by Sections 1 through 9 of this document.
12
+
13
+ "Licensor" shall mean the copyright owner or entity authorized by
14
+ the copyright owner that is granting the License.
15
+
16
+ "Legal Entity" shall mean the union of the acting entity and all
17
+ other entities that control, are controlled by, or are under common
18
+ control with that entity. For the purposes of this definition,
19
+ "control" means (i) the power, direct or indirect, to cause the
20
+ direction or management of such entity, whether by contract or
21
+ otherwise, or (ii) ownership of fifty percent (50%) or more of the
22
+ outstanding shares, or (iii) beneficial ownership of such entity.
23
+
24
+ "You" (or "Your") shall mean an individual or Legal Entity
25
+ exercising permissions granted by this License.
26
+
27
+ "Source" form shall mean the preferred form for making modifications,
28
+ including but not limited to software source code, documentation
29
+ source, and configuration files.
30
+
31
+ "Object" form shall mean any form resulting from mechanical
32
+ transformation or translation of a Source form, including but
33
+ not limited to compiled object code, generated documentation,
34
+ and conversions to other media types.
35
+
36
+ "Work" shall mean the work of authorship, whether in Source or
37
+ Object form, made available under the License, as indicated by a
38
+ copyright notice that is included in or attached to the work
39
+ (an example is provided in the Appendix below).
40
+
41
+ "Derivative Works" shall mean any work, whether in Source or Object
42
+ form, that is based on (or derived from) the Work and for which the
43
+ editorial revisions, annotations, elaborations, or other modifications
44
+ represent, as a whole, an original work of authorship. For the purposes
45
+ of this License, Derivative Works shall not include works that remain
46
+ separable from, or merely link (or bind by name) to the interfaces of,
47
+ the Work and Derivative Works thereof.
48
+
49
+ "Contribution" shall mean any work of authorship, including
50
+ the original version of the Work and any modifications or additions
51
+ to that Work or Derivative Works thereof, that is intentionally
52
+ submitted to Licensor for inclusion in the Work by the copyright owner
53
+ or by an individual or Legal Entity authorized to submit on behalf of
54
+ the copyright owner. For the purposes of this definition, "submitted"
55
+ means any form of electronic, verbal, or written communication sent
56
+ to the Licensor or its representatives, including but not limited to
57
+ communication on electronic mailing lists, source code control systems,
58
+ and issue tracking systems that are managed by, or on behalf of, the
59
+ Licensor for the purpose of discussing and improving the Work, but
60
+ excluding communication that is conspicuously marked or otherwise
61
+ designated in writing by the copyright owner as "Not a Contribution."
62
+
63
+ "Contributor" shall mean Licensor and any individual or Legal Entity
64
+ on behalf of whom a Contribution has been received by Licensor and
65
+ subsequently incorporated within the Work.
66
+
67
+ 2. Grant of Copyright License. Subject to the terms and conditions of
68
+ this License, each Contributor hereby grants to You a perpetual,
69
+ worldwide, non-exclusive, no-charge, royalty-free, irrevocable
70
+ copyright license to reproduce, prepare Derivative Works of,
71
+ publicly display, publicly perform, sublicense, and distribute the
72
+ Work and such Derivative Works in Source or Object form.
73
+
74
+ 3. Grant of Patent License. Subject to the terms and conditions of
75
+ this License, each Contributor hereby grants to You a perpetual,
76
+ worldwide, non-exclusive, no-charge, royalty-free, irrevocable
77
+ (except as stated in this section) patent license to make, have made,
78
+ use, offer to sell, sell, import, and otherwise transfer the Work,
79
+ where such license applies only to those patent claims licensable
80
+ by such Contributor that are necessarily infringed by their
81
+ Contribution(s) alone or by combination of their Contribution(s)
82
+ with the Work to which such Contribution(s) was submitted. If You
83
+ institute patent litigation against any entity (including a
84
+ cross-claim or counterclaim in a lawsuit) alleging that the Work
85
+ or a Contribution incorporated within the Work constitutes direct
86
+ or contributory patent infringement, then any patent licenses
87
+ granted to You under this License for that Work shall terminate
88
+ as of the date such litigation is filed.
89
+
90
+ 4. Redistribution. You may reproduce and distribute copies of the
91
+ Work or Derivative Works thereof in any medium, with or without
92
+ modifications, and in Source or Object form, provided that You
93
+ meet the following conditions:
94
+
95
+ (a) You must give any other recipients of the Work or
96
+ Derivative Works a copy of this License; and
97
+
98
+ (b) You must cause any modified files to carry prominent notices
99
+ stating that You changed the files; and
100
+
101
+ (c) You must retain, in the Source form of any Derivative Works
102
+ that You distribute, all copyright, patent, trademark, and
103
+ attribution notices from the Source form of the Work,
104
+ excluding those notices that do not pertain to any part of
105
+ the Derivative Works; and
106
+
107
+ (d) If the Work includes a "NOTICE" text file as part of its
108
+ distribution, then any Derivative Works that You distribute must
109
+ include a readable copy of the attribution notices contained
110
+ within such NOTICE file, excluding those notices that do not
111
+ pertain to any part of the Derivative Works, in at least one
112
+ of the following places: within a NOTICE text file distributed
113
+ as part of the Derivative Works; within the Source form or
114
+ documentation, if provided along with the Derivative Works; or,
115
+ within a display generated by the Derivative Works, if and
116
+ wherever such third-party notices normally appear. The contents
117
+ of the NOTICE file are for informational purposes only and
118
+ do not modify the License. You may add Your own attribution
119
+ notices within Derivative Works that You distribute, alongside
120
+ or as an addendum to the NOTICE text from the Work, provided
121
+ that such additional attribution notices cannot be construed
122
+ as modifying the License.
123
+
124
+ You may add Your own copyright statement to Your modifications and
125
+ may provide additional or different license terms and conditions
126
+ for use, reproduction, or distribution of Your modifications, or
127
+ for any such Derivative Works as a whole, provided Your use,
128
+ reproduction, and distribution of the Work otherwise complies with
129
+ the conditions stated in this License.
130
+
131
+ 5. Submission of Contributions. Unless You explicitly state otherwise,
132
+ any Contribution intentionally submitted for inclusion in the Work
133
+ by You to the Licensor shall be under the terms and conditions of
134
+ this License, without any additional terms or conditions.
135
+ Notwithstanding the above, nothing herein shall supersede or modify
136
+ the terms of any separate license agreement you may have executed
137
+ with Licensor regarding such Contributions.
138
+
139
+ 6. Trademarks. This License does not grant permission to use the trade
140
+ names, trademarks, service marks, or product names of the Licensor,
141
+ except as required for reasonable and customary use in describing the
142
+ origin of the Work and reproducing the content of the NOTICE file.
143
+
144
+ 7. Disclaimer of Warranty. Unless required by applicable law or
145
+ agreed to in writing, Licensor provides the Work (and each
146
+ Contributor provides its Contributions) on an "AS IS" BASIS,
147
+ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or
148
+ implied, including, without limitation, any warranties or conditions
149
+ of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A
150
+ PARTICULAR PURPOSE. You are solely responsible for determining the
151
+ appropriateness of using or redistributing the Work and assume any
152
+ risks associated with Your exercise of permissions under this License.
153
+
154
+ 8. Limitation of Liability. In no event and under no legal theory,
155
+ whether in tort (including negligence), contract, or otherwise,
156
+ unless required by applicable law (such as deliberate and grossly
157
+ negligent acts) or agreed to in writing, shall any Contributor be
158
+ liable to You for damages, including any direct, indirect, special,
159
+ incidental, or consequential damages of any character arising as a
160
+ result of this License or out of the use or inability to use the
161
+ Work (including but not limited to damages for loss of goodwill,
162
+ work stoppage, computer failure or malfunction, or any and all
163
+ other commercial damages or losses), even if such Contributor
164
+ has been advised of the possibility of such damages.
165
+
166
+ 9. Accepting Warranty or Additional Liability. While redistributing
167
+ the Work or Derivative Works thereof, You may choose to offer,
168
+ and charge a fee for, acceptance of support, warranty, indemnity,
169
+ or other liability obligations and/or rights consistent with this
170
+ License. However, in accepting such obligations, You may act only
171
+ on Your own behalf and on Your sole responsibility, not on behalf
172
+ of any other Contributor, and only if You agree to indemnify,
173
+ defend, and hold each Contributor harmless for any liability
174
+ incurred by, or claims asserted against, such Contributor by reason
175
+ of your accepting any such warranty or additional liability.
176
+
177
+ END OF TERMS AND CONDITIONS
178
+
179
+ APPENDIX: How to apply the Apache License to your work.
180
+
181
+ To apply the Apache License to your work, attach the following
182
+ boilerplate notice, with the fields enclosed by brackets "[]"
183
+ replaced with your own identifying information. (Don't include
184
+ the brackets!) The text should be enclosed in the appropriate
185
+ comment syntax for the file format. We also recommend that a
186
+ file or class name and description of purpose be included on the
187
+ same "printed page" as the copyright notice for easier
188
+ identification within third-party archives.
189
+
190
+ Copyright [2012] [Infobip]
191
+
192
+ Licensed under the Apache License, Version 2.0 (the "License");
193
+ you may not use this file except in compliance with the License.
194
+ You may obtain a copy of the License at
195
+
196
+ http://www.apache.org/licenses/LICENSE-2.0
197
+
198
+ Unless required by applicable law or agreed to in writing, software
199
+ distributed under the License is distributed on an "AS IS" BASIS,
200
+ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
201
+ See the License for the specific language governing permissions and
202
+ limitations under the License.
data/README.md ADDED
@@ -0,0 +1,103 @@
1
+ InfobipApi ruby client
2
+ ============================
3
+
4
+ Basic messaging example
5
+ -----------------------
6
+
7
+ First initialize the messaging client using your username and password:
8
+
9
+ sms_connector = InfobipApi::SmsClient.new(username, password)
10
+
11
+
12
+ An exception will be thrown if your username and/or password are incorrect.
13
+
14
+ Prepare the message:
15
+
16
+ sms = InfobipApi::SMSRequest.new
17
+ sms.sender_address = '38598123456'
18
+ sms.address = destination_address
19
+ sms.message = 'Test message'
20
+ sms.callback_data = 'Any string'
21
+
22
+
23
+ Send the message:
24
+
25
+ result = sms_connector.send_sms(sms)
26
+
27
+ # Store the client correlator to be able to query for the delivery status later:
28
+ client_correlator = result.client_correlator
29
+
30
+
31
+ Later you can query for the delivery status of the message:
32
+
33
+ delivery_status = sms_connector.query_delivery_status(client_correlator)
34
+
35
+
36
+ Possible statuses are: **DeliveredToTerminal**, **DeliveryUncertain**, **DeliveryImpossible**, **MessageWaiting** and **DeliveredToNetwork**.
37
+
38
+ Messaging with notification push example
39
+ -----------------------
40
+
41
+ Same as with the standard messaging example, but when preparing your message:
42
+
43
+ sms = InfobipApi::SMSRequest.new
44
+ sms.sender_address = '38598123456'
45
+ sms.address = '38598123456'
46
+ sms.message = 'Test message'
47
+ sms.callback_data = 'Any string'
48
+ sms.notify_url = "http://#{public_ip_address}:#{port}"
49
+
50
+
51
+ When the delivery notification is pushed to your server as a HTTP POST request, you must process the body of the message with the following code:
52
+
53
+ delivery_info = InfobipApi::SmsClient.unserialize_delivery_status(body)
54
+
55
+
56
+ Sending message with special characters example
57
+ -----------------------
58
+
59
+ If you want to send message with special characters, this is how you prepare your message:
60
+
61
+ #Create Language object
62
+ language = InfobipApi::Language.new
63
+
64
+ #set specific language code
65
+ language.language_code = 'TR'
66
+
67
+ #use single shift table for specific language ('false' or 'true')
68
+ language.use_single_shift = true
69
+
70
+ #use locking shift table for specific language ('false' or 'true')
71
+ language.use_locking_shift = false
72
+
73
+ sms = InfobipApi::SMSRequest.new
74
+ sms.sender_address = '38598123456'
75
+ sms.address = destination_address
76
+ sms.message = 'Some text in Turkish'
77
+ sms.callback_data = 'Any string'
78
+ sms.language = language
79
+
80
+ Currently supported languages (with their language codes) are: `Spanish - "SP"`, `Portuguese - "PT"`, `Turkish - "TR"`.
81
+
82
+
83
+ Testing Library
84
+ ---------------
85
+
86
+ To test the library, run :
87
+
88
+ API_USERNAME="Toto" API_PASSWORD="Titi" bundle exec ruby test/test.rb
89
+
90
+ API_USERNAME and API_PASSWORD must be valid account credentials for the Infobip API. For more information, go to https://dev.infobip.com/docs/getting-started
91
+
92
+ You must also provide a text file containing sms numbers where you can receive messages (one by line) :
93
+
94
+ echo "33123456789" > test-numbers.txt
95
+ echo "33012345678" >> test-numbers.txt
96
+
97
+ These numbers must be in international format (used by the API).
98
+
99
+
100
+ License
101
+ -------
102
+
103
+ This library is licensed under the [Apache License, Version 2.0](http://www.apache.org/licenses/LICENSE-2.0)
@@ -0,0 +1,27 @@
1
+ # coding: utf-8
2
+ lib = File.expand_path('../lib', __FILE__)
3
+ $LOAD_PATH.unshift(lib) unless $LOAD_PATH.include?(lib)
4
+ require 'infobipapi/version'
5
+
6
+ Gem::Specification.new do |spec|
7
+ spec.name = "infobipapi"
8
+ spec.version = InfobipApi::VERSION
9
+ spec.date = "2017-02-08"
10
+ spec.authors = ["Roland Laurès"]
11
+ spec.email = [ "roland.laures@netcat.io"]
12
+ spec.description = %q{InfobipApi}
13
+ spec.summary = %q{InfobipApi Ruby client library}
14
+ spec.homepage = "https://github.com/Gnuside/infobipapi"
15
+ spec.license = "Apache"
16
+
17
+ spec.files = `git ls-files`.split($/)
18
+ spec.executables = spec.files.grep(%r{^bin/}) { |f| File.basename(f) }
19
+ spec.test_files = spec.files.grep(%r{^(test|spec|features)/})
20
+ spec.require_paths = ["lib"]
21
+
22
+ spec.add_development_dependency "bundler", "~> 1.3"
23
+ spec.add_development_dependency "rake", "~> 12"
24
+ spec.add_development_dependency "minitest", "~> 5"
25
+ spec.add_development_dependency "pry-coolline", "~> 0"
26
+ spec.add_development_dependency "pry", "~> 0"
27
+ end
data/lib/infobipapi.rb ADDED
@@ -0,0 +1,10 @@
1
+ # vim: set sw=4 ts=4 et :
2
+
3
+ require "infobipapi/version"
4
+ require "infobipapi/utils"
5
+ require "infobipapi/objects"
6
+ require "infobipapi/models"
7
+ require "infobipapi/client"
8
+
9
+ module InfobipApi
10
+ end
@@ -0,0 +1,394 @@
1
+ # vim: set sw=4 ts=4 et :
2
+
3
+ #require 'pry'
4
+ require 'net/http'
5
+ require 'net/https'
6
+ require "base64"
7
+ require 'json'
8
+ require 'pry'
9
+
10
+ require_relative 'objects'
11
+ require_relative 'models'
12
+
13
+ module InfobipApi
14
+
15
+ class InfobipApiClient
16
+
17
+ def initialize(username, password, base_url=nil)
18
+ @username = username
19
+ @password = password
20
+ if base_url
21
+ @base_url = base_url
22
+ else
23
+ @base_url = 'https://api.infobip.com/'
24
+ end
25
+
26
+ if @base_url[-1, 1] != '/'
27
+ @base_url += '/'
28
+ end
29
+
30
+ @infobipapi_authentication = nil
31
+
32
+ login()
33
+ end
34
+
35
+
36
+ def login()
37
+ params = {
38
+ 'username' => @username,
39
+ 'password' => @password,
40
+ }
41
+
42
+ is_success, result = execute_POST('auth/1/session', params)
43
+
44
+ filled = fill_infobipapi_authentication(result, is_success)
45
+ #puts ""
46
+ #puts "login: #{filled.inspect}"
47
+ return filled
48
+ end
49
+
50
+ def get_or_create_client_correlator(client_correlator=nil)
51
+ if client_correlator
52
+ return client_correlator
53
+ end
54
+
55
+ return Utils.get_random_alphanumeric_string()
56
+ end
57
+
58
+ def prepare_headers(request)
59
+ request["User-Agent"] = "InfobipApi-#{InfobipApi::VERSION}"
60
+ request["Content-Type"] = "application/json"
61
+ if @infobipapi_authentication and @infobipapi_authentication.token
62
+ request['Authorization'] = "IBSSO #{@infobipapi_authentication.token}"
63
+ else
64
+ auth_string = Base64.encode64("#{@username}:#{@password}").strip
65
+ request['Authorization'] = "Basic #{auth_string}"
66
+ end
67
+ end
68
+
69
+ def is_success(response)
70
+ http_code = response.code.to_i
71
+ is_success = 200 <= http_code && http_code < 300
72
+
73
+ is_success
74
+ end
75
+
76
+ def urlencode(params)
77
+ if Utils.empty(params)
78
+ return ''
79
+ end
80
+ if params.instance_of? String
81
+ return URI.encode(params)
82
+ end
83
+ result = ''
84
+ params.each_key do |key|
85
+ if ! Utils.empty(result)
86
+ result += '&'
87
+ end
88
+ result += URI.encode(key.to_s) + '=' + URI.encode(params[key].to_s)
89
+ end
90
+
91
+ return result
92
+ end
93
+
94
+ def execute_GET(url, params=nil)
95
+ execute_request('GET', url, params)
96
+ end
97
+
98
+ def execute_POST(url, params=nil)
99
+ execute_request('POST', url, params)
100
+ end
101
+
102
+ def execute_request(http_method, url, params)
103
+ rest_url = get_rest_url(url)
104
+ uri = URI(URI.encode(rest_url))
105
+
106
+ if Utils.empty(params)
107
+ params = {}
108
+ end
109
+
110
+ if http_method == 'GET'
111
+ request = Net::HTTP::Get.new("#{uri.request_uri}?#{urlencode(params)}")
112
+ elsif http_method == 'POST'
113
+ request = Net::HTTP::Post.new(uri.request_uri)
114
+ #binding.pry if params.has_key?(:binary)
115
+ request.body = params.to_json
116
+ end
117
+
118
+ http = Net::HTTP.new(uri.host, uri.port)
119
+
120
+ use_ssl = rest_url.start_with? "https"
121
+ if use_ssl
122
+ http.use_ssl = true
123
+ http.verify_mode = OpenSSL::SSL::VERIFY_NONE
124
+ end
125
+
126
+ prepare_headers(request)
127
+ response = http.request(request)
128
+
129
+ #puts ""
130
+ #puts "response: #{response.inspect}"
131
+ #puts "body: #{response.body}"
132
+ #puts ""
133
+
134
+ return is_success(response), response.body
135
+ end
136
+
137
+ def get_rest_url(rest_path)
138
+ if not rest_path
139
+ return @base_url
140
+ end
141
+
142
+ if rest_path[0, 1] == '/'
143
+ return @base_url + rest_path[1, rest_path.length]
144
+ end
145
+
146
+ @base_url + rest_path
147
+ end
148
+
149
+ def fill_infobipapi_authentication(json, is_success)
150
+ @infobipapi_authentication = convert_from_json(AuthenticationAnswer, json, !is_success)
151
+
152
+
153
+ @infobipapi_authentication = nil if @infobipapi_authentication.token.nil? \
154
+ || @infobipapi_authentication.token.length == 0
155
+
156
+ @infobipapi_authentication
157
+ end
158
+
159
+ def convert_from_json(classs, json, is_error)
160
+ Conversions.from_json(classs, json, is_error)
161
+ end
162
+
163
+ end
164
+
165
+ class SmsClient < InfobipApiClient
166
+
167
+ def initialize(username, password, base_url=nil)
168
+ super(username, password, base_url)
169
+ end
170
+
171
+ # send single sms message to one or many destination addresses.
172
+ # cf: https://dev.infobip.com/docs/send-single-sms
173
+ # param fields names:
174
+ # - from: string
175
+ # Represents sender ID and it can be alphanumeric or numeric. Alphanumeric sender ID length should be between 3 and 11 characters (Example: CompanyName). Numeric sender ID length should be between 3 and 14 characters.
176
+ # - to: `required` array of strings
177
+ # Array of message destination addresses. If you want to send a message to one destination, a single String is supported instead of an Array. Destination addresses must be in international format (Example: 41793026727).
178
+ # - text: string
179
+ # Text of the message that will be sent.
180
+ # (Developper comment: chars must be 7bits or comportment is not predictable on the receiving phones)
181
+ #
182
+ def single_text_sms(sms)
183
+ params = {
184
+ :from => sms.from,
185
+ :to => sms.to,
186
+ :text => sms.text
187
+ }
188
+ is_success, result = execute_POST( "/sms/1/text/single", params )
189
+
190
+ convert_from_json(SimpleSMSAnswer, result, !is_success)
191
+ end
192
+
193
+ # send multiple sms message to one or many destination addresses.
194
+ # cf: https://dev.infobip.com/docs/send-multiple-sms
195
+ # param fields names, array of :
196
+ # - from: string
197
+ # Represents sender ID and it can be alphanumeric or numeric. Alphanumeric sender ID length should be between 3 and 11 characters (Example: CompanyName). Numeric sender ID length should be between 3 and 14 characters.
198
+ # - to: `required` array of strings
199
+ # Array of message destination addresses. If you want to send a message to one destination, a single String is supported instead of an Array. Destination addresses must be in international format (Example: 41793026727).
200
+ # - text: string
201
+ # Text of the message that will be sent.
202
+ # (Developper comment: chars must be 7bits or comportment is not predictable on the receiving phones)
203
+ #
204
+ def multiple_text_sms(smss)
205
+ params = {
206
+ :messages => []
207
+ }
208
+ smss.each { |sms|
209
+ params[:messages].push({
210
+ :from => sms.from,
211
+ :to => sms.to,
212
+ :text => sms.text
213
+ })
214
+ }
215
+
216
+ is_success, result = execute_POST( "/sms/1/text/multi", params )
217
+
218
+ convert_from_json(SimpleSMSAnswer, result, !is_success)
219
+ end
220
+
221
+ # .codepoints.map { |c| "%02x %02x" % [c / 256,c % 256] }.join " "
222
+
223
+ def compute_sms_usage(str)
224
+ # single SMS length per SMS (GSM7): 160
225
+ # multiple SMS length per SMS (GSM7): 153
226
+ # single SMS length per SMS (UCS-2): 70
227
+ # multiple SMS length per SMS (UCS-2): 67
228
+ sms_lengths = Hash.new
229
+ # ! has_unicode_char
230
+ sms_lengths[false] = Hash.new
231
+ sms_lengths[false][true] = 153 # need_more_than_one_sms
232
+ sms_lengths[false][false] = 160 # ! need_more_than_one_sms
233
+ # has_unicode_char
234
+ sms_lengths[true] = Hash.new
235
+ sms_lengths[true][true] = 67 # need_more_than_one_sms
236
+ sms_lengths[true][false] = 70 # ! need_more_than_one_sms
237
+ {
238
+ :single_gsm7 => 160,
239
+ :multi_gsm7 => 153,
240
+ :single_ucs2 => 70,
241
+ :multi_ucs2 => 67
242
+ }
243
+ has_unicode_char = false
244
+ need_more_than_one_sms = false
245
+ str.each_char { |c|
246
+ if not Utils.in_gsm7_set?(c) then
247
+ has_unicode_char = true
248
+ break
249
+ end
250
+ }
251
+ if has_unicode_char then
252
+ need_more_than_one_sms = str.length > 70
253
+ format = :unicode
254
+ else
255
+ need_more_than_one_sms = str.length > 160
256
+ format = :gsm7
257
+ end
258
+ return {
259
+ :format => format,
260
+ :length => str.length,
261
+ :length_by_sms => sms_lengths[has_unicode_char][need_more_than_one_sms],
262
+ :number_of_sms => (str.length.to_f / sms_lengths[has_unicode_char][need_more_than_one_sms].to_f).ceil
263
+ }
264
+ end
265
+
266
+ # send single sms message to one or many destination addresses.
267
+ # TEXT in UTF-8 format if all chars are gsm7 encoding compatible then
268
+ # the SMS is sent with gsm7 encoding. Else it will be sent in Unicode
269
+ # binary format.
270
+ # cf: https://dev.infobip.com/docs/send-single-sms
271
+ # cf: https://dev.infobip.com/docs/send-single-binary-sms
272
+ # param fields names:
273
+ # - from: string
274
+ # Represents sender ID and it can be alphanumeric or numeric. Alphanumeric sender ID length should be between 3 and 11 characters (Example: CompanyName). Numeric sender ID length should be between 3 and 14 characters.
275
+ # - to: `required` array of strings
276
+ # Array of message destination addresses. If you want to send a message to one destination, a single String is supported instead of an Array. Destination addresses must be in international format (Example: 41793026727).
277
+ # - text: string utf-8 encoded
278
+ # Text of the message that will be sent.
279
+ # (Developper comment: chars must be 7bits or comportment is not predictable on the receiving phones)
280
+ #
281
+ def single_utf8_sms(sms)
282
+ usage = self.compute_sms_usage(sms.text)
283
+ if usage[:format] == :gsm7 then
284
+ params = {
285
+ :from => sms.from,
286
+ :to => sms.to,
287
+ :text => sms.text
288
+ }
289
+ uri = "/sms/1/text/single"
290
+ else
291
+ text_array = sms.text.force_encoding('utf-8').codepoints.map { |c| sprintf('%02x', c) }
292
+ params = {
293
+ :from => sms.from,
294
+ :to => sms.to,
295
+ :binary => {
296
+ :hex => text_array.join(' '),
297
+ :dataCoding => 8,
298
+ :esmClass => 0
299
+ }
300
+ }
301
+ uri = "/sms/1/binary/single"
302
+ end
303
+ is_success, result = execute_POST(uri , params )
304
+ convert_from_json(SimpleSMSAnswer, result, !is_success)
305
+ end
306
+
307
+ # send multiple sms message to one or many destination addresses.
308
+ # TEXT in UTF-8 format if all chars are gsm7 encoding compatible then
309
+ # the SMS is sent with gsm7 encoding. Else it will be sent in Unicode
310
+ # binary format.
311
+ # cf: https://dev.infobip.com/docs/send-multiple-sms
312
+ # param fields names, array of :
313
+ # - from: string
314
+ # Represents sender ID and it can be alphanumeric or numeric. Alphanumeric sender ID length should be between 3 and 11 characters (Example: CompanyName). Numeric sender ID length should be between 3 and 14 characters.
315
+ # - to: `required` array of strings
316
+ # Array of message destination addresses. If you want to send a message to one destination, a single String is supported instead of an Array. Destination addresses must be in international format (Example: 41793026727).
317
+ # - text: string utf-8 encoded
318
+ # Text of the message that will be sent.
319
+ # (Developper comment: chars must be 7bits or comportment is not predictable on the receiving phones)
320
+ #
321
+ # Return an array of 2 results :
322
+ # one for a /sms/1/text/multi query (nil if none is sent as text)
323
+ # second one for a /sms/1/binary/multi query (nil if none is sent as binary)
324
+ def multiple_utf8_sms(smss)
325
+ params = {
326
+ :text => {
327
+ :uri => "/sms/1/text/multi",
328
+ :messages => []
329
+ },
330
+ :binary => {
331
+ :uri => "/sms/1/binary/multi",
332
+ :messages => []
333
+ }
334
+ }
335
+ smss.each { |sms|
336
+ usage = self.compute_sms_usage(sms.text)
337
+ if usage[:format] == :gsm7 then
338
+ params[:text][:messages].push({
339
+ :from => sms.from,
340
+ :to => sms.to,
341
+ :text => sms.text
342
+ })
343
+ else
344
+ text_array = sms.text.force_encoding('utf-8').codepoints.map { |c| sprintf('%02x', c) }
345
+ params[:binary][:messages].push({
346
+ :from => sms.from,
347
+ :to => sms.to,
348
+ :binary => {
349
+ :hex => text_array.join(' '),
350
+ :dataCoding => 8,
351
+ :esmClass => 0
352
+ }
353
+ })
354
+ end
355
+ }
356
+
357
+ results = []
358
+ if params[:text][:messages].length > 0 then
359
+ is_success, result = execute_POST( params[:text][:uri] , params[:text][:messages] )
360
+ results.push(convert_from_json(SimpleSMSAnswer, result, !is_success))
361
+ else
362
+ results.push(nil)
363
+ end
364
+
365
+ if params[:binary][:messages].length > 0 then
366
+ is_success, result = execute_POST( params[:binary][:uri] , params[:binary][:messages] )
367
+ results.push(convert_from_json(SimpleSMSAnswer, result, !is_success))
368
+ else
369
+ results.push(nil)
370
+ end
371
+ return results
372
+ end
373
+
374
+ # Get delivery reports
375
+ # cf: https://dev.infobip.com/docs/delivery-reports
376
+ # parm fields names :
377
+ # - bulkId: string
378
+ # The ID that uniquely identifies the request. Bulk ID will be received only when you send a message to more than one destination address.
379
+ # - messageId: string
380
+ # The ID that uniquely identifies the message sent.
381
+ # - limit: string
382
+ # Number of returned delivery reports. Default value is 50. Max number per request is 10000.
383
+ def delivery_reports(params)
384
+ req = {} # safety parameters treatment
385
+ req[:bulkId] = params[:bulkId] if params.has_key?:bulkId
386
+ req[:messageId] = params[:messageId] if params.has_key?:messageId
387
+ req[:limit] = params[:limit] if params.has_key?:limit
388
+ is_success, result = execute_GET("/sms/1/reports", req)
389
+ convert_from_json(DeliveryReportList,result, !is_success)
390
+ end
391
+ end
392
+
393
+ end
394
+