plainblack.com
Username Password
search
Bookmark and Share

Writing Shipping Drivers

Shipping drivers allow you to calculate and charge for shipping costs, and in some cases tie into third-party shipping providers such as UPS or FedEx.

 

API Highlights

WebGUI comes with two shipping drivers. FlatRate can calculate most basic shipping costs, but does not tie into any specific shipping provider. USPS interacts with the United States Postal Service APIs to calculate shipping costs based on weight and shipping address. They are both great reference material that you should have a look at and take the time to understand before you start writing your own shipping driver. When you are ready to write your own shipping driver, there are several parts of the API of which you should be aware.

 

The Master Classes

Just like with writing payment drivers, before you start writing your own shipping driver subclass, check out WebGUI::Shop::Ship and WebGUI::Shop::ShipDriver. Ship is the management interface for all ShipDrivers. ShipDriver is the master class that you'll be subclassing to create your own.

 

Ship hands off web requests to the ShipDrivers. It does this through its www_do() method. Along the URL it looks like:

 

/home?shop=ship;method=do;driverId=XXXXX;do=someMethod

 

Note the bolded “someMethod” part of the URL. That refers to a www_someMethod() method in your ShipDriver subclass. Generally speaking, you won't need this ability, but it's there if you do.

 

The Basics

There are really only two methods you should need to fill out in your shipping drivers, unless you do shipment tracking integration with a third party service. They are calculate() and definition().

 

  • The calculate method is the true heart of a ShipDriver. This method gets a reference to the cart, and from that calculates the shipping cost on the products in the cart.

  • The definition() method works just like the definition method in PayDrivers and is very similar to the definition() methods in Assets and Workflow Activities.

 

Free Shipping on Big Orders Example

Most shops would love it if their average order price were greater than $100. You can actually encourage that behavior using a custom shipping driver. Let's build a driver where the users will pay a base shipping fee of X and Y per item, unless the transaction is worth Z. For example, they will pay a base fee of $5 + $2 per item unless their transaction is > $100.

 

First, build the definition() method so you can define X, Y, and Z.

 

sub definition {

my ( $class, $session, $definition ) = @_;

WebGUI::Error::InvalidParam->throw(error => q{Must provide a session variable})

unless ref $session eq 'WebGUI::Session';

$definition ||= [];

tie my %fields, 'Tie::IxHash', (

baseFee => {

fieldType => 'float',

label => 'Base Fee',

hoverHelp => 'The amount of shipping applied to all orders.',

defaultValue => 5.00,

},

perItemFee => {

fieldType => 'float',

label => 'Per Item Fee',

hoverHelp => 'The additional shipping charge per item.',

defaultValue => 2.00,

},

freeThreshold => {

fieldType => 'float',

label => 'Free Threshold',

hoverHelp => 'The total amount of the order before shipping is free.',

defaultValue => 100,

},

);

push @{ $definition }, {

name => 'Free Shipping On Big Orders',

properties => \%fields,

};

return $class->SUPER::definition($session, $definition);

}

 

Now that you have the properties to work with, you can define your calculate() method.

 

sub calculate {

my ($self, $cart) = @_;

my $quantityOfShippableItems = 0;

foreach my $item (@{$cart->getItems}) {

my $sku = $item->getSku;

if ($sku->isShippingRequired) {

$quantityOfShippableItems += $item->get('quantity');

}

}

my $cost = 0;

if ($quantityOfShippableItems > 0) {

$cost = $self->get('baseFee') + ($quantityOfShippableItems * $self->get('perItemFee'));

}

if ($cost > $self->get('freeThreshold')) {

return '0.00';

}

return sprintf "%.2f", $cost;

}

 

The finished module should then look something like this:

 

package WebGUI::Shop::ShipDriver::FreeShippingOnBigOrders;



use strict;

use base qw/WebGUI::Shop::ShipDriver/;

use WebGUI::Exception;



=head1 NAME



Package WebGUI::Shop::ShipDriver::FreeShippingOnBigOrders



=head1 DESCRIPTION



This driver allows free shipping on big orders.



=head1 SYNOPSIS



=head1 METHODS



See the master class, WebGUI::Shop::ShipDriver for information about

base methods. These methods are customized in this class:



=cut



#-------------------------------------------------------------------



=head2 calculate ( $cart )



Returns a shipping price. Calculates the shipping price using the following formula:



baseFee + (perItemFee * item quantity) || 0 if (cart > freeThreshold)



=head3 $cart



A WebGUI::Shop::Cart object. The contents of the cart are analyzed to calculate the shipping costs. If no items in the cart require shipping, then no shipping

costs are assessed.



=cut



sub calculate {

my ($self, $cart) = @_;

my $quantityOfShippableItems = 0;

foreach my $item (@{$cart->getItems}) {

my $sku = $item->getSku;

if ($sku->isShippingRequired) {

$quantityOfShippableItems += $item->get('quantity');

}

}

my $cost = 0;

if ($quantityOfShippableItems > 0) {

$cost = $self->get('baseFee') + ($quantityOfShippableItems * $self->get('perItemFee'));

}

if ($cost > $self->get('freeThreshold')) {

return '0.00';

}

return sprintf "%.2f", $cost;

}



#-------------------------------------------------------------------



=head2 definition ( $session )



Add baseFee, perItemFee, and freeThreshold properties.



=cut



sub definition {

my ( $class, $session, $definition ) = @_;

WebGUI::Error::InvalidParam->throw(error => q{Must provide a session variable})

unless ref $session eq 'WebGUI::Session';

$definition ||= [];

tie my %fields, 'Tie::IxHash', (

baseFee => {

fieldType => 'float',

label => 'Base Fee',

hoverHelp => 'The amount of shipping applied to all orders.',

defaultValue => 5.00,

},

perItemFee => {

fieldType => 'float',

label => 'Per Item Fee',

hoverHelp => 'The additional shipping charge per item.',

defaultValue => 2.00,

},

freeThreshold => {

fieldType => 'float',

label => 'Free Threshold',

hoverHelp => 'The total amount of the order before shipping is free.',

defaultValue => 100,

},

);

push @{ $definition }, {

name => 'Free Shipping On Big Orders',

properties => \%fields,

};

return $class->SUPER::definition($session, $definition);

}



1;

Keywords: API shipping

Search | Most Popular | Recent Changes | Wiki Home
© 2018 Plain Black Corporation | All Rights Reserved