We help IT Professionals succeed at work.

Question: Help with an API for UPS

toolminator
toolminator asked
on
This is my first whack at a cgi interface to UPS's  online tracking utilities, and none of my books
cover API's and online documentation is even less help.

If someone could offer some assistance, it would be MOST appreciated....

This is what I've got so far.....

use LWP::UserAgent;
$ua = new LWP::UserAgent;
$ua->agent("AgentName/0.1 " . $ua->agent);

# Create a request
my $req = new HTTP::Request POST => 'https://www.ups.com/ups.app/xml/Rate';
$req->content_type('application/x-www-form-urlencoded');
$req->content('match=www&errors=0');

# Pass request to the user agent and get a response back
my $res = $ua->request($req);


# Check the outcome of the response
if ($res->is_success) {
print $res->content;
} else {
print "Error\n";
}


This was a tid bit that I managed to scrounge together starting out, but with the amount of variables
having to be sent in the request and then recieved in the response, is going to result in some pretty
sloppy code.

I'm hoping someone has done something similar and can give me an example of sending several variables in POST format during the request and then recieving several variables in the response.

                     Thankx all

Nat
Comment
Watch Question

Chad SmithSoftware Engineer
CERTIFIED EXPERT

Commented:
Here is a php class that I have been using to get rate quotes from UPS.  I have not needed to do this in perl so I haven't ported it, but the two languages are very similar so it would not be hard.


   // ********************************************************************************************
    // class UPSShipment extends Shipment:
    //          Class for UPS shipping prices and information.
    // ********************************************************************************************
    class UPSShipment extends Shipment
    {
        var $nda;
        var $sda;
        var $tds;
        var $gro;
        var $parent;

        var $NEXT_DAY = "1DA";
        var $SECOND_DAY = "2DA";
        var $THIRD_DAY = "3DS";
        var $GROUND = "GND";


        function UPSShipment()
        {
            $this->parent = new Shipment();
            $this->server = "http://www.ups.com:80/using/services/rave/qcost_dss.cgi?";            

            $this->keys = array(  "UPSOnLine",
                            "AppVersion",
                            "ReturnCode",
                            "MessageText",
                            "ActionCode",  
                            "ServiceLevelCode",
                            "ShipperPostalCode",
                            "ShipperCountry",
                            "ConsigneePostalCode",
                            "ConsigneeCountry",
                            "DeliveryZone",
                            "PackageActualWeight",
                            "ProductCharge",
                            "AccessorySurcharge",
                            "TotalCharge",
                            "CommitTime" );
            $this->nda = 0;
            $this->sda = 0;
            $this->tds = 0;
            $this->gro = 0;
            $this->maxWeight = 150;
            $this->msg = "<br>Unable to connect to the UPS server at " . $this->server . "<br>";
        }

        // *****
        // Set the status
        function setStatus( $get )
        {
            $retval = ( $this->getValue( $get ) == "0000" ) ? true : false;
            return $retval;
        }

        function getNextDayAirPrice()
        {
            return sprintf( "%01.2f", $this->nda );
        }

        function getSecondDayAirPrice()
        {
            return sprintf( "%01.2f", $this->sda );            
        }

        function getThreeDaySelectPrice()
        {
            return sprintf( "%01.2f", $this->tds );
        }
       
        function getGroundPrice()
        {
            return sprintf( "%01.2f", $this->gro );
        }                

        // *****
        // Set a message, if applicable
        function setMessage( $get )
        {
            return $this->getValue( $get );
        }

        // *****
        // Set the price
        function setPrice( $get )
        {
            return $this->getValue( $get );
        }

        // *****
        // Return the service type for the current line
        function currentServiceType( $get )
        {
            return $this->getValue( $get );
        }

        function loadVals( $valLine, $delim = "%" )
        {
            $this->vals = array();                        
            $tok = strtok( $valLine, $delim );

            while( $tok )
            {
                $this->vals[count($this->vals)] = $tok;
                $tok = strtok( $delim );                
            }

            if ( empty( $this->retcode ) )
            {
                $this->retcode = $this->setStatus( "ReturnCode" );
                $this->msg = $this->setMessage( "MessageText" );    
            }

            if ( $this->success() )
            {
                if ( $this->currentServiceType("ServiceLevelCode") == $this->NEXT_DAY )
                    $this->nda += $this->setPrice("TotalCharge");
                if ( $this->currentServiceType("ServiceLevelCode") == $this->SECOND_DAY )
                    $this->sda += $this->setPrice("TotalCharge");
                if ( $this->currentServiceType("ServiceLevelCode") == $this->THIRD_DAY )
                    $this->tds += $this->setPrice("TotalCharge");
                if ( $this->currentServiceType("ServiceLevelCode") == $this->GROUND )
                    $this->gro += $this->setPrice("TotalCharge");
            }
        }

        function buildQueryString( $toCode, $fromCode, $weight, $resOrInd = "0", $toCountry = "US", $fromCountry = "US" )
        {
            // need to pass the application information
            $this->queryString = "AppVersion=1.2&AcceptUPSLicenseAgreement=YES&";

            // "ActionCode" 3 specifies a rate for a selected service; 4 specifies rates for all available
            $this->queryString .= "ResponseType=application/x-ups-rss&ActionCode=4&";

            // "ServiceLevelCode" specifies which type of service available, even though we will get all (specified above)
            $this->queryString .= "ServiceLevelCode=GND&RateChart=Regular+Daily+Pickup&";

            // the "To" and "From" ZIP codes
            $this->queryString .= "ShipperPostalCode=$fromCode&ConsigneePostalCode=$toCode&";
       
            // "To" and "From" countries
            $this->queryString .= "ConsigneeCountry=$fromCountry&ShipperCountry=$toCountry&";
       
            // the weight of this package
            $this->queryString .= "PackageActualWeight=$weight&";

            // "ResidentialInd": 0 is commercial; 1 is residential; "PackagingType" is provided by shipper
            $this->queryString .= "ResidentialInd=$resOrInd&PackagingType=00";            
        }

        function getResponse()
        {
            $fp = @fopen( $this->getServer() . $this->getQueryString(), 'r');

            if( $fp == false )
                return false;

            while( $buffer = @fgets($fp, 4096) )
            {
                if ( strstr( $buffer, "UPSOnLine" ) )
                    $this->loadVals( $buffer );
            }

            @fclose( $fp );
            return true;
        }

    } // end of class
Software Engineer
CERTIFIED EXPERT
Commented:
Oops, you probably want the base class too.  Here it is

    // ********************************************************************************************
    // class Shipment:
    //          Base class for shipping methods where shipping information
    //          is retrieved via HTTP.
    //          
    //          Many pseudo-virtual methods in this class; inherit as necessary.
    // ********************************************************************************************
    class Shipment
    {
        var $keys;
        var $vals;
        var $msg;
        var $retcode;
        var $maxWeight;
        var $server;
        var $queryString;

        function Shipment()
        {            
            $this->msg = "";
            $this->retcode = false;
        }

        function success()
        {
            return $this->retcode;
        }

        function getMessage()
        {
            return $this->msg;
        }

        function getServer()
        {
            return $this->server;
        }

        function getQueryString()
        {
            return $this->queryString;
        }        

        function getKeys()
        {            
            // returns an array
            return $this->keys;
        }

        function countKeys()
        {            
            return count( $this->keys );
        }

        // *****
        // Get a given value based on a hash-like structure
        function getValue( $key )
        {        
            for ( $i = 0; $i < $this->countKeys(); $i++ )
            {
                if ( strcmp( $this->keys[$i], $key ) == 0 )
                    return $this->vals[$i];
            }

            return null;
        }

        function getResponse()
        {
            // virtual
        }

        function buildQueryString()
        {
            // virtual            
        }
       
       
        function setStatus()
        {
            // virtual            
        }

       
        function setMessage()
        {
            // virtual            
        }

       
        function setPrice()
        {
            // virtual            
        }

       
        function currentServiceType()
        {
            // virtual            
        }
       
    } // end of class    
CERTIFIED EXPERT

Commented:
toolminator,

Since you have found a solution to this question (http://www.experts-exchange.com/jsp/qShow.jsp?ta=cgi&qid=20194211), can you pl. go ahead and delete this question?

That will save you some points, & also keep the question list up-to-date.

Thanks,

Author

Commented:
I like!
excellent example... worth every point...

manesh, sorry for overlooking the delete question. was actually still fishing for someone who had done the ups rate quotes. A thousand apologies....
CERTIFIED EXPERT

Commented:
toolminator,

"..sorry for overlooking the delete question. was actually still fishing for someone who had done
                     the ups rate quotes. A thousand apologies.... .."

I didnt mean to sound mean & apologize if my comments came out that way.

My intention is to keep the PERL & CGI topic area up-to-date and free of duplicates.

Rgds,

Manesh