File Coverage

blib/lib/SMS/Send/SMSGlobal/HTTP.pm
Criterion Covered Total %
statement 76 84 90.4
branch 24 34 70.5
condition 8 18 44.4
subroutine 12 12 100.0
pod 2 2 100.0
total 122 150 81.3


line stmt bran cond sub pod time code
1             package SMS::Send::SMSGlobal::HTTP;
2              
3 3     3   73260 use warnings;
  3         8  
  3         100  
4 3     3   15 use strict;
  3         6  
  3         94  
5              
6 3     3   74 use 5.006;
  3         26  
  3         157  
7              
8 3     3   3446 use parent 'SMS::Send::Driver', 'Class::Accessor';
  3         981  
  3         23  
9              
10             require LWP::UserAgent;
11 3     3   203671 use HTTP::Request::Common qw(POST);
  3         702042  
  3         413  
12 3     3   1246 use Try::Tiny;
  3         2285  
  3         169  
13 3     3   20 use Scalar::Util qw();
  3         6  
  3         136  
14              
15             sub __fields {
16 6     6   100 return qw(action text to _user _password _from _maxsplit _scheduledatetime
17             _api _userfield __transport __verbose __ua __address __responses)
18             };
19              
20 3     3   3070 use fields __PACKAGE__->__fields;
  3         5183  
  3         23  
21             __PACKAGE__->mk_accessors( __PACKAGE__->__fields );
22              
23             =head1 NAME
24              
25             SMS::Send::SMSGlobal::HTTP - SMS::Send SMSGlobal.com Driver
26              
27             =head1 VERSION
28              
29             VERSION 0.12
30              
31             =cut
32              
33             our $VERSION = '0.12';
34              
35             =head1 DESCRIPTION
36              
37             SMS::Send::SMSGlobal::HTTP is a simple driver for L for sending
38             messages via www.smsglobal.com using the SMS Global HTTP API.
39              
40             =head1 SUBROUTINES/METHODS
41              
42             =head2 new
43              
44             use SMS::Send;
45              
46             my $sender = SMS::Send->new('SMSGlobal::HTTP',
47             _user => 'my-username',
48             _password => 'my-password',
49             __transport => 'https',
50             __verbose => 1
51             );
52              
53             =cut
54              
55             sub new {
56 11     11 1 225 my $class = shift;
57 11         79 my %args = @_;
58              
59             # Create the object
60 11         58 my $self = fields::new ($class);
61              
62             #
63             # Allow _user and _password aliases; just to ease interchange
64             # with other sms drivers
65             #
66              
67 11   33     18568 $self->{_user} = delete($args{_user})
68             || delete($args{_username})
69             || delete($args{_login});
70              
71 11   33     99 $self->{_password} = delete $args{_pass}
72             || delete $args{_password};
73              
74 11         90 foreach (sort keys %args) {
75 59         7884 $self->{$_} = $args{$_};
76             }
77              
78 11   100     59 $self->{_maxsplit} ||= 3;
79              
80 11   33     59 $self->{__ua} ||= LWP::UserAgent->new;
81              
82 11         48 return $self;
83             }
84              
85             =head2 send_sms
86              
87             my $sent = $sender->send_sms(
88             to => '+61 4 8799 9999',
89             text => 'Go to the window!',
90             _from => 'Clang',
91             _scheduledtime => DateTime
92             ->now(time_zone => 'Australia/Melbourne')
93             ->add(minutes => 5)
94             );
95              
96             =head3 Basic Options
97              
98             =over 4
99              
100             =item C
101              
102             The recipient number. This can either be an international number (prefixed
103             with C<+>) or an local number (with a leading C<0>).
104              
105             Note: In the case of a local number, the country will be determined by your
106             C Locale Setting in your account preferences.
107              
108             =item C
109              
110             The text of the message.
111              
112             =item C<_from>
113              
114             Sets the from caller-ID. This can either be a reply telephone number, or an
115             alphanumeric identifier matching C<^[0-9a-zA-Z_]+$>. For details. see
116             http://www.routomessaging.com/dynamic-sender-id-service.pmx .
117              
118             =item C<_maxsplit> (default 3)
119              
120             The maximum number of 150 character (approx) transmission chunks. You may need
121             to increase this to send longer messages.
122              
123             Note: Each chunk is metered as a separate message.
124              
125             =item C<_scheduledtime>
126              
127             Lets you delay sending of messages. This can be either (a) a string formatted
128             as C or (b) an object that supports C and
129             C methods. For example L or L objects.
130              
131             Note: Your date times need to to be specified in the same timezone as set in
132             your SMSGlobal account preferences.
133              
134             =back
135              
136             =head3 HTTP-2WAY Options
137              
138             Some extra options for handling SMS replies. These are useful when you are
139             using dedicated incoming numbers, with your account. See
140             L:
141              
142             =over 4
143              
144             =item C<_api>
145              
146             Set to 0, to disabled two-way messaging. The default is 1 (enabled).
147              
148             =item C<_userfield>
149              
150             Custom field to store internal IDs or other information (Maximum of
151             255 characters)
152              
153             =back
154              
155             =head3 Configuration Options
156              
157             =over 4
158              
159             =item C<__address>
160              
161             SMSGlobal gateway address (default: 'http://www.smsglobal.com/http-api.php');
162              
163             =item C<__transport>
164              
165             Transport to use: 'http' (default) or 'https'.
166              
167             Transport over 'https' is encrypted and more secure. However, this option
168             requires either L or L to be installed. More
169             information is available at
170             L.
171              
172             =item C<__verbose>
173              
174             Set to true to enable tracing.
175              
176             =back
177              
178             =cut
179              
180             sub send_sms {
181 9     9 1 30267 my $self = shift;
182 9         46 my %opt = @_;
183              
184 9         60 $self->__responses( [] );
185              
186 9         522 my $msg = ref($self)->new( %$self, %opt );
187              
188 9         44 my %http_params = (
189             action => 'sendsms',
190             );
191              
192 9         67 foreach (sort keys %$msg) {
193 74 100       220 next if m{^__};
194              
195 55 50       159 if (defined (my $val = $msg->{$_}) ) {
196 55         290 (my $key = $_) =~ s{^_}{};
197 55         165 $http_params{$key} = $val;
198             }
199             }
200              
201 9 100       38 if (ref $http_params{scheduledatetime} ) {
202             #
203             # stringify objects that support ymd & hms methods
204             #
205 1         5 for ( $http_params{scheduledatetime} ) {
206             $_ = $_->ymd('-') .' '.$_->hms(':')
207             if (Scalar::Util::blessed($_) && try {
208 1 50   1   28 $_->can('ymd') && $_->can('hms')
209             })
210 1 50 33     15 }
211             }
212              
213 9 50       382 if ( defined $http_params{to} ) {
214              
215 9 100 50     48 $http_params{to} = join(',', @{ $http_params{to} })
  1         4  
216             if (ref( $http_params{to} || '') eq 'ARRAY');
217             #
218             # smsglobl/http will accept 'to' as a comma-separated list of
219             # telephone numbers. Omit all but commas and alphanumerics.
220             #
221 9         61 $http_params{to} =~ s{[^\w,]}{}g;
222             }
223              
224 9 100       29 if ( defined $http_params{from} ) {
225             #
226             # restrict 'from' to an alphanumeric caller-ID
227             #
228 6         33 $http_params{from} =~ s{[^\w]}{}g;
229             }
230              
231 9 50       45 if ($msg->__verbose) {
232 0         0 print STDERR "http params:\n";
233 0         0 foreach (sort keys %http_params) {
234 0         0 print STDERR " $_: $http_params{$_}\n"
235             }
236             }
237              
238 9   50     152 my $address = $msg->__address || 'http://www.smsglobal.com/http-api.php';
239              
240 9 100       138 if (my $transport = $msg->__transport) {
241              
242 1 50       14 if ($transport eq 'http') {
    50          
243 0         0 $address =~ s{^https:}{http:}i;
244             }
245             elsif ($transport eq 'https') {
246 1         6 $address =~ s{^http:}{https:}i;
247             }
248             else {
249 0         0 die "transport '$transport': not 'http' or 'https'"
250             }
251             }
252              
253 9 50       121 print STDERR "Address : $address" if $msg->__verbose;
254              
255 9         293 my $req = POST($address => [ %{ \%http_params } ]);
  9         88  
256              
257 9         21397 my $response = $msg->__ua->request($req);
258              
259 9 50       1781 die "unable to get response"
260             unless $response;
261              
262 9 50       38 if ($msg->__verbose ) {
263 0         0 print STDERR "**Status**\n",$response->status_line,"\n";
264 0         0 print STDERR "**Headers**\n",$response->headers_as_string,"\n";
265 0         0 print STDERR "**Content**\n",$response->content,"\n";
266             }
267              
268 9         108 my $sent = 0;
269              
270 9 100       47 if ( $response->is_success ) {
271              
272 8         105 my @responses = split (/[\n\r]+/, $response->content);
273              
274 8         140 foreach (@responses) {
275 10         17 push ( @{ $self->__responses }, $_ );
  10         37  
276              
277 10 100       156 if ( m{^(OK|SMSGLOBAL DELAY)} ) {
278 8         28 $sent++;
279             }
280             }
281             }
282             else {
283 1         14 die $response->status_line;
284             }
285              
286 8         126 return $sent;
287             }
288              
289             =head2 Sending SMS to Multiple Recipients
290              
291             It is possible to specify multiple recipients in a request. However, this
292             requires direct use of the C driver:
293              
294             use SMS::Send::SMSGlobal::HTTP;
295              
296             my $driver = SMS::Send::SMSGlobal::HTTP->new(
297             _user => $sms_login,
298             _password => $sms_pass,
299             __verbose => 1,
300             __transport => 'https',
301             );
302              
303             The driver can accept either an array of mobile numbers or a string containing
304             a comma-separated list of mobile numbers.
305              
306             my @recipients = ( '+61(4)770090099', '0419 123 456' );
307              
308             my $sent = $driver->send_sms( _from => $caller_id,
309             to => \@recipients,
310             text => 'Hi everyone!',
311             );
312              
313             The return value is the number of messages queued for delivery to individual
314             recipients.
315              
316             C<__responses> contains sucesss or error codes for each recipient.
317              
318             if ( $sent < scalar @recipients ) {
319             warn "failed to send to some participants";
320              
321             my @responses = @{ $driver->__responses || [] };
322             for ( @responses ) {
323             warn $_ if m{ERROR};
324             }
325             }
326              
327             =head1 AUTHOR
328              
329             David Warring, C<< >>
330              
331             =head1 BUGS AND LIMITATIONS
332              
333             This module only attempts to implement the simple HTTP/S C command as
334             described in L and L.
335              
336             There are other API's available (L). Among the more fully featured are the SOAP interface (L) and SMPP (L).
337              
338             Please report any bugs or feature requests to C, or through
339             the web interface at L. I will be notified, and then you'll
340             automatically be notified of progress on your bug as I make changes.
341              
342             =head1 SUPPORT
343              
344             You can find documentation for this module with the perldoc command.
345              
346             perldoc SMS::Send::SMSGlobal::HTTP
347              
348             You can also look for information at:
349              
350             =over 4
351              
352             =item * RT: CPAN's request tracker
353              
354             L
355              
356             =item * AnnoCPAN: Annotated CPAN documentation
357              
358             L
359              
360             =item * CPAN Ratings
361              
362             L
363              
364             =item * Search CPAN
365              
366             L
367              
368             =back
369              
370              
371             =head1 LICENSE AND COPYRIGHT
372              
373             Copyright 2011-2012 David Warring.
374              
375             This program is free software; you can redistribute it and/or modify it
376             under the terms of either: the GNU General Public License as published
377             by the Free Software Foundation; or the Artistic License.
378              
379             See http://dev.perl.org/licenses/ for more information.
380              
381             =cut
382              
383             1; # End of SMS::Send::SMSGlobal::HTTP