NAME

Handel::Checkout - Checkout Pipeline Process

SYNOPSIS

use Handel::Checkout;

my $checkout = Handel::Checkout->new({
    cart    => '122345678-9098-7654-3212-345678909876',
    phases  => [CHECKOUT_PHASE_INITIALIZE, CHECKOUT_PHASE_VALIDATE]
});

if ($checkout->process == CHECKOUT_STATUS_OK) {
    print 'Your order number is ', $checkout->order->number;
} else {
    ...
};

DESCRIPTION

Handel::Checkout is a basic pipeline processor that uses plugins at various phases to perform any work necessary from credit card authorization to order delivery. Handel does not try to be all things to all people needing to place online orders. Instead, it provides a basic plugin mechanism allowing the checkout process to be customized for many different needs.

CONSTRUCTOR

new([\%options])

Creates a new checkout pipeline process and loads all available plugins. new accepts the following options in an optional HASH reference:

cart

A HASH reference, Handel::Cart object, or a cart id. This will be loaded into a new Handel::Order object and associated with the new checkout process.

See cart below for further details about the various values allowed to be passed.

Note: When creating a new order via Handel::Order, new will automatically create a checkout process and process the CHECKOUT_PHASE_INITIALIZE. However, when a new order is created using cart in Handel::Checkout, the automatic processing of CHECKOUT_PHASE_INITIALIZE is disabled.

order

A HASH reference, Handel::Order object, or an order id. This will be loaded and associated with the new checkout process.

See order below for further details about the various values allowed to be passed.

pluginpaths

An array reference or a comma (or space) seperated list containing the various namespaces of plugins to be loaded. This will override any settings in ENV or httpd.conf for the current checkout instance only.

my $checkout = Handel::Checkout->new({
    pluginpaths => [MyNamespace::Plugins, Other::Plugin]
});

my $checkout = Handel::Checkout->new({
    pluginpaths => 'MyNamespace::Plugins, Other::Plugin'
});

See "HandelPluginPaths" for more information about settings/resetting plugin search paths.

addpluginpaths

An array reference or a comma (or space) seperated list containing the various namespaces of plugin paths in addition to Handel::Checkout::Plugin to be loaded. If HandelAddPluginPaths is also specified, the two will be combined.

my $checkout = Handel::Checkout->new({
    addpluginpaths => [MyNamespace::Plugins, Other::Plugin]
});

my $checkout = Handel::Checkout->new({
    addpluginpaths => 'MyNamespace::Plugins, Other::Plugin'
});

See "HandelAddPluginPaths" for more information about settings/resetting plugin search paths.

phases

An array reference containing the various phases to be executed.

my $checkout = Handel::Checkout->new({
    phases => [CHECKOUT_PHASE_VALIDATION,
               CHECKOUT_PHASE_AUTHORIZATION]
});

METHODS

add_handler($phase, \&coderef)

Registers a code reference with the checkout phase specified. This is usually called within register on the current checkout context:

sub register {
    my ($self, $ctx) = @_;

    $ctx->add_handler(CHECKOUT_PHASE_DELIVER, \&myhandler);
};

sub myhandler {
    ...
};

add_message($message)

Adds a new text message or Handel::Checkout::Message based object to the message stack so plugins can log their issues for later inspection.

sub handler {
    my ($self, $ctx) = @_;
    ...
    $ctx->add_message('Skipping phase for countries other than US...');

    return CHECKOUT_HANDLER_DECLINE;
};

You can subclass Handel::Checkout::Message to add your own properties. If your adding a simple text message, a new Handel::Checkout::Message object will automatically be created and package, filename, and line properties will be set.

cart

Creates a new Handel::Order object from the specified cart and associates that order with the current checkout process. This is typeically only needed the first time you want to run checkout for a specific cart. From then on, you only need to load the already created order using order below.

cart can accept one of three possible parameter values:

cart(\%filter)

When you pass a HASH reference, cart will attempt to load all available carts using Handel::Cart::load(\%filter). If multiple carts are found, only the first one will be used.

$checkout->cart({
    shopper => '12345678-9098-7654-3212-345678909876',
    type => CART_TYPE_TEMP
});
cart(Handel::Cart)

You can also pass in an already existing Handel::Cart object. It will then be loaded into a new order object ans associated with the current checkout process.

my $cart = Handel::Cart->load({
    id => '12345678-9098-7654-3212-345678909876'
});

$checkout->cart($cart);
cart($cartid)

Finally, you can pass a valid cart/uuid into cart. The matching cart will be loaded into a new Handel::Order object and associated with the current checkout process.

$checkout->cart('12345678-9098-7654-3212-345678909876');

messages

Returns a reference to an array of Handel::Checkout::Message object containing additional information about plugin and other checkout decisions and activities.

foreach (@{$checkout->messages}) {
    warn $_->text, "\n";
};

plugins

Returns the plugins loaded for checkout instance

my $checkout = Handel::Checkout->new;
my @plugins = $checkout->plugins;

foreach (@plugins) {
    $_->cleanup_or_something;
};

order

Gets/Sets an existing Handel::Order object with the existing checkout process.

order can accept one of three possible parameter values:

order(\%filter)

When you pass a HASH reference, order will attempt to load all available order using Handel::Order::load(\%filter). If multiple order are found, only the first one will be used.

$checkout->order({
    shopper => '12345678-9098-7654-3212-345678909876',
    id => '11111111-2222-3333-4444-5555666677778888'
});
order(Handel::Order)

You can also pass in an already existing Handel::Order object. It will then be associated with the current checkout process.

my $order = Handel::Order->load({
    id => '12345678-9098-7654-3212-345678909876'
});

$checkout->order($order);
order($orderid)

Finally, you can pass a valid order/uuid into order. The matching order will be loaded and associated with the current checkout process.

$checkout->order('12345678-9098-7654-3212-345678909876');

phases(\@phases)

Get/Set the phases active for the current checkout process.

$checkout->phases([
    CHECKOUT_PHASE_INITIALIZE,
    CHECKOUT_PHASE_VALIDATION
]);

No attempt is made to sanitize the array for duplicates or the order of the phases. This means you can do evil things like run a phase twice, or run the phases out of order.

process([\@phases])

Executes the current checkout process pipeline and returns CHECKOUT_STATUS_*. Any plugin handler that doesn't return CHECKOUT_HANDLER_OK or CHECKOUT_HANDLER_DECLINE is considered to be an error that the chekcout process is aborted.

The call to process will return on of the following constants:

CHECKOUT_STATUS_OK

All plugin handlers were called and returned CHECKOUT_HANDLER_OK or CHECKOUT_HANDLER_DECLINE

CHECKOUT_STATUS_ERROR

At least one plugin failed to return or an error occurred while processing the registered plugin handlers.

CONFIGURATION

HandelPluginPaths

This resets the checkout plugin search path to a namespace of your choosing, The default plugin search path is Handel::Checkout::Plugin::*

PerlSetVar HandelPluginPaths MyApp::Plugins

In the example above, the checkout plugin search path will load all plugins in the MyApp::Plugins::* namespace (but not MyApp::Plugin itself). Any plugins in Handel::Checkout::Plugin::* will be ignored.

You can also pass a comma or space seperate list of namespaces.

PerlSetVar HandelPluginPaths 'MyApp::Plugins, OtherApp::Plugins'

Any plugin found in the search path that isn't a subclass of Handel::Checkout::Plugin will be ignored.

HandelAddPluginPaths

This adds an additional plugin search paths. This can be a comma or space seperated list of namespaces.

PerlSetVar HandelAddPluginPaths  'MyApp::Plugins, OtherApp::Plugins'

In the example above, when a checkout process is loaded, it will load all plugins in the Handel::Checkout::Plugin::*, MyApp::Plugins::*, and OtherApp::Plugins namespaces.

Any plugin found in the search path that isn't a subclass of Handel::Checkout::Plugin will be ignored.

SEE ALSO

Handel::Constants, Handel::Checkout::Plugin, Handel::Order

AUTHOR

Christopher H. Laco
CPAN ID: CLACO
claco@chrislaco.com
http://today.icantfocus.com/blog/