PHP Shipping Modules (Canada Post)

Over the last 3 months I have been working on an e-commerce store for our company. Even though the actual development time would be like 3 weeks (MAX), but the requirement of the store kept on changing from time to time, and then when the store was ready to get launched, due to other non-technical issues, the store was delayed from launching.

One thing I did realize that most of the shipping modules out there are quite complex to use. The modules that comes for osCommerce are though much easier, its just installing it and then ready to go (with some modifications). But, say if you just want a simple shipping module system, just one file, which will provide the functions to retrieve shipping cost for say, Canada Post, or UPS etc, its hard to find (I couldn't find any).

So, I decided to create one for Canada Post, as this is the most recent one I have worked with. Canada Post's specification requires parsing of XML files to retrieve values, hence I have used all PHP-5's new features to do the processing. I have used DomDocument, DomXPath and stream functions which will only work with PHP-5 (you would need additional libraries to run it in PHP-4)

The class provided is called class.canadapost.php and I below I will provide instructions on how to use it.
(note: To use Canada Post, Port 30000 must be opened.)

Show Class Code »

Instructions on How to use the class


At first make sure you include the class using require or include..
include 'path/to/class/class.canadapost.php';

Then Initialize the class and set your information (your as in the store's postal code, and canada posts' merchant CPCID) and the customer Information.
$cPost = new CanadaPost();

/* Set your manufacturer CPCID, postal code by calling the function setManufacturer and passing in associative array 
 * format shown below, pass the total Cost of the item to be shipped in itemsPrice.
 */
$cPost->setManufacturer( array (
      'merchantCPCID' => CPC_DEMO_XML, // use your merchantCPCID
      'fromPostalCode' => YOUR_POSTAL_CODE, // use your postal code from where the item will be shipped
      'turnAroundTime' => 24,
      'itemsPrice' => 14 // put the total cost of item to be shipped.
    )
); 

/* Then set the Customer address in the format shown below, again in associative array format.
 *  Note: you dont need to pass the city and provOrState, they are actually optional. You only need the Postal Code 
 *  and country. 
 */
$cPost->setCustomer( array (
     'city' => 'Brampton', [CUSTOMER_CITY]
     'provOrState' => 'Ontario', [CUSTOMER_STATE_PROVINCE]
     'country' => CA, [2 Digit Code, see Canada Post Specs for more Info]
     'postalCode' => 'L1JK9' [CUSTOMER_POSTAL_OR_ZIP_CODE]
   )
);

I have actually build to Class to keep in mind that we could have several stores in different location, from where we could be shipping items. However, if you have just one store, then you dont have to call the function setManufacturer every time, instead you can modify the class.canadapost.php's constructor and hardcode the items there. So, then, after initializing the class, all you need to do is call the setPrice function to set the total Price.
$cPost->setPrice(15);

Now, add the Products you want to ship. Weights are in KG and dimension should be in CM. In the quantity, pass the number of same products you wish to ship.
$cPost->addProduct(  array (
   'quantity' => 1,
   'weight'=> 2,
   'length' => 3,
   'width' => 1,
   'height' => 8,
  'description' => 'some Description about Product'
  )
 );

/** To add additional product, just call the same function i.e. addProduct again passing information about product as shown above **/

Now, the final part. To get the rates. You can either receive the entire XML response from Canada Post and do the parsing yourself, or you could ask the function to return you the response in associative array format, which would make it easier for you to fetch the information.
To receive in XML, do the following:
$responseXML = $cPost->getRates(); // returns in XML format. 

To receive in Associative Array, do the following:
$responseArray = $cPost->getRates('array');

If any error happens, the function getRates( ) would return false, and you can get the Error message from the function getErrorMessage( ), as shown below:
$rXML = $cPost->getRates(); // or $rXML= $cPost->getRates('array);
if( $rXML === false ) {
  echo $cPost->getErrorMessage();
}

When you receive the response in associative format, here's a var_dump how the array returns information:
array(2) {
  ["product"]=>
  array(3) {
    [0]=>
    array(7) {
      ["name"]=>
      string(16) "Priority Courier"
      ["rate"]=>
      string(5) "16.26"
      ["shippingDate"]=>
      string(10) "2008-09-29"
      ["deliveryDate"]=>
      string(10) "2008-09-30"
      ["deliveryDayOfWeek"]=>
      string(1) "3"
      ["nextDayAM"]=>
      string(4) "true"
      ["packingID"]=>
      string(3) "P_0"
    }
    [1]=>
    array(7) {
      ["name"]=>
      string(9) "Expedited"
      ["rate"]=>
      string(4) "7.34"
      ["shippingDate"]=>
      string(10) "2008-09-29"
      ["deliveryDate"]=>
      string(10) "2008-09-30"
      ["deliveryDayOfWeek"]=>
      string(1) "3"
      ["nextDayAM"]=>
      string(5) "false"
      ["packingID"]=>
      string(3) "P_0"
    }
    [2]=>
    array(7) {
      ["name"]=>
      string(7) "Regular"
      ["rate"]=>
      string(4) "7.34"
      ["shippingDate"]=>
      string(10) "2008-09-29"
      ["deliveryDate"]=>
      string(10) "2008-10-01"
      ["deliveryDayOfWeek"]=>
      string(1) "4"
      ["nextDayAM"]=>
      string(5) "false"
      ["packingID"]=>
      string(3) "P_0"
    }
  }
  ["shippingOptions"]=>
  array(3) {
    ["insurance"]=>
    string(2) "No"
    ["deliveryConfirmation"]=>
    string(3) "Yes"
    ["signature"]=>
    string(2) "No"
  }
}

As seen above, the response contains array of 2 elements, products and shippingOptions, and within products contains array of the different shipping rates available. Within shippingOptions, contains the shipping insurance, and other features. Insurance options can be selected from your Canada Posts account's page on the Canada Post Server.

I have attached 2 files, class.canadapost.php and estimate_shipping.php. Once again make sure you have port 30000 opened for it to function. Please rename the files from *.txt to *.php

AttachmentSize
class.canadapost.php7.25 KB
estimate_shipping.php4.39 KB
Tags:

Hi I am getting Connection

Hi

I am getting Connection Timeout error in this

Can you help me

Thanks for the code.Keep up

Thanks for the code.Keep up the good work.

Good Job

Good job on the script!.

Michael,
Vancouver.

How to make it work on PHP 4.4?

Nice work, Is there any way to make it work on PHP 4.4?.

Let me know at justin99[AT]hotmail[DOT]com.

Nice script, whats the license on it ?

Whats the license on the script (GPL ?). I want to use it for some of my work.

Mark

Hi There, No specific license for this script, use it freely

Normally, I put GPL license on my code. For this one, I didn't put any license. Feel free to use it, but, I will appreciate if you keep my name at the top of the script.

Thanks,

Nifty script

That's a nifty script you got there. As previously commented it lacks shipping insurance. Is there any possibility that you will add that in future ?

Please get back me to at matt4you@gmail.com.
Cheers,

Good work

Thanks for the code, its really simple to use and works great.
Best,
Alex.

Nice work, but lacks advanced features

Nice work and I like it how you made this work so simple by a simple class file, Kudos to you!!. But, it lacks advanced features like shipping insurance.

Joseph
http://www.creativemind.com/

Awesome!!!

Thanks you so much!!!!. Keep up the good work.

Maria

Very Nice !!!

Good work !!! I can't seem to find the script for Fedex on your blog?

Regards,
Tamim

Haven't had the time to develop Fedex's one

Sorry, I haven't had the time to develop a specific one for Fedex.

ReadyToShip

For those who don't want to use pre-saved boxes, here's a line you need to add in the prepareXML() function, just before "$lineItems->appendChild($eachItems);" :

$eachItems->appendChild( $sendXML->createElement('readyToShip') );

Otherwise, I was always getting a "Parcel too large to be shipped with CPC." error.

/Martin

Right.. thank you

Thank you for that addition :).

Well done!

Thank you very much! I just saved a lot of time thanks to your script!

Great work.

I have been looking for a script just like this... This made by life a lot easier.
Thank you so much.

Jacob.

Good Stuff

Thanks for giving this script. Its really good.

Thanks

Nice work. It worked like a charm.

Comment viewing options

Select your preferred way to display the comments and click "Save settings" to activate your changes.

Post new comment

The content of this field is kept private and will not be shown publicly.
  • Web page addresses and e-mail addresses turn into links automatically.
  • Allowed HTML tags: <a> <em> <strong> <cite> <code> <ul> <ol> <li> <dl> <dt> <dd>
  • Lines and paragraphs break automatically.

More information about formatting options

CAPTCHA
This question is for testing whether you are a human visitor and to prevent automated spam submissions.