Calculating UPS Shipping Rate with PHP

Written by Mark Sanborn: Nov 27, 2007
Update: For a no fuss, 100% complete UPS Online Tools script with label printing support, integration support and automatic certification generation (required by UPS), I have created, RocketShipIt.

Comments have also been disabled as this script is old and no longer being supported, if you need support please see: RocketShipIt

It’s actually very easy to calculate shipping from UPS with PHP once you know how. But at first glance it seems like an impossible task to do.

The UPS manual for XML shipping calculation is hundreds of pages long and unfortunately provides no examples written in PHP. Only ASP… Damn them! After hours of reading the UPS manual and lots of Google searching I figured out how to make my own and I thought I would share my method. So in today’s post we will look at an example ups rate calculation using PHP.

If you are looking for the United States Postal Service (USPS) function see, Calculating USPS Shipping Rates with PHP.

You can also integrate UPS Tracking features on your site once you get a handle on this.

Things you will need

  • UPS Online Tool Account - free but requires registration
  • UPS Access Key - Comes with the online tool account
  • cURL - Most LAMP (Linux, Apache, Mysql, PHP) web hosts have this installed by default.
  • PHP - You must know a little bit about using php. After all you are about to create a custom UPS shipping calculator.
  • XML - If you know what PHP is you should know what this is. If not read about it here.
  • SSH access - Many web hosts offer this. You don’t HAVE to have it but it makes troubleshooting easier.

Basically you start off by getting setup with UPS and grabbing a copy of their XML manual. Now you need to construct an XML file that will be later sent off to UPS’s server. UPS will then send a response back to you in XML format. We then use PHP to turn the XML into variables that we can use and manipulate. Even add the shipping cost into the subtotal or final checkout cost. After all, whats the use of calculating UPS shipping if you are not going to charge the user for it.

Copy the UPS PHP Function I have created into a new .txt file and name it ups.php.

Go through this function and find the parts in the XML file that are in CAPS, You will need to add your UPS shipper number, access key, username, password, departure zip, etc…

Then create another .php file and make sure to include ups.php.

It might look something like this:

require_once("ups.php")

Now all you have to do to get an accurate UPS rate for a package is call the ups function.

The basic syntax for the function is:

ups($dest_zip,$service,$weight,$length,$width,$height)

So, for example if you wanted to send a five pound package to Beverly Hills CA using UPS ground you would do this:

ups(90210,03,5,5,5,5)

Here is an already written php test file that uses the ups function.

By now you may be wondering how I know that 03 is the code for UPS ground and you also may be wondering what the code is for 2nd Day Air.

You can find all this information in the huge manual with the name dtk_RateXML_V1.zip. You can find this manual on the UPS website after you login under UPS Rates and Services Selection but to save you the time I have listed them below.

UPS Service Selection Codes

  • 01 - UPS Next Day Air
  • 02 - UPS Second Day Air
  • 03 - UPS Ground
  • 07 - UPS Worldwide Express
  • 08 - UPS Worldwide Expedited
  • 11 - UPS Standard
  • 12 - UPS Three-Day Select
  • 13 Next Day Air Saver
  • 14 - UPS Next Day Air Early AM
  • 54 - UPS Worldwide Express Plus
  • 59 - UPS Second Day Air AM
  • 65 - UPS Saver

Feel free to edit the function. The XML part of the code should be altered to fit your needs. This function only has the basic elements needed to calculate a rate. There are other attributes you can specify in the XML part of the document, such as pickup type, packaging type, etc…

Unlike some UPS Rate calculators you do not need to update the fuel surcharges or anything else. These rates come straight from UPS and are as accurate as your XML file has specified.

Troubleshooting

If it’s not working and you think you may have messed up the PHP code you can test to see if it is working by sending your XML file with curl.

Log into your host via SSH, make an xml file named RequestXML.txt. Then run this command.

curl -d @RequestXML.txt https://www.ups.com/ups.app/xml/Rate

If you want to use UPS’s testing server you can use this URL:

https://wwwcie.ups.com/ups.app/xml/Rate

Special Instructions for Godaddy

Godaddy requires a minor change in the ups function. After reading this article:

You need to have a proxy to use cURL on Godaddy.

So under this line: “curl_setopt($ch,CURLOPT_TIMEOUT, 60);”

add this: “curl_setopt($ch,CURLOPT_PROXY,’http://proxy.shr.secureserver.net:3128′);”

Information for Dreamhost Users

If you are using Dreamhost as your webhost, there is currently something wrong with the way they handle cURL. It takes almost 60 seconds to receive a response. This is not the script or UPS’s fault. As of 01-24-2008 I have a support ticket out to fix the problem. I am getting emails from them and I will update this post as soon as I get a fix or information from them.

Here are the emails I have received from Dreamhost regarding the issue:

On Thu, 24 Jan 2008, you wrote:

So I am using cURL to send a receive XML requests for the purposes of shipping products via UPS.

A year ago cURL responses were almost immediate. Today (and the last few months) they seem to take almost 60 seconds to send and receive the same XML file. Out of laziness on my part I have not complained about the issue until now. But I need to know what I can do to speed this up a bit.

Attached will be an example of the code I use.

Thanks in advance

Mark

We don’t really troubleshoot code but I would think the most likely explanation (since cURL in itself should be very fast) is that something changed with UPS’s site where it slowed down or the process keeps pending for some reason until it times out. You could try setting the timeout to a lower amount (15-20 seconds) and see if it still gets the data or not. Another thing to test the theory if its on USP’s site would be to make a regular static page which sends the same POST data to UPS’s site see how long it takes to fetch the results. Please let me know if you have any additional questions.

I guess I should have included this in my original email. I have tried this exact code on other hosting servers and it works almost instantly. I have indeed sshed and ran cURL by itself and it is extremely slow. This is definitely not a code issue or UPS slow server issue. I can send the same request via curl on my home computer and it is faster than dreamhost.

Please advise

Mark

Although normally we do not assist customers with third party software, I’ve dealt with similar issues in the past with UPS. Could you please send me the complete path of the PHP that’s running slowly? I can run some debugging software on it for you to see if there is anything hanging things up and anything I can do to fix it.

Thankyou for attempting to solve my issue. I still must insist that it is not a third party software issue. I believe this has nothing to do with UPS. As stated in my earlier email the PHP is not to blame here either. The problem lies within the response time of cURL.

To seperate php from the equation I went ahead and created an xml text file on my root directory on dreamhost. I then ran the following command:

curl -d @xml.txt https://www.ups.com/ups.app/xml/Rate

It took 56.853 seconds to receive a response from Dreamhost. I copied the same xml.txt file to my personal home computer and ran the same command and received a response in 1.2 seconds.

I will attach a log of the commands I ran.

As you can see it takes Dreamhost way longer to send/receive responses via curl. If you want to test it yourself you can run the same command I did from my home directory. The xml file is in there.

Thanks for your help in this matter. If you have any questions about my analysis please email.

Mark

Alright, I’ve run some tests and asked some admins their opinions and here are the results.

It appears that the slowness is because cURL is trying to reverse lookup the IP address for www.ups.com which is timing out. This is the culprit, but, unfortunately there is no easy fix for it if you must use cURL.

Here is the strace results:

connect(3, {sa_family=AF_INET, sin_port=htons(53), sin_addr=inet_addr(“66.33.216.208”)}, 28) = 0 send(3, “\230\313\1\102500322801203153\7”…, 43, 0) = 43 gettimeofday({1201218751, 713629}, NULL) = 0 poll(

This is what it’s lagging on (as the DNS lookup takes 3-5 seconds to time out)

One quick option may be to instead use fopen for the URL – of course to do this you’ll need to install a custom PHP.ini file and customize it to allow_url_fopen ( http://wiki.dreamhost.com/PHP.ini )

Sorry about the semi-bad news. Of course if you have any other questions

Why would a reverse look up to a well known domain such as www.ups.com fail? Why can other webhosts receive cURL responses with out a hangup?

When you say that a reverse lookup is causing a 3-5 second timeout why is curl taking over 60 seconds to receive a response? I would be more than happy to have a 3-5 second response time.

Why did curl respond much faster on Dreamhost prior to 10/09/2007? (I looked back in my emails and found the date I started having slow response times)

Mark

Sorry for the delay in getting back to you…our support system has been pretty backlogged lately. The only explanation I can come up with is a quirky routing issue or something…I’ve seen it before, specifically with UPS, and the only solution was to use the IPs rather than the hostnames. I am sorry we don’t have a better solution for you. If it is possibly something on our end, we have no idea what it is, I’m afraid. I apologize for the hassle.

Need to print shipping labels on your site?

Checkout my product RocketShipIt for simple easy-to-use developer tools for UPS™ FedEx™ USPS™ and more.

Share: