File Coverage

blib/lib/Net/Clickatell.pm
Criterion Covered Total %
statement 15 140 10.7
branch 0 74 0.0
condition 0 39 0.0
subroutine 5 21 23.8
pod 9 16 56.2
total 29 290 10.0


line stmt bran cond sub pod time code
1             package Net::Clickatell;
2              
3 1     1   7509 use strict;
  1         2  
  1         39  
4 1     1   4 use warnings;
  1         2  
  1         31  
5             #use diagnostics;
6              
7 1     1   56931 use LWP::UserAgent;
  1         69527  
  1         30  
8 1     1   9 use URI::Escape qw(uri_escape);
  1         1  
  1         68  
9 1     1   813 use HTTP::Request::Common;
  1         2014  
  1         1671  
10              
11             # See the bottom of this file for the POD documentation. Search for the
12             # string '=head'.
13              
14             # You can run this file through either pod2man or pod2html to produce pretty
15             # documentation in manual or html file format (these utilities are part of the
16             # Perl 5 distribution).
17              
18             # Copyright (c) 2010 Christopherus Goo. All rights reserved.
19             # It may be used and modified freely, but I do request that this copyright
20             # notice remain attached to the file. You may modify this module as you
21             # wish, but if you redistribute a modified version, please attach a note
22             # listing the modifications you have made.
23              
24             # The most recent version and complete docs are available at:
25             # http://www.artofmobile.com/software/
26              
27             # Clickatell is Copyright (c) 2010 Clickatell (Pty) Ltd: Bulk SMS Gateway
28              
29             #This software or the author aren't related to Clickatell in any way.
30              
31             # November 2010. Singapore.
32              
33             $Net::Clickatell::VERSION=0.5;
34              
35             =head1 NAME
36              
37             Net::Clickatell - Access to Clickatell HTTP API
38              
39             This module support the API from Clickatell's HTTP API Specification v.2.4.1.
40             The following is all the available API and not all are supported
41              
42             Basic Commands
43              
44             http://api.clickatell.com/http/auth Yes (But session not support)
45             http://api.clickatell.com/http/ping Yes (But session not support)
46             http://api.clickatell.com/http/querymsg Yes
47             http://api.clickatell.com/http/sendmsg Yes
48              
49             Additional Commands
50              
51             http://api.clickatell.com/http/delmsg No
52             http://api.clickatell.com/http/getbalance Yes
53             http://api.clickatell.com/http/routeCoverage.php Yes
54             http://api.clickatell.com/mms/ind_push.php Yes
55             http://api.clickatell.com/mms/si_push.php Yes
56             http://api.clickatell.com/http/getmsgcharge Yes
57             http://api.clickatell.com/http/token_pay No
58              
59             Batch Messaging
60              
61             http://api.clickatell.com/http_batch/startbatch No
62             http://api.clickatell.com/http_batch/senditem No
63             http://api.clickatell.com/http_batch/quicksend No
64             http://api.clickatell.com/http_batch/endbatch No
65              
66              
67              
68              
69             =head1 SYNOPSIS
70              
71             =head2 With SSL
72              
73             use Net::Clickatell;
74              
75             my $clickatell = Net::Clickatell->new( API_ID => $api_id, USERNAME =>$username, PASSWORD =>$password );
76             my $bal=$clickatell->getBalance;
77              
78             =head2 Without SSL
79              
80             use Net::Clickatell;
81              
82             my $clickatell = Net::Clickatell->new( UseSSL=>0, API_ID => $api_id, USERNAME =>$username, PASSWORD =>$password );
83             my $bal=$clickatell->getBalance;
84              
85             =head1 DESCRIPTION
86              
87             Clickatell (http://www.clickatell.com) is a commercial service that allows its users to send
88             SMS messages to anyone in the world. This perl module allow users to send SMS, WAP push and
89             MMS through Clickatell HTTP API.
90              
91             Please take note that neither this software nor the author are related to Clickatell in any way.
92              
93             =head1 METHODS
94              
95             =over 4
96              
97             =cut
98             my %status= (
99             "001", "Message unknown. The delivering network did not recognise the message type or content.",
100             "002", "Message queued. The message could not be delivered and has been queued for attempted redelivery.",
101             "003", "Delivered. Delivered to the network or gateway (delivered to the recipient).",
102             "004", "Received by recipient. Confirmation of receipt on the handset of the recipient.",
103             "005", "Error with message. There was an error with the message, probably caused by the content of the message itself.",
104             "006", "User cancelled message delivery. Client cancelled the message by setting the validity period, or the message was terminated by an internal mechanism.",
105             "007", "Error delivering message An error occurred delivering the message to the handset.",
106             "008", " OK. Message received by gateway.",
107             "009", "Routing error. The routing gateway or network has had an error routing the message.",
108             "010", "Message expired. Message has expired at the network due to the handset being off, or out of reach.",
109             "011", "Message queued for later delivery. Message has been queued at the Clickatell gateway for delivery at a later time (delayed delivery).",
110             "012", "Out of credit. The message cannot be delivered due to a lack of funds in your account. Please re-purchase credits."
111             );
112              
113             sub getStatusDetail {
114 0   0 0 0   my $class = shift || undef;
115 0 0         return undef if( !defined $class);
116              
117 0           my $ret = shift;
118              
119 0           my @allret=split ": ",$ret;
120 0           my $sc=$allret[@allret-1];
121 0           $sc=~s/\D//g;
122 0           return $class->getStatus($sc);
123             }
124              
125             sub getStatus {
126 0   0 0 0   my $class = shift || undef;
127 0 0         return undef if( !defined $class);
128              
129 0           my $scode = shift;
130 0           my $ret=$status{$scode};
131 0 0         return $scode,$ret if ($ret);
132 0           return -1,"Unknown Status";
133             }
134              
135             sub authentication {
136 0   0 0 0   my $class = shift || undef;
137 0 0         return undef if( !defined $class);
138              
139 0           return $class->connect('http/auth');
140             }
141              
142             sub ping {
143 0   0 0 0   my $class = shift || undef;
144 0 0         return undef if( !defined $class);
145              
146 0           my ($sid)=@_;
147 0           return $class->connect('http/ping','session_id',$sid);
148             }
149              
150             =item new
151              
152             This method is used to create the Clickatell object.
153              
154             Usage:
155              
156             my $clickatell = Net::Clickatell->new( API_ID => $api_id, USERNAME= $user, PASSWORD =>$passwd );
157              
158             The complete list of arguments is:
159              
160             API_ID : Unique number received from Clickatell when an account is created.
161             UseSSL : Tell Clickatell module whether to use SSL or not (0 or 1).
162             BaseURL : Default URL used to connect with Clickatell service.
163             UserAgent : Name of the user agent you want to display to Clickatell service.
164              
165             =cut
166              
167             sub new {
168 0   0 0 1   my $class = shift || undef;
169 0 0         return undef if( !defined $class);
170              
171             # Get arguments
172 0           my %args = ( UseSSL => 1,
173             UserAgent => 'Clickatell.pm/'. $Net::Clickatell::VERSION,
174             @_ );
175              
176             # Check arguments
177 0 0         if (!exists $args{API_ID}) {
178             # There isn't an API identification number. We can't continue
179 0           return undef;
180             }
181              
182 0 0         if (!exists $args{USERNAME}) {
183             # There isn't a USERNAME. We can't continue
184 0           return undef;
185             }
186              
187 0 0         if (!exists $args{PASSWORD}) {
188             # There isn't a PASSWORD. We can't continue
189 0           return undef;
190             }
191              
192 0 0         if ($args{UseSSL} =~ /\D/) {
193             # UseSSL argument wasn't valid. Set it to 1
194 0           $args{UseSSL} = 1;
195             }
196              
197 0 0         if (!exists $args{BaseURL}) {
198             # BaseURL argument wasn't passed. Set it to default.
199             # Check if we have to use SSL.
200 0 0 0       if (exists $args{UseSSL} && $args{UseSSL}==1) {
201 0           $args{BaseURL} = 'https://api.clickatell.com/';
202             } else {
203 0           $args{BaseURL} = 'http://api.clickatell.com/';
204             }
205             } else {
206             # Set BaseURL property value.
207             # Check if we have to use SSL.
208 0 0 0       if (exists $args{UseSSL} && $args{UseSSL}==1) {
209 0           $args{BaseURL} = 'https://'.$args{BaseURL};
210             } else {
211 0           $args{BaseURL} = 'http://'.$args{BaseURL};
212             }
213             }
214              
215 0           return bless { BASE_URL => $args{BaseURL},
216             API_ID => uri_escape($args{API_ID}),
217             USERNAME => uri_escape($args{USERNAME}),
218             PASSWORD => uri_escape($args{PASSWORD}),
219             USE_SSL => $args{UseSSL},
220             USER_AGENT => $args{UserAgent},
221             }, $class;
222             }
223              
224             sub connect {
225 0   0 0 0   my $class = shift || undef;
226 0 0         return undef if( !defined $class);
227              
228 0           my $url= shift;
229 0           my (@entry)=@_;
230              
231 0           my $ua = LWP::UserAgent->new(agent => $class->{USER_AGENT} );
232              
233 0           my %tags = @entry;
234 0           $tags{'api_id'} = $class->{API_ID};
235 0           $tags{'user'} = $class->{USERNAME};
236 0           $tags{'password'} = $class->{PASSWORD};
237              
238 0           my $res = $ua->request(
239             POST $class->{BASE_URL}.$url,
240             Content_Type => 'application/x-www-form-urlencoded',
241             Content => [ %tags ]
242             );
243 0           return $res->content;
244             }
245              
246             =item getBalance
247              
248             This method will return the Balance of the account.
249              
250             Usage:
251              
252             $clickatell->getBalance;
253              
254             Succesful example of the return is as followed:
255             OK: Credit: 100.3
256              
257             Failed example of the return is as followed:
258             ERR: 001, Authentication failed
259              
260             =cut
261              
262             sub getBalance {
263 0   0 0 1   my $class = shift || undef;
264 0 0         return undef if( !defined $class);
265              
266 0           my $ret= $class->connect('http/getbalance');
267 0 0         return "OK: $ret" unless $ret=~/^ERR: /;
268 0           return $ret;
269             }
270              
271             =item checkCoverage
272              
273             This method will return the Balance of the account.
274              
275             Usage:
276              
277             $clickatell->checkCoverage($msisdn);
278              
279             Succesful example of the return is as followed:
280             OK: This prefix is currently supported. Messages sent to this prefix will be routed. Charge: 1
281              
282             Failed example of the return is as followed:
283             ERR: This prefix is not currently supported. Messages sent to this prefix will fail. Please contact support for assistance.
284              
285             =cut
286              
287             sub checkCoverage {
288 0   0 0 1   my $class = shift || undef;
289 0 0         return undef if( !defined $class);
290              
291 0           my ($msisdn)=@_;
292 0           return $class->connect('utils/routeCoverage.php','msisdn',$msisdn);
293             }
294              
295             =item getQuery
296              
297             This method will return the Message Charge Status.
298              
299             Usage:
300              
301             my ($code,$querymessage)=$clickatell->getQuery($apimsgid);
302              
303             This method will return 2 values in a array which is as followed:
304             001
305             ID: add8f5556c0d3d54bc94a4cd8800f01b4 Status: 001, Message unknown. The delivering network did not recognise the message type or content.
306              
307             =cut
308              
309             sub getQuery {
310 0   0 0 1   my $class = shift || undef;
311 0 0         return undef if( !defined $class);
312              
313 0           my $apimsgid=shift;
314 0           my $ret= $class->connect('http/querymsg','apimsgid',$apimsgid);
315 0           my $code=-1;
316 0           my $scode='Error in the return status';
317 0 0         ($code,$scode)=$class->getStatusDetail($ret) if ($ret=~/status:/i);
318 0           return $code, ($ret.', '.$scode);
319             }
320              
321             =item getMessageCharge
322              
323             This method will return the Message Charge Status.
324              
325             Usage:
326              
327             my ($code,$messagecharge)=$clickatell->getMessageCharge($apimsgid);
328              
329             This method will return 2 values in a array which is as followed:
330             001
331             apiMsgId: add8f5556c0d3d54bc94a4cd8800f01b4 charge: 0 status: 001, Message unknown. The delivering network did not recognise the message type or content.
332              
333             =cut
334              
335             sub getMessageCharge {
336 0   0 0 1   my $class = shift || undef;
337 0 0         return undef if( !defined $class);
338              
339 0           my $apimsgid=shift;
340 0           my $ret= $class->connect('http/getmsgcharge','apimsgid',$apimsgid);
341 0           my $code=-1;
342 0           my $scode='Error in the return status';
343 0 0         ($code,$scode)=$class->getStatusDetail($ret) if ($ret=~/status:/i);
344 0           return $code, ($ret.', '.$scode);
345             }
346              
347             =item sendBasicSMSMessage
348              
349             This method is used to send a text SMS Message.
350              
351             Usage:
352              
353             my $smsResult=$clickatell->sendBasicSMSMessage($from,$to,$msg);
354              
355             Succesful example of the return is as followed:
356             OK: ID: dd8f5556c0d3d54bc94a4cd8800f01b4
357              
358             Failed example of the return is as followed:
359             ERR: 105, Invalid Destination Address
360              
361             =cut
362              
363             sub sendBasicSMSMessage {
364 0   0 0 1   my $class = shift || undef;
365 0 0         return undef if( !defined $class);
366              
367 0           my ($from,$to,$msg)=@_;
368 0           my $ret= $class->connect('http/sendmsg',"to",$to,'from',$from,'text',$msg);
369 0 0         return "OK: $ret" unless $ret=~/^ERR: /;
370 0           return $ret;
371             }
372              
373             =item sendAdvanceSMSMessage
374              
375             This method is used to send a customised SMS Message. The following are the accepted parameter format:
376             to
377             text
378             from
379             callback
380             deliv_time
381             concat
382             max_credits
383             req_feat
384             queue
385             escalate
386             mo
387             cliMsgId
388             Unicode
389             msg_type
390             udh
391             data
392             validity
393             binary
394             schedule_time
395              
396             Usage:
397              
398             my $smsResult=$clickatell->sendAdvanceSMSMessage(to=>'6591234567',from=>'6591234568',text=>'testing');
399              
400             Succesful example of the return is as followed:
401             OK: ID: dd8f5556c0d3d54bc94a4cd8800f01b4
402              
403             Failed example of the return is as followed:
404             ERR: 105, Invalid Destination Address
405              
406             =cut
407              
408             sub sendAdvanceSMSMessage {
409 0   0 0 1   my $class = shift || undef;
410 0 0         return undef if( !defined $class);
411             # Get arguments
412 0           my %args = @_;
413              
414             # Check arguments
415 0 0         if (!exists $args{to}) {
416 0           return "ERR: To field not found";
417             } else {
418 0 0         if (ref($args{to})) {
419 0 0         return "ERR: To field must be arrayref" unless ref($args{to}) eq "ARRAY";
420 0           my $tos=$args{to};
421 0 0         return "ERR: To field must be contain at least 1 number" unless (@$tos);
422 0           $args{to}=join ',',@$tos;
423 0           print $args{to}."\n";
424             }
425             }
426              
427 0 0         if (!exists $args{from}) {
428 0           return "ERR: From field not found";
429             }
430              
431 0 0 0       if (!exists $args{text} && !exists $args{data}){
432 0           return "ERR: Text field not found";
433             }
434              
435 0           my $ret= $class->connect('http/sendmsg',%args);
436 0 0         return "OK: $ret" unless $ret=~/^ERR: /;
437 0           return $ret;
438             }
439              
440             =item sendMMNotification
441              
442             This method is used to send a MMS Notification Push Message.
443              
444             Usage:
445              
446             my $mmsResult=$clickatell->sendMMNotification($from,$to,$subject,$expiry,$url);
447              
448             Succesful example of the return is as followed:
449             OK: ID: dd8f5556c0d3d54bc94a4cd8800f01b4
450              
451             Failed example of the return is as followed:
452             ERR: 105, Invalid Destination Address
453              
454             =cut
455              
456             sub sendMMNotification {
457 0   0 0 1   my $class = shift || undef;
458 0 0         return undef if( !defined $class);
459              
460 0           my ($from,$to,$subject,$expiry,$url)=@_;
461              
462             # mms_subject: subject
463             # mms_class: class (e.g. 80,81,82,83)
464             # mms_expire: seconds - different to the standard expire parameter
465             # mms_from: from text
466             # mms_url: the url with the mms content. The URL must be urlencoded.
467             # print "($from,$to,$subject,$expiry,$url)\n";
468              
469 0           my $loc=uri_escape($url);
470 0           my $ret= $class->connect('mms/ind_push.php',"to",$to,'from',$from,'mms_from',$from,
471             'mms_expire',$expiry,'mms_url',$loc,'mms_class','80','mms_subject',$subject);
472 0 0         return "OK: $ret" unless $ret=~/^ERR: /;
473 0           return $ret;
474              
475             }
476              
477             =item sendWAPPush
478              
479             This method is used to send a WAP Push. Currently, only SI WAP Push message is supported.
480              
481             Usage:
482              
483             my $wapResult=$clickatell->sendWAPPush($from,$to,$msg,$url);
484              
485             Succesful example of the return is as followed:
486             OK: ID: dd8f5556c0d3d54bc94a4cd8800f01b4
487              
488             Failed example of the return is as followed:
489             ERR: 105, Invalid Destination Address
490              
491             =cut
492              
493             sub sendWAPPush {
494 0   0 0 1   my $class = shift || undef;
495 0 0         return undef if( !defined $class);
496              
497 0           my ($from,$to,$message,$url)=@_;
498 0           my $rr=$to.rand(100);
499 0           $rr=~s/\D//g;
500 0           return $class->sendSIWAPPush($from,$to,$rr,'delete',$message,$url);
501             }
502              
503             sub sendSIWAPPush {
504 0   0 0 0   my $class = shift || undef;
505 0 0         return undef if( !defined $class);
506              
507 0           my ($from,$to,$si_id,$si_action,$message,$url)=@_;
508             #si_id: unique id for msg - must be used with a 'delete' action
509             #si_url: the url to be fetched (url encoded)
510             #si_text: notification text
511             #si_created: date in UTC
512             #si_expires: data in UTC
513             #si_action: one of (signal-none, signal-low, signal-medium, signal-high, delete)
514 0           my $nowt=&getTime(0);
515 0           my $nowx=&getTime(7);
516              
517 0           my $loc=uri_escape($url);
518 0           my $ret= $class->connect('mms/si_push','si_id',$si_id,'si_action',$si_action,
519             'si_created',$nowt,'si_expires',$nowx,
520             'to',$to,'from',$from,'si_text',$message,'si_url',$loc);
521 0 0         return "OK: $ret" unless $ret=~/^ERR: /;
522 0           return $ret;
523             }
524              
525             sub getTime {
526 0     0 0   my $day=shift;
527 0 0         $day=0 unless ($day);
528              
529 0           my ($sec,$min,$hour,$mday,$mon,$year,$wday,$yday,$isdst) = gmtime(time+($day*86400));
530 0           return sprintf("%04d%02d%02d%02d%02d%02d",$year+1900,$mon+1,$mday,$hour,$min,$sec);
531             }
532              
533              
534             =back 4
535              
536             =head1 AUTHOR
537              
538             Christopherus Goo
539              
540             =head1 COPYRIGHT
541              
542             Copyright (c) 2010 Christopherus Goo. All rights reserved.
543             This software may be used and modified freely, but I do request that this
544             copyright notice remain attached to the file. You may modify this module
545             as you wish, but if you redistribute a modified version, please attach a
546             note listing the modifications you have made.
547              
548             Clickatell is Copyright (c) 2010 Clickatell (Pty) Ltd: Bulk SMS Gateway
549              
550             This software or the author aren't related to Clickatell in any way.
551              
552             =cut
553              
554             1;
555              
556