Page 1 of 2

USPS

Posted: Wed Jun 11, 2003 12:10 pm
by matthiasone
Anyone familiar with interacting with USPS server? Send in XML Request? I have found a PHP script written by SauShip Developer. When I use the code I get back:

Code: Select all

<html><head><title>Error</title></head><body>The parameter is incorrect. </body></html>
Any Ideas?

Posted: Wed Jun 11, 2003 12:28 pm
by cactus
Post some code, we may be able to help, or a link to the source of the script by SauShip :)

Regards,

Posted: Wed Jun 11, 2003 12:36 pm
by matthiasone
the link is viewtopic.php?t=7148

here is what I am sending to the script

Code: Select all

<?php
   require_once("/usr/www/users/faog/functions/postage.php");

  $rate = sauship_usps_domestic_quote ('http://Production.ShippingAPIs.com/ShippingAPI.dll', 
    'xxxxxxxxxxxxx',             # Yoyr USPS user 
    'xxxxxxxxxxxxx',              # Your USPS password/access code 
    '1.0',                 # Actual Weight in pounds (LB) 
    '75901', 			   # From Zip
    '75949', 			   # To Zip
    'None',      #  0-109(n) | EP13(x) | EP14 | EP14F | None 
    'Regular',         #  Regular | Large | Oversize 
    '',     # Used for Parcel only 
    'Media'   # Array with many for multi-quote or single-string 
   );
//   echo array_keys($rate).'<br>';
   echo 'rate='.$rate;
   
   
   ?>

Re: USPS

Posted: Wed Jun 11, 2003 12:54 pm
by m3rajk
matthiasone wrote:Anyone familiar with interacting with USPS server? Send in XML Request? I have found a PHP script written by SauShip Developer. When I use the code I get back:

Code: Select all

<html><head><title>Error</title></head><body>The parameter is incorrect. </body></html>
Any Ideas?
what are you trying to get to their servers for? i know they have an online list of official abbreviations. if that's what it's for, since those are pretty stable, it might be easier and more efficient to code that into your page

Posted: Wed Jun 11, 2003 1:27 pm
by matthiasone
I am trying to get postage rates from thier server. Based upon size and location.

Posted: Wed Jun 11, 2003 2:49 pm
by Stoker
Turn debug on

define('DEBUG',1)

and then post the request it made, something went wrong somewhere..

PS! You should really NEVER EVER show your username and password for the USPS service, that is strictly private and for you only (you cna not distribute that in code), and I am sure you are violating the USPS terms by showing your login here.. mask that out before posting

Posted: Wed Jun 11, 2003 2:53 pm
by matthiasone
I already have debug on.....I get

Code: Select all

DEBUG:

Request:
<RateRequest USERID="xxxxxxxxxxxx" PASSWORD="xxxxxxxxxxx">
<Package ID="0">
<Service>Media</Service>
<ZipOrigination>75901</ZipOrigination>
<ZipDestination>75949</ZipDestination>
<Pounds>1</Pounds>
<Ounces>0</Ounces>
<Container>None</Container>
<Size>Regular</Size>
</Package></RateRequest>

http://Production.ShippingAPIs.com/ShippingAPI.dll?API=Rate&XML=<RateRequest USERID="xxxxxxxxxxxxxxx" PASSWORD="xxxxxxxxxxxx">
<Package ID="0">
<Service>Media</Service>
<ZipOrigination>75901</ZipOrigination>
<ZipDestination>75949</ZipDestination>
<Pounds>1</Pounds>
<Ounces>0</Ounces>
<Container>None</Container>
<Size>Regular</Size>
</Package></RateRequest>



Response:
<html><head><title>Error</title></head><body>The parameter is incorrect. </body></html>

-----

array(1) &#123;
  &#1111;"html"]=>
  array(2) &#123;
    &#1111;"@"]=>
    array(0) &#123;
    &#125;
    &#1111;"#"]=>
    array(2) &#123;
      &#1111;"head"]=>
      array(1) &#123;
        &#1111;0]=>
        array(1) &#123;
          &#1111;"#"]=>
          array(1) &#123;
            &#1111;"title"]=>
            array(1) &#123;
              &#1111;0]=>
              array(1) &#123;
                &#1111;"#"]=>
                string(5) "Error"
              &#125;
            &#125;
          &#125;
        &#125;
      &#125;
      &#1111;"body"]=>
      array(1) &#123;
        &#1111;0]=>
        array(1) &#123;
          &#1111;"#"]=>
          string(28) "The parameter is incorrect. "
        &#125;
      &#125;
    &#125;
  &#125;
&#125;
rate=0

Posted: Wed Jun 11, 2003 3:21 pm
by Stoker
Something else must be messed up in the script somewhere, perhaps you could post the whole usps-function?

I just tried the exact same request as you have there and I get this reply:

Code: Select all

<?xml version="1.0"?>
<RateResponse><Package ID="0"><Error><Number>-2147219487</Number><Source>DomesticRates:clsRateEngine.CalcDomesticRate;SolServer.CallRateDll</Source><Description>Machinable value must be 'True' or 'False'.</Description><HelpFile></HelpFile><HelpContext>1000440</HelpContext></Error></Package></RateResponse>
So you may want to add 'True' instead of an empty string for the machinable option....

Posted: Wed Jun 11, 2003 3:25 pm
by matthiasone
ok here you go

Code: Select all

<?php 

/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * 

   SauShip Developer Code Piece 
   Version 0.2.1   2003-03-03 

   (C) Copyright 2002-2003 Sauen.Com and Stoker (Jon T Stokkeland) 
   Sauen.Com, 302 East State Street, Salamanca, New York, 14779  sauship@sauen.com 
   This Code is Open/Free to use with the PHP, BSD, MPL or GPL License at your liking. 

   !WARNING! 
   This is just a bunch of code that happens to be useful if you are doing 
   UPS/USPS API integrations, it is not a solution of any kind and can only be 
   implemented and tested with the UPS/USPS systems by developers who have 
   developers access login/keys and have read and agreed to their terms. 
   Be aware of that UPS and USPS have very strict licensing and software packaging 
   rules, so you can not include this code in any product for sale or open source 
   application, you can only implement it on your own as the end user, or a developer 
   or consultant working on custom integrations directly for the end user which has 
   read and understood the terms from UPS/USPS. 

   This function-collection also includes code written by and Copyright by Hans Anderson 2003 
   Two XML functions, useful stuff: http://www.hansanderson.com/php/xml/xmlize.inc.txt 
    
   BTW: When doing USPS stuff, make sure you read the documentation very carefully, 
   their test server is very limited (idiotic) and will only respond correctly on the predefined 
   canned tests, change any value and you get an error, stupidity if you ask me, 
   or simply incompetent personel that created the system for USPS.. Also, their 
   servers does NOT accept anything else than GET, they never heard of POST I guess.. 
   The production server is quite a bit more forgiving, allows more correct XML etc. 

   .. Will create some docs some day .. 
    
  # Requires PHP with curl (and ssl for UPS) The USPS part can easily be rewritten 
  # to not use curl.. The UPS part could use command line curl if you need to. 
    
  * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */ 

  # All functions and global variables are prefixed with sauship_ (as a namespace). 
  # I did not create this as a class, mainly because PHP is not very efficient at OO code. 
  # If you would like a single-class version of this I can certainly create that for you  

  # Use this to debug 
  define('DEBUG',1); 

  ### Public Functions 
  
  
 
  ############################# 
  # USPS 

  function sauship_usps_domestic_quote ( 
    $usps_server_url,     # The server post URL provided to you by USPS 
    $username,             # Yoyr USPS user 
    $password,              # Your USPS password/access code 
    $weight,                 # Actual Weight in pounds (LB) 
    $from_zip, 
    $to_zip, 
    $container='None',      #  0-109(n) | EP13(x) | EP14 | EP14F | None 
    $psize='Regular',         #  Regular | Large | Oversize 
    $machinable='True',     # Used for Parcel only 
    $service=array('Priority','Express','Parcel')   # Array with many for multi-quote or single-string 
   ) 
  &#123; 
      
    # Very little error control for now 
    
    $timeout = 30; 
    if (!is_array($service)) $svc = array($service); 
    else $svc = &$service; 
    
    $p = ''; 
    $i = 0; 
    $pounds = (int) floor($weight); 
    $ounces = (int) ceil(((float)$weight - (float) $pounds) * 16); // Round up to nearest ounce 
    foreach ($svc as $s) &#123; 
        if ($s === 'Parcel') $m = sauship_xmltag('Machinable',0,$machinable,1)."\n"; 
        else $m = ''; 
        $p .= "\n". 
          sauship_xmltag('Package',array('ID'=> $i++), 
            "\n".sauship_xmltag('Service',0,$s,1)."\n" 
            .sauship_xmltag('ZipOrigination',0,$from_zip,1)."\n" 
            .sauship_xmltag('ZipDestination',0,$to_zip,1)."\n" 
            .sauship_xmltag('Pounds',0,$pounds,0)."\n" 
            .sauship_xmltag('Ounces',0,$ounces,0)."\n" 
            .sauship_xmltag('Container',0,$container,1)."\n" 
            .sauship_xmltag('Size',0,$psize,1)."\n" 
            .$m 
           ,0);          
    &#125; 

          $x = 
               sauship_xmltag('RateRequest',array( 
         'USERID'     => htmlspecialchars($username), 
         'PASSWORD' => htmlspecialchars($password) 
        ), 
        $p, 
        0 
    );
   $request = $usps_server_url.'?API=Rate&XML='.$x; 
    if (DEBUG) echo "<pre>DEBUG:\n\nRequest:\n".htmlspecialchars($x) ."\n\n". 
                            htmlspecialchars($request)."\n\n"; 
    
    # Do some fopen() or file() here instead if you don't have curl 

    $curlsession = curl_init(); 
    @curl_setopt ($curlsession, CURLOPT_URL, $request); 
    curl_setopt ($curlsession, CURLOPT_TIMEOUT, $timeout); 
    curl_setopt ($curlsession, CURLOPT_HEADER, 0); 
    curl_setopt ($curlsession, CURLOPT_RETURNTRANSFER, 1); 
    $response = @curl_exec ($curlsession); 
    $curlinfo = curl_getinfo($curlsession); 
    if (!$response) &#123; 
      $curl_error = curl_error($curlsession); 
      $curl_errno = curl_errno($curlsession); 
      $error = 'Curl error: '.$curl_errno.' '.$curl_error."\nConnection details:\n"; 
      if (is_array($curlinfo)) &#123; 
         while ($row = each($curlinfo)) &#123; 
              $curl_info .= '  ' . $row&#1111;0] . ' => ' . $row&#1111;1] . "\n"; 
         &#125; 
      &#125; else &#123; 
        $curl_info .= '  '.$curlinfo. ' ::: The request: '.serialize($request); 
      &#125; 
      $GLOBALS&#1111;'sauship_error'] = $curlinfo;  // Use this to debug 
      return 0; 
    &#125; 
    curl_close($curlsession); 

    if (DEBUG) echo "\n\nResponse:\n".htmlspecialchars($response)."\n\n-----\n\n"; 

    unset ($request); 
    $xmld = sauship_xmlize($response); 
    if (!$xmld) &#123; 
      $GLOBALS&#1111;'sauship_error'] = 'Xmlize failed, nothing returned. Response: '.serialize($response); // Use this to debug 
      return 0; 
    &#125; 
    unset ($response); 
    
    if (DEBUG) var_dump($xmld); 

    // If there where no rates found you can use this var to debug it - comment out if you don't want it.. 
    $GLOBALS&#1111;'sauship_response'] = $response; 

    $ratex = $xmld&#1111;'RateResponse']&#1111;'#']&#1111;'Package']; 

    if (!is_array($ratex)) &#123; 
      $GLOBALS&#1111;'sauship_error'] = 'Rateportion missing: '.serialize($response)."\n\nXmlized: ".serialize($xmld); // Use this to debug 

      // This could occur if your weight was way high and no rating was available, therefor I set this global var u can auto-debug with 
      $GLOBALS&#1111;'sauship_norate'] = 1; 

      return 0; 
    &#125; 
    unset($xmld); 
    
    foreach ($ratex as $cherr) if ($cherr&#1111;'#']&#1111;'Error']) &#123; 
        $err1 = (int) $cherr&#1111;'#']&#1111;'Error']&#1111;0]&#1111;'#']&#1111;'Number']&#1111;0]&#1111;'#']; 
        if ($err1 === -2147219498 || 
            $err1 === -2147219453 ) $GLOBALS&#1111;'sauship_wrongzip'] = 1; 
        else $GLOBALS&#1111;'sauship_norate'] = 1; 
         // This could happen if there is an error in just one part, the rest may be ok.. 
        $GLOBALS&#1111;'sauship_error'] = 'Errorcode in response: '.serialize($ratex); 
        return 0; 
    &#125; 
  
    $rates = array(); 
    foreach ($ratex as $rate) &#123; 
      $rates&#1111;(string) $rate&#1111;'#']&#1111;'Service']&#1111;0]&#1111;'#']] =  $rate&#1111;'#']&#1111;'Postage']&#1111;0]&#1111;'#']; 
    &#125; 

    if (DEBUG) &#123; echo "\nParse result:\n"; print_r($rates); echo "\n--\n"; &#125; 

    return $rates; 
  &#125; 
  
  
  
  
  
  


  ############################################################################################### 
  ### 
  ### Internal functions 
  ### 


     // This function was written by and is Copyright by Hans Anderson 2003 - http://www.hansanderson.com/php/xml/xmlize.inc.txt - PHP License 
     function sauship_xmlize($data) &#123; 
        $data = trim($data); 
        $vals = $index = $array = array(); 
        $parser = xml_parser_create(); 
        xml_parser_set_option($parser, XML_OPTION_CASE_FOLDING, 0); 
        xml_parser_set_option($parser, XML_OPTION_SKIP_WHITE, 1); 
        xml_parse_into_struct($parser, $data, $vals, $index); 
        xml_parser_free($parser); 
        $i = 0; 
        $tagname = $vals&#1111;$i]&#1111;'tag']; 
        if ( isset ($vals&#1111;$i]&#1111;'attributes'] ) ) &#123; 
            $array&#1111;$tagname]&#1111;'@'] = $vals&#1111;$i]&#1111;'attributes']; 
        &#125; else &#123; 
            $array&#1111;$tagname]&#1111;'@'] = array(); 
        &#125; 
        $array&#1111;$tagname]&#1111;"#"] = sauship_xml_depth($vals, $i); 
        return $array; 
     &#125; 

     // This function was written by and is Copyright by Hans Anderson 2003 - http://www.hansanderson.com/php/xml/xmlize.inc.txt - PHP License 
     function sauship_xml_depth($vals, &$i) &#123; 
         $children = array(); 
         if ( isset($vals&#1111;$i]&#1111;'value']) ) &#123; 
             array_push($children, $vals&#1111;$i]&#1111;'value']); 
         &#125; 
         while (++$i < count($vals)) &#123; 
             switch ($vals&#1111;$i]&#1111;'type']) &#123; 

                case 'open': 
                     if ( isset ( $vals&#1111;$i]&#1111;'tag'] ) ) &#123; 
                         $tagname = $vals&#1111;$i]&#1111;'tag']; 
                     &#125; else &#123; 
                         $tagname = ''; 
                     &#125; 
                     if ( isset ( $children&#1111;$tagname] ) ) &#123; 
                         $size = sizeof($children&#1111;$tagname]); 
                     &#125; else &#123; 
                         $size = 0; 
                     &#125; 
                     if ( isset ( $vals&#1111;$i]&#1111;'attributes'] ) ) &#123; 
                         $children&#1111;$tagname]&#1111;$size]&#1111;'@'] = $vals&#1111;$i]&#1111;"attributes"]; 
                     &#125; 
                     $children&#1111;$tagname]&#1111;$size]&#1111;'#'] = sauship_xml_depth($vals, $i); 
                 break; 

                 case 'cdata': 
                     array_push($children, $vals&#1111;$i]&#1111;'value']); 
                 break; 

                 case 'complete': 
                     $tagname = $vals&#1111;$i]&#1111;'tag']; 

                     if( isset ($children&#1111;$tagname]) ) &#123; 
                         $size = sizeof($children&#1111;$tagname]); 
                     &#125; else &#123; 
                         $size = 0; 
                     &#125; 
                     if( isset ( $vals&#1111;$i]&#1111;'value'] ) ) &#123; 
                         $children&#1111;$tagname]&#1111;$size]&#1111;"#"] = $vals&#1111;$i]&#1111;'value']; 
                     &#125; else &#123; 
                         $children&#1111;$tagname]&#1111;$size]&#1111;"#"] = ''; 
                     &#125; 
                     if ( isset ($vals&#1111;$i]&#1111;'attributes']) ) &#123; 
                         $children&#1111;$tagname]&#1111;$size]&#1111;'@'] = $vals&#1111;$i]&#1111;'attributes']; 
                     &#125;          
                 break; 
      
                 case 'close': 
                     return $children; 
                 break; 
             &#125; 
         &#125; 
    return $children; 
     &#125; 



     # Create the AccessRequest 'document' (UPS) 

     function sauship_accessrequest ( $username, $password, $xml_access_code ) &#123; 
        return '<?xml version="1.0"?>'."\n" 
          . @sauship_xmltag('AccessRequest',array('xml:lang'=>'en-US'), 
               @sauship_xmltag('AccessLicenseNumber',0,$xml_access_code,1) 
             . @sauship_xmltag('UserId',0,$username,1) 
             . @sauship_xmltag('Password',0,$password,1) 
         ); 
     &#125; 


     # Create XML tag 

     function sauship_xmltag ( 
       $tagname,                 # string 
       $params = array(),        # Associative array 
       $data ='',                # string 
       $convert_entities = 0     # konvert parameter values and data to legal entities 
      ) 
     &#123; 
         $result = "<$tagname"; 
         if ($params) &#123; 
           while (list ($key, $val) = each ($params)) &#123; 
             if ($convert_entities) &#123; 
                $val = str_replace('&','&',$val); 
                $val = str_replace('"','"',$val); 
                $val = str_replace('''','&apos;',$val); 
                $val = str_replace('>','>',$val); 
                $val = str_replace('<','<',$val); 
        &#125; 
             $result .= ' '.$key.'="'.addslashes($val).'"'; 
           &#125; 
         &#125;        
         if (trim($data) !== '') &#123; 
           if ($convert_entities) &#123; 
              $data = str_replace('&','&',$data); 
              $data = str_replace('"','"',$data); 
              $data = str_replace('''','&apos;',$data); 
              $data = str_replace('>','>',$data); 
              $data = str_replace('<','<',$data); 
      &#125; 
           $result .= '>'.$data.'</'.$tagname.'>'; 
        &#125; 
        else $result .= " />"; 
        return $result; 
     &#125; 



     function sauship_ups_service_code ($code = '') &#123; 

   static $c = array ( 
    '01' => 'Next Day Air', 
    '02' => '2nd Day Air', 
    '03' => 'Ground', 
    '07' => 'Worldwide Express', 
    '08' => 'Worldwide Expedited', 
    '11' => 'Standard', 
    '12' => '3-Day Select', 
    '13' => 'Next Day Air Saver', 
    '14' => 'Next Day Air Early AM', 
    '54' => 'Worldwide Express Plus', 
    '59' => '2nd Day Air AM', 
    '65' => 'Express Saver' 
   ); 

   if (empty($code)) return $c; 
   $code = sprintf('%02d',((int) $code)); 
   if (empty($c&#1111;$code])) return; 
   return $c&#1111;$code]; 

     &#125; 
      

     function sauship_usps_service_code ($code = '') &#123; 

   static $u = array ( 
    'Express' => 'Express mail', 
    'First Class ' => 'First Class mail', 
    'Priority' => 'Priority mail', 
    'Parcel' => 'Parcel Post', 
    'BPM' => 'BPM - Bound Printed Matter', 
    'Library' => 'Library', 
    'Media' => 'Media', 
   ); 

   if (empty($code)) return $u; 
   if (empty($u&#1111;$code])) return; 
   return $u&#1111;$code]; 
    
     &#125; 

?>

Posted: Wed Jun 11, 2003 3:33 pm
by Stoker
Do you have curl installed and working?

Posted: Wed Jun 11, 2003 3:35 pm
by Stoker
ah I think I see the bug, I posted that originally before I had tested much with it, try to replace the line

$request = $usps_server_url.'?API=Rate&XML='.$x;

with

$request = $usps_server_url.'?API=Rate&XML='.urlencode($x);

Posted: Wed Jun 11, 2003 3:39 pm
by matthiasone
yes, I use curl on a different scipt, but I use an exec command to run it.

Posted: Wed Jun 11, 2003 3:43 pm
by matthiasone
that got me a different error message.......

Code: Select all

Response:
<?xml version="1.0"?>
<RateResponse><Package ID="0"><Error><Number>-2147219487</Number><Source>DomesticRates:clsRateEngine.CalcDomesticRate;SolServer.CallRateDll</Source><Description>Machinable value must be 'True' or 'False'.</Description><HelpFile></HelpFile><HelpContext>1000440</HelpContext></Error></Package></RateResponse>

Posted: Wed Jun 11, 2003 3:48 pm
by matthiasone
I modified it to always put a Machinable tags and I got a valid response.

I can't get this thing to work.

Posted: Fri Jun 13, 2003 2:18 pm
by chadpry
i can't get this thing to work... i'm not getting any error messages back at.

is it sending all the required xml tags?

Code: Select all

<?php

/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *

   SauShip Developer Code Piece
   Version 0.2.1   2003-03-03

   (C) Copyright 2002-2003 Sauen.Com and Stoker (Jon T Stokkeland)
   Sauen.Com, 302 East State Street, Salamanca, New York, 14779  sauship@sauen.com
   This Code is Open/Free to use with the PHP, BSD, MPL or GPL License at your liking.

   !WARNING!
   This is just a bunch of code that happens to be useful if you are doing
   UPS/USPS API integrations, it is not a solution of any kind and can only be
   implemented and tested with the UPS/USPS systems by developers who have
   developers access login/keys and have read and agreed to their terms.
   Be aware of that UPS and USPS have very strict licensing and software packaging
   rules, so you can not include this code in any product for sale or open source
   application, you can only implement it on your own as the end user, or a developer
   or consultant working on custom integrations directly for the end user which has
   read and understood the terms from UPS/USPS.

   This function-collection also includes code written by and Copyright by Hans Anderson 2003
   Two XML functions, useful stuff: http://www.hansanderson.com/php/xml/xmlize.inc.txt
   
   BTW: When doing USPS stuff, make sure you read the documentation very carefully,
   their test server is very limited (idiotic) and will only respond correctly on the predefined
   canned tests, change any value and you get an error, stupidity if you ask me,
   or simply incompetent personel that created the system for USPS.. Also, their
   servers does NOT accept anything else than GET, they never heard of POST I guess..
   The production server is quite a bit more forgiving, allows more correct XML etc.

   .. Will create some docs some day ..
   
  # Requires PHP with curl (and ssl for UPS) The USPS part can easily be rewritten
  # to not use curl.. The UPS part could use command line curl if you need to.
   
  * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */

  # All functions and global variables are prefixed with sauship_ (as a namespace).
  # I did not create this as a class, mainly because PHP is not very efficient at OO code.
  # If you would like a single-class version of this I can certainly create that for you 

  # Use this to debug
  define('DEBUG',1);

  ### Public Functions
 
 

  #############################
  # USPS

  function sauship_usps_domestic_quote (
    $usps_server_url,     # The server post URL provided to you by USPS
    $username,             # Yoyr USPS user
    $password,              # Your USPS password/access code
    $weight,                 # Actual Weight in pounds (LB)
    $from_zip,
    $to_zip,
    $container='None',      #  0-109(n) | EP13(x) | EP14 | EP14F | None
    $psize='Regular',         #  Regular | Large | Oversize
    $machinable='True',     # Used for Parcel only
    $service=array('Priority','Express','Parcel')   # Array with many for multi-quote or single-string
   )
  &#123;
     
    # Very little error control for now
   
    $timeout = 30;
    if (!is_array($service)) $svc = array($service);
    else $svc = &$service;
   
    $p = '';
    $i = 0;
    $pounds = (int) floor($weight);
    $ounces = (int) ceil(((float)$weight - (float) $pounds) * 16); // Round up to nearest ounce
    foreach ($svc as $s) &#123;
        if ($s === 'Parcel') $m = sauship_xmltag('Machinable',0,$machinable,1)."\n";
        else $m = '';
        $p .= "\n".
          sauship_xmltag('Package',array('ID'=> $i++),
            "\n".sauship_xmltag('Service',0,$s,1)."\n"
            .sauship_xmltag('ZipOrigination',0,$from_zip,1)."\n"
            .sauship_xmltag('ZipDestination',0,$to_zip,1)."\n"
            .sauship_xmltag('Pounds',0,$pounds,0)."\n"
            .sauship_xmltag('Ounces',0,$ounces,0)."\n"
            .sauship_xmltag('Container',0,$container,1)."\n"
            .sauship_xmltag('Size',0,$psize,1)."\n"
            .$m
           ,0);         
    &#125;

          $x =
               sauship_xmltag('RateRequest',array(
         'USERID'     => htmlspecialchars($username),
         'PASSWORD' => htmlspecialchars($password)
        ),
        $p,
        0
    );
   $request = $usps_server_url.'?API=Rate&XML='.urlencode($x);
    if (DEBUG) echo "<pre>DEBUG:\n\nRequest:\n".htmlspecialchars($x) ."\n\n".
                            htmlspecialchars($request)."\n\n";
   
    # Do some fopen() or file() here instead if you don't have curl

    $curlsession = curl_init();
    @curl_setopt ($curlsession, CURLOPT_URL, $request);
    curl_setopt ($curlsession, CURLOPT_TIMEOUT, $timeout);
    curl_setopt ($curlsession, CURLOPT_HEADER, 0);
    curl_setopt ($curlsession, CURLOPT_RETURNTRANSFER, 1);
    $response = @curl_exec ($curlsession);
    $curlinfo = curl_getinfo($curlsession);
    if (!$response) &#123;
      $curl_error = curl_error($curlsession);
      $curl_errno = curl_errno($curlsession);
      $error = 'Curl error: '.$curl_errno.' '.$curl_error."\nConnection details:\n";
      if (is_array($curlinfo)) &#123;
         while ($row = each($curlinfo)) &#123;
              $curl_info .= '  ' . $row&#1111;0] . ' => ' . $row&#1111;1] . "\n";
         &#125;
      &#125; else &#123;
        $curl_info .= '  '.$curlinfo. ' ::: The request: '.serialize($request);
      &#125;
      $GLOBALS&#1111;'sauship_error'] = $curlinfo;  // Use this to debug
      return 0;
    &#125;
    curl_close($curlsession);

    if (DEBUG) echo "\n\nResponse:\n".htmlspecialchars($response)."\n\n-----\n\n";

    unset ($request);
    $xmld = sauship_xmlize($response);
    if (!$xmld) &#123;
      $GLOBALS&#1111;'sauship_error'] = 'Xmlize failed, nothing returned. Response: '.serialize($response); // Use this to debug
      return 0;
    &#125;
    unset ($response);
   
    if (DEBUG) var_dump($xmld);

    // If there where no rates found you can use this var to debug it - comment out if you don't want it..
    $GLOBALS&#1111;'sauship_response'] = $response;

    $ratex = $xmld&#1111;'RateResponse']&#1111;'#']&#1111;'Package'];

    if (!is_array($ratex)) &#123;
      $GLOBALS&#1111;'sauship_error'] = 'Rateportion missing: '.serialize($response)."\n\nXmlized: ".serialize($xmld); // Use this to debug

      // This could occur if your weight was way high and no rating was available, therefor I set this global var u can auto-debug with
      $GLOBALS&#1111;'sauship_norate'] = 1;

      return 0;
    &#125;
    unset($xmld);
   
    foreach ($ratex as $cherr) if ($cherr&#1111;'#']&#1111;'Error']) &#123;
        $err1 = (int) $cherr&#1111;'#']&#1111;'Error']&#1111;0]&#1111;'#']&#1111;'Number']&#1111;0]&#1111;'#'];
        if ($err1 === -2147219498 ||
            $err1 === -2147219453 ) $GLOBALS&#1111;'sauship_wrongzip'] = 1;
        else $GLOBALS&#1111;'sauship_norate'] = 1;
         // This could happen if there is an error in just one part, the rest may be ok..
        $GLOBALS&#1111;'sauship_error'] = 'Errorcode in response: '.serialize($ratex);
        return 0;
    &#125;
 
    $rates = array();
    foreach ($ratex as $rate) &#123;
      $rates&#1111;(string) $rate&#1111;'#']&#1111;'Service']&#1111;0]&#1111;'#']] =  $rate&#1111;'#']&#1111;'Postage']&#1111;0]&#1111;'#'];
    &#125;

    if (DEBUG) &#123; echo "\nParse result:\n"; print_r($rates); echo "\n--\n"; &#125;

    return $rates;
  &#125;
 
 
 
 
 
 


  ###############################################################################################
  ###
  ### Internal functions
  ###


     // This function was written by and is Copyright by Hans Anderson 2003 - http://www.hansanderson.com/php/xml/xmlize.inc.txt - PHP License
     function sauship_xmlize($data) &#123;
        $data = trim($data);
        $vals = $index = $array = array();
        $parser = xml_parser_create();
        xml_parser_set_option($parser, XML_OPTION_CASE_FOLDING, 0);
        xml_parser_set_option($parser, XML_OPTION_SKIP_WHITE, 1);
        xml_parse_into_struct($parser, $data, $vals, $index);
        xml_parser_free($parser);
        $i = 0;
        $tagname = $vals&#1111;$i]&#1111;'tag'];
        if ( isset ($vals&#1111;$i]&#1111;'attributes'] ) ) &#123;
            $array&#1111;$tagname]&#1111;'@'] = $vals&#1111;$i]&#1111;'attributes'];
        &#125; else &#123;
            $array&#1111;$tagname]&#1111;'@'] = array();
        &#125;
        $array&#1111;$tagname]&#1111;"#"] = sauship_xml_depth($vals, $i);
        return $array;
     &#125;

     // This function was written by and is Copyright by Hans Anderson 2003 - http://www.hansanderson.com/php/xml/xmlize.inc.txt - PHP License
     function sauship_xml_depth($vals, &$i) &#123;
         $children = array();
         if ( isset($vals&#1111;$i]&#1111;'value']) ) &#123;
             array_push($children, $vals&#1111;$i]&#1111;'value']);
         &#125;
         while (++$i < count($vals)) &#123;
             switch ($vals&#1111;$i]&#1111;'type']) &#123;

                case 'open':
                     if ( isset ( $vals&#1111;$i]&#1111;'tag'] ) ) &#123;
                         $tagname = $vals&#1111;$i]&#1111;'tag'];
                     &#125; else &#123;
                         $tagname = '';
                     &#125;
                     if ( isset ( $children&#1111;$tagname] ) ) &#123;
                         $size = sizeof($children&#1111;$tagname]);
                     &#125; else &#123;
                         $size = 0;
                     &#125;
                     if ( isset ( $vals&#1111;$i]&#1111;'attributes'] ) ) &#123;
                         $children&#1111;$tagname]&#1111;$size]&#1111;'@'] = $vals&#1111;$i]&#1111;"attributes"];
                     &#125;
                     $children&#1111;$tagname]&#1111;$size]&#1111;'#'] = sauship_xml_depth($vals, $i);
                 break;

                 case 'cdata':
                     array_push($children, $vals&#1111;$i]&#1111;'value']);
                 break;

                 case 'complete':
                     $tagname = $vals&#1111;$i]&#1111;'tag'];

                     if( isset ($children&#1111;$tagname]) ) &#123;
                         $size = sizeof($children&#1111;$tagname]);
                     &#125; else &#123;
                         $size = 0;
                     &#125;
                     if( isset ( $vals&#1111;$i]&#1111;'value'] ) ) &#123;
                         $children&#1111;$tagname]&#1111;$size]&#1111;"#"] = $vals&#1111;$i]&#1111;'value'];
                     &#125; else &#123;
                         $children&#1111;$tagname]&#1111;$size]&#1111;"#"] = '';
                     &#125;
                     if ( isset ($vals&#1111;$i]&#1111;'attributes']) ) &#123;
                         $children&#1111;$tagname]&#1111;$size]&#1111;'@'] = $vals&#1111;$i]&#1111;'attributes'];
                     &#125;         
                 break;
     
                 case 'close':
                     return $children;
                 break;
             &#125;
         &#125;
    return $children;
     &#125;



     # Create the AccessRequest 'document' (UPS)

     function sauship_accessrequest ( $username, $password, $xml_access_code ) &#123;
        return '<?xml version="1.0"?>'."\n"
          . @sauship_xmltag('AccessRequest',array('xml:lang'=>'en-US'),
               @sauship_xmltag('AccessLicenseNumber',0,$xml_access_code,1)
             . @sauship_xmltag('UserId',0,$username,1)
             . @sauship_xmltag('Password',0,$password,1)
         );
     &#125;


     # Create XML tag

     function sauship_xmltag (
       $tagname,                 # string
       $params = array(),        # Associative array
       $data ='',                # string
       $convert_entities = 0     # konvert parameter values and data to legal entities
      )
     &#123;
         $result = "<$tagname";
         if ($params) &#123;
           while (list ($key, $val) = each ($params)) &#123;
             if ($convert_entities) &#123;
                $val = str_replace('&','&',$val);
                $val = str_replace('"','"',$val);
                $val = str_replace('''','&apos;',$val);
                $val = str_replace('>','>',$val);
                $val = str_replace('<','<',$val);
        &#125;
             $result .= ' '.$key.'="'.addslashes($val).'"';
           &#125;
         &#125;       
         if (trim($data) !== '') &#123;
           if ($convert_entities) &#123;
              $data = str_replace('&','&',$data);
              $data = str_replace('"','"',$data);
              $data = str_replace('''','&apos;',$data);
              $data = str_replace('>','>',$data);
              $data = str_replace('<','<',$data);
      &#125;
           $result .= '>'.$data.'</'.$tagname.'>';
        &#125;
        else $result .= " />";
        return $result;
     &#125;



     function sauship_ups_service_code ($code = '') &#123;

   static $c = array (
    '01' => 'Next Day Air',
    '02' => '2nd Day Air',
    '03' => 'Ground',
    '07' => 'Worldwide Express',
    '08' => 'Worldwide Expedited',
    '11' => 'Standard',
    '12' => '3-Day Select',
    '13' => 'Next Day Air Saver',
    '14' => 'Next Day Air Early AM',
    '54' => 'Worldwide Express Plus',
    '59' => '2nd Day Air AM',
    '65' => 'Express Saver'
   );

   if (empty($code)) return $c;
   $code = sprintf('%02d',((int) $code));
   if (empty($c&#1111;$code])) return;
   return $c&#1111;$code];

     &#125;
     

     function sauship_usps_service_code ($code = '') &#123;

   static $u = array (
    'Express' => 'Express mail',
    'First Class ' => 'First Class mail',
    'Priority' => 'Priority mail',
    'Parcel' => 'Parcel Post',
    'BPM' => 'BPM - Bound Printed Matter',
    'Library' => 'Library',
    'Media' => 'Media',
   );

   if (empty($code)) return $u;
   if (empty($u&#1111;$code])) return;
   return $u&#1111;$code];
   
     &#125;
	 
	 sauship_usps_domestic_quote (
    'https://wwwcie.ups.com/ups.app/xml/Rate',     # The server post URL 
    'myusername',             # Yoyr USPS user
    'mypassword',              # Your USPS password/access code
    '2',                 # Actual Weight in pounds (LB)
    '28804',
    '27534',
    'None',      #  0-109(n) | EP13(x) | EP14 | EP14F | None
    'Regular',         #  Regular | Large | Oversize
    'True',     # Used for Parcel only
    'Media'   # Array with many for multi-quote or single-string
   )

?>