Geekpedia Programming Tutorials






Creating a UPS Shipping Calculator

This tutorial will teach you how to calculate the shipping cost based on the weight, height, length and depth of the box, the distance and the UPS service type. A sample form will be created that will post information to a UPS page. The PHP script will then retrieve and display the shipping cost.

On Monday, August 6th 2007 at 12:37 AM
By Andrew Pociu (View Profile)
*****   (Rated 4.7 with 14 votes)
Contextual Ads
More PHP Resources
Advertisement
Pretty much every website that implements a shopping cart with online payment and checkout of products to be shipped, needs to have a shipping calculator. Depending on the company or companies that you choose to ship the products with, you'll need to read the documentation of their web service. One popular choice is UPS, and because the documentation on implementing their shipping calculator is scarce, that's the one we're going to code in this tutorial.

First you may want to sign up with UPS.com. It's not really needed for the implementation we're doing in this tutorial, however if you'll want to go more advanced, you'll need a developer key and an access key, and at the end of this tutorial there's more information on that.

Let's start with creating the form. In your real application you're probably going to fill your own package size and weight depending on the products ordered. But here we'll be entering these details through the form.

<form action="UPSShip.php" method="post">
Address Type:
<select name="selResidential">
   <option value="01">Residential</option>
   <option value="02">Commercial</option>
</select>
<br />
Packaging:
<select name="selPackaging">
   <option value="00">Customer Packaging</option>
   <option value="01">UPS Letter Envelope</option>
   <option value="03">UPS Tube</option>
   <option value="21">UPS Express Box</option>
   <option value="24">UPS Worldwide 25KG Box</option>
   <option value="25">UPS Worldwide 10KG Box</option>
</select>
<br />
Service Type:
<select name="selService">
   <option value="1DM">Next Day Air Early AM</option>
   <option value="1DA">Next Day Air</option>
   <option value="1DP">Next Day Air Saver</option>
   <option value="2DM">2nd Day Air AM</option>
   <option value="2DA">2nd Day Air</option>
   <option value="3DS">3 Day Select</option>
   <option value="GND">Ground</option>
   <option value="STD">Canada Standard</option>
   <option value="XPR">Worldwide Express</option>
   <option value="XDM">Worldwide Express Plus</option>
   <option value="XPD">Worldwide Expedited</option>
   <option value="WXS">Worldwide Saver</option>
</select>
<br />
Rate:
<select name="selRate">
   <option value="Regular+Daily+Pickup">Daily Pickup service</option>
   <option value="OP_WEB">Oncall Air Pickup Web (arrange on the web for UPS to pick up my packages)</option>
   <option value="OP_PHONE">Oncall Air Pickup Phone (arrange by phone for UPS to pick up my packages)</option>
   <option value="One+Time+Pickup">One Time Pickup</option>
   <option value="Letter+Center">Drop-box Letter Center</option>
   <option value="Customer+Counter">Customer Counter</option>
</select>
<br />
Package Weight: <input type="text" name="txtPackWeight" value="1" /> pounds
<br />
Package Length: <input type="text" name="txtPackLength" value="5" /> inches
<br />
Package Width: <input type="text" name="txtPackWidth" value="5" /> inches
<br />
Package Height: <input type="text" name="txtPackHeight" value="5" /> inches
<br />
From Zip: <input type="text" name="txtFromZip" value="98052" />
<br />
From City: <input type="text" name="txtFromCity" value="Redmond" />
<br />
From Country: <input type="text" name="txtFromCountry" value="US" />
<br />
To Zip: <input type="text" name="txtToZip" value="94043" />
<br />
To City: <input type="text" name="txtToCity" value="Mountain View" />
<br />
To Country: <input type="text" name="txtToCountry" value="US" />
<br />
<input type="submit" value="Submit" />
</form>


As you can see, there are some specific codes that specify the service type, rate and package. You should check the UPS Online Tools Developer's Guide for a complete list on these.

Now that we got the HTML part ready, let's do the PHP. The following PHP code should be placed above the HTML form, in the same file (UPSShip.php.)

<?php

if($_POST['txtFromZip'])
{
   $Url = join("&", array("http://www.ups.com/using/services/rave/qcostcgi.cgi?accept_UPS_license_agreement=yes",
   "10_action=3",
   "13_product=".$_POST['selService'],
   "14_origCountry=".$_POST['txtFromCountry'],
   "15_origPostal=".$_POST['txtFromZip'],
   "origCity=".$_POST['txtFromCity'],
   "19_destPostal=".$_POST['txtToZip'],
   "20_destCity=".$_POST['txtToCity'],
   "22_destCountry=".$_POST['txtToCountry'],
   "23_weight=".$_POST['txtPackWeight'],
   "47_rateChart=".$_POST['selRate'],
   "48_container=".$_POST['selPackaging'],
   "49_residential=".$_POST['selResidential'],
   "25_length=".$_POST['txtPackLength'],
   "26_width=".$_POST['txtPackWidth'],
   "27_height=".$_POST['txtPackHeight']));

   $Resp = fopen($Url, "r");
   while(!feof($Resp))
   {   
      $Result = fgets($Resp, 500);
      $Result = explode("%", $Result);
      $Err = substr($Result[0], -1);

      switch($Err)
      {
         case 3:
         $ResCode = $Result[8];
         break;
         case 4:
         $ResCode = $Result[8];
         break;
         case 5:
         $ResCode = $Result[1];
         break;
         case 6:
         $ResCode = $Result[1];
         break;
      }
   }
   fclose($Resp);
   if(!$ResCode)
   {
      $ResCode = "An error occured.";
   }
   echo $ResCode;
}
?>


All that we're doing is to pass the values of the form fields to an URL at ups.com. That page will then return the shipping cost, or a message such as "The requested service is invalid from the selected origin."

UPS Shipping

Getting a Developer's Key and an Access Key from UPS

There are more options provided by UPS not only in calculating the shipping cost, but also in buying and printing the shipping label. More information on those services is available at the UPS site; it's likely that you'll be needing a Developer's Key and an Access Key for that. To get one is as simple as 1, 2, 3... 4, 5, 6. Or is it?

It's actually not that easy to obtain the access key, you have to go through a number of forms.

First you need to register with My UPS: https://www.ups.com/one-to-one/register?sysid=myups&lang=en&langc=US&loc=en_US
Then you need to sign up for UPS OnLine Tools by entering more information about you and your company, including your account number (you got this in an email from UPS when you signed up.)
You know you're signed up with UPS OnLine Tools when you get this message "Thank you for joining the growing community of UPS OnLine® Tool end users. Upon your agreement to the developer's license, a Developer's Key has been issued and will be e-mailed shortly to the address you provided during registration. Please continue by selecting one of the UPS OnLine Tools listed below."
Then you get emailed a download key, followed by an access key. "An Access Key provides exactly that -- access to UPS systems, which hold the information you or your customers need to ship, track, or rate a package. Your Developer's Key lets you get UPS OnLine Tool documentation; the Access Key lets you actually implement UPS OnLine® Tools."
In order to get the access key, you need to go through one more form, which should be already filled with your current account information. Finally you should receive your Access Key in an email, and in the confirmation message:

Your HTML Access Key is XXXXXXXXXXXXXX.

You now have access to the following UPS OnLine® Tools:

UPS Rates & Service Selection HTML, Version 1.0
UPS Tracking HTML, Version 3.0

Digg Digg It!     Del.icio.us Del.icio.us     Reddit Reddit     StumbleUpon StumbleIt     Newsvine Newsvine     Furl Furl     BlinkList BlinkList

Rate Rate this tutorial
Comment Current Comments
by mohanp on Wednesday, September 26th 2007 at 06:18 AM

it is very helpful to men.can u suggest met how to write this using web services . thank in advance .

by bk on Tuesday, October 23rd 2007 at 10:49 AM

the rates are always 10-15% lower than the ones posted online. can you please clarify?

by Adam on Saturday, October 27th 2007 at 02:52 PM

I agree with bk. how come the rates are lower than the ones quoted directly on ups.com?

by Synapsix on Thursday, January 17th 2008 at 10:58 PM

Commercial rates are incorrect. Any updates to correct this?

by Doug Henderson on Wednesday, February 6th 2008 at 02:00 PM

Hi, I am trying to resolve a bug with UPS using this method you are graciously providing
above. The /services/rave/qcostcgi.cgi? gateway seems to reply with a strange result
and I wonder if you can verify this as strange, a bug, or ? The issue is trying to get a
Worldwide Saver shipment to New Zealand, with an address of

Doug Henderson
5 Kitchener Street
Otago, 9016
Dunedin, New Zealand

The response is something like :

[0] => UPSOnLine4
[1] => WXS
[2] => 97206
[3] => US
[4] => 9035
[5] => NZ
[6] => 404
[7] => 1
[8] => 82.59
[9] => 0.00
[10] => 82.59
[11] => 11:30 P.M.
[12] => )


where I am questioning the 11th result. I usually see a -1 in place of the 11:30 P.M.
which seems a strange result in comparison. Do you know what the 11th return result is and what it is supposed to be? Any light shed on this would be greatfully appreciated.

Thanks,

Doug


by ryan on Thursday, February 28th 2008 at 04:21 PM

I'm not sure if anyone is still interested, but it looks like the UPS website's quote is not taking into consideration the package's dimensions (height,width,length). If you run the above code and remove:

"25_length=".$_POST['txtPackLength'],
"26_width=".$_POST['txtPackWidth'],
"27_height=".$_POST['txtPackHeight']

you will get a very similar quote. After testing this, I was able to get within 60 cents ($9.18 above quote and $9.78 through the UPS website).

by suraj kumar on Tuesday, May 27th 2008 at 03:42 AM

the rates are always 10-15% lower than the ones posted online. can you please clarify?

by suraj kumar on Tuesday, May 27th 2008 at 03:45 AM

the rates are always 10-15% lower than the ones posted online. can you please clarify? as far as
rate is concern through above mention gateway.rate always lower than original means
ups online rate tracking gateway.can any one clarify these thing

by Ed on Friday, August 8th 2008 at 10:28 PM

I am trying to set the "10_action=" entry to allow all available shipping options to display. According to the UPS rep, 3 prices a single product, and 4 shops the entire UPS product range. In actual practice, 3 prices the overnight UPS product, and 4 prices the least expensive UPS product. Tried 0 through 5 with no success. How can I get all the options to display at the same time? Thanks!

by Kevin on Tuesday, October 28th 2008 at 03:21 PM

Where exactly does the php code get placed? Above the HTML form? Where?

This is what I have so far:

<?php
if($_POST['txtFromZip'])
{
$Url = join("

by Kevin on Wednesday, October 29th 2008 at 06:59 PM

Is there a method to add 15% to the final calculation?

by Sonicode on Sunday, April 5th 2009 at 06:08 PM

If you want to save some time, I wrote a PHP Shipping Rates Calculator that is available here: http://www.sonicode.com/php_shipping_rates_calculator.php

by Harshith on Wednesday, May 27th 2009 at 02:59 AM

Does this code work with canada?means if i want to ship from canada to canada.For me this code is not working with canada.I am getting error that "Origin postal code must have five digits." please give me suggestions on this

by Harshith on Wednesday, May 27th 2009 at 04:12 AM

Does this code work with canada?means if i want to ship from canada to canada.For me this code is not working with canada.I am getting error that "Origin postal code must have five digits." please give me suggestions on this

by Yuguang on Tuesday, July 14th 2009 at 08:28 AM

There's no way this can work in Canada. Use UPS XML.

by Jonathan on Friday, September 18th 2009 at 12:26 PM

@ Kevin:

I think if you want to add 15% to the final charge, in the last line of code:

echo $ResCode;

change it to

echo $ResCode = $ResCode * .15;

should work

by Jonatan on Friday, September 18th 2009 at 12:28 PM

Correction, should be:

echo $ResCode = $ResCode * .15;

by Joe on Tuesday, September 22nd 2009 at 04:56 PM

Well I bought the $50 version from Sonic Code. No instructions that I can find. What I cannot figure out is this script (above on the page) works fine for residential UPS without any registration at all. However it seems to not produce Commercial rates. You get the same values regardless of what is selected. Will it calculate commercial?

by Stan on Sunday, October 4th 2009 at 04:32 PM

There is somewhat a differnts in the price that is returned by this script and what is found when you use the UPS.com sites interface. Even with all the settings being the same.
I came up with this odd formula that brings this scripts prices closer in line.
With this the prices are just a bit higher. Between a few cents on the low end (1.lb)and less than a dollar at the hight end that I tested (75lbs).
As to how I figured this little formula out? Well, I am not a math genius( as those who Are could tell with my solution) But I just grafted the UPS.com prices (at 1,10,25,50 and 75 lbs,)for a given address (zip and city) and compared them with a graft of prices given by this script. Then keep playing with the two values (Weight and $ResCode) in a excel formula until a graft of the new values came close to matching up with the upc.com graft. The excel formula is "=(((Bx*Ax)/(Ax/1.6))-(Ax*0.01))-4" with "A" being the weight column, "B" being the value given by $ResCode form this script, And "x" being the Cell address.
Yes it is a little odd but it has worked with each zip code and weight that I have tested it on, using the "shipping from" zip code of Oklahoma City.
just add this to the end of the above script.

$w=$_POST['txtPackWeight']; //this is the weight form the forms page.
$t=$ResCode;
$total=((($t*$w)/($w/1.6))-($w*0.1))-4; // this is the Formula
echo $total;

by Joe on Wednesday, October 7th 2009 at 01:17 PM

Ignore my stupid post about buying this script. I had it confused with something else.

My only question is ....

Does anyone know why the script won't calculate Commercial? Switching from Residential and Commercial gives me the exact same result.

by will on Wednesday, October 7th 2009 at 01:44 PM

$ResCode = $ResCode * 1.15;
echo $ResCode;

otherwise you will show just 15% of the total for shipping.

by matt on Wednesday, October 14th 2009 at 11:11 AM

Does anybody know how to make this work with the dimensions? length width and height have no effect on the output. HELP!

by Stan on Wednesday, October 14th 2009 at 08:21 PM

Dimensions have no barring on shipping price unless the total of LxWxH is larger than normal limits

from UPS site....
Your UPS domestic or UPS Standard package is considered a Large Package when its length, combined with twice the width plus twice the height, exceeds 130 inches and is equal to or less than 165 inches.

See more about this at
http://www.ups.com/content/us/en/resources/ship/packaging/dim_weight.html

so unless the package is larger than 130 inches there will be no price differences.

by Stan on Wednesday, October 14th 2009 at 08:22 PM

Dimensions have no barring on shipping price unless the total of LxWxH is larger than normal limits

from UPS site....
Your UPS domestic or UPS Standard package is considered a Large Package when its length, combined with twice the width plus twice the height, exceeds 130 inches and is equal to or less than 165 inches.

See more about this at
http://www.ups.com/content/us/en/resources/ship/packaging/dim_weight.html

so unless the package is larger than 130 inches there will be no price differences.

by Stan on Wednesday, October 14th 2009 at 08:24 PM

Dimensions have no barring on shipping price unless the total of LxWxH is larger than normal limits

from UPS site....
Your UPS domestic or UPS Standard package is considered a Large Package when its length, combined with twice the width plus twice the height, exceeds 130 inches and is equal to or less than 165 inches.

See more about this at
http://www.ups.com/content/us/en/resources/ship/packaging/dim_weight.html

so unless the package is larger than 130 inches there will be no price differences.

by matt on Wednesday, October 14th 2009 at 10:43 PM

I figured it out after reading more about it. There is a typo in the code.

"47_rateChart=".$_POST['selRate'],

needs to be

"47_rate_chart=".$_POST['selRate'],

by matt on Monday, October 19th 2009 at 12:39 AM

If anyone is wondering why the rates come out lower, I finally figured it out. For some reason UPS does not calculate the fuel surcharge before returning the rates. For ground, the fuel surcharge is 4%, so you will need to multiply the rate by the percentage and then add the product to the original returned rate. I noticed that the fuel surcharge percentage is different for different services. I think next day air was 9.5%.

by matt on Monday, October 19th 2009 at 12:49 AM

UPS ground comes out perfect to the penny with:

$ResCode = $ResCode * 1.04;
echo $ResCode;

by Stan on Monday, October 19th 2009 at 11:52 AM

Matt.
I ran your 1.04 in my graph I used to adjust the prices.
a simple multiplying of the fuel surcharge will not work. perhaps it is close enough at some lower weights, but it quickly fails.

see this chart image
http://www.flickr.com/photos/40259924@N02

The 4 upper charts show the results with my formula calculated in (see my post above for formula)

The lower 4 with the 1.04 shown

The calculations were tested for the the weights of
1,10,25,50 and 75 pounds
For 4 different zip codes from OKC. Two were to in state zip codes and 1 to Dallas TX. and one to Mountain view CA.

The BLUE line show the calculated price given by the native ups code provided in this topic.

The YELLOW line show prices given by UPS.com

The ORANGE line shows the adjusted calculation

My formula as odd as it is , shows an adjustment closer inline with UPS.com

At one pound there was about 3 cents difference and at 75 pounds less than a dollar.

I also tested some of the other solutions above but the results were similar to the 1.04 test.

by Uday on Wednesday, October 21st 2009 at 09:16 AM

Hi all
How can i integrate UPS shipping so that if customer order then it should go autometically to UPS for shipping and generate a tracking number.
Plez help

by Uday on Wednesday, October 21st 2009 at 09:17 AM

Hi all
How can i integrate UPS shipping so that if customer order then it should go autometically to UPS for shipping and generate a tracking number.
Plez help

by matt on Thursday, October 29th 2009 at 05:40 PM

4% works all the way through for ground. The pesky modifier is that there is an $8 handling charge if the package weighs more than 70lbs. I used an "if" to add $8 if $_POST['txtPackWeight'] > '70'....hopefully that makes sense. I got within $0.02 up to 150lbs with the dimensions. That's close enough for me. I ended up doing it differently, but your solution definitely works well.

by matt on Thursday, October 29th 2009 at 05:41 PM

Uday, you need a developer's key for that. You have to sign up with UPS. It's a pain, trust me.

by Uday Chatterjee on Friday, November 6th 2009 at 04:00 AM

Hi All,
Can i ship my order from China to US with UPS.Which shipping method should i use.Plez Help.

by John Josef on Tuesday, November 17th 2009 at 09:16 AM

This functions works much better and matches the quotes on the site:

function getQuote(){
$url = "http://www.ups.com/using/services/rave/qcost_dss.cgi?AppVersion=1.2

by John Josef on Tuesday, November 17th 2009 at 09:19 AM

Looks like I can paste code here, I put this online:

http://johnjosef.com/projects/ups/class.shipping.phps

by Joe on Tuesday, November 17th 2009 at 12:57 PM

Hi John...

Being a PHP know nothing can you illustrate how to set your new script in a form?

by Julie on Sunday, February 7th 2010 at 01:35 PM

Hi,
I need a simple shippping calculator showing only the zip code destination and weight of the item shipped using United State Postal Service rates to their furthest USA destinations. Can someone please email me the code to add this to my website? Thank you sooooo much!!!
Julie
jb2000@millenicom.com

by Julie on Sunday, February 7th 2010 at 01:35 PM

Hi,
I need a simple shippping calculator showing only the zip code destination and weight of the item shipped using United State Postal Service rates to their furthest USA destinations. Can someone please email me the code to add this to my website? Thank you sooooo much!!!
Julie
jb2000@millenicom.com

by Gumball Machines on Sunday, May 16th 2010 at 02:31 AM

our website currently has a basic shipping calculator for <a href="http://www.gumball-machine.com">gumball machines</a> and <a href="http://www.gumball-machine.com/gumballs.html">gumballs</a>. our problem is when we have to figure our when to combine shipping for the 2 boxes together and when to figure out separate packages... does any body have any ideas as to how to add another checkpoint before the shipping is calculated ? each gumball machine can be strapped with 5 more and gumballs can only have 2 boxes together... the problem we have is when the 2 are combined because of irregular shapes ...


Comment Comment on this tutorial
Name: Email:
Message:
Comment Related Tutorials
There are no related tutorials.

Comment Related Source Code
There is no related source code.

Jobs PHP Job Search
My skills include:
Enter a City:

Select a State:


Advanced Search >>
Advertisement

Free Magazine Subscriptions

Today's Pictures

Today's Video

Other Resources

Latest Download

Latest Icons