File Coverage

blib/lib/WWW/Namecheap/API.pm
Criterion Covered Total %
statement 47 80 58.7
branch 6 24 25.0
condition 2 12 16.6
subroutine 13 15 86.6
pod 5 5 100.0
total 73 136 53.6


line stmt bran cond sub pod time code
1             package WWW::Namecheap::API;
2              
3 11     11   149710 use 5.006;
  11         29  
4 11     11   36 use strict;
  11         7  
  11         161  
5 11     11   30 use warnings;
  11         11  
  11         182  
6 11     11   30 use Carp();
  11         7  
  11         106  
7 11     11   6360 use LWP::UserAgent ();
  11         337693  
  11         224  
8 11     11   54 use URI::Escape;
  11         16  
  11         535  
9 11     11   7840 use XML::Simple;
  11         67491  
  11         88  
10              
11             # For convenience methods
12 11     11   5368 use WWW::Namecheap::Domain ();
  11         22  
  11         182  
13 11     11   3784 use WWW::Namecheap::DNS ();
  11         18  
  11         5518  
14              
15             =head1 NAME
16              
17             WWW::Namecheap::API - Perl interface to the Namecheap API
18              
19             =cut
20              
21             our $VERSION = '0.06';
22             our %APIURL = (
23             prod => 'https://api.namecheap.com/xml.response',
24             test => 'https://api.sandbox.namecheap.com/xml.response',
25             );
26              
27             =head1 SYNOPSIS
28              
29             Perl interface to the Namecheap API. API details at:
30              
31             https://www.namecheap.com/support/api/api.aspx
32              
33             Actual API calls happen in the other modules in the distribution, which
34             can be accessed via convenience methods from an API object. Brief
35             example:
36              
37             use WWW::Namecheap::API;
38              
39             my $api = WWW::Namecheap::API->new(
40             System => 'test',
41             ApiUser => 'wwwnamecheapapi',
42             ApiKey => 'keyhere',
43             DefaultIp => '1.2.3.4',
44             );
45              
46             my $result = $api->domain->check(Domains => ['example.com']);
47              
48             if ($result->{'example.com'}) {
49             $api->domain->create(
50             DomainName => 'example.com',
51             Years => 1,
52             Registrant => {
53             OrganizationName => 'Foo Bar Inc.',
54             FirstName => 'Joe',
55             LastName => 'Manager',
56             Address1 => '123 Fake Street',
57             City => 'Univille',
58             StateProvince => 'SD',
59             PostalCode => '12345',
60             Country => 'US',
61             Phone => '+1.2125551212',
62             EmailAddress => 'joe@example.com',
63             },
64             );
65             }
66              
67             =head1 GLOBAL PARAMETERS
68              
69             There are a few parameters that can be included in any of the individual
70             methods within the Namecheap API modules. These are listed below.
71              
72             =head2 ClientIp
73              
74             The client IP address for which this request is effective. If a DefaultIp
75             was not provided when setting up the parent API object, this parameter
76             is required, otherwise it is optional.
77              
78             =head2 UserName
79              
80             A sub-user (see L) under which the command should
81             be performed. A DefaultUser may be specified at API object creation
82             time; if one is not specified there, the default is to use the ApiUser
83             unless a UserName is provided for the specific command being issued.
84              
85             =head1 SUBROUTINES/METHODS
86              
87             =head2 WWW::Namecheap::API->new(%hash)
88              
89             Instantiate a new API object. Example:
90              
91             my $api = WWW::Namecheap::API->new(
92             System => 'test', # or 'prod' for production, default test
93             ApiUser => 'username',
94             ApiKey => 'apikey',
95             DefaultIp => '1.2.3.4', # optional
96             DefaultUser => 'otheruser', #optional, default ApiUser
97             ApiUrl => 'https://foo.bar/', # overrides URL chosen by System
98             Agent => 'My API Agent/1.0', # optional, overrides default UA
99             );
100              
101             Only ApiUser and ApiKey are required, in which case System will default
102             to 'test' and Agent defaults to 'WWW::Namecheap::API/$VERSION'. This
103             API object will be passed to the constructors of the other classes in
104             the distribution (or you can use its built-in convenience methods to
105             get objects of those classes directly).
106              
107             =cut
108              
109             sub new {
110 1     1 1 72879 my $class = shift;
111              
112 1         3 my $params = _argparse(@_);
113              
114 1         2 for (qw(ApiUser ApiKey)) {
115 2 50       6 Carp::croak("${class}->new(): Mandatory parameter $_ not provided.") unless $params->{$_};
116             }
117              
118             my $ua = LWP::UserAgent->new(
119 1   33     11 agent => $params->{'Agent'} || "WWW::Namecheap::API/$VERSION",
120             );
121              
122 1         1948 my $apiurl;
123 1 50       4 if ($params->{'ApiUrl'}) {
124 0         0 $apiurl = $params->{'ApiUrl'}; # trust the user?!?!
125             } else {
126 1 50       2 if ($params->{'System'}) {
127 1         3 $apiurl = $APIURL{$params->{'System'}};
128             } else {
129 0         0 $apiurl = $APIURL{'test'};
130             }
131             }
132              
133             my $self = {
134             ApiUrl => $apiurl,
135             ApiUser => $params->{'ApiUser'},
136             ApiKey => $params->{'ApiKey'},
137             DefaultUser => $params->{'DefaultUser'} || $params->{'ApiUser'},
138 1   33     8 DefaultIp => $params->{'DefaultIp'},
139             _ua => $ua,
140             };
141              
142 1         6 return bless($self, $class);
143             }
144              
145             =head2 $api->request(%hash)
146              
147             Send a request to the Namecheap API. Returns the XML response parsed into
148             Perl form by XML::Simple. Intended for use by sub-classes, not outside
149             calls. Parameters should be of the type and quantity required by the
150             Namecheap API for the given Command. Example:
151              
152             my $xml = $api->request(
153             Command => 'namecheap.domains.check',
154             DomainList => 'example.com,example2.net',
155             ClientIp => '1.2.3.4', # required if no DefaultIp in $api
156             );
157              
158             =cut
159              
160             sub request {
161 0     0 1 0 my $self = shift;
162 0         0 my %reqparams = @_;
163              
164 0 0       0 unless ($reqparams{'Command'}) {
165 0         0 Carp::carp("No command specified, bailing!");
166 0         0 return;
167             }
168              
169 0   0     0 my $clientip = delete($reqparams{'ClientIp'}) || $self->{'DefaultIp'};
170 0 0       0 unless ($clientip) {
171 0         0 Carp::carp("No Client IP or default IP specified, cannot perform request.");
172 0         0 return;
173             }
174 0   0     0 my $username = delete($reqparams{'UserName'}) || $self->{'DefaultUser'};
175              
176 0 0       0 map { delete($reqparams{$_}) unless defined($reqparams{$_}) } keys %reqparams;
  0         0  
177              
178 0         0 my $ua = $self->{_ua}; # convenience
179             my $url = sprintf('%s?ApiUser=%s&ApiKey=%s&UserName=%s&Command=%s&ClientIp=%s&',
180             $self->{'ApiUrl'}, $self->{'ApiUser'}, $self->{'ApiKey'},
181 0         0 $username, delete($reqparams{'Command'}), $clientip);
182 0         0 $url .= join('&', map { join('=', map { uri_escape($_) } each %reqparams) } keys %reqparams);
  0         0  
  0         0  
183             #print STDERR "Sent URL $url\n";
184 0         0 my $response = $ua->get($url);
185              
186 0 0       0 unless ($response->is_success) {
187 0         0 Carp::carp("Request failed: " . $response->message);
188 0         0 return;
189             }
190              
191 0         0 my $xml = XMLin($response->content);
192              
193 0 0       0 if ($xml->{Status} eq 'ERROR') {
194 0         0 $self->{_error} = $xml;
195 0         0 return;
196             }
197 0         0 return $xml;
198             }
199              
200             =head2 $api->domain()
201              
202             Helper method to create and return a WWW::Namecheap::Domain object utilizing
203             this API object. Always returns the same object within a given session via
204             internal caching.
205              
206             =cut
207              
208             sub domain {
209 1     1 1 336 my $self = shift;
210              
211 1 50       5 if ($self->{_domain}) {
212 0         0 return $self->{_domain};
213             }
214              
215 1         8 return $self->{_domain} = WWW::Namecheap::Domain->new(API => $self);
216             }
217              
218             =head2 $api->dns()
219              
220             Helper method to create and return a WWW::Namecheap::DNS object utilizing
221             this API object. Always returns the same object within a given session via
222             internal caching.
223              
224             =cut
225              
226             sub dns {
227 1     1 1 1669 my $self = shift;
228              
229 1 50       4 if ($self->{_dns}) {
230 0         0 return $self->{_dns};
231             }
232              
233 1         6 return $self->{_dns} = WWW::Namecheap::DNS->new(API => $self);
234             }
235              
236             =head2 $api->error()
237              
238             Returns the full XML response from the API if an error occurred during
239             the request. Most likely key of interest is $xml->{Errors} and below.
240              
241             =cut
242              
243             sub error {
244 0     0 1 0 return $_[0]->{_error};
245             }
246              
247             sub _argparse {
248 1     1   2 my $hashref;
249 1 50       4 if (@_ % 2 == 0) {
    0          
250 1         5 $hashref = { @_ }
251             } elsif (ref($_[0]) eq 'HASH') {
252 0         0 $hashref = \%{$_[0]};
  0         0  
253             }
254 1         2 return $hashref;
255             }
256              
257             =head1 AUTHOR
258              
259             Tim Wilde, C<< >>
260              
261             =head1 BUGS
262              
263             Please report any bugs or feature requests to C, or through
264             the web interface at L. I will be notified, and then you'll
265             automatically be notified of progress on your bug as I make changes.
266              
267              
268              
269             =head1 SUPPORT
270              
271             You can find documentation for this module with the perldoc command.
272              
273             perldoc WWW::Namecheap::API
274              
275              
276             You can also look for information at:
277              
278             =over 4
279              
280             =item * RT: CPAN's request tracker (report bugs here)
281              
282             L
283              
284             =item * AnnoCPAN: Annotated CPAN documentation
285              
286             L
287              
288             =item * CPAN Ratings
289              
290             L
291              
292             =item * Search CPAN
293              
294             L
295              
296             =back
297              
298              
299             =head1 ACKNOWLEDGEMENTS
300              
301              
302             =head1 LICENSE AND COPYRIGHT
303              
304             Copyright 2011 Tim Wilde.
305              
306             This program is free software; you can redistribute it and/or modify it
307             under the terms of either: the GNU General Public License as published
308             by the Free Software Foundation; or the Artistic License.
309              
310             See http://dev.perl.org/licenses/ for more information.
311              
312              
313             =cut
314              
315             1; # End of WWW::Namecheap::API