NAME

Net::UPS - Implementation of UPS Online Tools API in Perl

SYNOPSIS

    use Net::UPS;
    $ups = Net::UPS->new($userid, $password, $accesskey);
    $rate = $ups->rate($from_zip, $to_zip, $package);
    printf("Shipping this package $from_zip => $to_zip will cost you \$.2f\n", $rate->total_charges);

DESCRIPTION

PLEASE NOTE: this distribution is considered "old". Only critical fixes will be released here. All new work is done in Net::Async::Webservice::UPS, which can be used even without any async library.

Net::UPS implements UPS' Online Tools API in Perl. In a nutshell, Net::UPS knows how to retrieve rates and service information for shipping packages using UPS, as well as for validating U.S. addresses.

This manual is optimized to be used as a quick reference. If you're knew to Net::UPS, and this manual doesn't seem to help, you're encouraged to read Net::UPS::Tutorial first.

METHODS

Following are the list and description of methods available through Net::UPS. Provided examples may also use other Net::UPS::* libraries and their methods. For the details of those please read their respective manuals. (See SEE ALSO)

live ($bool)

By default, all the API calls in Net::UPS are directed to UPS.com's test servers. This is necessary in testing your integration interface, and not to exhaust UPS.com live servers.

Once you want to go live, live() class method needs to be called with a true argument to indicate you want to switch to the UPS.com's live interface. It is recommended that you call live() before creating a Net::UPS instance by calling new(), like so:

    use Net::UPS;
    Net::UPS->live(1);
    $ups = Net::UPS->new($userid, $password, $accesskey);
new($userid, $password, $accesskey)
new($userid, $password, $accesskey, \%args)
new($config_file)
new($config_file, \%args)

Constructor method. Builds and returns Net::UPS instance. If an instance exists, new() returns that instance.

$userid and $password are your login information to your UPS.com profile. $accesskey is something you have to request from UPS.com to be able to use UPS Online Tools API.

\%args, if present, are the global arguments you can pass to customize Net::UPS instance, and further calls to UPS.com. Available arguments are as follows:

pickup_type

Type of pickup to be assumed by subsequent rate() and shop_for_rates() calls. See PICKUP TYPES for the list of available pickup types.

ups_account_number

If you have a UPS account number, place it here.

customer_classification

Your Customer Classification. For details refer to UPS Online Tools API manual. In general, you'll get the lowest quote if your pickup_type is DAILY and your customer_classification is WHOLESALE. See CUSTOMER CLASSIFICATION

cache_life

Enables caching, as well as defines the life of cache in minutes.

cache_root

File-system location of a cache data. Return value of tmpdir() is used as default location.

av_proxy

The URL to use to access the AV service. If you set this one, the "live" setting will be ignored, and this URL always used.

rate_proxy

The URL to use to access the Rate service. If you set this one, the "live" setting will be ignored, and this URL always used.

user_agent

A custom User Agent object, usually an instance of LWP::UserAgent, or maybe something else that implements the same interface (at least the request method). It not supplied, a LWP::UserAgent will be instantiated, with env_proxy set, and "ssl_options" will be used to set its ssl_opts attribute.

ssl_options

A hashref that will be passed to the constructor of LWP::UserAgent when building the default "user_agent". The default value sets full TLS validation, and makes sure that the Verisign certificate currently (as of 2015-02-03) used by the UPS servers is recognised (see "TLS notes" in UPS SSL).

Please note that if you set a custom "user_agent", these options will be ignored.

All the %args (apart from user_agent and ssl_options, where it would not make sense) can also be defined in the $config_file. %args can be used to overwrite the default arguments. See CONFIGURATION FILE

instance ()

Returns an instance of Net::UPS object. Should be called after an instance is created previously by calling new(). instance() croaks if there is no object instance.

userid ()
password ()
access_key ()

Return UserID, Password and AccessKey values respectively

ssl_options ()

Returns a hashref of the SSL options that may have been used to build the user agent. See "ssl_options" above for details.

user_agent ()

Returns the user agent object that will be used to talk with the UPS servers. See "user_agent" above for details.

rate ($from, $to, $package)
rate ($from, $to, \@packages)
rate ($from, $to, \@packages, \%args)

Returns one Net::UPS::Rate instance for every package requested. If there is only one package, returns a single reference to Net::UPS::Rate. If there are more then one packages passed, returns an arrayref of Net::UPS::Rate objects.

$from and $to can be either plain postal (zip) codes, or instances of Net::UPS::Address. In latter case, the only value required is postal_code().

$package should be of Net::UPS::Package type and @packages should be an array of Net::UPS::Package objects.

    $rate = $ups->rate(15146, 15241, $package);
    printf("Your cost is \$.2f\n", $rate->total_charges);

See Net::UPS::Package for examples of building a package. See Net::UPS::Rate for examples of using $rate.

\%args, if present, can be used to customize rate()ing process. Available arguments are:

service

Specifies what kind of service to rate the package against. Default is GROUND, which rates the package for UPS Ground. See SERVICE TYPES for a list of available UPS services to choose from.

shop_for_rates ($from, $to, $package)
shop_for_rates ($from, $to, \@packages)
shop_for_rates ($from, $to, \@packages, \%args)

The same as rate(), except on success, returns a reference to a list of available services. Each service is represented as an instance of Net::UPS::Service class. Output is sorted by total_charges() in ascending order. Example:

    $services = $ups->shop_for_rates(15228, 15241, $package);
    while (my $service = shift @$services ) {
        printf("%-22s => \$.2f", $service->label, $service->total_charges);
        if ( my $days = $service->guaranteed_days ) {
            printf("(delivers in %d day%s)\n", $days, ($days > 1) ? "s" : "");
        } else {
            print "\n";
        }
    }

Above example returns all the service types available for shipping $package from 15228 to 15241. Output may be similar to this:

    GROUND                 => $5.20
    3_DAY_SELECT           => $6.35  (delivers in 3 days)
    2ND_DAY_AIR            => $9.09  (delivers in 2 days)
    2ND_DAY_AIR_AM         => $9.96  (delivers in 2 days)
    NEXT_DAY_AIR_SAVER     => $15.33 (delivers in 1 day)
    NEXT_DAY_AIR           => $17.79 (delivers in 1 day)
    NEXT_DAY_AIR_EARLY_AM  => $49.00 (delivers in 1 day)

The above example won't change even if you passed multiple packages to be rated. Individual package rates can be accessed through rates() method of Net::UPS::Service.

\%args, if present, can be used to customize the rating process and/or the return value. Currently supported arguments are:

limit_to

Tells Net::UPS which service types the result should be limited to. limit_to should always refer to an array of services. For example:

    $services = $ups->shop_for_rates($from, $to, $package, {
                            limit_to=>['GROUND', '2ND_DAY_AIR', 'NEXT_DAY_AIR']
    });

This example returns rates for the selected service types only. All other service types will be ignored. Note, that it doesnt' guarantee all the requested service types will be available in the return value of shop_for_rates(). It only returns the services (from the list provided) that are available between the two addresses for the given package(s).

exclude

The list provided in exclude will be excluded from the list of available services. For example, assume you don't want rates for 'NEXT_DAY_AIR_SAVER', '2ND_DAY_AIR_AM' and 'NEXT_DAY_AIR_EARLY_AM' returned:

    $service = $ups->from_for_rates($from, $to, $package, {
                    exclude => ['NEXT_DAY_AIR_SAVER', '2ND_DAY_AIR_AM', 'NEXT_DAY_AIR_EARLY_AM']});

Note that excluding services may even generate an empty service list, because for some location excluded services might be the only services available. You better contact your UPS representative for consultation. As of this writing I haven't done that yet.

service ()

Returns the last service used by the most recent call to rate().

validate_address ($address)
validate_address ($address, \%args)

Validates a given address against UPS' U.S. Address Validation service. $address can be one of the following:

  • US Zip Code

  • Hash Reference - keys of the hash should correspond to attributes of Net::UPS::Address

  • Net::UPS::Address class instance

%args, if present, contains arguments that effect validation results. As of this release the only supported argument is tolerance, which defines threshold for address matches. tolerance is a floating point number between 0 and 1, inclusively. The higher the tolerance threshold, the more loose the address match is, thus more address suggestions are returned. Default tolerance value is 0.05, which only returns very close matches.

    my $addresses = $ups->validate_address($address);
    unless ( defined $addresses ) {
        die $ups->errstr;
    }
    unless ( @$addresses ) {
        die "Address is not correct, nor are there any suggestions\n";
    }
    if ( $addresses->[0]->is_match ) {
        print "Address Matches Exactly!\n";
    } else {
        print "Your address didn't match exactly. Following are some valid suggestions\n";
        for (@$addresses ) {
            printf("%s, %s %s\n", $_->city, $_->state, $_->postal_code);
        }
    }

BUGS AND KNOWN ISSUES

No bugs are known of as of this release. If you think you found a bug, document it at http://rt.cpan.org/NoAuth/Bugs.html?Dist=Net-UPS. It's more likely to get noticed in there than in my busy inbox.

TODO

There are still a lot of features UPS.com offers in its Online Tools API that Net::UPS doesn't handle. This is the list of features that need to be supported before Net::UPS can claim full compliance.

PACKAGE OPTIONS

Following features needs to be supported by Net::UPS::Package class to define additional package options:

COD
Delivery Confirmation
Insurance
Additional Handling flag

SERVICE OPTIONS

Following featureds need to be supported by Net::UPS::Service as well as in form of arguments to rate() and shop_for_rates() methods:

Saturday Pickup
Saturday Delivery
COD Service request
Handling Charge

AUTHOR

Sherzod B. Ruzmetov <sherzodr@cpan.org>, http://author.handalak.com/

CREDITS

Thanks to Christian - <cpan [AT] pickledbrain.com> for locating and fixing a bug in Net::UPS::Package::is_oversized(). See the source for details.

COPYRIGHT

Copyright (C) 2005 Sherzod Ruzmetov. All rights reserved. This library is free software. You can modify and/or distribute it under the same terms as Perl itself.

DISCLAIMER

THIS LIBRARY IS PROVIDED WITH USEFULNES IN MIND, BUT WITHOUT ANY GUARANTEE (NEITHER IMPLIED NOR EXPRESSED) OF ITS FITNES FOR A PARTICUALR PURPOSE. USE IT AT YOUR OWN RISK.

SEE ALSO

Net::UPS::Address, Net::UPS::Rate, Net::UPS::Service, Net::UPS::Package, Net::UPS::Tutorial

APPENDIXES

Some options need to be provided to UPS in the form of codes. These two-digit numbers are not ideal for mortals to work with. That's why Net::UPS decided to assign them symbolic names, constants, if you wish.

SERVICE TYPES

Following is the table of SERVICE TYPE codes, and their symbolic names assigned by Net::UPS. One of these options can be passed as service argument to rate(), as in:

    $rates = $ups->rate($from, $to, $package, {service=>'2ND_DAY_AIR'});

    +------------------------+-----------+
    |    SYMBOLIC NAMES      | UPS CODES |
    +------------------------+-----------+
    | NEXT_DAY_AIR           |    01     |
    | 2ND_DAY_AIR            |    02     |
    | GROUND                 |    03     |
    | WORLDWIDE_EXPRESS      |    07     |
    | WORLDWIDE_EXPEDITED    |    08     |
    | STANDARD               |    11     |
    | 3_DAY_SELECT           |    12     |
    | NEXT_DAY_AIR_SAVER     |    13     |
    | NEXT_DAY_AIR_EARLY_AM  |    14     |
    | WORLDWIDE_EXPRESS_PLUS |    54     |
    | 2ND_DAY_AIR_AM'        |    59     |
    +------------------------+-----------+

CUSTOMER CLASSIFICATION

Following are the possible customer classifications. Can be passed to new() as part of the argument list, as in:

    $ups = Net::UPS->new($userid, $password, $accesskey, {customer_classification=>'WHOLESALE'});

    +----------------+-----------+
    | SYMBOLIC NAMES | UPS CODES |
    +----------------+-----------+
    | WHOLESALE      |     01    |
    | OCCASIONAL     |     03    |
    | RETAIL         |     04    |
    +----------------+-----------+

PACKAGE CODES

Following are all valid packaging types that can be set through packaging_type attribute of Net::UPS::Package, as in:

    $package = Net::UPS::Package->new(weight=>10, packaging_type=>'TUBE');

    +-----------------+-----------+
    | SYMBOLIC NAMES  | UPS CODES |
    +-----------------+-----------+
    | LETTER          |     01    |
    | PACKAGE         |     02    |
    | TUBE            |     03    |
    | UPS_PAK         |     04    |
    | UPS_EXPRESS_BOX |     21    |
    | UPS_25KG_BOX    |     24    |
    | UPS_10KG_BOX    |     25    |
    +-----------------+-----------+

CONFIGURATION FILE

Net::UPS object can also be instantiated using a configuration file. Example:

    $ups = Net::UPS->new("/home/sherzodr/.upsrc");
    # or
    $ups = Net::UPS->new("/home/sherzodr/.upsrc", \%args);

All the directives in the configuration file intended for use by Net::UPS will be prefixed with UPS. All other directives that Net::UPS does not recognize will be conveniently ignored. Configuration file uses the following format:

    DirectiveName  DirectiveValue

Where DirectiveName is one of the keywords documented below.

SUPPORTED DIRECTIVES

UPSAccessKey

AccessKey as acquired from UPS.com Online Tools web site. Required.

UPSUserID

Online login id for the account. Required.

UPSPassword

Online password for the account. Required.

UPSCacheLife

To Turn caching on. Value of the directive also defines life-time for the cache.

UPSCacheRoot

Place to store cache files in. Setting this directive does not automatically turn caching on. UPSCacheLife needs to be set for this directive to be effective. UPSCacheRoot will defautlt o your system's temporary folder if it's missing.

UPSLive

Setting this directive to any true value will make Net::UPS to initiate calls to UPS.com's live servers. Without this directive Net::UPS always operates under test mode.

UPSPickupType
UPSAccountNumber
UPSCustomerClassification

UPS SSL/TLS notes

In December 2014, UPS notified all its users that it would stop supporting SSLv3 in March 2015. This library has no problems with that, since LWP has supported TLS for years.

Another, unrelated, issue cropped up at rougly the same time, to confuse the situation: Mozilla::CA, which is used to get the root certificates to verify connections, dropped a top-level Verisign certificate that Verisign stopped using in 2010, but the UPS servers' certificate was signed with it, so LWP stopped recognising the servers' certificate. Net::UPS 0.14 works around the problem by always including the root certificate in the default "ssl_options". If you set a custom user agent, you may want to set its SSL options appropriately. See also https://rt.cpan.org/Ticket/Display.html?id=101908