package WebGUI::Operation::Commerce; use strict; use WebGUI::Session; use WebGUI::SQL; use WebGUI::ErrorHandler; use WebGUI::Commerce::Transaction; use WebGUI::Commerce::ShoppingCart; use WebGUI::Commerce::Payment; use WebGUI::AdminConsole; use WebGUI::TabForm; use WebGUI::Style; use WebGUI::Commerce; use WebGUI::Operation; use WebGUI::URL; use WebGUI::International; use WebGUI::Asset::Template; use WebGUI::HTTP; use WebGUI::Paginator; use WebGUI::Form; #------------------------------------------------------------------- sub _submenu { my $i18n = WebGUI::International->new("Commerce"); my $workarea = shift; my $title = shift; $title = $i18n->get($title) if ($title); my $help = shift; my $ac = WebGUI::AdminConsole->new("commerce"); if ($help) { $ac->setHelp($help, 'Commerce'); } $ac->addSubmenuItem(WebGUI::URL::page('op=editCommerceSettings'), $i18n->get('manage commerce settings')); $ac->addSubmenuItem(WebGUI::URL::page('op=listPendingTransactions'), $i18n->get('pending transactions')); return $ac->render($workarea, $title); } #------------------------------------------------------------------- sub _gatewaySelected { return 0 unless ($session{form}{paymentGateway}); my $plugin = WebGUI::Commerce::Payment->load($session{form}{paymentGateway}); return 1 if ($plugin && $plugin->enabled); return 0; } #------------------------------------------------------------------- sub www_cancelTransaction { my ($transaction, %var); $transaction = WebGUI::Commerce::Transaction->new($session{form}{tid}); unless ($transaction->status eq 'Completed') { $transaction->cancelTransaction; } $var{message} = WebGUI::International::get('checkout canceled message', 'Commerce'); return WebGUI::Asset::Template->new($session{setting}{commerceCheckoutCanceledTemplateId})->process(\%var); } # This operation is here for easier future extensions to the commerce system. #------------------------------------------------------------------- sub www_checkout { return WebGUI::Operation::execute('checkoutConfirm'); } #------------------------------------------------------------------- sub www_checkoutConfirm { my ($plugin, $f, %var, $errors, $i18n, $shoppingCart, $normal, $recurring); $errors = shift; $i18n = WebGUI::International->new('Commerce'); # If the user isn't logged in yet, let him do so or have him create an account if ($session{user}{userId} == 1) { WebGUI::Session::setScratch('redirectAfterLogin', WebGUI::URL::page('op=checkout')); return WebGUI::Operation::execute('displayLogin'); } # If no payment gateway has been selected yet, have the user do so now. return WebGUI::Operation::execute('selectPaymentGateway') unless _gatewaySelected; $var{errorLoop} = [ map {{message => $_}} @{$errors} ] if $errors; # Put contents of cart in template vars $shoppingCart = WebGUI::Commerce::ShoppingCart->new; ($normal, $recurring) = $shoppingCart->getItems; $var{normalItemLoop} = $normal; $var{normalItems} = scalar(@$normal); $var{recurringLoop} = $recurring; $var{recurringItems} = scalar(@$recurring); $plugin = WebGUI::Commerce::Payment->load($session{form}{paymentGateway}); $f = WebGUI::HTMLForm->new; $f->hidden('op', 'checkoutSubmit'); $f->hidden('paymentGateway', $session{form}{paymentGateway}); $f->raw($plugin->checkoutForm); $f->submit($i18n->get('pay button')); $var{form} = $f->print; $var{title} = $i18n->get('checkout confirm title'); return WebGUI::Asset::Template->new($session{setting}{commerceConfirmCheckoutTemplateId})->process(\%var); } #------------------------------------------------------------------- sub www_checkoutSubmit { my ($plugin, $shoppingCart, $transaction, $var, $amount, @cartItems, $i18n, @transactions, @normal, $currentPurchase, $checkoutError, @resultLoop, %param, $normal, $recurring, $formError); $i18n = WebGUI::International->new('Commerce'); # check if user has already logged in if ($session{user}{userId} == 1) { WebGUI::Session::setScratch('redirectAfterLogin', WebGUI::URL::page('op=checkout')); return WebGUI::Operation::execute('displayLogin'); } # Check if a valid payment gateway has bee selected. If not have the user do so. return WebGUI::Operation::execute('selectPaymentGateway') unless _gatewaySelected; $plugin = WebGUI::Commerce::Payment->load($session{form}{paymentGateway}); $shoppingCart = WebGUI::Commerce::ShoppingCart->new; ($normal, $recurring) = $shoppingCart->getItems; # Check if shoppingcart contains any items. If not the user probably clicked reload, so we redirect to the current page. unless (@$normal || @$recurring) { WebGUI::HTTP::setRedirect(WebGUI::URL::page); return ''; } # check submitted form params $formError = $plugin->validateFormData; return www_checkoutConfirm($formError) if ($formError); # Combine all non recurring item in one transaction and combine with all recurring ones map {push(@transactions, {recurring => 1, items => [$_]})} @$recurring; push(@transactions, {recurring => 0, items => [@$normal]}) if (@$normal); $shoppingCart->empty; foreach $currentPurchase (@transactions) { $amount = 0; $var = {}; # Write transaction to the log with status pending $transaction = WebGUI::Commerce::Transaction->new('new'); foreach (@{$currentPurchase->{items}}) { $transaction->addItem($_->{item}, $_->{quantity}); $amount += ($_->{item}->price * $_->{quantity}); $var->{purchaseDescription} .= $_->{quantity}.' x '.$_->{item}->name.'
'; } $var->{purchaseAmount} = sprintf('%.2f', $amount); # submit if ($currentPurchase->{recurring}) { $transaction->isRecurring(1); $plugin->recurringTransaction({ amount => $amount, id => $transaction->transactionId, term => 0, payPeriod => $currentPurchase->{items}->[0]->{item}->duration, profilename => $currentPurchase->{items}->[0]->{item}->name, checkCard => 1, }); } else { $plugin->normalTransaction({ amount => $amount, id => $transaction->transactionId, }); } $transaction->gatewayId($plugin->gatewayId); $transaction->gateway($plugin->namespace); # check transaction result unless ($plugin->connectionError) { unless ($plugin->transactionError) { $transaction->completeTransaction if ($plugin->transactionCompleted); $var->{status} = $i18n->get('ok'); } elsif ($plugin->transactionPending) { $checkoutError = 1; $var->{status} = $i18n->get('pending'); $var->{error} = $plugin->transactionError; $var->{errorCode} = $plugin->errorCode; } else { $checkoutError = 1; $var->{status} = $i18n->get('transaction error'); $var->{error} = $plugin->transactionError; $var->{errorCode} = $plugin->errorCode; $transaction->delete; } } else { $checkoutError = 1; $var->{status} = $i18n->get('connection error'); $var->{error} = $plugin->connectionError; $var->{errorCode} = $plugin->errorCode; $transaction->delete; } push(@resultLoop, $var); } $param{title} = $i18n->get('transaction error title'); $param{statusExplanation} = $i18n->get('status codes information'); $param{resultLoop} = \@resultLoop; # If everythings ok show the purchase history return WebGUI::Operation::execute('viewPurchaseHistory') unless ($checkoutError); # If an error has occurred show the template errorlog return WebGUI::Asset::Template->new($session{setting}{commerceTransactionErrorTemplateId})->process(\%param); } #------------------------------------------------------------------- sub www_completePendingTransaction { return WebGUI::AdminConsole->new("commerce")->render(WebGUI::Privilege::adminOnly()) unless (WebGUI::Grouping::isInGroup(3)); WebGUI::Commerce::Transaction->new($session{form}{tid})->completeTransaction; return WebGUI::Operation::execute('listPendingTransactions'); } #------------------------------------------------------------------- sub www_confirmRecurringTransaction { my($plugin, %var); $plugin = WebGUI::Commerce::Payment->load($session{form}{gateway}); if ($plugin) { $plugin->confirmRecurringTransaction; } } #------------------------------------------------------------------- sub www_confirmTransaction { my($plugin, %var); $plugin = WebGUI::Commerce::Payment->load($session{form}{pg}); if ($plugin->confirmTransaction) { WebGUI::Commerce::Transaction->new($plugin->getTransactionId)->completeTransaction; } } #------------------------------------------------------------------- sub www_editCommerceSettings { my (%tabs, $tabform, $jscript, $currentPlugin, $ac, $jscript, $i18n, $paymentPlugin, @paymentPlugins, %paymentPlugins, @failedPaymentPlugins, $plugin); return WebGUI::AdminConsole->new("commerce")->render(WebGUI::Privilege::adminOnly()) unless (WebGUI::Grouping::isInGroup(3)); $i18n = WebGUI::International->new('Commerce'); tie %tabs, 'Tie::IxHash'; %tabs = ( payment=>{label=>$i18n->get('payment tab')}, general=>{label=>$i18n->get('general tab')}, ); $paymentPlugin = $session{config}{paymentPlugins}->[0]; $tabform = WebGUI::TabForm->new(\%tabs); $tabform->hidden({name => 'op', value => 'editCommerceSettingsSave'}); # general $tabform->getTab('general')->template( -name => 'commerceConfirmCheckoutTemplateId', -label => $i18n->get('confirm checkout template'), -value => $session{setting}{commerceConfirmCheckoutTemplateId}, -namespace => 'Commerce/ConfirmCheckout' ); $tabform->getTab('general')->template( -name => 'commerceTransactionErrorTemplateId', -label => $i18n->get('transaction error template'), -value => $session{setting}{commerceTransactionPendingTemplateId}, -namespace => 'Commerce/TransactionError' ); $tabform->getTab('general')->template( -name => 'commerceCheckoutCanceledTemplateId', -label => $i18n->get('checkout canceled template'), -value => $session{setting}{commerceCheckoutCanceledTemplateId}, -namespace => 'Commerce/CheckoutCanceled' ); $tabform->getTab('general')->template( -name => 'commerceSelectPaymentGatewayTemplateId', -label => $i18n->get('checkout select payment template'), -value => $session{setting}{commerceSelectPaymentGatewayTemplateId}, -namespace => 'Commerce/SelectPaymentGateway' ); $tabform->getTab('general')->email( -name => 'commerceSendDailyReportTo', -label => $i18n->get('daily report email'), -value => $session{setting}{commerceSendDailyReportTo} ); # Check which payment plugins will compile, and load them. foreach (@{$session{config}{paymentPlugins}}) { $plugin = WebGUI::Commerce::Payment->load($_); if ($plugin) { push(@paymentPlugins, $plugin); $paymentPlugins{$_} = $plugin->name; } else { push(@failedPaymentPlugins, $_); } } # payment plugin if (%paymentPlugins) { $tabform->getTab('payment')->raw(''); $tabform->getTab("payment")->selectList( -name => 'commercePaymentPlugin', -options => \%paymentPlugins, -label => $i18n->get('payment form'), -value => [$paymentPlugin], -extras => 'onChange="activePayment=operateHidden(this.options[this.selectedIndex].value,activePayment)"' ); $jscript = ''; $tabform->getTab('payment')->raw($jscript); } else { $tabform->getTab('payment')->raw(''.$i18n->get('no payment plugins selected').''); } if (@failedPaymentPlugins) { $tabform->getTab('payment')->raw('
'.$i18n->get('failed payment plugins'). '
'); } $tabform->submit; WebGUI::Style::setScript($session{config}{extrasURL}.'/swapLayers.js',{language=>"Javascript"}); return _submenu($tabform->print, 'edit commerce settings title', 'commerce manage'); } #------------------------------------------------------------------- sub www_editCommerceSettingsSave { return WebGUI::AdminConsole->new("commerce")->render(WebGUI::Privilege::adminOnly()) unless (WebGUI::Grouping::isInGroup(3)); foreach (keys(%{$session{form}})) { # Store the plugin confiuration data in a special table for security and the general settings in the # normal settings table for easy access. if (/~([^~]*)~([^~]*)~([^~]*)/) { WebGUI::Commerce::setCommerceSetting({ type => $1, namespace => $2, fieldName => $3, fieldValue => $session{form}{$_} }); } elsif ($_ ne 'op') { WebGUI::SQL->write('update settings set value='.quote($session{form}{$_}).' where name='.quote($_)); } } return WebGUI::Operation::execute('adminConsole'); } #------------------------------------------------------------------- sub www_listPendingTransactions { my ($p, $transactions, $output, $properties, $i18n); return WebGUI::AdminConsole->new("commerce")->render(WebGUI::Privilege::adminOnly()) unless (WebGUI::Grouping::isInGroup(3)); $i18n = WebGUI::International->new("Commerce"); $p = WebGUI::Paginator->new(WebGUI::URL::page('op=listPendingTransactions')); $p->setDataByArrayRef(WebGUI::Commerce::Transaction->pendingTransactions); $transactions = $p->getPageData; $output = $p->getBarTraditional($session{form}{pn}); $output .= ''; $output .= ''. ''; foreach (@{$transactions}) { $properties = $_->get; $output .= ''; $output .= ''; $output .= ''; $output .= ''; $output .= ''; $output .= ''; $output .= ''; } $output .= '
'.$i18n->get('transactionId').''.$i18n->get('gateway').''.$i18n->get('gatewayId').''.$i18n->get('init date').'
'.$properties->{transactionId}.''.$properties->{gatewayId}.''.$properties->{gateway}.''.WebGUI::DateTime::epochToHuman($properties->{initDate}).''.$i18n->get('complete pending transaction').'
'; $output .= $p->getBarTraditional($session{form}{pn}); _submenu($output, 'list pending transactions', 'list pending transactions'); } #------------------------------------------------------------------- sub www_selectPaymentGateway { my ($plugins, $f, $i18n, @pluginLoop, %var); $i18n = WebGUI::International->new('Commerce'); $plugins = WebGUI::Commerce::Payment->getEnabledPlugins; foreach (@$plugins) { push(@pluginLoop, { name => $_->name, namespace => $_->namespace, formElement => WebGUI::Form::radio({name=>'paymentGateway', value=>$_->namespace}) }); } $var{pluginLoop} = \@pluginLoop; $var{message} = $i18n->get('select payment gateway'); $var{pluginsAvailable} = @$plugins; $var{noPluginsMessage} = $i18n->get('no payment gateway'); $var{formHeader} = WebGUI::Form::formHeader.WebGUI::Form::hidden({name=>'op', value=>'checkoutConfirm'}); $var{formSubmit} = WebGUI::Form::submit({value=>$i18n->get('payment gateway select')}); $var{formFooter} = WebGUI::Form::formFooter; return WebGUI::Asset::Template->new($session{setting}{commerceSelectPaymentGatewayTemplateId})->process(\%var); } #------------------------------------------------------------------- sub www_transactionComplete { return WebGUI::Operation::execute('viewPurchaseHistory'); } 1;