package Dancer::Plugin::Interchange6;
use strict;
use warnings;
use Dancer qw(:syntax !before !after);
use Dancer::Plugin;
use Dancer::Plugin::DBIC;
use Dancer::Plugin::Auth::Extensible;
use Interchange6::Class;
use Interchange6::Cart;
use Dancer::Plugin::Interchange6::Business::OnlinePayment;
=head1 NAME
Dancer::Plugin::Interchange6 - Interchange6 Shop Plugin for Dancer
=head1 VERSION
Version 0.008
=cut
our $VERSION = '0.008';
=head1 REQUIREMENTS
All Interchange6 Dancer applications need to use the L<Dancer::Session::DBIC>
engine.
The easiest way to configure this is in your main module, just after all
the C<use> statements:
set session => 'DBIC';
set session_options => {schema => schema};
=head1 ROUTES
You can use the L<Dancer::Plugin::Interchange6::Routes> plugin bundled with this
plugin to setup standard routes for:
=over 4
=item product listing
=item product display
=item cart display
=item checkout form
=back
To enable these routes, you put the C<shop_setup_routes> keyword at the end
of your main module:
package MyShop;
use Dancer ':syntax';
use Dancer::Plugin::Interchange6;
use Dancer::Plugin::Interchange6::Routes;
get '/shop' => sub {
...
};
...
shop_setup_routes;
true;
Please refer to L<Dancer::Plugin::Interchange6::Routes> for configuration options
and further information.
=head1 HOOKS
This plugin installs the following hooks:
=head2 Add to cart
The functions registered for these hooks receive the cart object
and the item to be added as parameters.
=over 4
=item before_cart_add_validate
Triggered before item is validated for adding to the cart.
=item before_cart_add
Triggered before item is added to the cart.
=item after_cart_add
Triggered after item is added to the cart.
Used by DBI backend to save item to the database.
=back
=head2 Update cart
The functions registered for these hooks receive the cart object,
the current item in the cart and the updated item.
=over 4
=item before_cart_update
Triggered before cart item is updated (changing quantity).
=item after_cart_update
Triggered after cart item is updated (changing quantity).
Used by DBI backend to update item to the database.
=back
=head2 Remove from cart
The functions registered for these hooks receive the cart object
and the item to be added as parameters.
=over 4
=item before_cart_remove_validate
Triggered before item is validated for removal.
Receives cart object and item SKU.
=item before_cart_remove
Triggered before item is removed from the cart.
Receives cart object and item.
=item after_cart_remove
Triggered after item is removed from the cart.
Used by DBI backend to delete item from the database.
Receives cart object and item.
=back
=head2 Clear cart
=over 4
=item before_cart_clear
Triggered before cart is cleared.
=item after_cart_clear
Triggered after cart is cleared.
=back
=head2 Rename cart
The functions registered for these hooks receive the cart object,
the old name and the new name.
=over 4
=item before_cart_rename
Triggered before cart is renamed.
=item after_cart_rename
Triggered after cart is renamed.
=item before_cart_set_users_id
Triggered before users_id is set for the cart.
=item after_cart_set_users_id
Triggered after users_id is set for the cart.
=item before_cart_set_sessions_id
Triggered before sessions_id is set for the cart.
=item after_cart_set_sessions_id
Triggered after sessions_id is set for the cart.
=back
=head1 EXPIRE DBIC SESSIONS
This command expires/manages DBIC sessions and carts. NOTE: For proper
functionality please copy/link to Dancer App/bin directory.
interchange6-expire-sessions
=cut
register_hook(qw/before_cart_add_validate
before_cart_add after_cart_add
before_cart_update after_cart_update
before_cart_remove_validate
before_cart_remove after_cart_remove
before_cart_rename after_cart_rename
before_cart_clear after_cart_clear
before_cart_set_users_id after_cart_set_users_id
before_cart_set_sessions_id after_cart_set_sessions_id
/);
register shop_schema => sub {
_shop_schema(@_);
};
register shop_address => sub {
_shop_resultset('Address', @_);
};
register shop_attribute => sub {
_shop_resultset('Attribute', @_);
};
register shop_country => sub {
_shop_resultset('Country', @_);
};
register shop_navigation => sub {
_shop_resultset('Navigation', @_);
};
register shop_order => sub {
_shop_resultset('Order', @_);
};
register shop_product => sub {
_shop_resultset('Product', @_);
};
register shop_review => sub {
_shop_resultset('Review', @_);
};
register shop_user => sub {
_shop_resultset('User', @_);
};
register shop_charge => sub {
my (%args) = @_;
my ($schema, $bop_object, $payment_settings, $provider, $provider_settings);
$payment_settings = plugin_setting->{payment};
# determine payment provider
if (exists $args{provider} && $args{provider}) {
$provider = $args{provider};
}
else {
$provider = $payment_settings->{default_provider};
}
if (exists $payment_settings->{providers}->{$provider}) {
$provider_settings = $payment_settings->{providers}->{$provider};
}
else {
die "Settings for provider $provider missing.";
}
# create BOP object wrapper with provider settings
$bop_object = Dancer::Plugin::Interchange6::Business::OnlinePayment->new($provider, %$provider_settings);
# call charge method
debug "Charging with the following parameters: ", \%args;
# log request
$schema = _shop_schema();
my %payment_data = (payment_mode => $provider,
status => 'request',
sessions_id => session->id,
payment_action => 'charge',
amount => $args{amount},
users_id => session('logged_in_user_id'),
);
my $payment_order = $schema->resultset('PaymentOrder')->create(\%payment_data);
$bop_object->charge(%args);
if ($bop_object->is_success) {
$payment_order->update({
status => 'success',
auth_code => $bop_object->authorization,
});
}
else {
$payment_order->update({
status => 'failure',
});
}
return $bop_object;
};
register cart => \&_shop_cart;
register shop_cart => \&_shop_cart;
sub _shop_cart {
my $name = 'main';
my ($user_ref, $cart);
if (@_ == 1) {
$name = $_[0];
}
$cart = Interchange6::Class->instantiate('Dancer::Plugin::Interchange6::Cart::DBIC',
name => $name,
session_id => session->id,
run_hooks => sub {execute_hook(@_)});
if ($user_ref = logged_in_user) {
$cart->load(users_id => $user_ref->users_id,
session_id => session->id);
}
else {
$cart->load(session_id => session->id);
}
return $cart;
};
sub _shop_schema {
my $schema_key;
if (@_) {
$schema_key = $_[0];
}
else {
$schema_key = 'default';
}
return schema($schema_key);
};
sub _shop_resultset {
my ($name, $key) = @_;
if (defined $key) {
return resultset($name)->find($key);
}
return resultset($name);
};
register_plugin;
=head1 ACKNOWLEDGEMENTS
The L<Dancer> developers and community for their great application framework
and for their quick and competent support.
Peter Mottram for his patches.
=head1 LICENSE AND COPYRIGHT
Copyright 2010-2014 Stefan Hornburg (Racke).
This program is free software; you can redistribute it and/or modify it
under the terms of either: the GNU General Public License as published
by the Free Software Foundation; or the Artistic License.
See http://dev.perl.org/licenses/ for more information.
=head1 SEE ALSO
L<Interchange6>, L<Interchange6::Schema>
=cut
1;