File Coverage

blib/lib/Net/SMS/ArxMobile.pm
Criterion Covered Total %
statement 17 19 89.4
branch n/a
condition n/a
subroutine 7 7 100.0
pod n/a
total 24 26 92.3


line stmt bran cond sub pod time code
1             package Net::SMS::ArxMobile;
2             BEGIN {
3 1     1   26829 $Net::SMS::ArxMobile::VERSION = '0.01';
4             }
5              
6             # ABSTRACT: Send SMS messages via the ArXMobile HTTP API
7              
8 1     1   9 use strict;
  1         2  
  1         42  
9 1     1   5 use warnings;
  1         2  
  1         91  
10              
11              
12 1     1   10 use Carp ();
  1         1  
  1         20  
13             #se Data::Dumper ();
14 1     1   788 use HTTP::Request ();
  1         32096  
  1         25  
15 1     1   1154 use LWP::UserAgent ();
  1         40019  
  1         31  
16 1     1   2876 use XML::Simple ();
  0            
  0            
17              
18             use constant {
19             XML_DECL => q{}, # Ugh
20             API_URL_SEND => q{https://invenue.com/api/message.php},
21             API_URL_QUERY => q{https://invenue.com/api/query.php},
22             API_TIMEOUT => 30,
23             };
24              
25             sub new {
26             my ($class, %args) = @_;
27              
28             if (! exists $args{_auth_code} || ! $args{_auth_code}) {
29             Carp::croak("${class}->new() requires the ArXMobile '_auth_code' parameter\n");
30             }
31              
32             my $self = \%args;
33             bless $self, $class;
34             }
35              
36             sub _useragent {
37             my ($self) = @_;
38              
39             my $ua = LWP::UserAgent->new();
40             $ua->timeout(API_TIMEOUT);
41             $ua->agent("Net::SMS::ArxMobile/$Net::SMS::ArxMobile::VERSION");
42              
43             return $ua;
44             }
45              
46             sub _query_smsid_xml {
47             my ($self, %args) = @_;
48              
49             my $smsid = $args{smsid};
50             my $auth_code = $args{_auth_code};
51              
52             my $xml = _to_xml({
53             query => {
54             auth_code => $auth_code,
55             smsid => $smsid,
56             },
57             });
58              
59             return $xml;
60             }
61              
62             sub _send_sms_xml {
63             my ($self, %args) = @_;
64              
65             my $body = $args{text};
66             my $phone = $args{to};
67             my $auth_code = $args{_auth_code};
68              
69             my $xml = _to_xml({
70             message => {
71             auth_code => $auth_code,
72             body => $body,
73             user => {
74             phone => $phone,
75             },
76             },
77             });
78              
79             return $xml;
80             }
81              
82             sub _to_xml {
83             my ($data_struct) = @_;
84             my %xml_opts = _xml_out_opts();
85             return XML::Simple::XMLout($data_struct, %xml_opts);
86             }
87              
88             sub _xml_out_opts {
89             return (
90             KeepRoot => 1,
91             NoAttr => 1,
92             XMLDecl => XML_DECL,
93             );
94             }
95              
96             sub query_smsid {
97             my ($self, %args) = @_;
98              
99             my $ua = _useragent();
100             my $api_url = API_URL_QUERY;
101             my $req_xml = $self->_query_smsid_xml(
102             _auth_code => $self->{_auth_code},
103             smsid => $args{smsid},
104             );
105              
106             my $req = HTTP::Request->new(POST => $api_url);
107             $req->header("Content-Type" => "text/xml");
108             $req->content($req_xml);
109              
110             my $resp = $ua->request($req);
111             my $as_string = $resp->as_string;
112             my $resp_body = $resp->content;
113              
114             if (! $resp->is_success) {
115             my $status = $resp->status_line;
116             warn "HTTP request failed: $status\n$resp_body\n";
117             return;
118             }
119              
120             #warn "HTTP Request: " . $req->as_string . "\n";
121             #warn "HTTP Response: $as_string\n";
122             #warn "HTTP Response content: $resp_body\n";
123              
124             my $api_data = XML::Simple::XMLin($resp_body, SuppressEmpty => '');
125             if (! $api_data || ref $api_data ne "HASH") {
126             warn "No result (or invalid XML?) from API\n";
127             return;
128             }
129              
130             my $sms_data = $api_data->{result};
131             return $sms_data;
132             }
133              
134             sub send_sms {
135             my ($self, %args) = @_;
136              
137             $args{to} =~ s{^\+}{};
138             $args{to} =~ s{[- ]}{}g;
139              
140             my $ua = $self->_useragent();
141             my $api_url = API_URL_SEND;
142             my $req_xml = $self->_send_sms_xml(
143             _auth_code => $self->{_auth_code},
144             text => $args{text},
145             to => $args{to},
146             );
147              
148             my $req = HTTP::Request->new(POST => $api_url);
149             $req->header("Content-Type" => "text/xml");
150             $req->content($req_xml);
151              
152             my $resp = $ua->request($req);
153             my $as_string = $resp->as_string;
154              
155             #warn "HTTP Request: " . $req->as_string . "\n";
156             #warn "HTTP Response: $as_string\n";
157             #warn "HTTP Response content: " . $resp->content . "\n";
158              
159             if (! $resp->is_success) {
160             my $status = $resp->status_line;
161             warn "HTTP request failed: $status\n$as_string\n";
162             return 0;
163             }
164              
165             my $xml = $resp->content;
166             my $api_data = XML::Simple::XMLin($xml, SuppressEmpty => '');
167              
168             if (! $api_data || ref $api_data ne "HASH") {
169             warn "No response (or invalid XML) from API\n";
170             return;
171             }
172              
173             #warn Data::Dumper::Dumper($api_data), "\n";
174              
175             my $sms = $api_data->{result};
176              
177             if (! $sms || ref $sms ne "HASH") {
178             warn "Couldn't find any sms result in the XML\n";
179             return;
180             }
181              
182             if ($sms->{error}) {
183             warn "Failed: $sms->{error}\n";
184             return;
185             }
186              
187             my $smsid = $sms->{smsid};
188             if (! $smsid) {
189             warn "smsid not found in ArxMobile response:\n$xml\n";
190             }
191              
192             return $smsid;
193             }
194              
195             1;
196              
197              
198             __END__