line |
stmt |
bran |
cond |
sub |
pod |
time |
code |
1
|
|
|
|
|
|
|
package SMS::Send::Mocean; |
2
|
|
|
|
|
|
|
|
3
|
4
|
|
|
4
|
|
497300
|
use 5.008_005; |
|
4
|
|
|
|
|
23
|
|
4
|
4
|
|
|
4
|
|
21
|
use strict; |
|
4
|
|
|
|
|
7
|
|
|
4
|
|
|
|
|
95
|
|
5
|
4
|
|
|
4
|
|
20
|
use warnings; |
|
4
|
|
|
|
|
8
|
|
|
4
|
|
|
|
|
99
|
|
6
|
4
|
|
|
4
|
|
19
|
use utf8; |
|
4
|
|
|
|
|
7
|
|
|
4
|
|
|
|
|
26
|
|
7
|
|
|
|
|
|
|
|
8
|
4
|
|
|
4
|
|
95
|
use Carp; |
|
4
|
|
|
|
|
6
|
|
|
4
|
|
|
|
|
257
|
|
9
|
4
|
|
|
4
|
|
1943
|
use HTTP::Request::Common qw(POST); |
|
4
|
|
|
|
|
91043
|
|
|
4
|
|
|
|
|
281
|
|
10
|
4
|
|
|
4
|
|
2446
|
use JSON qw(decode_json); |
|
4
|
|
|
|
|
37412
|
|
|
4
|
|
|
|
|
24
|
|
11
|
4
|
|
|
4
|
|
3108
|
use LWP::UserAgent; |
|
4
|
|
|
|
|
98949
|
|
|
4
|
|
|
|
|
169
|
|
12
|
4
|
|
|
4
|
|
1794
|
use URL::Encode qw(url_decode); |
|
4
|
|
|
|
|
20181
|
|
|
4
|
|
|
|
|
239
|
|
13
|
4
|
|
|
4
|
|
1898
|
use XML::Hash::LX qw(xml2hash); |
|
4
|
|
|
|
|
185371
|
|
|
4
|
|
|
|
|
28
|
|
14
|
|
|
|
|
|
|
|
15
|
4
|
|
|
4
|
|
340
|
use base 'SMS::Send::Driver'; |
|
4
|
|
|
|
|
10
|
|
|
4
|
|
|
|
|
2143
|
|
16
|
|
|
|
|
|
|
|
17
|
|
|
|
|
|
|
our $VERSION = '0.03'; |
18
|
|
|
|
|
|
|
|
19
|
|
|
|
|
|
|
sub new { |
20
|
4
|
|
|
4
|
1
|
3335
|
my $class = shift; |
21
|
4
|
|
|
|
|
12
|
my $args = { @_ }; |
22
|
|
|
|
|
|
|
|
23
|
4
|
|
|
|
|
19
|
_required($args, qw(_api_key _api_secret)); |
24
|
|
|
|
|
|
|
|
25
|
|
|
|
|
|
|
my $opts = { |
26
|
|
|
|
|
|
|
_endpoint => 'https://rest.moceanapi.com/rest/1/sms', |
27
|
1
|
|
|
|
|
2
|
%{$args} |
|
1
|
|
|
|
|
5
|
|
28
|
|
|
|
|
|
|
}; |
29
|
|
|
|
|
|
|
|
30
|
1
|
|
|
|
|
2
|
my $self = bless $opts, $class; |
31
|
|
|
|
|
|
|
|
32
|
1
|
|
|
|
|
10
|
$self->{ua} = LWP::UserAgent->new( |
33
|
|
|
|
|
|
|
agent => __PACKAGE__ . q| v| . $SMS::Send::Mocean::VERSION, |
34
|
|
|
|
|
|
|
timeout => 10, |
35
|
|
|
|
|
|
|
); |
36
|
|
|
|
|
|
|
|
37
|
1
|
|
|
|
|
2865
|
return $self; |
38
|
|
|
|
|
|
|
} |
39
|
|
|
|
|
|
|
|
40
|
|
|
|
|
|
|
sub send_sms { |
41
|
0
|
|
|
0
|
1
|
0
|
my $self = shift; |
42
|
0
|
|
|
|
|
0
|
my $args = { @_ }; |
43
|
|
|
|
|
|
|
|
44
|
0
|
|
|
|
|
0
|
_required($args, qw(to text _from)); |
45
|
|
|
|
|
|
|
|
46
|
0
|
|
|
|
|
0
|
my @extra_args = qw( |
47
|
|
|
|
|
|
|
_udh |
48
|
|
|
|
|
|
|
_coding |
49
|
|
|
|
|
|
|
_dlr_mask |
50
|
|
|
|
|
|
|
_dlr_url |
51
|
|
|
|
|
|
|
_schedule |
52
|
|
|
|
|
|
|
_mclass |
53
|
|
|
|
|
|
|
_alt_dcs |
54
|
|
|
|
|
|
|
_charset |
55
|
|
|
|
|
|
|
_validity |
56
|
|
|
|
|
|
|
_resp_format |
57
|
|
|
|
|
|
|
); |
58
|
|
|
|
|
|
|
|
59
|
0
|
|
|
|
|
0
|
my @extra_params; |
60
|
0
|
|
|
|
|
0
|
foreach (@extra_args) { |
61
|
|
|
|
|
|
|
push @extra_params, _to_mocean_field_name($_) => $args->{$_} |
62
|
0
|
0
|
|
|
|
0
|
if (defined $args->{$_}); |
63
|
|
|
|
|
|
|
} |
64
|
|
|
|
|
|
|
|
65
|
|
|
|
|
|
|
my $request = POST($self->{_endpoint}, [ |
66
|
|
|
|
|
|
|
'mocean-api-key' => $self->{_api_key}, |
67
|
|
|
|
|
|
|
'mocean-api-secret' => $self->{_api_secret}, |
68
|
|
|
|
|
|
|
'mocean-to' => $args->{to}, |
69
|
|
|
|
|
|
|
'mocean-text' => $args->{text}, |
70
|
|
|
|
|
|
|
'mocean-from' => $args->{_from}, |
71
|
|
|
|
|
|
|
@extra_params |
72
|
0
|
|
|
|
|
0
|
]); |
73
|
|
|
|
|
|
|
|
74
|
0
|
0
|
0
|
|
|
0
|
my $format = defined $args->{_resp_format} && lc($args->{_resp_format}) eq 'json' |
75
|
|
|
|
|
|
|
? 'json' : 'xml'; |
76
|
|
|
|
|
|
|
|
77
|
0
|
|
|
|
|
0
|
my $response = $self->{ua}->request($request); |
78
|
|
|
|
|
|
|
|
79
|
0
|
0
|
|
|
|
0
|
if ($response->is_success) { |
80
|
0
|
0
|
|
|
|
0
|
my $content = ($format eq 'json') |
81
|
|
|
|
|
|
|
? decode_json($response->decoded_content) |
82
|
|
|
|
|
|
|
: xml2hash $response->decoded_content; |
83
|
|
|
|
|
|
|
|
84
|
0
|
|
|
|
|
0
|
return $content->{result}->{message}; |
85
|
|
|
|
|
|
|
} |
86
|
|
|
|
|
|
|
else { |
87
|
0
|
|
|
|
|
0
|
my ($error_code, $error_msg) = ('', ''); |
88
|
|
|
|
|
|
|
|
89
|
0
|
0
|
|
|
|
0
|
if ($format eq 'json') { |
90
|
0
|
|
|
|
|
0
|
my $content = decode_json($response->decoded_content); |
91
|
0
|
|
|
|
|
0
|
$error_code = $content->{status}; |
92
|
0
|
|
|
|
|
0
|
$error_msg = url_decode($content->{err_msg}); |
93
|
|
|
|
|
|
|
} |
94
|
|
|
|
|
|
|
else { |
95
|
0
|
|
|
|
|
0
|
my $content = xml2hash $response->decoded_content; |
96
|
0
|
|
|
|
|
0
|
$error_code = $content->{result}->{status}; |
97
|
0
|
|
|
|
|
0
|
$error_msg = url_decode($content->{result}->{err_msg}); |
98
|
|
|
|
|
|
|
} |
99
|
|
|
|
|
|
|
|
100
|
0
|
|
|
|
|
0
|
croak sprintf "\n%s (error code: %d)", $error_msg, $error_code; |
101
|
|
|
|
|
|
|
} |
102
|
|
|
|
|
|
|
} |
103
|
|
|
|
|
|
|
|
104
|
|
|
|
|
|
|
sub _required { |
105
|
5
|
|
|
5
|
|
189
|
my ($args, @required_args) = @_; |
106
|
|
|
|
|
|
|
|
107
|
5
|
|
|
|
|
12
|
foreach (@required_args) { |
108
|
8
|
100
|
|
|
|
83
|
croak "'$_' parameter required" unless $args->{$_} |
109
|
|
|
|
|
|
|
} |
110
|
1
|
|
|
|
|
2
|
return; |
111
|
|
|
|
|
|
|
} |
112
|
|
|
|
|
|
|
|
113
|
|
|
|
|
|
|
sub _to_mocean_field_name { |
114
|
3
|
|
|
3
|
|
1509
|
my ($name) = @_; |
115
|
|
|
|
|
|
|
|
116
|
3
|
|
|
|
|
7
|
$name =~ tr/_/-/; |
117
|
|
|
|
|
|
|
|
118
|
3
|
|
|
|
|
18
|
return qq|mocean$name|; |
119
|
|
|
|
|
|
|
} |
120
|
|
|
|
|
|
|
|
121
|
|
|
|
|
|
|
|
122
|
|
|
|
|
|
|
1; |
123
|
|
|
|
|
|
|
__END__ |
124
|
|
|
|
|
|
|
|
125
|
|
|
|
|
|
|
=encoding utf-8 |
126
|
|
|
|
|
|
|
|
127
|
|
|
|
|
|
|
=for stopwords mocean sms |
128
|
|
|
|
|
|
|
|
129
|
|
|
|
|
|
|
=head1 NAME |
130
|
|
|
|
|
|
|
|
131
|
|
|
|
|
|
|
SMS::Send::Mocean - SMS::Send driver to send messages via Mocean, |
132
|
|
|
|
|
|
|
https://moceanapi.com/. |
133
|
|
|
|
|
|
|
|
134
|
|
|
|
|
|
|
=head1 SYNOPSIS |
135
|
|
|
|
|
|
|
|
136
|
|
|
|
|
|
|
use SMS::Send; |
137
|
|
|
|
|
|
|
|
138
|
|
|
|
|
|
|
my $gateway = SMS::Send->new( |
139
|
|
|
|
|
|
|
'Mocean', |
140
|
|
|
|
|
|
|
'_api_key' => 'foo', |
141
|
|
|
|
|
|
|
'_api_secret' => 'bar' |
142
|
|
|
|
|
|
|
); |
143
|
|
|
|
|
|
|
|
144
|
|
|
|
|
|
|
$gateway->send_sms( |
145
|
|
|
|
|
|
|
to => '+60123456789', |
146
|
|
|
|
|
|
|
ext => 'Hello', |
147
|
|
|
|
|
|
|
_from => 'foobar' |
148
|
|
|
|
|
|
|
); |
149
|
|
|
|
|
|
|
|
150
|
|
|
|
|
|
|
=head1 DESCRIPTION |
151
|
|
|
|
|
|
|
|
152
|
|
|
|
|
|
|
SMS::Send::Mocean is a driver for L<SMS::Send|SMS::Send> to send message via Mocean, |
153
|
|
|
|
|
|
|
https://moceanapi.com/. |
154
|
|
|
|
|
|
|
|
155
|
|
|
|
|
|
|
=head1 DEVELOPMENT |
156
|
|
|
|
|
|
|
|
157
|
|
|
|
|
|
|
Source repository at L<https://github.com/kianmeng/send-sms-mocean|https://github.com/kianmeng/sms-send-mocean>. |
158
|
|
|
|
|
|
|
|
159
|
|
|
|
|
|
|
How to contribute? Follow through the L<CONTRIBUTING.md|https://github.com/kianmeng/sms-send-mocean/blob/master/CONTRIBUTING.md> document to setup your development environment. |
160
|
|
|
|
|
|
|
|
161
|
|
|
|
|
|
|
=head1 METHODS |
162
|
|
|
|
|
|
|
|
163
|
|
|
|
|
|
|
=head2 new(_api_key, _api_secret) |
164
|
|
|
|
|
|
|
|
165
|
|
|
|
|
|
|
Construct a new SMS::Send instance. |
166
|
|
|
|
|
|
|
|
167
|
|
|
|
|
|
|
my $gateway = SMS::Send->new( |
168
|
|
|
|
|
|
|
'Mocean', |
169
|
|
|
|
|
|
|
'_api_key' => 'foo', |
170
|
|
|
|
|
|
|
'_api_secret' => 'bar' |
171
|
|
|
|
|
|
|
); |
172
|
|
|
|
|
|
|
|
173
|
|
|
|
|
|
|
=head3 _api_key |
174
|
|
|
|
|
|
|
|
175
|
|
|
|
|
|
|
Compulsory. The API access key used to make request through web service. |
176
|
|
|
|
|
|
|
|
177
|
|
|
|
|
|
|
=head3 _api_secret |
178
|
|
|
|
|
|
|
|
179
|
|
|
|
|
|
|
Compulsory. The API secret key. |
180
|
|
|
|
|
|
|
|
181
|
|
|
|
|
|
|
=head2 send_sms(to, text, _from, [%params]) |
182
|
|
|
|
|
|
|
|
183
|
|
|
|
|
|
|
Send the SMS text to a mobile user. |
184
|
|
|
|
|
|
|
|
185
|
|
|
|
|
|
|
# Default parameters with XML response format if the '_resp_format' field |
186
|
|
|
|
|
|
|
# is not defined. |
187
|
|
|
|
|
|
|
$gateway->send_sms( |
188
|
|
|
|
|
|
|
to => '+60123456789', |
189
|
|
|
|
|
|
|
ext => 'Hello', |
190
|
|
|
|
|
|
|
_from => 'foobar', |
191
|
|
|
|
|
|
|
); |
192
|
|
|
|
|
|
|
|
193
|
|
|
|
|
|
|
# With JSON response format. |
194
|
|
|
|
|
|
|
$gateway->send_sms( |
195
|
|
|
|
|
|
|
to => '+60123456789', |
196
|
|
|
|
|
|
|
ext => 'Hello', |
197
|
|
|
|
|
|
|
_from => 'foobar', |
198
|
|
|
|
|
|
|
_resp_format => 'json', |
199
|
|
|
|
|
|
|
); |
200
|
|
|
|
|
|
|
|
201
|
|
|
|
|
|
|
=head3 to |
202
|
|
|
|
|
|
|
|
203
|
|
|
|
|
|
|
Compulsory. The required field needed by SMS::Send. Only accept leading-plus |
204
|
|
|
|
|
|
|
number in the format of "+99 999 9999". |
205
|
|
|
|
|
|
|
|
206
|
|
|
|
|
|
|
=head3 text |
207
|
|
|
|
|
|
|
|
208
|
|
|
|
|
|
|
Compulsory. The required field needed by SMS::Send. The content of the SMS |
209
|
|
|
|
|
|
|
message. Depends on the language of the content, there is a limit of characters |
210
|
|
|
|
|
|
|
that can be sent. |
211
|
|
|
|
|
|
|
|
212
|
|
|
|
|
|
|
=head3 _from |
213
|
|
|
|
|
|
|
|
214
|
|
|
|
|
|
|
Compulsory. The login username of the Mocean API portal. |
215
|
|
|
|
|
|
|
|
216
|
|
|
|
|
|
|
=head3 [%params] |
217
|
|
|
|
|
|
|
|
218
|
|
|
|
|
|
|
Optional. Additional parameters that can be used when sending SMS. Check the |
219
|
|
|
|
|
|
|
Mocean API documentation on the L<available parameters|https://moceanapi.com/docs/#sms-api>. |
220
|
|
|
|
|
|
|
Due to the design constraints of L<SMS::Send::Driver|SMS::Send::Driver>, all |
221
|
|
|
|
|
|
|
parameters name must start with underscore. For example, '_resp_format'. This |
222
|
|
|
|
|
|
|
driver will convert the parameter name to equivalent format used by Mocean. In |
223
|
|
|
|
|
|
|
this case, '_foo_bar' will be formatted as 'mocean-resp-format'. |
224
|
|
|
|
|
|
|
|
225
|
|
|
|
|
|
|
$gateway->send_sms( |
226
|
|
|
|
|
|
|
to => '+60123456789', |
227
|
|
|
|
|
|
|
ext => 'Hello', |
228
|
|
|
|
|
|
|
_from => 'foobar', |
229
|
|
|
|
|
|
|
_resp_format => 'json', |
230
|
|
|
|
|
|
|
_charset => 'utf-8', |
231
|
|
|
|
|
|
|
); |
232
|
|
|
|
|
|
|
|
233
|
|
|
|
|
|
|
=head1 AUTHOR |
234
|
|
|
|
|
|
|
|
235
|
|
|
|
|
|
|
Kian Meng, Ang E<lt>kianmeng@cpan.orgE<gt> |
236
|
|
|
|
|
|
|
|
237
|
|
|
|
|
|
|
=head1 COPYRIGHT AND LICENSE |
238
|
|
|
|
|
|
|
|
239
|
|
|
|
|
|
|
This software is Copyright (c) 2019 Kian Meng, Ang. |
240
|
|
|
|
|
|
|
|
241
|
|
|
|
|
|
|
This is free software, licensed under: |
242
|
|
|
|
|
|
|
|
243
|
|
|
|
|
|
|
The Artistic License 2.0 (GPL Compatible) |
244
|
|
|
|
|
|
|
|
245
|
|
|
|
|
|
|
=head1 SEE ALSO |
246
|
|
|
|
|
|
|
|
247
|
|
|
|
|
|
|
L<SMS::Driver|SMS::Driver> |