File Coverage

blib/lib/SMS/API/CMTelecom.pm
Criterion Covered Total %
statement 54 57 94.7
branch 18 22 81.8
condition 4 6 66.6
subroutine 11 11 100.0
pod 3 3 100.0
total 90 99 90.9


line stmt bran cond sub pod time code
1             package SMS::API::CMTelecom;
2              
3 4     4   40347 use 5.006;
  4         14  
4 4     4   20 use strict;
  4         8  
  4         70  
5 4     4   17 use warnings;
  4         10  
  4         102  
6 4     4   1970 use LWP::UserAgent;
  4         137257  
  4         124  
7 4     4   1560 use JSON;
  4         24387  
  4         20  
8              
9             =head1 NAME
10              
11             SMS::API::CMTelecom - SMS API for cmtelecom.com
12              
13             =head1 VERSION
14              
15             Version 0.01
16              
17             =cut
18              
19             our $VERSION = '0.02';
20              
21              
22             =head1 SYNOPSIS
23              
24             use SMS::API::CMTelecom;
25             my $sms = SMS::API::CMTelecom->new(
26             product_token => '00000000-0000-0000-0000-000000000000',
27             );
28              
29             $sms->send(
30             sender => '00480000111111111',
31             message => 'please call me!',
32             recipients => '00490000000000000',
33             reference => 293854,
34             );
35              
36             # bulk send to many recipients:
37             $sms->send(
38             sender => '00480000111111111',
39             message => 'please call me!',
40             recipients => ['00490000000000000', '00480000000000', '004300021651202'],
41             reference => 293854,
42             );
43              
44              
45             =head1 METHODS
46              
47             =head2 new(%options)
48              
49             Instantiate and initialise object with the following options:
50              
51             =over 4
52              
53             =item C<< product_token => $product_token >>
54              
55             The product token is required to authenticate with the CM Telecom API.
56              
57             =item C<< sender => $sender >>
58              
59             Optional. SMS sender number.
60              
61             =back
62              
63             =cut
64              
65             sub new {
66 9     9 1 6416 my $class = shift;
67 9         32 my %params = @_;
68 9 100       36 die $class.'->new requires product_token parameter' if not exists $params{product_token};
69 8         13 my $self = \%params;
70 8         19 bless $self, $class;
71              
72 8         31 $self->{_ua} = LWP::UserAgent::->new();
73 8         13523 $self->{_ua}->agent('SMS::API::CMTelecom/'.$VERSION);
74 8 50       501 if ($self->{_ua}->can('ssl_opts')) {
75 8         28 $self->{_ua}->ssl_opts( verify_hostname => 0, );
76             }
77              
78 8         195 return $self;
79             }
80              
81             =head2 send
82              
83             =over 4
84              
85             =item C<< message => $message >>
86              
87             Mandatory. Message text to send.
88              
89             =item C<< recipients => $recipients >>
90              
91             Mandatory. May be a scalar containing one phone number or an array reference
92             holding multiple scalars containing one phone number each.
93              
94             =item C<< sender => $sender >>
95              
96             Optional. Can also be set globally when construction the object with C.
97              
98             =back
99              
100             If sending fails, C is returned, otherwise a hashref with some status information:
101              
102             {
103             messages => [
104             {
105             messageDetails => undef,
106             parts => 1,
107             reference => 51314,
108             status => "Accepted",
109             to => "0049123456784510",
110             },
111             ],
112             }
113              
114             You can retrieve the error message via
115              
116             my $msg = $sms->error_message();
117              
118             =cut
119              
120             sub send {
121 8     8 1 1288 my $self = shift;
122 8         39 my %params = @_;
123              
124 8         34 $self->_reset_error_message();
125              
126 8 100 66     38 my @recipients = ref $params{recipients} eq 'ARRAY' ? @{ $params{recipients} } : ($params{recipients} || ());
  3         9  
127              
128 8 100       25 return $self->_set_error_message(ref($self).'->send requires at least one recipient number') if !@recipients;
129 6         15 for my $recipient (@recipients) {
130 9 100       23 return $self->_set_error_message('recipient may not be undefined') if !defined $recipient;
131 8 100       20 return $self->_set_error_message('recipient must be a telephone number') if ref $recipient;
132 7 100       22 return $self->_set_error_message('recipient may not be an empty string') if $recipient eq '';
133             }
134              
135 3   66     12 my $sender = $params{sender} // $self->{sender};
136 3 100       17 return $self->_set_error_message(ref($self).'->send requires a sender number') if !defined $sender;
137              
138             my $payload = {
139             messages => {
140             authentication => {
141             producttoken => $self->{product_token},
142             },
143             msg => [
144             {
145             from => $sender,
146 1         5 to => [ map { +{ number => $self->_clean_number($_) } } @recipients ],
147             body => {
148             type => 'AUTO',
149             content => $params{message},
150             },
151 1 50       5 exists $params{reference} ? (reference => $params{reference}) : (),
152             },
153             ],
154             },
155             };
156              
157 1         30 my $req = HTTP::Request->new(
158             POST => 'https://gw.cmtelecom.com/v1.0/message',
159             ['Content-Type' => 'application/json'],
160             encode_json $payload,
161             );
162 1         6765 my $res = $self->{_ua}->request( $req );
163              
164 1 50       311663 if ($res->code == 200) {
165 0         0 my $result = decode_json $res->content();
166             return {
167             messages => $result->{messages},
168 0         0 };
169             }
170              
171 1         15 my $result = eval { decode_json $res->content() };
  1         27  
172 1 50       32 return $self->_set_error_message($result->{details}) if ref $result eq 'HASH';
173              
174 0         0 return $self->_set_error_message('HTTP request returned with status '.$res->code);
175             }
176              
177             sub _clean_number {
178 1     1   3 my ($self, $number) = @_;
179              
180             # strip all non-number chars
181 1         4 $number =~ s/\D//g;
182              
183 1         12 return $number;
184             }
185              
186             sub _set_error_message {
187 8     8   20 my ($self, $message) = @_;
188 8         54 $self->{error_message} = $message;
189 8         63 return;
190             }
191              
192             sub _reset_error_message {
193 8     8   21 my ($self, $message) = @_;
194 8         15 $self->{error_message} = undef;
195 8         14 return;
196             }
197              
198             =head2 error_message
199              
200             Returns the last set error message.
201              
202             =cut
203              
204             sub error_message {
205 7     7 1 2696 return shift()->{error_message};
206             }
207              
208              
209             =head1 AUTHOR
210              
211             Dominic Sonntag, C<< >>
212              
213             =head1 BUGS AND SUPPORT
214              
215             Please report any bugs or feature requests on Github: L
216              
217              
218             =head1 LICENSE AND COPYRIGHT
219              
220             Copyright 2017 Dominic Sonntag.
221              
222             This program is free software; you can redistribute it and/or modify it
223             under the terms of the the Artistic License (2.0). You may obtain a
224             copy of the full license at:
225              
226             L
227              
228             =cut
229              
230             1; # End of SMS::API::CMTelecom