1 # Copyright 2002-2009 Interchange Development Group and others
3 # This program is free software; you can redistribute it and/or modify
4 # it under the terms of the GNU General Public License as published by
5 # the Free Software Foundation; either version 2 of the License, or
6 # (at your option) any later version. See the LICENSE file for details.
8 UserTag usps-query Order service weight
9 UserTag usps-query addAttr
10 UserTag usps-query Version 1.10
11 UserTag usps-query Routine <<EOR
14 my ($service, $weight, $opt) = @_;
15 my ($rate, $resp, $xml, $mailtype, @intl, $m_rep, $m_mod);
16 my %supported_services = (
24 'GLOBAL EXPRESS GUARANTEED' => 1,
25 'GLOBAL EXPRESS GUARANTEED NON-DOCUMENT RECTANGULAR' => 1,
26 'GLOBAL EXPRESS GUARANTEED NON-DOCUMENT NON-RECTANGULAR' => 1,
27 'USPS GXG ENVELOPES' => 1,
28 'EXPRESS MAIL INTERNATIONAL (EMS)' => 1,
29 'EXPRESS MAIL INTERNATIONAL (EMS) FLAT-RATE ENVELOPE' => 1,
30 'PRIORITY MAIL INTERNATIONAL' => 1,
31 'PRIORITY MAIL INTERNATIONAL FLAT-RATE ENVELOPE' => 1,
32 'PRIORITY MAIL INTERNATIONAL REGULAR FLAT-RATE BOXES' => 1,
33 'PRIORITY MAIL INTERNATIONAL LARGE FLAT-RATE BOX' => 1,
34 'PRIORITY MAIL INTERNATIONAL SMALL FLAT-RATE BOX' => 1,
35 'FIRST CLASS MAIL INTERNATIONAL LARGE ENVELOPE' => 1,
36 'FIRST CLASS MAIL INTERNATIONAL PACKAGE' => 1,
37 'MATTER FOR THE BLIND - ECONOMY MAIL' => 1,
46 'postcards or aerogrammes' => 1,
47 'matter for the blind' => 1,
51 my $error_msg = 'USPS: ';
52 my $origin = $opt->{origin} || $::Variable->{USPS_ORIGIN} || $::Variable->{UPS_ORIGIN};
53 my $destination = $opt->{destination} || $::Values->{zip} || $::Variable->{SHIP_DEFAULT_ZIP};
54 my $userid = $opt->{userid} || $::Variable->{USPS_ID};
55 my $passwd = $opt->{passwd} || $::Variable->{USPS_PASSWORD};
56 my $url = $opt->{url} || $::Variable->{USPS_URL} || 'http://Production.ShippingAPIs.com/ShippingAPI.dll';
57 my $container = $opt->{container} || $::Variable->{USPS_CONTAINER} || 'None';
58 my $machinable = $opt->{machinable} || $::Variable->{USPS_MACHINABLE} || 'False';
60 $service = uc $service;
61 if (! $supported_services{$service}) {
62 $error_msg .= "unknown service type $service.";
66 my $size = uc ($opt->{size} || $::Variable->{USPS_SIZE} || 'REGULAR');
67 if (! $package_sizes{$size}) {
68 $error_msg .= "unknown package size $size.";
72 if ($service eq 'PARCEL') {
73 if ($weight < .375 or $weight > 35) {
74 $machinable = 'False';
78 if ($opt->{country}) {
79 $mailtype = lc ($opt->{mailtype} || $::Variable->{USPS_MAILTYPE} || 'package');
80 unless ($mailtypes{$mailtype}) {
81 $error_msg = "unknown mail type '$mailtype'.";
86 my $modulo = $opt->{modulo} || $::Variable->{USPS_MODULO};
87 if ($modulo and ($modulo < $weight)) {
88 $m_rep = int $weight / $modulo;
89 $m_mod = $weight % $modulo;
95 my $ounces = int(($weight - int($weight)) * 16);
96 $weight = int $weight;
98 if ($opt->{country}) {
100 q{United Kingdom} => q{Great Britain},
101 q{Virgin Islands, British} => q{British Virgin Islands},
102 q{Viet Nam} => q{Vietnam},
103 q{Tanzania, United Republic Of} => q{Tanzania},
104 q{Slovakia} => q{Slovak Republic},
105 q{Serbia} => q{Serbia-Montenegro},
106 q{Montenegro} => q{Serbia-Montenegro},
107 q{Samoa} => q{Western Samoa},
108 q{Saint Kitts And Nevis} => q{St. Christopher and Nevis},
109 q{Russian Federation} => q{Russia},
110 q{Pitcairn} => q{Pitcairn Island},
111 q{Moldova, Republic Of} => q{Moldova},
112 q{Marshall Islands} => q{Republic of the Marshall Islands},
113 q{Macedonia, The Former Yugoslav R} => q{Macedonia, Republic of},
114 q{Libyan Arab Jamahiriya} => q{Libya},
115 q{Lao People's Democratic Republic} => q{Laos},
116 q{Korea, Republic of} => q{South Korea},
117 q{Iran, Islamic Republic Of} => q{Iran},
118 q{Holy See (Vatican City State)} => q{Vatican City},
119 q{Georgia} => q{Georgia, Republic of},
120 q{Falkland Islands (Malvinas)} => q{Falkland Islands},
121 q{Cote d'Ivoire (Ivory Coast)} => q{Cote d'Ivoire},
122 q{Congo, The Democratic Republic O} => q{Democratic Republic of the Congo},
123 q{Congo} => q{Congo, Republic of the},
124 q{Bosnia And Herzegowina} => q{Bosnia-Herzegovina},
127 my $usps_country = $map{ $opt->{country} }
130 $xml = qq{API=IntlRate\&XML=<IntlRateRequest USERID="$userid" PASSWORD="$passwd">};
133 <Pounds>$weight</Pounds>
134 <Ounces>$ounces</Ounces>
135 <MailType>$mailtype</MailType>
136 <Country>$usps_country</Country>
142 $xml = qq{API=Rate\&XML=<RateRequest USERID="$userid" PASSWORD="$passwd">};
145 <Service>$service</Service>
146 <ZipOrigination>$origin</ZipOrigination>
147 <ZipDestination>$destination</ZipDestination>
148 <Pounds>$weight</Pounds>
149 <Ounces>$ounces</Ounces>
150 <Container>$container</Container>
152 <Machinable>$machinable</Machinable>
158 my $ua = new LWP::UserAgent;
159 my $req = new HTTP::Request 'POST', "$url";
160 $req->content_type('application/x-www-form-urlencoded');
162 my $response = $ua->request($req);
164 $error_msg = 'USPS: ';
165 if ($response->is_success) {
166 $resp = $response->content;
169 $error_msg .= 'Error obtaining rate quote from usps.com.';
172 if ($resp =~ /<Error>/i) {
173 $resp =~ m|<Description>(.+)</Description>|;
177 if ($opt->{country}) {
178 @intl = split /<Service/, $resp;
180 m|<SvcDescription>(.+)</SvcDescription>|;
182 if ($resp eq $service) {
183 m|<Postage>(.+)</Postage>|;
191 $resp =~ m|<Postage>(.+)</Postage>|;
199 $rate *= $m_rep; undef $m_rep;
202 $weight = $m_mod; undef $m_mod;
206 $::Session->{ship_message} .= " $error_msg" if $error_msg;
211 UserTag usps-query Documentation <<EOD
216 usps-query tag -- calculate USPS costs via www
221 service="service name"
223 userid="USPS webtools user id"*
224 passwd="USPS webtools password"*
228 container="container type"*
230 machinable="True/False"*
231 mailtype="mailing type"*
232 country="Country name"*
238 Calculates USPS costs via the WWW using the United States Postal Service Rate
239 Rate Calculator API. You *MUST* register with USPS in order to use this service.
240 Visit http://www.usps.com/webtools and follow the link(s) to register. You will
241 receive a confirmation email upon completing the registration process. You
242 *MUST* follow the instructions in this email to obtain access to the production
243 rate quote server. THIS USERTAG WILL NOT WORK WITH USPS's TEST SERVER.
248 =head2 Base Parameters (always required):
255 The USPS service you wish to get a rate quote for. Services currently supported:
264 GLOBAL EXPRESS GUARANTEED
265 GLOBAL EXPRESS GUARANTEED NON-DOCUMENT RECTANGULAR
266 GLOBAL EXPRESS GUARANTEED NON-DOCUMENT NON-RECTANGULAR
268 EXPRESS MAIL INTERNATIONAL (EMS)
269 EXPRESS MAIL INTERNATIONAL (EMS) FLAT-RATE ENVELOPE
270 PRIORITY MAIL INTERNATIONAL
271 PRIORITY MAIL INTERNATIONAL FLAT-RATE ENVELOPE
272 PRIORITY MAIL INTERNATIONAL REGULAR FLAT-RATE BOXES
273 PRIORITY MAIL INTERNATIONAL LARGE FLAT-RATE BOX
274 PRIORITY MAIL INTERNATIONAL SMALL FLAT-RATE BOX
275 FIRST CLASS MAIL INTERNATIONAL LARGE ENVELOPE
276 FIRST CLASS MAIL INTERNATIONAL PACKAGE
277 MATTER FOR THE BLIND - ECONOMY MAIL
282 The total weight of the items to be mailed/shipped.
286 Your USPS webtools userid, which was obtained by registering.
287 This will default to $Variable->{USPS_ID}, which is the preferred
288 way to set this parameter.
292 Your USPS webtools passwd, which was obtained by registering.
293 This will default to $Variable->{USPS_PASSWORD}, which is the
294 preferred way to set this parameter.
298 =head2 Extended Parameters (domestic and international services)
305 The URL of the USPS rate quote API. The default is $Variable->{USPS_URL}
306 or 'http://Production.ShippingAPIs.com/ShippingAPI.dll'.
310 Enables a rudimentary method of obtaining rate quotes for multi-box shipments.
311 'modulo' is a number which represents the maximum weight per box; the default
312 is $Variable->{USPS_MODULO}. When modulo > 0, the shipping weight will be divided
313 into the number of individual parcels of max. weight 'modulo' which will accommodate
314 the whole shipment, and the total rate will be calculated accordingly.
315 Example: with modulo = 10, a 34.5lbs. shipment will be calculated as 3 parcels
316 weighing 10lbs. each, plus one parcel weighing 4lbs. 8oz.
320 =head2 Extended Parameters for domestic (U.S.) services only
327 Origin zip code. Default is $Variable->{USPS_ORIGIN} or $Variable->{UPS_ORIGIN}.
331 Destination zip code. Default is $Values->{zip} or $Variable->{SHIP_DEFAULT_ZIP}.
335 The USPS-defined container type for the shipment. Default is
336 Variable->{USPS_CONTAINER} or 'None". Please see the Technical Guide to the
337 Domestic Rates Calculator Application Programming Interface for a complete
338 list of container types.
342 The USPS-defined package size for the shipment. Valid choices are
343 'REGULAR', 'LARGE', and 'OVERSIZE'. The default is $Variable->{USPS_SIZE} or
344 'REGULAR'. Please see the Technical Guide to the Domestic Rates Calculator
345 Application Programming Interface for a definition of package sizes.
347 =item machinable (for PARCEL service only)
349 Possible value are 'True' and 'False'. Indicates whether or not the shipment
350 qualifies for machine processing by UPS. Default is $Variable->{USPS_MACHINABLE}
351 or 'False". Consult the USPS service guides for more info on this subject.
355 =head2 Extended parameters for International services only
362 The USPS-defined mail type for the shipment. Valid choices are:
365 postcards or aerogrammes
369 Default is $Variable->{USPS_MAILTYPE} or 'package'. See the USPS international
370 service guides for more information on this topic.
372 =item country (required for international services)
374 Destination country. No default. You must pass the name of the country, not the ISO
375 code or abbreviation (i.e. 'Canada', not 'CA'). Note that USPS maintains a table of
376 valid country names which does not necessarily match all entries in the country
377 table which is distributed with the standard demo, so modifications may be needed
378 if you intend to use USPS international services. Consult the USPS International
379 Services guide for more information.
389 Ed LaFrance <edl@newmediaems.com>
390 Josh Lavin <josh@perusion.com>
391 Mathew Jones <mat@bibliopolis.com>