File Coverage

blib/lib/Business/US/USPS/WebTools.pm
Criterion Covered Total %
statement 40 70 57.1
branch 5 10 50.0
condition 2 8 25.0
subroutine 15 24 62.5
pod 9 9 100.0
total 71 121 58.6


line stmt bran cond sub pod time code
1 2     2   1525 use v5.10;
  2         7  
2 2     2   1075 use utf8;
  2         25  
  2         10  
3              
4             package Business::US::USPS::WebTools;
5 2     2   76 use strict;
  2         3  
  2         41  
6 2     2   9 no warnings 'uninitialized';
  2         3  
  2         84  
7              
8 2     2   9 use Carp qw(carp croak);
  2         4  
  2         116  
9              
10 2     2   1132 use subs qw();
  2         43  
  2         49  
11 2     2   10 use vars qw($VERSION);
  2         4  
  2         1171  
12              
13             $VERSION = '1.125';
14              
15             =encoding utf8
16              
17             =head1 NAME
18              
19             Business::US::USPS::WebTools - Use the US Postal Service Web Tools
20              
21             =head1 SYNOPSIS
22              
23             use Business::US::USPS::WebTools;
24              
25             # see subclasses for API details
26              
27             =head1 DESCRIPTION
28              
29             *** THIS IS ALPHA SOFTWARE ***
30              
31             This is the base class for the WebTools web service from the US Postal
32             Service. The USPS offers several services, and this module handles the
33             parts common to all of them: making the request, getting the response,
34             parsing error reponses, and so on. The interesting stuff happens in
35             one of the subclasses which implement a particular service. So far,
36             the only subclass in this distribution is
37             C.
38              
39             =over
40              
41             =cut
42              
43             =item new( ANONYMOUS_HASH )
44              
45             Make the web service object. Pass is an anonymous hash with these keys:
46              
47             UserID the user id provided by the USPS
48             Password the password provided by the USPS
49             Testing true or false, to select the right server
50              
51             If you don't pass the UserID or Password entries, C looks in the
52             environment variables USPS_WEBTOOLS_USERID and USPS_WEBTOOLS_PASSWORD.
53              
54             If C cannot find both the User ID and the Password, it croaks.
55              
56             If you pass a true value with the Testing key, the object will use the
57             testing server host name and the testing URL path. If the Testing key
58             is false or not present, the object uses the live server details.
59              
60             =cut
61              
62             sub new {
63 3     3 1 6295 my( $class, $args ) = @_;
64              
65             my $user_id = $args->{UserID} || $ENV{USPS_WEBTOOLS_USERID} ||
66 3   0     14 croak "No user ID for USPS WebTools! Pass UserID or set the USPS_WEBTOOLS_USERID environment varaible.";
67              
68             my $password = $args->{Password} || $ENV{USPS_WEBTOOLS_PASSWORD} ||
69 3   0     9 croak "No password for USPS WebTools! Pass Password or set the USPS_WEBTOOLS_PASSWORD environment variable.";
70              
71 3         7 $args->{UserID} = $user_id;
72 3         6 $args->{Password} = $password;
73 3   100     29 $args->{testing} = $args->{Testing} || 0;
74 3         8 $args->{live} = ! $args->{Testing};
75              
76 3         17 bless $args, $class;
77             }
78              
79 6     6   31 sub _testing { $_[0]->{testing} }
80 8     8   43 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 tx
98              
99             Returns the transaction from the Mojo::UserAgent request.
100              
101             =item response
102              
103             Returns the response from the web service. This is the slightly modified
104             response. So far it only fixes up line endings and normalizes some error
105             output for inconsistent responses from different physical servers.
106              
107             =cut
108              
109 0     0 1 0 sub userid { $_[0]->{UserID} }
110 0     0 1 0 sub password { $_[0]->{Password} }
111              
112 0 0   0 1 0 sub url { $_[0]->{url} || $_[0]->_make_url( $_[1] ) }
113 0     0 1 0 sub tx { $_[0]->{transaction} }
114 0     0 1 0 sub response { $_[0]->{response} }
115              
116             sub _api_host {
117 3     3   8 my $self = shift;
118              
119 3 100       8 if( $self->_testing ) { $self->test_server_host }
  1 50       3  
120 2         8 elsif( $self->_live ) { $self->live_server_host }
121 0         0 else { die "Am I testing or live?" }
122             }
123              
124             sub _api_path {
125 3 100   3   12 $_[0]->_live ?
126             "/ShippingAPI.dll"
127             :
128             "/ShippingAPI.dll"
129             }
130              
131             sub _make_url {
132 0     0   0 state $rc = require Mojo::URL;
133 0         0 my( $self, $hash ) = @_;
134              
135 0         0 $self->{url} = Mojo::URL->new
136             ->scheme('https')
137             ->host( $self->_api_host )
138             ->path( $self->_api_path )
139             ->query(
140             API => $self->_api_name,
141             XML => $self->_make_query_xml( $hash )
142             );
143             }
144              
145             sub _make_request {
146 0     0   0 my( $self, $url ) = @_;
147 0         0 state $rc = require Mojo::UserAgent;
148 0         0 state $ua = Mojo::UserAgent->new;
149              
150 0         0 $self->{error} = undef;
151              
152 0         0 $self->{transaction} = $ua->get( $self->url );
153 0         0 $self->{response} = $self->{transaction}->result->body;
154              
155 0         0 $self->is_error;
156              
157 2     2   1193 use Data::Dumper;
  2         12466  
  2         745  
158             # print STDERR "In _make_request:\n" . Dumper( $self ) . "\n";
159              
160 0         0 $self->{response};
161             }
162              
163             sub _clone {
164 0     0   0 my $rc = require Storable;
165 0         0 my( $self ) = @_;
166              
167 0         0 my $clone = Storable::dclone( $self );
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 0     0 1 0 my $self = shift;
188              
189 0 0       0 return 0 unless $self->response =~ "";
190              
191 0         0 $self->{error} = {};
192              
193             # Apparently not all servers return this string in the
194             # same way. Some have SOL and some have SoL
195 0         0 $self->{response} =~ s/SOLServer/SOLServer/ig;
196              
197 0         0 ( $self->{error}{number} ) = $self->response =~ m|(-?\d+)|g;
198 0         0 ( $self->{error}{source} ) = $self->response =~ m|(.*?)|g;
199 0         0 ( $self->{error}{description} ) = $self->response =~ m|(.*?)|g;
200 0         0 ( $self->{error}{help_file} ) = $self->response =~ m|(.*?)|ig;
201 0         0 ( $self->{error}{help_context} ) = $self->response =~ m|(.*?)|ig;
202              
203 0         0 1;
204             }
205              
206             =item live_server_host
207              
208             This is production.shippingapis.com. The modules choose this host
209             when you have not set C to a true value.
210              
211             =item test_server_host
212              
213             For most APIs, this is testing.shippingapis.com. The modules choose this host
214             when you have set C to a true value.
215              
216             =cut
217              
218 2     2 1 9 sub live_server_host { "production.shippingapis.com" };
219 1     1 1 5 sub test_server_host { "stg-production.shippingapis.com" };
220              
221              
222             =back
223              
224             =head1 SEE ALSO
225              
226             The WebTools API is documented on the US Postal Service's website:
227              
228             http://www.usps.com/webtools/htm/Address-Information.htm
229              
230             =head1 SOURCE AVAILABILITY
231              
232             This source is in GitHub:
233              
234             https://github.com/ssimms/business-us-usps-webtools
235              
236             =head1 AUTHOR
237              
238             brian d foy
239              
240             =head1 MAINTAINER
241              
242             Steve Simms
243              
244             =head1 COPYRIGHT AND LICENSE
245              
246             Copyright © 2020, Steve Simms. All rights reserved.
247              
248             This program is free software; you can redistribute it and/or modify
249             it under the terms of the Artistic License 2.0.
250              
251             =cut
252              
253             1;