PHP Shipping Calculator Class...my first class as it were

Posted 8 Years Ago



So I decided it was time I dive into that mysterious world of Objected Oriented Programming.  Of course, I've worked with classes and PHP 5 and all that good stuff before.  I've used many-a-class for things like Authorize.net payment processing, Facebook applications, YouTube integration, and OpenInviter.

I had not, however, written my own class from scratch... that is until this evening.

Why a Shipping Calculator?

I must admit that I have been (and still am, come to that) a little hesitant to embrace classes.  I have not been offered a good reason for their use as opposed to well written functions.  It seems to me that you're just doing more work to create and execute more restricted functions.

However, looking through my standard website framework I decided that the three seperate shipping calculator functions (UPS, USPS, and FedEx) would probably qualify as a good candidate for one unified class so I whipped up this little class in about an hour and a half (yes, I am bragging).

Here is the result..

Features

  • Calculates shipping rates for UPS, USPS, and FedEx
  • Allows you to set package size in either inches, centimeters, or feet
  • Allows you to set package weight in either pounds, ounces, grams, or kilograms
  • Automatically converts weight and sizes
  • Handles Batch or Single Rate Calculation
  • Two ways to pass configuration
  • Built in debugging
  • Small (309 lines)

You'll find the source code at the end of this article.  Before we get to that though, let's see an example or two of what this class does:

Examples


Imlementation

To see how we got these let's first take a look at an array ($services) of the various Shipping Companies and Methods which we'll use in calculating shipping rates:

Services Array

// UPS
$services['ups']['14'] = 'Next Day Air Early AM';
$services['ups']['01'] = 'Next Day Air';
$services['ups']['65'] = 'Saver';
$services['ups']['59'] = '2nd Day Air Early AM';
$services['ups']['02'] = '2nd Day Air';
$services['ups']['12'] = '3 Day Select';
$services['ups']['03'] = 'Ground';
$services['ups']['11'] = 'Standard';
$services['ups']['07'] = 'Worldwide Express';
$services['ups']['54'] = 'Worldwide Express Plus';
$services['ups']['08'] = 'Worldwide Expedited';
// USPS
$services['usps']['EXPRESS'] = 'Express';
$services['usps']['PRIORITY'] = 'Priority';
$services['usps']['PARCEL'] = 'Parcel';
$services['usps']['FIRST CLASS'] = 'First Class';
$services['usps']['EXPRESS SH'] = 'Express SH';
$services['usps']['BPM'] = 'BPM';
$services['usps']['MEDIA '] = 'Media';
$services['usps']['LIBRARY'] = 'Library';
// FedEx
$services['fedex']['PRIORITYOVERNIGHT'] = 'Priority Overnight';
$services['fedex']['STANDARDOVERNIGHT'] = 'Standard Overnight';
$services['fedex']['FIRSTOVERNIGHT'] = 'First Overnight';
$services['fedex']['FEDEX2DAY'] = '2 Day';
$services['fedex']['FEDEXEXPRESSSAVER'] = 'Express Saver';
$services['fedex']['FEDEXGROUND'] = 'Ground';
$services['fedex']['FEDEX1DAYFREIGHT'] = 'Overnight Day Freight';
$services['fedex']['FEDEX2DAYFREIGHT'] = '2 Day Freight';
$services['fedex']['FEDEX3DAYFREIGHT'] = '3 Day Freight';
$services['fedex']['GROUNDHOMEDELIVERY'] = 'Home Delivery';
$services['fedex']['INTERNATIONALECONOMY'] = 'International Economy';
$services['fedex']['INTERNATIONALFIRST'] = 'International First';
$services['fedex']['INTERNATIONALPRIORITY'] = 'International Priority';


Here's we have the basic configuration we'll send to the class.  You'll notice we use the $services array we just created to define the shipping methods we want to find the rates for:

Configuration

// Config
$config = array(
    // Services
    'services' => $services,
    // Weight
    'weight' => 2, // Default = 1
    'weight_units' => 'lb', // lb (default), oz, gram, kg
    // Size
    'size_length' => 5, // Default = 8
    'size_width' => 6, // Default = 4
    'size_height' => 3, // Default = 2
    'size_units' => 'in', // in (default), feet, cm
    // From
    'from_zip' => 97210,
    'from_state' => "OR", // Only Required for FedEx
    'from_country' => "US",
    // To
    'to_zip' => 55455,
    'to_state' => "MN", // Only Required for FedEx
    'to_country' => "US",
   
    // Service Logins
    'ups_access' => '', // UPS Access License Key
    'ups_user' => '', // UPS Username 
    'ups_pass' => '', // UPS Password 
    'ups_account' => '', // UPS Account Number
    'usps_user' => '', // USPS User Name
    'fedex_account' => '', // FedEX Account Number
    'fedex_meter' => '' // FedEx Meter Number
);

// Create Class (with config array)
$ship = new ShippingCalculator ($config);
// Get Rates
$rates = $ship->calculate();

Note: You'll have to get the various usernames, passwords, and accounts from UPS, USPS, and FedEx to run this class.  I've added several links and the exact things you need at the very end of this article.

Finally, here's how we call the class and get our rates:


Implemetation

// Create Class (with config array)
$ship = new ShippingCalculator ($config);
// Get Rates
$rates = $ship->calculate();


Results

This class spits out information via the calculate(); method.  In our example above $rates is an array of the rates we calculated.  I ran a quick example using a few shipping methods from each company (not all of them); here's what the results look like:

Rates Array

Array (
    [ups] => Array (
        [12] => 15.07
        [03] => 8.35
        [11] =>
    )
    [usps] => Array (
        [PRIORITY] => 8.10
        [PARCEL] => 7.62
        [FIRST CLASS] =>
    )
    [fedex] => Array (
        [FEDEX2DAY] => 18.55
        [FEDEXEXPRESSSAVER] => 13.53
        [FEDEXGROUND] => 6.34
    )
)

You'll notice some are empty. This means that, for one reason or another, the shipping company doesn't ship your query via that method.  Perhaps it was a worldwide shipping method and your shippment is local, etc.

One more note before I leave you.  If you wanted to match these rates with their more user friendly names (as seen in the original $services array) and wanted to simultaneously print some radio buttons where a user could select their shipping method you could do something simple like this:

Printing Radio Buttons

foreach($rates as $company => $codes) {
    foreach($codes as $code => $rate) print "
<input type='checkbox' name='shipping' value='".$rate."' /> ".$services[$company][$code]."<br />";
}

And of course, here's the source code:

Download Source Code
 

Enjoy! and let me know if you have any input, find any bugs, etc.

Update: 03-20-2010


  • Fixed the link to the source code.
  • Fixed incorrect name of constructor function
  • Added 'batch' rate lookup for USPS (the only company that lets you get rates for more than one method at a time).

And, as promised, here is some info about obtaining all the proper access keys, etc. from the different shipping companies (all are free):

UPS Online Tools Account

Link: https://www.ups.com/upsdeveloperkit?loc=en_US
What You Need:
  • Username
  • Password
  • Access License Key
  • Account Number

USPS Webtools Account
Link: https://secure.shippingapis.com/registration/
What You Need:
  • Username

FedEX Developer Account
Link: http://www.fedex.com/us/developer/
What You Need (test account versions are fine):
  • Account Number
  • Meter Number



Tags: php, class, shipping, conversion, ups, usps, fedex, rates





Comments

Name
E-mail
Website

Optional



to

Posted 2 Weeks Ago




vs

Posted 2 Months Ago



Posted 2 Months Ago



Posted 4 Months Ago



Posted 5 Months Ago



Posted 6 Months Ago




Meir

Posted 2 Years Ago


Nice job, thanks.

I noticed a bug in the curl function, the connection is never closed since it returns before closing the connection. You should move the return statement to after closing the curl connection.


vivek

Posted 2 Years Ago


I got this message "The requested service is unavailable between the selected locations."when using
// From
    'fromZip' => 78759,
    'fromState' => "AUSTIN", // Only Required for FedEx
    'fromCountry' => "US",
    // To
    'toZip' => 110092,
    'toState' => "Delhi", // Only Required for FedEx
    'toCountry' => "IN"

Daniel

Posted 3 Years Ago


dear, I have tried using the USPS method and nothing comes out, you can give me some solution or am I setting the wrong function

Tridibesh

Posted 3 Years Ago


The code for ups is working but for the fedex account it does not work. It does not give any result for price.