Calculating UPS Shipping Rate with PHP

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.

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
  • 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.

If this article helped you in any way please consider digging this article by clicking the “digg it” link below. This will help others find the article. :)



76 Responses to "Calculating UPS Shipping Rate with PHP"
  1. Jason on November 30th, 2007

    You are my hero!

  2. Mark Sanborn on November 30th, 2007

    Thanks,

    I assume the code worked good for ya :)

  3. CJJUNE on December 1st, 2007

    I obtain an error saying Fatal error: Cannot use string offset as an array in upsxml.php

    linewith error in the code is this:
    $eta_array = explode(”-”, $this->servicesTimeintransit[$type]["date"]);

    Please help. Thanks

  4. CJJUNE on December 1st, 2007

    I obtained the code from here http://www.brandnamebatteries.com/contributions/index.htm

    Please help.

  5. CJJUNE on December 1st, 2007

    Where should I place the “RequestXML.txt” file? In the root folder?

  6. Mark Sanborn on December 1st, 2007

    I didn’t make the zen-cart UPS code so I cannot help you with that. If you want to get UPS rates you can use the code that I have listed above.

    The RequestXML.txt is just for troubleshooting if the code is not working you can send the xml file directly to UPS without PHP using CURL. It doesn’t matter where you put the RequestXML.txt. Just login via SSH and change to the directory where you saved it and execute this command, “curl -d @RequestXML.txt https://www.ups.com/ups.app/xml/Rate“.

    Remember that you have to change some of the lines in the code to include your own UPS Access key, username, password, and originating zipcode.

  7. Leon Roose on December 3rd, 2007

    I tried to copy your UPS PHP Function. I got this:

    The XML page cannot be displayed
    Cannot view XML input using XSL style sheet. Please correct the error and then click the Refresh button, or try again later.

    ——————————————————————————–

    A string literal was expected, but no opening quote character was found. Error processing resource ‘http://www.marksanborn….

    —————————–^

    Something wrong on my end?
    LR

  8. Mark Sanborn on December 3rd, 2007

    Hi Leon,

    I have some questions about your question :P
    What do you mean you try and copy the PHP function? are you clicking the link and copy and pasting the text?

    Are you having trouble opening the link to the function?

    Or is this a PHP error after you have pasted the function on your server in a .php file?

  9. Leon on December 3rd, 2007

    I clicked on the UPS PHP Function link in order to do a copy (as I think you instructed) and then to do a paste.

    My browser displayed the message given above. What should I be doing?

  10. Mark Sanborn on December 3rd, 2007

    Ok In my current browser, (firefox) I can either click on the link and text will show up that I can copy and paste elsewhere. Or, I can right click on the link and do a save link as. This will save the ups.txt file.

    I’m assuming your browser thinks that the link is an actual XML link. It is only a txt file with PHP in it, so your browser should just display text instead of parsing XML.

    What browser are you using?

  11. Christopher Malone on December 5th, 2007

    Hi Mark -

    Thanks so much for posting this code. I have been losing my mind trying to integrate the UPS Rate code into a shopping cart I’m building with PHP/MySql.

    In testing your code I have run into a problem. I wanted to test just to see what UPS would send back. I did everything necessary in the ups.php file. Then, I created a file upstest.php that has the simple code:

    When I run that, I receive the following errors on the page:

    Warning: main(upsphp): failed to open stream: No such file or directory in /home/content/o/v/e/html/upstest.php on line 3

    Fatal error: main(): Failed opening required ‘upsphp’ (include_path=’.:/usr/local/lib/php’) in /home/content/o/v/e/html/upstest.php on line 3

    Any advice on this?

    Thank you!

  12. Mark Sanborn on December 5th, 2007

    Ok make a .php file with the ups function in it. Make sure you modify the php function to include your shipper ID and password.

    Then make another .php file, include or require the ups function via the php include/require command. Then do something like this in the php, without quotes.

    “ups(90210,03,5,5,5,5)”

    The error you are recieving is saying that it cannot find the ups function that you are “requiring”. the difference between the require command and include is that the include will include it if it is there. The require says that if it isn’t there spit out a fatal error. (the one you are seeing above.

    If this isn’t clear I will write another comment later today explaining it better.

    Thanks for reading my blog :)

  13. Christopher Malone on December 5th, 2007

    You’re very welcome. I think I’m getting somewhere… almost. Ok… so I have one .php file which is the ups.php one from here. I customized it with my UPS info. I created another file that has only two lines of php code. The first is the require_once command which I have also tried as an include and the second line is the one you have in quotes above. Saved as upstest.php. Now, instead of the errors, the page waits for a while then displays nothing.

  14. Mark Sanborn on December 5th, 2007

    Try changing this line:

    “curl_setopt($ch,CURLOPT_TIMEOUT, 60);”

    to,

    “curl_setopt($ch,CURLOPT_TIMEOUT, 90);”

    What webhost do you use by chance? I use Dreamhost any recently it has been taking longer to get a cURL request back and I had to change my timeout to 60 (used to be 30).

    Let me know what you find.

  15. Christopher Malone on December 5th, 2007

    I made the changes, but it is still taking a long and not passing any information back. This site is hosted on GoDaddy, so I’m thinking that it might have to do with their curl settings, perhaps? I can tell that the code is working, but there just seems to be something that is causing this error, most likely something to do with the settings?

  16. Mark Sanborn on December 6th, 2007

    Christopher,

    I think I have a solution for you. Godaddy requires special instructions. After reading this article:
    http://help.godaddy.com/article.php?article_id=289&topic_id=435

    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′);”

  17. Christopher Malone on December 6th, 2007

    Hi Mark -

    Thanks so much again for your help! I believe those fixes have worked and should be useful for anyone using GoDaddy. The only issue now is that it is giving the error “XML document must have a top level element. Error processing resource…”.

  18. Mark Sanborn on December 10th, 2007

    Hmm, Is anyone else getting this error? Try making an XML txt file and send it with curl via the command line in SSH (See the troubleshooting section of this post). See if that helps, if not I will check into it.

  19. Chris on December 13th, 2007

    Hello Mark -
    Thanks for posting this code. Once I get it working, it should work well for me! I am trying to get it into the cart application I’m building.

    As a test, I have ups_test.php calling the ups function, then calling an instance of the ups function:

    Running this returns a blank page, but when I look at the source code, there’s a bunch of XML code there.

    Among the XML code, I see:

    FailureHard10001The XML document is not well formed

    What would be causing this?

    In the meantime, I need to figure out how to get my php pages to parse the XML!

  20. Chris on December 13th, 2007

    I also wanted to mention that I have my username, password, access key and zipcodes entered in the proper places.

    Any ideas?

    Thanks again!

  21. Mark Sanborn on December 13th, 2007

    Chris,

    First off I want to thank you for checking out my site and using my blog.

    It is really easy to forget to change the XML to meet your needs since there are many things you need to change. I have now changed the UPS function in this post so you can now see everything that needs to be personalized in one central location.

    I also forgot to mention that this function will print out the XML that it receives from UPS in “html comments”. This is why you can view the source of the page and see the error. This is incredibly useful for finding out what went wrong.

    In your case it seems like the function is contacting UPS successfully and UPS is telling you that your XML portion of the function is not correct.

    Go back and copy the new UPS function, edit the area near the top and save it in a text file named ‘ups.php’. Then copy the PHP test file that I just created and linked to this post to a new file called ‘upstest.php’. Upload those to files to your host.

    It should return a monetary value of the shipping cost from your area to Beverly Hills California.

    If it doesn’t, view the source code and tell me what the error says.

    I just went through the code and tried it on my host and the code still works. So don’t give up. You are almost there. :)

  22. Chris on December 14th, 2007

    Mark –

    I tried it again using your updated code and suggestions - and it works!

    My only other question is if it is possible to use the function without passing any of the dimensions? Would it work if I pass only the destination zip and weight?

    Thanks again for your help!

  23. Mark Sanborn on December 14th, 2007

    Well, I found that UPS doesn’t really change the rate based on the dimensions so in my shopping carts I usually make the dimension always 5×5x5. I am not sure on this but when I created that function I believe that UPS required the dimension to process the rate quote.

    Is keeping the dimension always 5×5x5 an option for you? Or would you like me to look into it further?

  24. Chris on December 14th, 2007

    Not necessary. I had not anticipated needing to separate out the dimensions for the product entries in my database. I’m still early enough in the process that I am able to add it in.

    I have the dimensions being dynamically supplied to the function call now and its working. Now the trick is to keep a running tally for the dimensions of all the items in my cart…

    It would still be handy to know if the dimensions are really required, or if the weight is enough. But if you don’t have time, please don’t worry on my account.

    Thanks again for publishing this code - it REALLY saved me alot of time!

  25. Chris on December 14th, 2007

    I just tested it by removing my dynamic code and putting in 5s for those 3 values - and it still returned the same value for shipping.

    Weight and zipcode appear to be the determining factors. So I think the problem is solved!

  26. Mark Sanborn on December 14th, 2007

    Cool, now as a tip maybe in my next post I will describe how I managed to come up with exact rates for bundles of stuff in the shopping cart. Meaning it will calculate how much stuff can go in one box before having to start calculating the shipping for another package.

    This is especially useful if you have a customer buying 12 small items. You don’t want to calculate 12 separate boxes at one pound. I would be a $100 shipping charge.

    On the flip side you don’t want to calculate shipping for 10 large items as one package.

    Would that be something that would be interesting?

  27. Chris on December 14th, 2007

    Definately. In fact, thats exactly what I’m working on now.

    The cart I’m building is for a lumber company. They want to sell stuff online - from a small decorative piece for a doorway all the way up to big lumber packages.

    So that would definately be helpful.

    One other question I thought of after the fact. Is the weight we pass in ounces or pounds?

  28. Mark Sanborn on December 14th, 2007

    Pounds be default. As far as I know UPS doesn’t measure anything in unites less than 1 pound and always rounds up.

  29. Dave Alvarado on December 17th, 2007

    Hi,

    Just downloaded the code. Seems to work but I’m getting warnings. Specifically they are:

    Notice: Undefined index: value in /usr/local/apache2/htdocs/dhlovelife/v2/ups_shipping_fns2.php(118) : eval()’d code on line 1

    Notice: Undefined index: value in /usr/local/apache2/htdocs/dhlovelife/v2/ups_shipping_fns2.php(118) : eval()’d code on line 1

    They are complaining about this line:

    eval($php_stmt);

    The XML doc returned appears to be valid and I’m getting a value. But I’m a stickler for warnings so wondering if there is something I can do to make them go away. Let me know what additional info I should provide. Thanks, - Dave

  30. Mark Sanborn on December 17th, 2007

    Are these showing up on the html page or are these in a PHP error log?

    What version of PHP are you using?

  31. Dave Alvarado on December 17th, 2007

    I’m using PHP 4.4.4 on Fedora Core 6 Linux. These are showing up on the HTML page itself. I’m testing this on a development machine with the PHP error reporting set to E_ALL.

    Thanks for any info, - Dave

  32. David on December 20th, 2007

    Thanks for the coding. Works Great for US but how do I get it to do International. I tested using UPS country codes but keeps throwing The requested service is unavailable between the selected locations. Maybe wrong shipping type?

  33. David on December 20th, 2007

    Yuppers thats what it was. Works awesomely well now :)

  34. Mark Sanborn on December 20th, 2007

    David, glad you got it working. Some international areas (anything overseas) requires a different type of shipping. Its called UPS Worldwide and UPS World wide Express, etc…

    To my knowledge you can ship standard UPS ground to Mexico and Canada.

    Dave Alvarado, I am not sure why it is giving you errors were you ever able to figure it out?

  35. Klynt Maston on January 16th, 2008

    Mark,

    I’m getting this error:

    Notice: Undefined index: RATINGSERVICESELECTIONRESPONSE

    Would you know how to fix this? I kept your code mainly the same. I just added one line - curl_setopt($ch,CURLOPT_PROXY,’http://proxy.shr.secureserver.net:3128′);

    Thanks a lot!

  36. cheeby on January 17th, 2008

    Really nice.

    I was in the same boat as you until I found your post. Thanks Mark.

    Here’s what my ship_test.php looks like:

    “;

    $dest_zip = “53703″;
    $service = “03″;
    $weight = “73″;
    $length = “60″;
    $height = “14″;
    $width = “12″;

    $result = ups($dest_zip,$service,$weight,$length,$width,$height);

    // can now use $result for whatever purpose
    // for now, just echo out the cost

    echo “shipping cost is $result”;
    ?>

  37. gknight on January 19th, 2008

    Mark,
    I keep trying EVERYTHING that I can to get this thing to work. I have changed all of the information that I have needed to change and added the GoDaddy Proxy server line for cURL. No matter what I do, I keep getting the Hard Error 250000. Basically telling me that there is no XML in the request. I have copied everything from their examples to replace what you had in the file originally, but it still won’t work. Some help would REALLY be nice right now……;)

    Thanks in advance,
    GKnight

  38. gknight on January 19th, 2008

    Ummmmm, ok, uuummmmm, nevermind. It just magically started working. Don’t know what happened, but I am not complaining one bit. I will say this, I have seen some of the weirdest stuff happen while dealing with GoDaddy hosting. Oh well, it is working now. Thank you so VERY much for posting this script for free. There’s no words that can tell you how much I, and most likely a lot of other people as well, appreciate it.

    Kudos to you!!!
    GKngiht

  39. Mark Sanborn on January 19th, 2008

    I too have seen some weird things with GoDaddy hosting.

    You are welcome for the script. I love to get these comments from people. It motivates me to write more. A lot of people read my articles but don’t comment so it is hard to judge if they appreciate my work.

    For that, I thank you sir. :)
    Mark

  40. Chris on January 23rd, 2008

    Hi Mark,
    Thanks for posting your solution. I found it quite helpful.

    I also use Dreamhost and also noticed that the script is averaging just under a minute to return a rate amount on one of their shared accounts. (Interestingly, the script runs in under a second on a different ISP’s shared machine.)

    I’m wondering how you make use of the script (assuming it’s being used on Dreamhost) given that performance is rather slow in the shared hosting environment. Do you use it as part of a web application? My first impulse was to leverage the script in a cart I’m developing on DH, but I fear that it’s just too slow there to be of practical use.

    Thanks again for sharing,
    -Chris

  41. Mark Sanborn on January 24th, 2008

    Chris,

    I wrote a big long comment yesterday explaining how I was going to investigate the issue; however, for some reason it didn’t get submitted. Anyways I apologize for not responding quicker.

    I am currently sending emails back and fourth to Dreamhost trying to find out why cURL is so slow on their servers. At this time they are mostly ignoring me. They believe the problem is UPS but I am assuring them that I can request the same xml file from my home computer and receive it instantly.

    There is obviously something wrong with the way Dreamhost is handling cURL.

    As soon as I get a solid answer from Dreamhost I will post it here. Along with the emails that I have been sending back and fourth to them.

    -Mark

  42. Ken on January 29th, 2008

    Thank you. The most difficult part was getting all them damn codes from UPS.

    I plugged ‘em in, and presto your function spewed the expected result.

    Where’s your DONATE button? You saved me at least a full afternoon of messing with someone else’s poorly constructed Open Source code.

  43. Mark Sanborn on January 29th, 2008

    I know exactly how you feel. The only reason I now know how to calculate UPS shipping with PHP is because I spent hours figuring it out.

    Ken, thank you for your motivating comment. I love to hear that my articles are helping people out. Every time I get a comment like this it inspires me to write more.

    I added a donate button on the right side just for you. :)

  44. Chris on February 10th, 2008

    Hi Mark,

    Did you make any headway with DreamHost on the PHP/cURL performance issue?

    I’ve been pursuing the same problem with them and have yet to get anywhere…

    -Chris

  45. Mark Sanborn on February 11th, 2008

    Chris,

    I have not made any more headway. What are they telling you?

    If enough of us complain maybe they will fix it.

    Mark

  46. Bryan on February 13th, 2008

    Thanks, this looks great! The UPS website is a real pain though. To get an XML access key you need a developer’s key. To get that key you need a UPS account. To set up that account they need a credit card.

    Why must UPS store my credit card so I can look up some shipping rates? Did anyone find a way a round this?

  47. Chris on February 14th, 2008

    Hey Mark,

    Basically, they’re passing the buck. The latest feedback after monitoring the rate lookup script in action on my account:

    cURL is having troubles on doing a reverse lookup on ups.com’s IP, which is mis-configured (e.g.. it doesn’t reverse lookup correctly). I’m going to be speaking with an admin to hopefully find a band-aide solution to make cURL stop going this, but it actually appears the culprit is ups.com’s DNS setup.

    For the time being, you may want to consider trying an alternative method; maybe use ups.com’s IP address instead of domain or find an alternative domain name to use, another possibility would be to use fopen for the URL (Although this would require you configure your own PHP — so it may not be worth the extra effort).

  48. Conrad on February 17th, 2008

    Thanks for putting this up, you saved me a lot of time and helped my client and I out a lot!

  49. Mark Sanborn on February 18th, 2008

    Conrad,

    Glad I could help.

    Mark

  50. Brian on February 26th, 2008

    Great script works like a charm with 1and1 linux hosting!

  51. Arun on March 17th, 2008

    Hi Mark Sanborn!

    I have used your code for UPS rate calculation. its working fine. thanks for this wonderful guidance.

    I having a problem while i post the “ShipmentConfirmationRequest”

    I have put only for choices of services

    code description
    1. 02 => “UPS Second Day Air”
    2. 03 => “UPS Ground”
    3. 12 => “UPS Three-Day Select”
    4. 14 => “UPS Next Day Air® Early A.M. SM”

    when i select the fourth option, the ShipmentConfirmationRequest is come successfully. whereas i select the rest of the options I am getting the following error :

    1.00010 Failure Hard 121175 Verbal Confirmation of Delivery is unavailable with the selected service.

    So, Please help me out,

    Thanks in advance.

  52. Mark Sanborn on March 17th, 2008

    Well it means exactly what it says. UPS is telling you that they don’t support verbal confirmation with the selected service. Contact them and ask them why.

  53. Greg Walsh on March 21st, 2008

    Hi Mark

    I used your script and it appears to be working correctly but the UPS server is responding with “0FailureHard250005No Access Identification provided”. Not that it is bad mind you but that it is not provided. it is. I even stripped it down to just the access xml and i always get the same response

    i tried it using the command line and the xml content in a file

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

    and it did work however when i tried this

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

    without the @ sign i did get back the original error message. it appears to be something in the php interface.

    thoughts?

  54. Mark Sanborn on March 25th, 2008

    “FailureHard250005No Access Identification provided”

    Usually means the xml file does not contain your credentials.

  55. Arod on April 2nd, 2008

    Hello,

    I’m trying to have a section on my site that allows for multiple shipping destinations, is there a way to execute this function twice on the same page?

  56. Mark Sanborn on April 2nd, 2008

    Arod,

    Yes of course.

    $rate1 = ups(90210,03,5,5,5,5)
    $rate2 = ups(97470,03,5,5,5,5)

    rate1 will have the UPS ground rate of a 5lb package to California.

    rate2 will have the UPS ground rate of 5lb package to Oregon.

  57. Rashmi on April 3rd, 2008

    all is working fine , html page displaying shipping amount , but along with this error notice 9.85PHP Notice: Undefined index: value in D:\www\ups.php(114) : eval()’d code on line 1 PHP Notice: Undefined index: value in D:\www\ups.php(114) : eval()’d code on line 1

    its coming on html page. i think eval($php_stmt); is the source of problem. pls let me know how to overcome with this problem.

  58. Rashmi on April 6th, 2008

    Hi, how can we run this code in test mode? pls let me know.

  59. [...] do I use the UPS API of which they supply close to 70 pages of documentation? Well, first off read this article and download his code. I am not going to take credit in creating the function I use. He also takes [...]

  60. Bob TImms on April 11th, 2008

    I keep getting a parse error and I’ve triple checked that the code is identical to that posted.

    Parse error: syntax error, unexpected T_STRING in /home/pro/public_html/ups.php on line 14

    Any suggestions would be greatly appreciated.

  61. Mark Sanborn on April 11th, 2008

    Bob Tlmms,

    The code as is in this post works when I try it. But different hosts may have php configured differently.

    I was looking at the code and your php may be erroring when it reaches, ‘?>’ <—- that part of the code on line 14.

    The $data variable is defined with double quotes. This means that it will try to execute code within before converting it to a string. Your php may be trying to end the code when it reaches the question mark-greater than.

    You can try escaping the question mark or converting is to ascii code.

    Let me know if this helps. I will also do some further investigation for fixing this in the future.

  62. Bob TImms on April 11th, 2008

    Thanks Mark. Tried both suggestions with same results. FWIW, its working the same on my local xampp which is php 4 and my vps which is php 5.

  63. Bob TImms on April 11th, 2008

    Actually I was saving the changed file to wrong directory - when I escape the ? the error starts moving down the page and the ‘ also need escaping.

  64. Bob TImms on April 11th, 2008

    Well I finally got it fixed. Added opening and closing taqs . I didn’t think they were needed in the included/required file.

  65. jared on April 18th, 2008

    Mark,

    Let me echo everyone else’s sentiments and say thanks for sharing your code. It has certainly made my life alot easier :)
    Rashmi,

    You can run Mark’s code in test mode by changing this line:

    $ch = curl_init(”https://www.ups.com/ups.app/xml/Rate”);

    to this:
    $ch = curl_init(”https://wwwcie.ups.com/ups.app/xml/Rate”);

    In UPS’s documentation, they recommend you use their staging environment so that a pickup doesn’t inadvertently get scheduled.

    I assume this is not a problem with Mark’s code?

  66. Fos on April 19th, 2008

    THANK YOU SO MUCH!!!!!!!!!!!!!!
    you just taught me how to get out of the mass with ups libcurl stuff, which I have been struggled for about 3 days! It just works perfect! I can’t thank you enough for your work and this post.

    One little note is that I had to put quotes around $service.
    ex) ups(90010, “03″, 5, 5, 5, 5);
    Otherwise, the response showed 111209 error, which is not even listed on the guide manual from UPS. It said something like Invalid Servcie Name on the XML response though.

    I hope UPS could add this onto their manul for PHP examples.

    THANK YOU once again!

  67. Mark Sanborn on April 21st, 2008

    Jared: You make a great point. UPS has a test server for testing your application. I didn’t use this in my testing since UPS comes for pickup everyday anyways. So I over looked this. I will add it into my post.

    Mark

  68. Fos on April 24th, 2008

    Hi, I came back :) I needed to ask something.
    I’m not getting any xml response from UPS right now…
    is it my falut?? I’m just so confused.
    The thing is that the other site with other way to get XML rate from UPS is also failing. So I don’t think it’s the problem with the code on this post, but I was just curious… am I the only experiencing failures all the sudden?

  69. Frank of Zoinks Graphics on April 29th, 2008

    Hey Mark:

    Allow me to join the choir singing your praises! Why UPS makes this so tough for PHP coders is beyond me. :/

    Feedback: I too was having trouble getting your script to work until I put in the quotes around $service as indicated a few posts above…

    BTW, I found this post via a last-ditch Google search for “ups rates on my site”. May I suggest listing on HotScripts? That’s where I generally go first for stuff like this, and I’m sure you could get a lot more traffic that way. Plus $$$ if you put up a donation link!

    Thanks again!!!

  70. Frank of Zoinks Graphics on April 29th, 2008

    Whoops, I missed the “Donate” tab right at the top of the page. Just sent you some “happy money” for getting me out of my UPS hole!

  71. Frank of Zoinks Graphics on April 29th, 2008

    Okay, one other question… My client is selling perishable items (gourmet cookie dough) and wants to have shipping based on time of year. Ie. In the winter offer slower-UPS options, but in the summer only faster ones. Is there a way to query the UPS XML for their estimated shipping times based on delivery zip code? I’m thinking I’ll have to do 2 XML queries, the first for the shipping time and the second for the resultant charges…

    Any help in this direction would be greatly appreciated!!

  72. Frank of Zoinks Graphics on April 29th, 2008

    Oops, that’s “TimeInTransitRequest” request…

  73. Mark Sanborn on April 29th, 2008

    Frank,

    Thanks for the donation. :) I am really glad that at least some of my articles are helping people.

    I will look into putting the script in other places like hotscripts. Anything to help people figure out the same problems I was having with UPS.

    You may want to subscribe to the blog. Based on the popularity of this article I am going to continue writing more articles on the topic of setting up shopping carts and calculating shipping costs.

    Mark

  74. Frank of Zoinks Graphics on April 29th, 2008

    Cool, helping people… and making a little scratch too. That’s what it’s all about!

    I’ve asked UPS for help on translating the TimeInTransit XML call, but not sure if they’ll be any help. So if you have any ideas….

  75. Girish on May 2nd, 2008

    Hi,
    Can you please tell me What is UPS shipper number ?

    Thanks in advance

    With Regards,
    S. Girish

  76. Mark Sanborn on May 4th, 2008

    Girish,

    It is the number given to you by UPS. You will need an account with them if you wish to use this service.

Leave a reply