Printing a Label for USPS with PHP

If you have been following the posts on USPS you should know how to calculate USPS shipping rates with PHP. Today we are going to use the same USPS API to print out a label. One of the advantages of this is that you get free tracking on all priority shipments when you create your own label. The other advantages is that you get to integrate automatic label generation with your website for customers or for your own shipping.

Start off by making a file called, USPSLabel.php and copy and paste the code below and save it.

Then Change the userName variable with your USPS username and change the rest of the variables to match your label.

USPSLabel.php

<?php
function USPSLabel() {

// This script was written by Mark Sanborn at http://www.marksanborn.net
// If this script benefits you are your business please consider a donation
// You can donate at http://www.marksanborn.net/donate.

// ========== CHANGE THESE VALUES TO MATCH YOUR OWN ===========

$userName = ''; // Your USPS Username
$FromName = '';
$FromAddress2 = '';
$FromCity = '';
$FromState = '';
$FromZip5 = '';

$ToName = '';
$ToAddress2 = '';
$ToCity = '';
$ToState = '';
$ToZip5 = '';

$weightOunces = 5;

// =============== DON'T CHANGE BELOW THIS LINE ===============

$url = "https://Secure.ShippingAPIs.com/ShippingAPI.dll";
$ch = curl_init();

// set the target url
curl_setopt($ch, CURLOPT_URL,$url);
curl_setopt($ch, CURLOPT_HEADER, 1);
curl_setopt($ch,CURLOPT_RETURNTRANSFER,1);

// parameters to post
curl_setopt($ch, CURLOPT_POST, 1);

$data = "API=DeliveryConfirmationV3&XML=<DeliveryConfirmationV3.0Request USERID=\"$userName\">
<Option>1</Option>
<ImageParameters />
<FromName>$FromName</FromName>
<FromFirm />
<FromAddress1 />
<FromAddress2>$FromAddress2</FromAddress2>
<FromCity>$FromCity</FromCity>
<FromState>$FromState</FromState>
<FromZip5>$FromZip5</FromZip5>
<FromZip4 />
<ToName>$ToName</ToName>
<ToFirm />
<ToAddress1 />
<ToAddress2>$ToAddress2</ToAddress2>
<ToCity>$ToCity</ToCity>
<ToState>$ToState</ToState>
<ToZip5>$ToZip5</ToZip5>
<ToZip4 />
<WeightInOunces>$weightOunces</WeightInOunces>
<ServiceType>Priority</ServiceType>
<POZipCode />
<ImageType>PDF</ImageType>
<LabelDate />
</DeliveryConfirmationV3.0Request>";

// send the POST values to USPS
curl_setopt($ch, CURLOPT_POSTFIELDS,$data);

$result=curl_exec ($ch);
$data = strstr($result, '<?');
// echo '<!-- '. $data. ' -->'; // Uncomment to show XML in comments

$xmlParser = new uspsxmlParser();
$fromUSPS = $xmlParser->xmlparser($data);
$fromUSPS = $xmlParser->getData();

curl_close($ch);
return $fromUSPS;
}

class uspsxmlParser {

var $params = array(); //Stores the object representation of XML data
var $root = NULL;
var $global_index = -1;
var $fold = false;

/* Constructor for the class
* Takes in XML data as input( do not include the <xml> tag
*/
function xmlparser($input, $xmlParams=array(XML_OPTION_CASE_FOLDING => 0)) {
    $xmlp = xml_parser_create();
        foreach($xmlParams as $opt => $optVal) {
            switch( $opt ) {
            case XML_OPTION_CASE_FOLDING:
                $this->fold = $optVal;
            break;
            default:
            break;
            }
            xml_parser_set_option($xmlp, $opt, $optVal);
    }

    if(xml_parse_into_struct($xmlp, $input, $vals, $index)) {
        $this->root = $this->_foldCase($vals[0]['tag']);
        $this->params = $this->xml2ary($vals);
    }
    xml_parser_free($xmlp);
}

function _foldCase($arg) {
    return( $this->fold ? strtoupper($arg) : $arg);
}

/*
 * Credits for the structure of this function
 * http://mysrc.blogspot.com/2007/02/php-xml-to-array-and-backwards.html
 *
 * Adapted by Ropu - 05/23/2007
 *
*/

function xml2ary($vals) {

    $mnary=array();
    $ary=&$mnary;
    foreach ($vals as $r) {
        $t=$r['tag'];
        if ($r['type']=='open') {
            if (isset($ary[$t]) && !empty($ary[$t])) {
                if (isset($ary[$t][0])){
                    $ary[$t][]=array();
                } else {
                    $ary[$t]=array($ary[$t], array());
                }
                $cv=&$ary[$t][count($ary[$t])-1];
            } else {
                $cv=&$ary[$t];
            }
            $cv=array();
            if (isset($r['attributes'])) {
                foreach ($r['attributes'] as $k=>$v) {
                $cv[$k]=$v;
                }
            }

            $cv['_p']=&$ary;
            $ary=&$cv;

            } else if ($r['type']=='complete') {
                if (isset($ary[$t]) && !empty($ary[$t])) { // same as open
                    if (isset($ary[$t][0])) {
                        $ary[$t][]=array();
                    } else {
                        $ary[$t]=array($ary[$t], array());
                    }
                $cv=&$ary[$t][count($ary[$t])-1];
            } else {
                $cv=&$ary[$t];
            }
            if (isset($r['attributes'])) {
                foreach ($r['attributes'] as $k=>$v) {
                    $cv[$k]=$v;
                }
            }
            $cv['VALUE'] = (isset($r['value']) ? $r['value'] : '');

            } elseif ($r['type']=='close') {
                $ary=&$ary['_p'];
            }
    }

    $this->_del_p($mnary);
    return $mnary;
}

// _Internal: Remove recursion in result array
function _del_p(&$ary) {
    foreach ($ary as $k=>$v) {
	if ($k==='_p') {
          unset($ary[$k]);
        }
        else if(is_array($ary[$k])) {
          $this->_del_p($ary[$k]);
        }
    }
}

/* Returns the root of the XML data */
function GetRoot() {
  return $this->root;
}

/* Returns the array representing the XML data */
function GetData() {
  return $this->params;
}
}
?>

Then make another file and include the functions like this:

<?php
require('USPSLabel.php');

echo '<pre>'; print_r(USPSLabel()); echo '</pre>';
$USPSResponse = USPSLabel();
$USPSLabel = $USPSResponse['DeliveryConfirmationV3.0Response']['DeliveryConfirmationLabel']['VALUE'];
?>

Then use PHP’s base64_decode(); to convert the image to PDF and save it with fwrite.

USPS Label

Unfortunately the security on this domain won’t allow me to write out an fopen/fwrite statement without throwing out a 503 error. So you will have to look it up. It is about 3 lines of code.

You should end up with a a PDF label like the one to the right. There are options to specify the size and type of label for people with regular printers or thermal label printers.

This is basically just a sample of what you can do. Check out the USPS Webtools guide and just adapt the XML part of the code to your integration needs.


Was this information useful?


20 Responses to "Printing a Label for USPS with PHP"
  1. Greg on December 1st, 2008

    Nice function. Great info for USPS.

    For the fwrite statement, you could always throw the three lines of code into an image and just display the image :)

    sneaky sneaky

  2. Mark Sanborn on December 1st, 2008

    ahh good idea… :) I might just do that

  3. Robert on December 2nd, 2008

    If I try this exact code, with my own USPS username in the proper place, should I get any readable response back? (I uncommented the echo statement on line 69.)

    I’ve been trying things for hours now and can’t get any response at all. I was hoping for an error, or anything, but I get nothing at all.

    My account works properly for the shipping cost calculator. Does the account have to be authorized specifically for shipping labels?

    I also tried the “testing” servers, but they don’t respond either. These are the servers I’ve tried:

    https://Secure.ShippingAPIs.com/ShippingAPI.dll

    https://secure.shippingapis.co/ShippingAPITest.dll

    http://testing.shippingapis.co/ShippingAPITest.dll

  4. Mark Sanborn on December 2nd, 2008

    Opps my bad… Yes, you need to contact USPS again and get production activated for printing labels.

    Pain in the butt isn’t it? They don’t even give you an error like UPS does.

  5. Robert on December 2nd, 2008

    YES! We have labels.

    You must call the USPS tech support number and ask them to activate the Delivery Confirmation API to make the above code work. They are very particular about exactly which API you want – don’t just say “shipping labels” because that’s not clear enough.

  6. prashanthi on December 19th, 2008

    I am using the Delivery Confirmation API.
    I am getting errors

    You are not authorized to connect to this server.

    The servers I’ve tried

    https://secure.shippingapis.co/ShippingAPITest.dll
    i need to activate the account for Delivery Confirmation Api?

    Please help me

  7. Mark Sanborn on December 19th, 2008

    Yes you need to call USPS and request access for their delivery confirmation API.

  8. Wes on December 22nd, 2008

    I did not see a place to input insurance for domestic mail. Is there one? Also, how do you pay for the shipping once the label is printed? I am trying to have a customer pay shipping and I generate the label and send it someone else for printing.

  9. Mark Sanborn on December 22nd, 2008

    Not sure about insurance but as far as the pay goes USPS makes you pay BEFORE the package goes out. UPS/FedEx make you pay once the package is delivered. For USPS they basically force you to use Endicia and stamps.com. I will look but I am pretty sure USPS doesn’t give out accounts on credit.

  10. Christian on January 31st, 2009

    I would like to point out that if you want to print out a sample label you need to change
    API=DeliveryConfirmationV3&XML=<DeliveryConfirmationV3.0Request…

    TO

    API=DelivConfirmCertifyV3&XML=<DelivConfirmCertifyV3.0Request…

    Don’t forget to get the closing XML tag as well.

    Christian

  11. Shawn on February 25th, 2009

    I think I got most of the script working, except the last 3 lines I do not understand. Can you email what I am supposed to put and where?

  12. chama on March 2nd, 2009

    Hi
    Can you help me to get printable view of usps shipping label.i try many ways but it wont work.is there any tutorials how to get it to printable view.I’m using php.

  13. Smoky on March 10th, 2009

    I wrote some code similar to yours last summer. I’m trying to get it print on my dymo thermal printer like PayPal shipping does. It would be great if you could pay for the shipping in the same api call with a credit card. I’ve been waiting for that for years.

  14. Anit on April 19th, 2009

    Hi Mark – Thank you for providing this code. I’ve been searching for hours on google, and this is exactly what I needed. I too am struggling with what the last 3 lines should be to convert this into a PDF file.

  15. Cynthia on May 18th, 2009

    Hi Mark,
    Can u please help me for shipping label API (ExpressMailLabel). I’m using testing server url and running testing scripts as provided in the API Doc. But its giving error: API Authorization failure. ExpressMailLabel is not a valid API name for this protocol.

    What could be the reason? or Do i need to request access for testing also?

  16. ryan on May 21st, 2009

    I too do not quite understand what to do about those 3 lines. Can you email them to me too?

    Thanks a bunch!

  17. Eli on May 26th, 2009

    Hi Mark,
    This is great, thanks.
    The only thing is that it retrieves nothing from the secure servers.
    I took only the curl part that go to the server and sends the XML, I got no response what so ever.
    Any ideas?

  18. Ben Olsen on August 27th, 2009

    Mark, thank you SO much for posting this. I was having a terrible time working with USPS support, and their docs are not very useful. After struggling with them for days, I found your tutorial and had our delivery confirmation labels working in about an hour. This was exactly what I was looking for.

  19. Chris on October 23rd, 2009

    Are these pre-paid labels that are billed directly to the customer’s account (the USPS rep I spoke with called it “PC Postage” vs something called manifesting which has minimum mailing requirements and requires a daily “closeout manifest”)? I was told that the only way to achieve this was by going through a 3rd party (Endicia).

  20. Jason on January 24th, 2010

    Great articles, I’m a .net developer and this will point me in the right direction.

    I looked over their api, but the one thing that I do not see anything on is actually paying for the label.

    How do you pay for it?
    Currently, I use PayPal to print the label and the costs are deducted from my account.

    Are we able to do something similar?