August, 2009
PHP Shipping Calculator Class...my first class as it were
Posted 7 Months 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.
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..
So, enough about how awesome it is, let's take a look at the actual class:
..here's an array ($services) of the various Shipping Companies and Methods which we'll use in the configuration in a moment:
..and here's an example of the configuration and implemenation:
Notice: You'll have to get the various usernames, passwords, and accounts from UPS, USPS, and FedEx to run this class. I'll try and add some information about how to do that soon.
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:
And of course, here's the source code:
Enjoy! and let me know if you have any input, find any bugs, etc.
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 (288 lines)
So, enough about how awesome it is, let's take a look at the actual class:
Shipping Calculator Class
<?php
class ShippingCalculator {
// Defaults
var $weight = 1;
var $weight_unit = "lb";
var $size_length = 4;
var $size_width = 8;
var $size_height = 2;
var $size_unit = "in";
var $debug = false; // Turn on to see XML sent and recieved
// Config (you can either set these here or send them in a config array when creating an instance of the class)
var $services;
var $from_zip;
var $from_state;
var $from_country;
var $to_zip;
var $to_stat;
var $to_country;
var $ups_access;
var $ups_user;
var $ups_pass;
var $ups_account;
var $usps_user;
var $fedex_account;
var $fedex_meter;
// Results
var $rates;
// Setup Class with Config Options
function shipping_calculator($config) {
if($config) {
foreach($config as $k => $v) {
$this->$k = $v;
print $this->$k."<br />";
}
}
}
// Calculate
function calculate($company = NULL,$code = NULL) {
$this->rates = NULL;
$services = $this->services;
if($company and $code) $services[$company][$code] = 1;
foreach($services as $company => $codes) {
foreach($codes as $code => $name) {
switch($company) {
case "ups":
$this->rates[$company][$code] = $this->calculate_ups($code);
break;
case "usps":
$this->rates[$company][$code] = $this->calculate_usps($code);
break;
case "fedex":
$this->rates[$company][$code] = $this->calculate_fedex($code);
break;
}
}
}
return $this->rates;
}
// Calculate UPS
function calculate_ups($code) {
$url = "https://www.ups.com/ups.app/xml/Rate";
$data = '<?xml version="1.0"?>
<AccessRequest xml:lang="en-US">
<AccessLicenseNumber>'.$this->ups_access.'</AccessLicenseNumber>
<UserId>'.$this->ups_user.'</UserId>
<Password>'.$this->ups_pass.'</Password>
</AccessRequest>
<?xml version="1.0"?>
<RatingServiceSelectionRequest xml:lang="en-US">
<Request>
<TransactionReference>
<CustomerContext>Bare Bones Rate Request</CustomerContext>
<XpciVersion>1.0001</XpciVersion>
</TransactionReference>
<RequestAction>Rate</RequestAction>
<RequestOption>Rate</RequestOption>
</Request>
<PickupType>
<Code>01</Code>
</PickupType>
<Shipment>
<Shipper>
<Address>
<PostalCode>'.$this->from_zip.'</PostalCode>
<CountryCode>'.$this->from_country.'</CountryCode>
</Address>
<ShipperNumber>'.$this->ups_account.'</ShipperNumber>
</Shipper>
<ShipTo>
<Address>
<PostalCode>'.$this->to_zip.'</PostalCode>
<CountryCode>'.$this->to_country.'</CountryCode>
<ResidentialAddressIndicator/>
</Address>
</ShipTo>
<ShipFrom>
<Address>
<PostalCode>'.$this->from_zip.'</PostalCode>
<CountryCode>'.$this->from_country.'</CountryCode>
</Address>
</ShipFrom>
<Service>
<Code>'.$code.'</Code>
</Service>
<Package>
<PackagingType>
<Code>02</Code>
</PackagingType>
<Dimensions>
<UnitOfMeasurement>
<Code>IN</Code>
</UnitOfMeasurement>
<Length>'.($this->size_unit != "in" ? $this->convert_sze($this->size_length,$this->size_unit,"in") : $this->size_length).'</Length>
<Width>'.($this->size_unit != "in" ? $this->convert_sze($this->size_width,$this->size_unit,"in") : $this->size_width).'</Width>
<Height>'.($this->size_unit != "in" ? $this->convert_sze($this->size_height,$this->size_unit,"in") : $this->size_height).'</Height>
</Dimensions>
<PackageWeight>
<UnitOfMeasurement>
<Code>LBS</Code>
</UnitOfMeasurement>
<Weight>'.($this->weight_unit != "lb" ? $this->convert_weight($this->weight,$this->weight_unit,"lb") : $this->weight).'</Weight>
</PackageWeight>
</Package>
</Shipment>
</RatingServiceSelectionRequest>';
// Curl
$results = $this->curl($url,$data);
// Debug
if($this->debug == true) {
print "<xmp>".$data."</xmp><br />";
print "<xmp>".$results."</xmp><br />";
}
// Match Rate
preg_match('/<MonetaryValue>(.*?)</MonetaryValue>/',$results,$rate);
return $rate[1];
}
// Calculate USPS
function calculate_usps($code) {
// Weight (in lbs)
if($this->weight_unit != 'lb') $weight = $this->convert_weight($weight,$this->weight_unit,'lb');
else $weight = $this->weight;
// Split into Lbs and Ozs
$lbs = floor($weight);
$ozs = ($weight - $lbs) * 16;
if($lbs == 0 and $ozs < 1) $ozs = 1;
$url = "http://Production.ShippingAPIs.com/ShippingAPI.dll";
$data = 'API=RateV2&XML=<RateV2Request USERID="'.$this->usps_user.'"><Package ID="0"><Service>'.$code.'</Service><ZipOrigination>'.$this->from_zip.'</ZipOrigination><ZipDestination>'.$this->to_zip.'</ZipDestination><Pounds>'.$lbs.'</Pounds><Ounces>'.$ozs.'</Ounces><Size>REGULAR</Size><Machinable>TRUE</Machinable></Package></RateV2Request>';
// Curl
$results = $this->curl($url,$data);
// Debug
if($this->debug == true) {
print "<xmp>".$data."</xmp><br />";
print "<xmp>".$results."</xmp><br />";
}
// Match Rate
preg_match('/<Rate>(.+?)</Rate>/',$results,$rate);
return $rate[1];
}
// Calculate FedEX
function calculate_fedex($code) {
$url = "https://gatewaybeta.fedex.com/GatewayDC";
$data = '<?xml version="1.0" encoding="UTF-8" ?>
<FDXRateRequest xmlns:api="http://www.fedex.com/fsmapi" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:noNamespaceSchemaLocation="FDXRateRequest.xsd">
<RequestHeader>
<CustomerTransactionIdentifier>Express Rate</CustomerTransactionIdentifier>
<AccountNumber>'.$this->fedex_account.'</AccountNumber>
<MeterNumber>'.$this->fedex_meter.'</MeterNumber>
<CarrierCode>'.(in_array($code,array('FEDEXGROUND','GROUNDHOMEDELIVERY')) ? 'FDXG' : 'FDXE').'</CarrierCode>
</RequestHeader>
<DropoffType>REGULARPICKUP</DropoffType>
<Service>'.$code.'</Service>
<Packaging>YOURPACKAGING</Packaging>
<WeightUnits>LBS</WeightUnits>
<Weight>'.number_format(($this->weight_unit != 'lb' ? convert_weight($this->weight,$this->weight_unit,'lb') : $this->weight), 1, '.', '').'</Weight>
<OriginAddress>
<StateOrProvinceCode>'.$this->from_state.'</StateOrProvinceCode>
<PostalCode>'.$this->from_zip.'</PostalCode>
<CountryCode>'.$this->from_country.'</CountryCode>
</OriginAddress>
<DestinationAddress>
<StateOrProvinceCode>'.$this->to_state.'</StateOrProvinceCode>
<PostalCode>'.$this->to_zip.'</PostalCode>
<CountryCode>'.$this->to_country.'</CountryCode>
</DestinationAddress>
<Payment>
<PayorType>SENDER</PayorType>
</Payment>
<PackageCount>1</PackageCount>
</FDXRateRequest>';
// Curl
$results = $this->curl($url,$data);
// Debug
if($this->debug == true) {
print "<xmp>".$data."</xmp><br />";
print "<xmp>".$results."</xmp><br />";
}
// Match Rate
preg_match('/<NetCharge>(.*?)</NetCharge>/',$results,$rate);
return $rate[1];
}
// Curl
function curl($url,$data = NULL) {
$ch = curl_init();
curl_setopt($ch, CURLOPT_URL, $url);
curl_setopt($ch, CURLOPT_HEADER, 1);
curl_setopt($ch, CURLOPT_TIMEOUT, 60);
curl_setopt($ch, CURLOPT_RETURNTRANSFER, 1);
curl_setopt($ch, CURLOPT_SSL_VERIFYPEER, 0);
curl_setopt($ch, CURLOPT_SSL_VERIFYHOST, 0);
if($data) {
curl_setopt($ch, CURLOPT_POST,1);
curl_setopt($ch, CURLOPT_POSTFIELDS,$data);
}
curl_setopt($ch, CURLOPT_USERAGENT, $_SERVER['HTTP_USER_AGENT']);
$contents = curl_exec ($ch);
return $contents;
curl_close ($ch);
}
// Convert Weight
function convert_weight($weight,$old_unit,$new_unit) {
$units['oz'] = 1;
$units['lb'] = 0.0625;
$units['gram'] = 28.3495231;
$units['kg'] = 0.0283495231;
// Convert to Ounces (if not already)
if($old_unit != "oz") $weight = $weight / $units[$old_unit];
// Convert to New Unit
$weight = $weight * $units[$new_unit];
// Minimum Weight
if($weight < .1) $weight = .1;
// Return New Weight
return round($weight,2);
}
// Convert Size
function convert_size($size,$old_unit,$new_unit) {
$units['in'] = 1;
$units['cm'] = 2.54;
$units['feet'] = 0.083333;
// Convert to Inches (if not already)
if($old_unit != "in") $size = $size / $units[$old_unit];
// Convert to New Unit
$size = $size * $units[$new_unit];
// Minimum Size
if($size < .1) $size = .1;
// Return New Size
return round($size,2);
}
// Set Value
function set_value($k,$v) {
$this->$k = $v;
}
}
?>
<?php
class ShippingCalculator {
// Defaults
var $weight = 1;
var $weight_unit = "lb";
var $size_length = 4;
var $size_width = 8;
var $size_height = 2;
var $size_unit = "in";
var $debug = false; // Turn on to see XML sent and recieved
// Config (you can either set these here or send them in a config array when creating an instance of the class)
var $services;
var $from_zip;
var $from_state;
var $from_country;
var $to_zip;
var $to_stat;
var $to_country;
var $ups_access;
var $ups_user;
var $ups_pass;
var $ups_account;
var $usps_user;
var $fedex_account;
var $fedex_meter;
// Results
var $rates;
// Setup Class with Config Options
function shipping_calculator($config) {
if($config) {
foreach($config as $k => $v) {
$this->$k = $v;
print $this->$k."<br />";
}
}
}
// Calculate
function calculate($company = NULL,$code = NULL) {
$this->rates = NULL;
$services = $this->services;
if($company and $code) $services[$company][$code] = 1;
foreach($services as $company => $codes) {
foreach($codes as $code => $name) {
switch($company) {
case "ups":
$this->rates[$company][$code] = $this->calculate_ups($code);
break;
case "usps":
$this->rates[$company][$code] = $this->calculate_usps($code);
break;
case "fedex":
$this->rates[$company][$code] = $this->calculate_fedex($code);
break;
}
}
}
return $this->rates;
}
// Calculate UPS
function calculate_ups($code) {
$url = "https://www.ups.com/ups.app/xml/Rate";
$data = '<?xml version="1.0"?>
<AccessRequest xml:lang="en-US">
<AccessLicenseNumber>'.$this->ups_access.'</AccessLicenseNumber>
<UserId>'.$this->ups_user.'</UserId>
<Password>'.$this->ups_pass.'</Password>
</AccessRequest>
<?xml version="1.0"?>
<RatingServiceSelectionRequest xml:lang="en-US">
<Request>
<TransactionReference>
<CustomerContext>Bare Bones Rate Request</CustomerContext>
<XpciVersion>1.0001</XpciVersion>
</TransactionReference>
<RequestAction>Rate</RequestAction>
<RequestOption>Rate</RequestOption>
</Request>
<PickupType>
<Code>01</Code>
</PickupType>
<Shipment>
<Shipper>
<Address>
<PostalCode>'.$this->from_zip.'</PostalCode>
<CountryCode>'.$this->from_country.'</CountryCode>
</Address>
<ShipperNumber>'.$this->ups_account.'</ShipperNumber>
</Shipper>
<ShipTo>
<Address>
<PostalCode>'.$this->to_zip.'</PostalCode>
<CountryCode>'.$this->to_country.'</CountryCode>
<ResidentialAddressIndicator/>
</Address>
</ShipTo>
<ShipFrom>
<Address>
<PostalCode>'.$this->from_zip.'</PostalCode>
<CountryCode>'.$this->from_country.'</CountryCode>
</Address>
</ShipFrom>
<Service>
<Code>'.$code.'</Code>
</Service>
<Package>
<PackagingType>
<Code>02</Code>
</PackagingType>
<Dimensions>
<UnitOfMeasurement>
<Code>IN</Code>
</UnitOfMeasurement>
<Length>'.($this->size_unit != "in" ? $this->convert_sze($this->size_length,$this->size_unit,"in") : $this->size_length).'</Length>
<Width>'.($this->size_unit != "in" ? $this->convert_sze($this->size_width,$this->size_unit,"in") : $this->size_width).'</Width>
<Height>'.($this->size_unit != "in" ? $this->convert_sze($this->size_height,$this->size_unit,"in") : $this->size_height).'</Height>
</Dimensions>
<PackageWeight>
<UnitOfMeasurement>
<Code>LBS</Code>
</UnitOfMeasurement>
<Weight>'.($this->weight_unit != "lb" ? $this->convert_weight($this->weight,$this->weight_unit,"lb") : $this->weight).'</Weight>
</PackageWeight>
</Package>
</Shipment>
</RatingServiceSelectionRequest>';
// Curl
$results = $this->curl($url,$data);
// Debug
if($this->debug == true) {
print "<xmp>".$data."</xmp><br />";
print "<xmp>".$results."</xmp><br />";
}
// Match Rate
preg_match('/<MonetaryValue>(.*?)</MonetaryValue>/',$results,$rate);
return $rate[1];
}
// Calculate USPS
function calculate_usps($code) {
// Weight (in lbs)
if($this->weight_unit != 'lb') $weight = $this->convert_weight($weight,$this->weight_unit,'lb');
else $weight = $this->weight;
// Split into Lbs and Ozs
$lbs = floor($weight);
$ozs = ($weight - $lbs) * 16;
if($lbs == 0 and $ozs < 1) $ozs = 1;
$url = "http://Production.ShippingAPIs.com/ShippingAPI.dll";
$data = 'API=RateV2&XML=<RateV2Request USERID="'.$this->usps_user.'"><Package ID="0"><Service>'.$code.'</Service><ZipOrigination>'.$this->from_zip.'</ZipOrigination><ZipDestination>'.$this->to_zip.'</ZipDestination><Pounds>'.$lbs.'</Pounds><Ounces>'.$ozs.'</Ounces><Size>REGULAR</Size><Machinable>TRUE</Machinable></Package></RateV2Request>';
// Curl
$results = $this->curl($url,$data);
// Debug
if($this->debug == true) {
print "<xmp>".$data."</xmp><br />";
print "<xmp>".$results."</xmp><br />";
}
// Match Rate
preg_match('/<Rate>(.+?)</Rate>/',$results,$rate);
return $rate[1];
}
// Calculate FedEX
function calculate_fedex($code) {
$url = "https://gatewaybeta.fedex.com/GatewayDC";
$data = '<?xml version="1.0" encoding="UTF-8" ?>
<FDXRateRequest xmlns:api="http://www.fedex.com/fsmapi" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:noNamespaceSchemaLocation="FDXRateRequest.xsd">
<RequestHeader>
<CustomerTransactionIdentifier>Express Rate</CustomerTransactionIdentifier>
<AccountNumber>'.$this->fedex_account.'</AccountNumber>
<MeterNumber>'.$this->fedex_meter.'</MeterNumber>
<CarrierCode>'.(in_array($code,array('FEDEXGROUND','GROUNDHOMEDELIVERY')) ? 'FDXG' : 'FDXE').'</CarrierCode>
</RequestHeader>
<DropoffType>REGULARPICKUP</DropoffType>
<Service>'.$code.'</Service>
<Packaging>YOURPACKAGING</Packaging>
<WeightUnits>LBS</WeightUnits>
<Weight>'.number_format(($this->weight_unit != 'lb' ? convert_weight($this->weight,$this->weight_unit,'lb') : $this->weight), 1, '.', '').'</Weight>
<OriginAddress>
<StateOrProvinceCode>'.$this->from_state.'</StateOrProvinceCode>
<PostalCode>'.$this->from_zip.'</PostalCode>
<CountryCode>'.$this->from_country.'</CountryCode>
</OriginAddress>
<DestinationAddress>
<StateOrProvinceCode>'.$this->to_state.'</StateOrProvinceCode>
<PostalCode>'.$this->to_zip.'</PostalCode>
<CountryCode>'.$this->to_country.'</CountryCode>
</DestinationAddress>
<Payment>
<PayorType>SENDER</PayorType>
</Payment>
<PackageCount>1</PackageCount>
</FDXRateRequest>';
// Curl
$results = $this->curl($url,$data);
// Debug
if($this->debug == true) {
print "<xmp>".$data."</xmp><br />";
print "<xmp>".$results."</xmp><br />";
}
// Match Rate
preg_match('/<NetCharge>(.*?)</NetCharge>/',$results,$rate);
return $rate[1];
}
// Curl
function curl($url,$data = NULL) {
$ch = curl_init();
curl_setopt($ch, CURLOPT_URL, $url);
curl_setopt($ch, CURLOPT_HEADER, 1);
curl_setopt($ch, CURLOPT_TIMEOUT, 60);
curl_setopt($ch, CURLOPT_RETURNTRANSFER, 1);
curl_setopt($ch, CURLOPT_SSL_VERIFYPEER, 0);
curl_setopt($ch, CURLOPT_SSL_VERIFYHOST, 0);
if($data) {
curl_setopt($ch, CURLOPT_POST,1);
curl_setopt($ch, CURLOPT_POSTFIELDS,$data);
}
curl_setopt($ch, CURLOPT_USERAGENT, $_SERVER['HTTP_USER_AGENT']);
$contents = curl_exec ($ch);
return $contents;
curl_close ($ch);
}
// Convert Weight
function convert_weight($weight,$old_unit,$new_unit) {
$units['oz'] = 1;
$units['lb'] = 0.0625;
$units['gram'] = 28.3495231;
$units['kg'] = 0.0283495231;
// Convert to Ounces (if not already)
if($old_unit != "oz") $weight = $weight / $units[$old_unit];
// Convert to New Unit
$weight = $weight * $units[$new_unit];
// Minimum Weight
if($weight < .1) $weight = .1;
// Return New Weight
return round($weight,2);
}
// Convert Size
function convert_size($size,$old_unit,$new_unit) {
$units['in'] = 1;
$units['cm'] = 2.54;
$units['feet'] = 0.083333;
// Convert to Inches (if not already)
if($old_unit != "in") $size = $size / $units[$old_unit];
// Convert to New Unit
$size = $size * $units[$new_unit];
// Minimum Size
if($size < .1) $size = .1;
// Return New Size
return round($size,2);
}
// Set Value
function set_value($k,$v) {
$this->$k = $v;
}
}
?>
..here's an array ($services) of the various Shipping Companies and Methods which we'll use in the configuration in a moment:
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';
// 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';
..and here's an example of the configuration and implemenation:
Configuration and Implementation
// 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();
// 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();
Notice: You'll have to get the various usernames, passwords, and accounts from UPS, USPS, and FedEx to run this class. I'll try and add some information about how to do that soon.
Results
This class spits ou 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; 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
)
)
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 />";
}
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:
Enjoy! and let me know if you have any input, find any bugs, etc.



