-
Notifications
You must be signed in to change notification settings - Fork 0
/
int-send_sms.php
372 lines (328 loc) · 12.5 KB
/
int-send_sms.php
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
<?php
/*
* Requirements: your PHP installation needs cUrl support, which not all PHP installations
* include by default.
*
* Simply substitute your own username, password and phone number
* below, and run the test code:
*/
$username = 'KushalNaresh';
$password = 'kush@123';
/*
* Your phone number, including country code, i.e. +44123123123 in this case:
*/
$msisdn = '+94768526186';
/*
* Please see the FAQ regarding HTTPS (port 443) and HTTP (port 80/5567)
*/
$url = 'https://bulksms.vsms.net/eapi/submission/send_sms/2/2.0';
/*
* A 7-bit GSM SMS message can contain up to 160 characters (longer messages can be
* achieved using concatenation).
*
* All non-alphanumeric 7-bit GSM characters are included in this example. Note that Greek characters,
* and extended GSM characters (e.g. the caret "^"), may not be supported
* to all networks. Please let us know if you require support for any characters that
* do not appear to work to your network.
*/
//$seven_bit_msg = "Test message: all non-alphanumeric GSM characters: $@!\"#%&,;:<>¡£¤¥§¿ÄÅÆÇÉÑÖØÜßàèéùìòå¿äöñüà\nGreek: ΩΘΔΦΓΛΩΠΨΣΘΞ";
/*
* A Unicode SMS can contain only 70 characters. Any Unicode character can be sent,
* including those GSM and accented ISO-8859 European characters that are not
* catered for by the GSM character set, but note that mobile phones are only able
* to display certain Unicode characters, based on their geographic market.
* Nonetheless, every mobile phone should be able to display at least the text
* "Unicode test message:" from the test message below. Your browser may be able to
* display more of the characters than your phone. The text of the message below is:
*/
$unicode_msg = "Unicode test message: ☺ \nArabic: شصض\nChinese: 本网";
/*
* There are a number of 8 bit messages that one can send to a handset, the most popular of the lot is Service Indication(Wap Push).
* Some other popular ones are vCards and vCalendars, headers may vary depending on which of message one opts to send.
* The User Data Header(UDH) is solely responsible for determining which
* type of messages will be sent to one's handset.
* In a nutshell, SI(service indication) messages will have, in the final message body, both the UDH
* and WSP(Wireless Session Protocol) appended to each other forming a prefix of the ASCII string of the Hex value
* of the actual content. For example, suppose our intended Wap message body is as follows:
*
* <si><indication href="http://www.bulksms.com">Visit BulkSMS.com homepage</indication></si>
*
* Our headers will be -- UDH + WSP = FINAL_HEADER
* '0605040B8423F0' + 'DC0601AE' = '0605040B8423F0DC0601AE'
*
* The UDH contains a destination port(0B84) and the origin port(23F0)
* the WSP is broken down into the following:
*
* DC - Transaction ID (used to associate PDUs)
* 06 - PDU type (push PDU)
* 01 - HeadersLen (total of content-type and headers, i.e. zero headers)
* AE - Content Type: application/vnd.wap.sic
*
* For this example our 8 bit message(what becomes our Wap Push) will look like this:
* $msg = '0605040B8423F0DC0601AE02056a0045c60d0362756c6b736d732e636f6d00010356697369742042756c6b534d532e636f6d20686f6d6570616765000101';
*
* You will only get UDH for both vCard and vCalendar type of 8 bit messages and no WSP, which will look something to this effect:
* '06050423F4000'
*
* In order to convert an xml document into its binary representation (wbxml), one would need to install a wbxml library (libwbxml)
* Once that has been successfully achieved, that binary representation will then be finally converted into its hexadecimal value
* in order to complete the transaction. With that done, the appropriate headers are then appended to this hex string to complete
* the Wap Push/8-bit messaging
*
* $eight_bit_msg = get_headers( $msg_type ) . xml_to_wbxml( $msg_body );
* get_headers(...) function commented out. uncomment when you use it.
* $msg_type = 'wap_push';
* $msg_body = '<si><indication href="http://www.bulksms.com">Visit BulkSMS.com homepage</indication></si>';
*/
//$eight_bit_msg = '0605040B8423F0DC0601AE02056a0045c60d0362756c6b736d732e636f6d00010356697369742042756c6b534d532e636f6d20686f6d6570616765000101';
/*
* These error codes will be retried if encountered. For your final application,
* you may wish to include statuses such as "25: You do not have sufficient credits"
* in this list, and notify yourself upon such errors. However, if you are writing a
* simple application which does no queueing (e.g. a Web page where a user simply
* POSTs a form back to the page that will send the message), then you should not
* add anything to this list (perhaps even removing the item below), and rather just
* display an error to your user immediately.
*/
$transient_errors = array(
40 => 1 # Temporarily unavailable
);
/*
* Sending 7-bit message
*/
/*$post_body = seven_bit_sms( $username, $password, $seven_bit_msg, $msisdn );
$result = send_message( $post_body, $url );
if( $result['success'] ) {
print_ln( formatted_server_response( $result ) );
}
else {
print_ln( formatted_server_response( $result ) );
}
*/
/*
* Sending unicode message
*/
$post_body = unicode_sms( $username, $password, $unicode_msg, $msisdn );
$result = send_message( $post_body, $url );
if( $result['success'] ) {
print_ln( formatted_server_response( $result ) );
}
else {
print_ln( formatted_server_response( $result ) );
}
/*
* Sending 8-bit message
*/
/*$post_body = eight_bit_sms( $username, $password, $eight_bit_msg, $msisdn );
$result = send_message( $post_body, $url );
if( $result['success'] ) {
print_ln( formatted_server_response( $result ) );
}
else {
print_ln( formatted_server_response( $result ) );
}
*/
/*
* If you don't see this, and no errors appeared to screen, you should
* check your Web server's error logs for error output:
*/
print_ln("Script ran to completion");
function print_ln($content) {
if (isset($_SERVER["SERVER_NAME"])) {
print $content."<br />";
}
else {
print $content."\n";
}
}
function formatted_server_response( $result ) {
$this_result = "";
if ($result['success']) {
$this_result .= "Success: batch ID " .$result['api_batch_id']. "API message: ".$result['api_message']. "\nFull details " .$result['details'];
}
else {
$this_result .= "Fatal error: HTTP status " .$result['http_status_code']. ", API status " .$result['api_status_code']. " API message " .$result['api_message']. " full details " .$result['details'];
if ($result['transient_error']) {
$this_result .= "This is a transient error - you should retry it in a production environment";
}
}
return $this_result;
}
function send_message ( $post_body, $url ) {
/*
* Do not supply $post_fields directly as an argument to CURLOPT_POSTFIELDS,
* despite what the PHP documentation suggests: cUrl will turn it into in a
* multipart formpost, which is not supported:
*/
$ch = curl_init( );
curl_setopt ( $ch, CURLOPT_URL, $url );
curl_setopt ( $ch, CURLOPT_POST, 1 );
curl_setopt ( $ch, CURLOPT_RETURNTRANSFER, 1 );
curl_setopt ( $ch, CURLOPT_POSTFIELDS, $post_body );
// Allowing cUrl funtions 20 second to execute
curl_setopt ( $ch, CURLOPT_TIMEOUT, 20 );
// Waiting 20 seconds while trying to connect
curl_setopt ( $ch, CURLOPT_CONNECTTIMEOUT, 20 );
$response_string = curl_exec( $ch );
$curl_info = curl_getinfo( $ch );
$sms_result = array();
$sms_result['success'] = 0;
$sms_result['details'] = '';
$sms_result['transient_error'] = 0;
$sms_result['http_status_code'] = $curl_info['http_code'];
$sms_result['api_status_code'] = '';
$sms_result['api_message'] = '';
$sms_result['api_batch_id'] = '';
if ( $response_string == FALSE ) {
$sms_result['details'] .= "cURL error: " . curl_error( $ch ) . "\n";
} elseif ( $curl_info[ 'http_code' ] != 200 ) {
$sms_result['transient_error'] = 1;
$sms_result['details'] .= "Error: non-200 HTTP status code: " . $curl_info[ 'http_code' ] . "\n";
}
else {
$sms_result['details'] .= "Response from server: $response_string\n";
$api_result = explode( '|', $response_string );
$status_code = $api_result[0];
$sms_result['api_status_code'] = $status_code;
$sms_result['api_message'] = $api_result[1];
if ( count( $api_result ) != 3 ) {
$sms_result['details'] .= "Error: could not parse valid return data from server.\n" . count( $api_result );
} else {
if ($status_code == '0') {
$sms_result['success'] = 1;
$sms_result['api_batch_id'] = $api_result[2];
$sms_result['details'] .= "Message sent - batch ID $api_result[2]\n";
}
else if ($status_code == '1') {
# Success: scheduled for later sending.
$sms_result['success'] = 1;
$sms_result['api_batch_id'] = $api_result[2];
}
else {
$sms_result['details'] .= "Error sending: status code [$api_result[0]] description [$api_result[1]]\n";
}
}
}
curl_close( $ch );
return $sms_result;
}
function seven_bit_sms ( $username, $password, $message, $msisdn ) {
$post_fields = array (
'username' => $username,
'password' => $password,
'message' => character_resolve( $message ),
'msisdn' => $msisdn,
'allow_concat_text_sms' => 0, # Change to 1 to enable long messages
'concat_text_sms_max_parts' => 2
);
return make_post_body($post_fields);
}
function unicode_sms ( $username, $password, $message, $msisdn ) {
$post_fields = array (
'username' => $username,
'password' => $password,
'message' => string_to_utf16_hex( $message ),
'msisdn' => $msisdn,
'dca' => '16bit'
);
return make_post_body($post_fields);
}
/*
function get_headers ( $msg_type ) {
if( $msg_type == 'wap_push' ) {
$udh = '0605040B8423F0';
$wsp = 'DC0601AE';
return $udh . $wsp;
}
else if( $msg_type == 'vCard' || $msg_type == 'vCalendar' ) {
return '06050423F40000';
}
}
*/
function eight_bit_sms( $username, $password, $message, $msisdn ) {
$post_fields = array (
'username' => $username,
'password' => $password,
'message' => $message,
'msisdn' => $msisdn,
'dca' => '8bit'
);
return make_post_body($post_fields);
}
function make_post_body($post_fields) {
$stop_dup_id = make_stop_dup_id();
if ($stop_dup_id > 0) {
$post_fields['stop_dup_id'] = make_stop_dup_id();
}
$post_body = '';
foreach( $post_fields as $key => $value ) {
$post_body .= urlencode( $key ).'='.urlencode( $value ).'&';
}
$post_body = rtrim( $post_body,'&' );
return $post_body;
}
function character_resolve($body) {
$special_chrs = array(
'Δ'=>'0xD0', 'Φ'=>'0xDE', 'Γ'=>'0xAC', 'Λ'=>'0xC2', 'Ω'=>'0xDB',
'Π'=>'0xBA', 'Ψ'=>'0xDD', 'Σ'=>'0xCA', 'Θ'=>'0xD4', 'Ξ'=>'0xB1',
'¡'=>'0xA1', '£'=>'0xA3', '¤'=>'0xA4', '¥'=>'0xA5', '§'=>'0xA7',
'¿'=>'0xBF', 'Ä'=>'0xC4', 'Å'=>'0xC5', 'Æ'=>'0xC6', 'Ç'=>'0xC7',
'É'=>'0xC9', 'Ñ'=>'0xD1', 'Ö'=>'0xD6', 'Ø'=>'0xD8', 'Ü'=>'0xDC',
'ß'=>'0xDF', 'à'=>'0xE0', 'ä'=>'0xE4', 'å'=>'0xE5', 'æ'=>'0xE6',
'è'=>'0xE8', 'é'=>'0xE9', 'ì'=>'0xEC', 'ñ'=>'0xF1', 'ò'=>'0xF2',
'ö'=>'0xF6', 'ø'=>'0xF8', 'ù'=>'0xF9', 'ü'=>'0xFC',
);
$ret_msg = '';
if( mb_detect_encoding($body, 'UTF-8') != 'UTF-8' ) {
$body = utf8_encode($body);
}
for ( $i = 0; $i < mb_strlen( $body, 'UTF-8' ); $i++ ) {
$c = mb_substr( $body, $i, 1, 'UTF-8' );
if( isset( $special_chrs[ $c ] ) ) {
$ret_msg .= chr( $special_chrs[ $c ] );
}
else {
$ret_msg .= $c;
}
}
return $ret_msg;
}
/*
* Unique ID to eliminate duplicates in case of network timeouts - see
* EAPI documentation for more. You may want to use a database primary
* key. Warning: sending two different messages with the same
* ID will result in the second being ignored!
*
* Don't use a timestamp - for instance, your application may be able
* to generate multiple messages with the same ID within a second, or
* part thereof.
*
* You can't simply use an incrementing counter, if there's a chance that
* the counter will be reset.
*/
function make_stop_dup_id() {
return 0;
}
function string_to_utf16_hex( $string ) {
return bin2hex(mb_convert_encoding($string, "UTF-16", "UTF-8"));
}
function xml_to_wbxml( $msg_body ) {
$wbxmlfile = 'xml2wbxml_'.md5(uniqid(time())).'.wbxml';
$xmlfile = 'xml2wbxml_'.md5(uniqid(time())).'.xml';
//create temp file
$fp = fopen($xmlfile, 'w+');
fwrite($fp, $msg_body);
fclose($fp);
//convert temp file
exec(xml2wbxml.' -v 1.2 -o '.$wbxmlfile.' '.$xmlfile.' 2>/dev/null');
if(!file_exists($wbxmlfile)) {
print_ln('Fatal error: xml2wbxml conversion failed');
return false;
}
$wbxml = trim(file_get_contents($wbxmlfile));
//remove temp files
unlink($xmlfile);
unlink($wbxmlfile);
return $wbxml;
}
?>