PHP: USPS rates calculator

The USPS Web Tools allow developers of web-based and shrink-wrapped applications access to the on-line services of the United States Postal Service (USPS). They provide easy access to shipping information and services for your customers. Your customers can utilize the functions provided by the USPS without ever leaving your web site. Once the Web Tools are integrated, your server communicates through the USPS Web Tools server over HTTP using XML (eXtensible Markup Language).

Rates Calculators

Everything in details can be found here:
http://www.usps.com/webtools/rate.htm

First steps:

  1. Register online (You will get your own user name)
  2. Test this script (You can use only test data)
  3. Contact ICCC and go live.

When you have completed your testing, email the USPS Internet Customer Care Center (ICCC). They will switch your profile to allow you access to the production server and will provide you with the production URL.

Domestic and International Rates

Domestic rates

Test 1:


    $usps = new USPS;
    $usps->setServer("http://testing.shippingapis.com/ShippingAPITest.dll");
    $usps->setUserName("?????????");
    $usps->setService("PRIORITY");
    $usps->setDestZip("20008");
    $usps->setOrigZip("10022");
    $usps->setWeight(10, 5);
    $usps->setContainer("Flat Rate Box");
    $usps->setCountry("USA");
    $price = $usps->getPrice();

Response 1:


    usps Object
    (
        [server] => http://testing.shippingapis.com/ShippingAPITest.dll
        [user] => ???????????
        [pass] =>
        [service] => PRIORITY
        [dest_zip] => 20008
        [orig_zip] => 10022
        [pounds] => 10
        [ounces] => 5
        [container] => Flat Rate Box
        [size] => REGULAR
        [machinable] =>
        [country] => USA
        [zone] => 3
        [list] => Array
            (
                [0] => price Object
                    (
                        [mailservice] => "Priority Mail Flat Rate Box (11.25'' x 8.75'' x 6'')"
                        [rate] => 7.70
                    )
                [1] => price Object
                    (
                        [mailservice] => "Priority Mail Flat Rate Box (14''x 12'' x 3.5'')"
                        [rate] => 7.70
                    )
            )
    )

Test 2:


    $usps = new USPS;
    $usps->setServer("http://testing.shippingapis.com/ShippingAPITest.dll");
    $usps->setUserName("?????????");
    $usps->setService("All");
    $usps->setDestZip("20008");
    $usps->setOrigZip("10022");
    $usps->setWeight(10, 5);
    $usps->setContainer("Flat Rate Box");
    $usps->setCountry("USA");
    $usps->setMachinable("true");
    $usps->setSize("LARGE");
    $price = $usps->getPrice();

Response 2:


    usps Object
    (
        [server] => http://testing.shippingapis.com/ShippingAPITest.dll
        [user] => ???????????
        [pass] =>
        [service] => All
        [dest_zip] => 20008
        [orig_zip] => 10022
        [pounds] => 10
        [ounces] => 5
        [container] => Flat Rate Box
        [size] => LARGE
        [machinable] => true
        [country] => USA
        [zone] => 3
        [list] => Array
            (
                [0] => price Object
                    (
                        [mailservice] => "Express Mail to PO Addressee"
                        [rate] => 39.20
                    )
                [1] => price Object
                    (
                        [mailservice] => "Priority Mail"
                        [rate] => 8.95
                    )
                [2] => price Object
                    (
                        [mailservice] => "Parcel Post"
                        [rate] => 7.80
                    )
                [3] => price Object
                    (
                        [mailservice] => "Bound Printed Matter"
                        [rate] => 3.53
                    )
                [4] => price Object
                    (
                        [mailservice] => "Media Mail"
                        [rate] => 5.14
                    )
                [5] => price Object
                    (
                        [mailservice] => "Library Mail"
                        [rate] => 4.91
                    )
            )
    )

International rates:

Test 1:


    $usps = new USPS;
    $usps->setServer("http://testing.shippingapis.com/ShippingAPITest.dll");
    $usps->setUserName("??????????");
    $usps->setWeight(2, 0);
    $usps->setCountry("Albania");
    $price = $usps->getPrice();

Response 1:


    usps Object
    (
        [server] => http://testing.shippingapis.com/ShippingAPITest.dll
        [user] => ?????????
        [pass] =>
        [service] =>
        [dest_zip] =>
        [orig_zip] =>
        [pounds] => 2
        [ounces] => 0
        [container] => None
        [size] => REGULAR
        [machinable] =>
        [country] => Albania
        [list] => Array
            (
                [0] => intprice Object
                    (
                        [id] => 0
                        [rate] => 87
                        [pounds] => 2
                        [ounces] => 0
                        [mailtype] => "Package"
                        [country] => "ALBANIA"
                        [svccommitments] => "See Service Guide"
                        [svcdescription] => "Global Express Guaranteed (GXG) Document Service"
                        [maxdimensions] => "Max. length 46'', depth 35'', height 46'' and max. girth 108''"
                        [maxweight] => 22
                    )
                [1] => intprice Object
                    (
                        [id] => 1
                        [rate] => 96
                        [pounds] => 2
                        [ounces] => 0
                        [mailtype] => "Package"
                        [country] => "ALBANIA"
                        [svccommitments] => "See Service Guide"
                        [svcdescription] => "Global Express Guaranteed (GXG) Non-Document Service"
                        [maxdimensions] => "Max. length 46'', depth 35'', height 46'' and max. girth 108''"
                        [maxweight] => 22
                    )
            )
    )

Possible errors:


    usps Object
    (
        [server] => http://testing.shippingapis.com/ShippingAPITest.dll
        [user] => ???????????
        [pass] =>
        [service] => Alll
        [dest_zip] => 20008
        [orig_zip] => 10022
        [pounds] => 10
        [ounces] => 5
        [container] => Flat Rate Box
        [size] => LARGE
        [machinable] => true
        [country] => USA
        [error] => error Object
            (
                [number] => -2147219487
                [source] => Rate_Respond;SOLServerRatesTest.RateV2_Respond
                [description] => "Invalid value for package size."
                [helpcontext] => 1000440
                [helpfile] =>
            )
    )

Downlod this freeware PHP script: USPS rates calculator v1.2

Please make a donation of 1$ if you find our software useful and want to support the continued development.


Thank you.

64 Comments

  1. pawan says:

    thanks,Algirdas for reply, i want to know what is the process of implementation of usps after rate calculator.thanks

  2. pawan says:

    please provide me way of implementation(process) of usps after rate calculator.actully i want to know about reallty implementation of usps.thanks

  3. usmanabdulrazzaq says:

    Hi,

    Domestic rates work fine, but the international don’t.

    This is the error Message
    API Authorization failure. IntlRate is not a valid API name for this protocol.

    Thanks in Advnace

  4. Tim says:

    I’m also getting “Please enter a valid ZIP Code for the sender.” I’m on production, so why can’t I enter whatever zip codes I want?

    This is not working for me.

  5. Aiks says:

    It don’t work. Got the valid zip msg. Any idea?

  6. Kevin says:

    RE Implementation problems some are having: USPS returns an object, which can be converted into an array if you want to get up and running quickly. (PHP 5+ does not do this automatically anymore) Use the objectToArray function found here: http://www.phpro.org/examples/Convert-Object-To-Array-With-PHP.html. (Reposting due to cutoff text)

    USPS Rates

    setServer(“http://testing.shippingapis.com/ShippingAPITest.dll”);
    $usps->setUserName(“650SQUIS8177″);
    $usps->setService(“All”);
    $usps->setDestZip(“20008″);
    $usps->setOrigZip(“10022″);
    $usps->setWeight(10, 5);
    $usps->setContainer(“Flat Rate Box”);
    $usps->setCountry(“USA”);
    $usps->setMachinable(“true”);
    $usps->setSize(“LARGE”);
    $price = $usps->getPrice();
    print_r($price);
    $arrayprice=objectToArray($price); // convert object to array

    echo ‘This is the price for’ . $arrayprice['list'][1]['mailservice'] . ‘: ‘ . . ‘
    This is the price for ‘ . $arrayprice['list'][2]['mailservice'] . ‘ :’ . $arrayprice['list'][2]['rate'] . ”;
    ?>

  7. Alexey says:

    Hi,

    International rates don’t work :(

    This is the error Message
    API Authorization failure. IntlRate is not a valid API name for this protocol.

    Help please:)

  8. Manish says:

    I am also getting the same error..

    API Authorization failure. IntlRate is not a valid API name for this protocol.

    Please help…

  9. Mauricio says:

    International rates don’t work :(

    a blank page with USPS Rates title.

    please help..

  10. Mauricio says:

    hi, egain.

    international rates don’t work…

    USPS Object
    (
    [server] => http://testing.shippingapis.com/ShippingAPITest.dll
    [user] => xxxxxxxxxxx
    [pass] =>
    [service] =>
    [dest_zip] =>
    [orig_zip] =>
    [pounds] => 10
    [ounces] => 0
    [container] => None
    [size] => REGULAR
    [machinable] =>
    [country] => Albania
    [error] => error Object
    (
    [number] => 80040b1a
    [source] => UspsCom::DoAuth
    [description] => API Authorization failure. IntlRate is not a valid API name for this protocol.
    [helpcontext] =>
    [helpfile] =>
    )

    )

  11. am also getting the same error..

    API Authorization failure. IntlRate is not a valid API name for this protocol.

    Please help…

  12. vinay says:

    i am going to implementing ‘Electronic Merchandise Return Service’ with appropriate xml for request but i am getting same error

    [error] => error Object
    (
    [number] => 80040b1a
    [source] => UspsCom::DoAuth
    [description] => API Authorization failure. IntlRate is not a valid API name for this protocol.
    [helpcontext] =>
    [helpfile] =>
    )

  13. sandeep kumar says:

    all three file xmlparser.php,usps.php and index.php put in folder and run
    //xmlparser.php

    class xmlparser
    {

    function GetChildren($vals, &$i)
    {
    $children = array();

    if (isset($vals[$i]['value']))
    $children['VALUE'] = $vals[$i]['value'];

    while (++$i GetChildren($vals, $i));
    } else {
    $children[$vals[$i]['tag']][] = $this->GetChildren($vals, $i);
    }
    break;

    case ‘close’:
    return $children;
    }
    }
    }

    function GetXMLTree($xml)
    {
    $data = $xml;

    $parser = xml_parser_create();
    xml_parser_set_option($parser, XML_OPTION_SKIP_WHITE, 1);
    xml_parse_into_struct($parser, $data, $vals, $index);
    xml_parser_free($parser);

    //print_r($index);

    $tree = array();
    $i = 0;

    if (isset($vals[$i]['attributes'])) {
    $tree[$vals[$i]['tag']][]['ATTRIBUTES'] = $vals[$i]['attributes'];
    $index = count($tree[$vals[$i]['tag']])-1;
    $tree[$vals[$i]['tag']][$index] = array_merge($tree[$vals[$i]['tag']][$index], $this->GetChildren($vals, $i));
    }
    else
    $tree[$vals[$i]['tag']][] = $this->GetChildren($vals, $i);

    return $tree;
    }

    function printa($obj) {
    global $__level_deep;
    if (!isset($__level_deep)) $__level_deep = array();

    if (is_object($obj))
    print ‘[obj]‘;
    elseif (is_array($obj)) {
    foreach(array_keys($obj) as $keys) {
    array_push($__level_deep, “[".$keys."]“);
    $this->printa($obj[$keys]);
    array_pop($__level_deep);
    }
    }
    else print implode(” “,$__level_deep).” = $obj\n”;
    }
    }

    //usps.php

    require_once(“xmlparser.php”);

    class USPS {

    var $server = “”;
    var $user = “”;
    var $pass = “”;
    var $service = “”;
    var $dest_zip;
    var $orig_zip;
    var $pounds;
    var $ounces;
    var $container = “None”;
    var $size = “REGULAR”;
    var $machinable;
    var $country = “USA”;

    function setServer($server) {
    $this->server = $server;
    }

    function setUserName($user) {
    $this->user = $user;
    }

    function setPass($pass) {
    $this->pass = $pass;
    }

    function setService($service) {
    /* Must be: Express, Priority, or Parcel */
    $this->service = $service;
    }

    function setDestZip($sending_zip) {
    /* Must be 5 digit zip (No extension) */
    $this->dest_zip = $sending_zip;
    }

    function setOrigZip($orig_zip) {
    $this->orig_zip = $orig_zip;
    }

    function setWeight($pounds, $ounces=0) {
    /* Must weight less than 70 lbs. */
    $this->pounds = $pounds;
    $this->ounces = $ounces;
    }

    function setContainer($cont) {
    $this->container = $cont;
    }

    function setSize($size) {
    $this->size = $size;
    }

    function setMachinable($mach) {
    /* Required for Parcel Post only, set to True or False */
    $this->machinable = $mach;
    }

    function setCountry($country) {
    $this->country = $country;
    }

    function getPrice() {
    if($this->country==”USA”){
    // may need to urlencode xml portion
    $str = $this->server. “?API=RateV2&XML=user . “\”%20PASSWORD=\”" . $this->pass . “\”>”;
    $str .= $this->service . “” . $this->orig_zip . “”;
    $str .= “” . $this->dest_zip . “”;
    $str .= “” . $this->pounds . “” . $this->ounces . “”;
    $str .= “” . urlencode($this->container) . “” . $this->size . “”;
    $str .= “” . $this->machinable . “”;
    }
    else {
    $str = $this->server. “?API=IntlRate&XML=user . “\”%20PASSWORD=\”" . $this->pass . “\”>”;
    $str .= “” . $this->pounds . “” . $this->ounces . “”;
    $str .= “Package”.urlencode($this->country).”";
    }

    $ch = curl_init();
    // set URL and other appropriate options
    curl_setopt($ch, CURLOPT_URL, $str);
    curl_setopt($ch, CURLOPT_HEADER, 0);
    curl_setopt($ch, CURLOPT_RETURNTRANSFER, 1);

    // grab URL and pass it to the browser
    $ats = curl_exec($ch);
    // close curl resource, and free up system resources
    curl_close($ch);
    $xmlParser = new xmlparser();
    $array = $xmlParser->GetXMLTree($ats);
    //$xmlParser->printa($array);
    if(count($array['ERROR'])) { // If it is error
    $error = new error();
    $error->number = $array['ERROR'][0]['NUMBER'][0]['VALUE'];
    $error->source = $array['ERROR'][0]['SOURCE'][0]['VALUE'];
    $error->description = $array['ERROR'][0]['DESCRIPTION'][0]['VALUE'];
    $error->helpcontext = $array['ERROR'][0]['HELPCONTEXT'][0]['VALUE'];
    $error->helpfile = $array['ERROR'][0]['HELPFILE'][0]['VALUE'];
    $this->error = $error;
    } else if(count($array['RATEV2RESPONSE'][0]['PACKAGE'][0]['ERROR'])) {
    $error = new error();
    $error->number = $array['RATEV2RESPONSE'][0]['PACKAGE'][0]['ERROR'][0]['NUMBER'][0]['VALUE'];
    $error->source = $array['RATEV2RESPONSE'][0]['PACKAGE'][0]['ERROR'][0]['SOURCE'][0]['VALUE'];
    $error->description = $array['RATEV2RESPONSE'][0]['PACKAGE'][0]['ERROR'][0]['DESCRIPTION'][0]['VALUE'];
    $error->helpcontext = $array['RATEV2RESPONSE'][0]['PACKAGE'][0]['ERROR'][0]['HELPCONTEXT'][0]['VALUE'];
    $error->helpfile = $array['RATEV2RESPONSE'][0]['PACKAGE'][0]['ERROR'][0]['HELPFILE'][0]['VALUE'];
    $this->error = $error;
    } else if(count($array['INTLRATERESPONSE'][0]['PACKAGE'][0]['ERROR'])){ //if it is international shipping error
    $error = new error($array['INTLRATERESPONSE'][0]['PACKAGE'][0]['ERROR']);
    $error->number = $array['INTLRATERESPONSE'][0]['PACKAGE'][0]['ERROR'][0]['NUMBER'][0]['VALUE'];
    $error->source = $array['INTLRATERESPONSE'][0]['PACKAGE'][0]['ERROR'][0]['SOURCE'][0]['VALUE'];
    $error->description = $array['INTLRATERESPONSE'][0]['PACKAGE'][0]['ERROR'][0]['DESCRIPTION'][0]['VALUE'];
    $error->helpcontext = $array['INTLRATERESPONSE'][0]['PACKAGE'][0]['ERROR'][0]['HELPCONTEXT'][0]['VALUE'];
    $error->helpfile = $array['INTLRATERESPONSE'][0]['PACKAGE'][0]['ERROR'][0]['HELPFILE'][0]['VALUE'];
    $this->error = $error;
    } else if(count($array['RATEV2RESPONSE'])){ // if everything OK
    //print_r($array['RATEV2RESPONSE']);
    $this->zone = $array['RATEV2RESPONSE'][0]['PACKAGE'][0]['ZONE'][0]['VALUE'];
    foreach ($array['RATEV2RESPONSE'][0]['PACKAGE'][0]['POSTAGE'] as $value){
    $price = new price();
    $price->mailservice = $value['MAILSERVICE'][0]['VALUE'];
    $price->rate = $value['RATE'][0]['VALUE'];
    $this->list[] = $price;
    }
    } else if (count($array['INTLRATERESPONSE'][0]['PACKAGE'][0]['SERVICE'])) { // if it is international shipping and it is OK
    foreach($array['INTLRATERESPONSE'][0]['PACKAGE'][0]['SERVICE'] as $value) {
    $price = new intPrice();
    $price->id = $value['ATTRIBUTES']['ID'];
    $price->pounds = $value['POUNDS'][0]['VALUE'];
    $price->ounces = $value['OUNCES'][0]['VALUE'];
    $price->mailtype = $value['MAILTYPE'][0]['VALUE'];
    $price->country = $value['COUNTRY'][0]['VALUE'];
    $price->rate = $value['POSTAGE'][0]['VALUE'];
    $price->svccommitments = $value['SVCCOMMITMENTS'][0]['VALUE'];
    $price->svcdescription = $value['SVCDESCRIPTION'][0]['VALUE'];
    $price->maxdimensions = $value['MAXDIMENSIONS'][0]['VALUE'];
    $price->maxweight = $value['MAXWEIGHT'][0]['VALUE'];
    $this->list[] = $price;
    }

    }

    return $this;
    }
    }
    class error
    {
    var $number;
    var $source;
    var $description;
    var $helpcontext;
    var $helpfile;
    }
    class price
    {
    var $mailservice;
    var $rate;
    }
    class intPrice
    {
    var $id;
    var $rate;
    }
    //index.php

    require(“usps.php”);

    function objectToArray( $object )
    {
    if( !is_object( $object ) && !is_array( $object ) )
    {
    return $object;
    }
    if( is_object( $object ) )
    {
    $object = get_object_vars( $object );
    }
    return array_map( ‘objectToArray’, $object );
    }

    $usps = new USPS;
    //$usps->setServer(“http://testing.shippingapis.com/ShippingAPITest.dll”);
    $usps->setServer(“http://production.shippingapis.com/ShippingAPI.dll”);
    $usps->setUserName(“xxxxxxxxxxxx”);
    $usps->setService(“All”);
    $usps->setDestZip(“90805″);
    $usps->setOrigZip(“10022″);
    $usps->setWeight(10, 5);
    $usps->setContainer(“Flat Rate Box”);
    $usps->setCountry(“USA”);
    $usps->setMachinable(“true”);
    $usps->setSize(“REGULAR”);
    $price = $usps->getPrice();
    //print_r($price);

    $arrayprice=objectToArray($price); // convert object to array
    $val=count($arrayprice['list']);
    ?>

    Sr.
    Available Option
    Post Office Price

    <?php
    $i=1;
    for($i=1;$i<$val;$i++)
    {
    echo "”;
    echo “”.$i.”";
    echo ” .html_entity_decode($arrayprice['list'][$i]['mailservice']). ‘ ‘ .html_entity_decode($arrayprice['list'][$i]['rate']).”";
    echo “”;
    }
    echo “”;
    ?>

  14. sameh says:

    about International shipment
    what if i want to get in response all valid services according to specific weight and dimensions
    For Example
    ———–
    Request
    ——-
    size : Large
    container: Rectangular
    mailType : Envelope
    weight : ( ex : 2 ounces )
    Dimensions : ( L X W X H )
    and so on the rest of parameters ….

    Response
    ———-
    List of services filtered according to the weight (sent in request) .

Leave a Reply