File Coverage

blib/lib/Business/US/USPS/WebTools.pm
Criterion Covered Total %
statement 33 63 52.3
branch 5 10 50.0
condition 4 8 50.0
subroutine 11 19 57.8
pod 6 6 100.0
total 59 106 55.6


line stmt bran cond sub pod time code
1             # $Id: WebTools.pm 2360 2007-11-03 04:48:52Z comdog $
2             package Business::US::USPS::WebTools;
3 2     2   7454 use strict;
  2         4  
  2         82  
4 2     2   12 no warnings 'uninitialized';
  2         2  
  2         84  
5              
6 2     2   11 use Carp qw(croak);
  2         5  
  2         127  
7              
8 2     2   1709 use subs qw();
  2         59  
  2         44  
9 2     2   11 use vars qw($VERSION);
  2         4  
  2         1183  
10              
11             $VERSION = '1.11';
12              
13             =head1 NAME
14              
15             Business::US::USPS::WebTools - Use the US Postal Service Web Tools
16              
17             =head1 SYNOPSIS
18              
19             use Business::US::USPS::WebTools;
20            
21             # see subclasses for API details
22              
23             =head1 DESCRIPTION
24              
25             *** THIS IS ALPHA SOFTWARE ***
26              
27             This is the base class for the WebTools web service from the US Postal
28             Service. The USPS offers several services, and this module handles the
29             parts common to all of them: making the request, getting the response,
30             parsing error reponses, and so on. The interesting stuff happens in
31             one of the subclasses which implement a particular service. So far,
32             the only subclass in this distribution is
33             C.
34              
35             =over
36              
37             =cut
38              
39             my $LiveServer = "production.shippingapis.com";
40             my $TestServer = "testing.shippingapis.com";
41              
42             =item new( ANONYMOUS_HASH )
43              
44             Make the web service object. Pass is an anonymous hash with these keys:
45              
46             UserID the user id provided by the USPS
47             Password the password provided by the USPS
48             Testing true or false, to select the right server
49            
50             If you don't pass the UserID or Password entries, C looks in the
51             environment variables USPS_WEBTOOLS_USERID and USPS_WEBTOOLS_PASSWORD.
52              
53             If C cannot find both the User ID and the Password, it croaks.
54              
55             If you pass a true value with the Testing key, the object will use the
56             testing server host name and the testing URL path. If the Testing key
57             is false or not present, the object uses the live server details.
58              
59             =cut
60              
61             sub new
62             {
63 3     3 1 1285 my( $class, $args ) = @_;
64            
65 3   33     20 my $user_id = $args->{UserID} || $ENV{USPS_WEBTOOLS_USERID} ||
66             croak "No user ID for USPS WebTools!";
67              
68 3   33     17 my $password = $args->{Password} || $ENV{USPS_WEBTOOLS_PASSWORD} ||
69             croak "No password for USPS WebTools!";
70            
71 3         5 $args->{UserID} = $user_id;
72 3         7 $args->{Password} = $password;
73 3   100     17 $args->{testing} = $args->{Testing} || 0;
74 3         9 $args->{live} = ! $args->{Testing};
75            
76 3         15 bless $args, $class;
77             }
78              
79 6     6   629 sub _testing { $_[0]->{testing} }
80 8     8   42 sub _live { $_[0]->{live} }
81              
82             =item userid
83              
84             Returns the User ID for the web service. You need to get this from the
85             US Postal Service.
86              
87             =item password
88              
89             Returns the Password for the web service. You need to get this from the
90             US Postal Service.
91              
92             =item url
93              
94             Returns the URL for the request to the web service. So far, all requests
95             are GET request with all of the data in the query string.
96              
97             =item response
98              
99             Returns the response from the web service. This is the slightly modified
100             response. So far it only fixes up line endings and normalizes some error
101             output for inconsistent responses from different physical servers.
102              
103             =cut
104              
105 0     0 1 0 sub userid { $_[0]->{UserID} }
106 0     0 1 0 sub password { $_[0]->{Password} }
107              
108 0 0   0 1 0 sub url { $_[0]->{url} || $_[0]->_make_url }
109 0     0 1 0 sub response { $_[0]->{response} }
110              
111             sub _api_host
112             {
113 3     3   7 my $self = shift;
114            
115 3 100       5 if( $self->_testing ) { $TestServer }
  1 50       5  
116 2         7 elsif( $self->_live ) { $LiveServer }
117 0         0 else { die "Am I testing or live?" }
118             }
119              
120             sub _api_path {
121 3 100   3   10 $_[0]->_live ?
122             "/ShippingAPI.dll"
123             :
124             "/ShippingAPITest.dll"
125             }
126              
127             sub _make_query_string
128             {
129 0     0     require URI;
130            
131 0           my( $self, $hash ) = @_;
132            
133 0           my $xml = $self->_make_query_xml( $hash );
134            
135 0           my $uri = URI->new;
136 0           $uri->query_form(
137             API => $self->_api_name,
138             XML => $xml,
139             );
140            
141 0           $uri->query; # this should work, but doesn't
142             }
143            
144             sub _make_url
145             {
146 0     0     my( $self, $hash ) = @_;
147            
148 0           $self->{url} = qq|http://| . $self->_api_host . $self->_api_path .
149             "?" . $self->_make_query_string( $hash );
150             }
151            
152             sub _make_request
153             {
154 0     0     my( $self, $url ) = @_;
155 0           require LWP::Simple;
156            
157 0           $self->{error} = undef;
158            
159 0           $self->{response} = LWP::Simple::get( $self->url );
160 0           $self->{response} =~ s/\015\012/\n/g;
161              
162 0           $self->is_error;
163            
164 2     2   1910 use Data::Dumper;
  2         13845  
  2         707  
165             # print STDERR "In _make_request:\n" . Dumper( $self ) . "\n";
166            
167 0           $self->{response};
168             }
169              
170             =item is_error
171              
172             Returns true if the response to the last request was an error, and false
173             otherwise.
174              
175             If the response was an error, this method sets various fields in the
176             object:
177              
178             $self->{error}{number}
179             $self->{error}{source}
180             $self->{error}{description}
181             $self->{error}{help_file}
182             $self->{error}{help_context}
183              
184             =cut
185              
186             sub is_error
187             {
188 0     0 1   my $self = shift;
189            
190 0 0         return 0 unless $self->response =~ "";
191            
192 0           $self->{error} = {};
193            
194             # Apparently not all servers return this string in the
195             # same way. Some have SOL and some have SoL
196 0           $self->{response} =~ s/SOLServer/SOLServer/ig;
197            
198 0           ( $self->{error}{number} ) = $self->response =~ m|(-?\d+)|g;
199 0           ( $self->{error}{source} ) = $self->response =~ m|(.*?)|g;
200 0           ( $self->{error}{description} ) = $self->response =~ m|(.*?)|g;
201 0           ( $self->{error}{help_file} ) = $self->response =~ m|(.*?)|ig;
202 0           ( $self->{error}{help_context} ) = $self->response =~ m|(.*?)|ig;
203            
204 0           1;
205             }
206              
207             =back
208              
209             =head1 SEE ALSO
210              
211             The WebTools API is documented on the US Postal Service's website:
212              
213             http://www.usps.com/webtools/htm/Address-Information.htm
214              
215             =head1 SOURCE AVAILABILITY
216              
217             This source is part of a SourceForge project which always has the
218             latest sources in CVS, as well as all of the previous releases.
219              
220             http://sourceforge.net/projects/brian-d-foy/
221              
222             If, for some reason, I disappear from the world, one of the other
223             members of the project can shepherd this module appropriately.
224              
225             =head1 AUTHOR
226              
227             brian d foy, C<< >>
228              
229             =head1 COPYRIGHT AND LICENSE
230              
231             Copyright (c) 2006-2007 brian d foy. All rights reserved.
232              
233             This program is free software; you can redistribute it and/or modify
234             it under the same terms as Perl itself.
235              
236             =cut
237              
238             1;