package WebGUI::Shop::PayDriver::CreditCard; use strict; use Readonly; =head1 NAME WebGUI::Shop::PayDriver::CreditCard =head2 DESCRIPTION A base class for credit card payment drivers. They all need pretty much the same information, the only difference is the servers you talk to. Leaves you to handle recurring payments, processPayment, www_edit, and whatever else you want to - but the user-facing code is pretty much taken care of. =head2 METHODS The following methods are available from this class. =cut use base qw/WebGUI::Shop::PayDriver/; Readonly my $I18N => 'PayDriver_CreditCard'; #------------------------------------------------------------------- sub _monthYear { my $session = shift; my $form = $session->form; tie my %months, "Tie::IxHash"; tie my %years, "Tie::IxHash"; %months = map { sprintf( '%02d', $_ ) => sprintf( '%02d', $_ ) } 1 .. 12; %years = map { $_ => $_ } 2004 .. 2099; my $monthYear = WebGUI::Form::selectBox( $session, { name => 'expMonth', options => \%months, value => [ $form->process("expMonth") ] }) . " / " . WebGUI::Form::selectBox( $session, { name => 'expYear', options => \%years, value => [ $form->process("expYear") ] }); return $monthYear; } #------------------------------------------------------------------- =head2 appendCredentialVars Add template vars for www_getCredentials. Override this to add extra fields. =cut sub appendCredentialVars { my ($self, $var) = @_; my $session = $self->session; my $u = $session->user; my $form = $session->form; my $i18n = WebGUI::International->new($session, $I18N); $var->{formHeader} = WebGUI::Form::formHeader($session) . $self->getDoFormTags('pay'); $var->{formFooter} = WebGUI::Form::formFooter(); my @fieldLoop; # Credit card information $var->{cardNumberField} = WebGUI::Form::text($session, { name => 'cardNumber', value => $self->session->form->process("cardNumber"), }); $var->{monthYearField} = WebGUI::Form::readOnly($session, { value => _monthYear( $session ), }); $var->{cvv2Field} = WebGUI::Form::integer($session, { name => 'cvv2', value => $self->session->form->process("cvv2"), }) if $self->get('useCVV2'); $var->{checkoutButton} = WebGUI::Form::submit($session, { value => $i18n->get('checkout button', 'Shop'), }); return; } #------------------------------------------------------------------- sub definition { my ($class, $session, $definition) = @_; my $i18n = WebGUI::International->new($session, $I18N); tie my %fields, 'Tie::IxHash', ( useCVV2 => { fieldType => 'yesNo', label => $i18n->get('use cvv2'), hoverHelp => $i18n->get('use cvv2 help'), }, credentialsTemplateId => { fieldType => 'template', label => $i18n->get('credentials template'), hoverHelp => $i18n->get('credentials template help'), namespace => 'Shop/Credentials', defaultValue => 'itransact_credentials1', }, ); push @{ $definition }, { name => 'Credit Card Base Class', properties => \%fields, }; return $class->SUPER::definition($session, $definition); } #------------------------------------------------------------------- =head2 processCredentials Process the form where credentials (name, address, phone number and credit card information) are entered. =cut sub processCredentials { my $self = shift; my $session = $self->session; my $form = $session->form; my $i18n = WebGUI::International->new($session, $I18N); my @error; # Check credit card data push @error, $i18n->get( 'invalid card number' ) unless $form->integer('cardNumber'); push @error, $i18n->get( 'invalid cvv2' ) if ($self->get('useCVV2') && !$form->integer('cvv2')); # Check if expDate and expYear have sane values my ($currentYear, $currentMonth) = $self->session->datetime->localtime; my $expires = $form->integer( 'expYear' ) . sprintf '%02d', $form->integer( 'expMonth' ); my $now = $currentYear . sprintf '%02d', $currentMonth; push @error, $i18n->get('invalid expiration date') unless $expires =~ m{^\d{6}$}; push @error, $i18n->get('expired expiration date') unless $expires >= $now; return \@error if scalar @error; # Everything ok process the actual data $self->{ _cardData } = { acct => $form->integer( 'cardNumber' ), expMonth => $form->integer( 'expMonth' ), expYear => $form->integer( 'expYear' ), cvv2 => $form->integer( 'cvv2' ), }; return; } #------------------------------------------------------------------- =head2 www_getCredentials ( $errors ) Build a templated form for asking the user for their credentials. =head3 $errors An array reference of errors to show the user. =cut sub www_getCredentials { my $self = shift; my $errors = shift; my $session = $self->session; my $form = $session->form; my $i18n = WebGUI::International->new($session, $I18N); my $var = {}; # Process form errors $var->{errors} = []; if ($errors) { $var->{error_message} = $i18n->get('error occurred message'); foreach my $error (@{ $errors} ) { push @{ $var->{errors} }, { error => $error }; } } $self->appendCredentialVars($var); $self->appendCartVariables($var); my $template = WebGUI::Asset::Template->new($session, $self->get("credentialsTemplateId")); my $output; if (defined $template) { $template->prepare; $output = $template->process($var); } else { $output = $i18n->get('template gone'); } return $session->style->userStyle($output); } #------------------------------------------------------------------- =head2 www_pay Makes sure that the user has all the requirements for checking out, including getting credentials, it processes the transaction and then displays a thank you screen. =cut sub www_pay { my $self = shift; my $session = $self->session; # Check whether the user filled in the checkout form and process those. my $credentialsErrors = $self->processCredentials; # Go back to checkout form if credentials are not ok return $self->www_getCredentials( $credentialsErrors ) if $credentialsErrors; # Payment time! my $transaction = $self->processTransaction( ); if ($transaction->get('isSuccessful')) { return $transaction->thankYou(); } # Payment has failed... return $self->displayPaymentError($transaction); } 1;