#!/usr/local/bin/perl
#?use CGI::Carp qw(fatalsToBrowser);
#
# Make sure "." is included in the @INC directory list so we can find our packages
#
my $bFound = 0;
my $sDir;
foreach $sDir (@INC)
{
if ($sDir eq ".")
{
$bFound = 1;
last;
}
}
if (!$bFound)
{
push (@INC, ".");
}
#
# NT systems rarely execute the CGI scripts in the cgi-bin, so attempt to locate
# the packages in that case. This may still fail if the cgi-bin folder is named
# something else, but at least we will catch 80% of the cases.
#
push (@INC, "cgi-bin");
require al000000;
require as000000;
require ad000000;
require ae000000;
require ao000000;
use Socket;
use strict;
#######################################################
# #
# The above is the Path to Perl on the ISP's server #
# #
# Requires Perl version 5.002 or later #
# #
#######################################################
#######################################################
# #
# CATALOG SHOPPING CART CGI/PERL SCRIPT #
# #
# Copyright (c) 1998 ACTINIC SOFTWARE LIMITED #
# #
# written by George Menyhert #
# #
#######################################################
#
# Some global constants
#
$::prog_name = "ORDERSCR"; # Program Name
$::prog_name = $::prog_name;
$::prog_ver = '$Revision: 122 $ '; # program version
$::prog_ver = substr($::prog_ver, 11); # strip the revision information
$::prog_ver =~ s/ \$//; # and the trailers
$::FORWARD = 0; # the direction of the order progress
$::BACKWARD = 1;
$::g_sSmtpServer = "smtp.netcom.net.uk";
#
# Global variables
#
$::g_nCurrentSequenceNumber = -1;
$::g_nNextSequenceNumber = -1;
Init(); # initialize the script
ProcessInput(); # execute the input commands
exit;
#######################################################
#
# Init - initialize the script
#
#######################################################
sub Init
{
$::g_bFirstError = $::TRUE; # this flag indicates that the display page method has entered recursion
# due to errors - it prevents infinite recursion
my (@Response, $Status, $Message);
@Response = ReadAndParseInput(); # read the input from the CGI call
($Status, $Message) = @Response; # parse the response
if ($Status != $::SUCCESS)
{
ACTINIC::ReportError($Message, $::g_InputHash{'PATH'});
}
@Response = ReadAndParseBlobs(); # read the catalog blobs
($Status, $Message) = @Response; # parse the response
if ($Status != $::SUCCESS)
{
ACTINIC::ReportError($Message, $::g_InputHash{'PATH'});
}
#
# initialize some global hashes (must come after prompt file)
#
ACTINIC::InitMonthMap();
}
#######################################################
#
# ReadAndParseInput - read the input and parse it
#
# Expects: $ENV to be defined
#
# Affects: @::g_PageList - global list of pages visited
#
# Returns: ($ReturnCode, $Error)
# if $ReturnCode = $FAILURE, the operation failed
# for the reason specified in $Error
# Otherwise everything is OK
#
#######################################################
sub ReadAndParseInput
{
my ($status, $message, $temp);
($status, $message, $::g_OriginalInputData, $temp, %::g_InputHash) = ACTINIC::ReadAndParseInput();
if ($status != $::SUCCESS)
{
return ($status, $message, 0, 0);
}
#
# parse the ref page list
#
($status, $message, @::g_PageList) = ACTINIC::ProcessReferencePageData(%::g_InputHash);
if ($status != $::SUCCESS)
{
return ($status, $message, 0, 0);
}
#######
# retrieve the web site url
#######
($status, $message, $::g_sWebSiteUrl, $::g_sContentUrl) = ACTINIC::GetWebSiteURL(@::g_PageList);
if ($status != $::SUCCESS)
{
return ($status, $message, 0, 0);
}
return ($::SUCCESS, "", 0, 0);
}
#######################################################
#
# ReadAndParseBlobs - read the blobs and store them
# in global data structures
#
# Expects: %::g_InputHash - the input hash table should
# be defined
#
# Affects: $g_sCartId - the cart ID for this customer
# %g_BillContact - the invoice contact information
# %g_ShipContact - the delivery contact information
# %g_ShipInfo - the shipping information
# %g_TaxInfo - the tax information
# %g_GeneralInfo - general information
# %g_PaymentInfo - payment information
#
# Returns: ($ReturnCode, $Error)
# if $ReturnCode = $FAILURE, the operation failed
# for the reason specified in $Error
# Otherwise everything is OK
#
#######################################################
sub ReadAndParseBlobs
{
my ($Status, $Message, @Response, $sPath);
$sPath = $::g_InputHash{"PATH"}; # get the path to the web site
@Response = ACTINIC::ReadCatalogFile($sPath); # read the catalog blob
($Status, $Message) = @Response; # parse the response
if ($Status != $::SUCCESS) # on error, bail
{
return (@Response);
}
@Response = ACTINIC::ReadSetupFile($sPath); # read the setup
($Status, $Message) = @Response;
if ($Status != $::SUCCESS)
{
return (@Response);
}
#
# read the phase blob
#
@Response = ACTINIC::ReadPhaseFile($sPath);
if ($Response[0] != $::SUCCESS)
{
return (@Response);
}
#
# read the prompt blob
#
@Response = ACTINIC::ReadPromptFile($sPath);
if ($Response[0] != $::SUCCESS)
{
return (@Response);
}
#
# read the cart ID
#
@Response = ActinicOrder::GetCartID($::g_InputHash{"PATH"}); # retrieve the cart ID
($Status, $Message, $::g_sCartId) = @Response;
if ($Status != $::SUCCESS) # error out
{
return (@Response);
}
#
# read the checkout status
#
my ($pBillContact, $pShipContact, $pShipInfo, $pTaxInfo, $pGeneralInfo, $pPaymentInfo);
@Response = ActinicOrder::RetrieveCheckoutStatus($sPath, $::g_sCartId);
if ($Response[0] != $::SUCCESS)
{
return (@Response);
}
($Status, $Message, $pBillContact, $pShipContact, $pShipInfo, $pTaxInfo, $pGeneralInfo, $pPaymentInfo) = @Response;
%::g_BillContact = %$pBillContact; # copy the hashes to global tables
%::g_ShipContact = %$pShipContact;
%::g_ShipInfo = %$pShipInfo;
%::g_TaxInfo = %$pTaxInfo;
%::g_GeneralInfo = %$pGeneralInfo;
%::g_PaymentInfo = %$pPaymentInfo;
return ($::SUCCESS, "", 0, 0);
}
#######################################################
#
# ProcessInput - read the input parameters and
# call the appropriate function in response
#
#######################################################
sub ProcessInput
{
my (@Response);
#
# Find out where we are
#
$::g_nCurrentSequenceNumber = $::g_InputHash{'SEQUENCE'}; # determine the sequence number of the calling page
if (!defined $::g_nCurrentSequenceNumber) # if we are at the beginning
{
$::g_nCurrentSequenceNumber = $::STARTSEQUENCE;
}
#
# Get the button names
#
my ($sStartButton, $sDoneButton, $sNextButton, $sFinishButton, $sBackButton, $sCancelButton);
$sStartButton = ACTINIC::GetPhrase(-1, 113);
$sDoneButton = ACTINIC::GetPhrase(-1, 114);
$sNextButton = ACTINIC::GetPhrase(-1, 502);
$sBackButton = ACTINIC::GetPhrase(-1, 503);
$sFinishButton = ACTINIC::GetPhrase(-1, 504);
$sCancelButton = ACTINIC::GetPhrase(-1, 505);
#
# If the progress is forward
#
my ($sHTML, $sAction, $eDirection);
$sAction = $::g_InputHash{'ACTION'};
if ($sAction =~ m/$sStartButton/i ||
$sAction =~ m/$sNextButton/i ||
$sAction =~ m/$sFinishButton/i ||
$sAction =~ m/AUTHORIZE/i ||
$sAction =~ m/RECORDORDER/i)
{
$eDirection = $::FORWARD;
}
elsif ($sAction =~ m/$sBackButton/i) # move backwards
{
$eDirection = $::BACKWARD;
}
elsif ($sAction =~ m/$sDoneButton/i) # return to the catalog header page
{
my ($sRefPage) = $::g_sWebSiteUrl . $::g_InputHash{'HOME'}; # find the catalog page
@Response = ACTINIC::BounceToPagePlain(0, undef, undef, \@::g_PageList, $::g_sWebSiteUrl,
$::g_sContentUrl, $::g_pSetupBlob, $sRefPage, \%::g_InputHash);
if ($Response[0] != $::SUCCESS)
{
ACTINIC::ReportError($Response[1], $::g_InputHash{'PATH'});
return;
}
$sHTML = $Response[2];
goto THEEND;
}
else # cancel
{
$sHTML = GetCancelPage();
goto THEEND;
}
#
# Validate and store the current page information
#
@Response = ValidateInput($eDirection);
if ($Response[0] == $::BADDATA)
{
$sHTML = $Response[1];
goto THEEND;
}
elsif ($Response[0] != $::SUCCESS)
{
ACTINIC::ReportError($Response[1], $::g_InputHash{'PATH'});
return;
}
#
# Determine the next step
#
if ($eDirection == $::FORWARD)
{
$::g_nNextSequenceNumber = $::g_nCurrentSequenceNumber + 1;
}
else
{
$::g_nNextSequenceNumber = $::g_nCurrentSequenceNumber - 1;
}
#
# Display the next page
#
@Response = DisplayPage("", $::g_nNextSequenceNumber, $eDirection);
if ($Response[0] != $::SUCCESS)
{
ACTINIC::ReportError($Response[1], $::g_InputHash{'PATH'});
return;
}
$sHTML = $Response[2];
THEEND:
ACTINIC::UpdateDisplay($sHTML, $::g_OriginalInputData, \@::g_PageList);
}
#######################################################
#
# ValidateInput - validate and save any input from the
# current page. If the input parameter is false,
# the validation is skipped. This occurs when we are
# moving backwards.
#
# Params: 0 - the direction
#
# Returns: 0 - status ($::BADDATA if the validation
# fails)
# 1 - error message (HTML of error page
# if status is $::BADDATA)
#
#######################################################
sub ValidateInput
{
my ($eDirection);
if ($#_ != 0)
{
$eDirection = $::FORWARD;
}
($eDirection) = @_;
my ($bActuallyValidate) = ($eDirection == $::FORWARD); # only validate text when moving forward
my (@Response);
#
# special case - startup
#
if ($::g_nCurrentSequenceNumber == $::STARTSEQUENCE) # if this is startup
{
@Response = ValidateStart($bActuallyValidate); # validate the input/cart settings
return (@Response);
}
else
{
#
# get the phase list for this page
#
my ($sPhaseList) = $$::g_pPhaseList{$::g_nCurrentSequenceNumber};
#
# validate each phase in the current block
#
my (@Phases) = split (//, $sPhaseList);
my ($nPhase, $sError);
foreach $nPhase (@Phases)
{
#
# dispatch the page-specific data
#
if ($nPhase == $::BILLCONTACTPHASE)
{
$sError .= ValidateBill($bActuallyValidate);
}
elsif ($nPhase == $::SHIPCONTACTPHASE)
{
$sError .= ValidateShipContact($bActuallyValidate);
}
elsif ($nPhase == $::SHIPCHARGEPHASE)
{
$sError .= ValidateShipCharge($bActuallyValidate);
}
elsif ($nPhase == $::TAXCHARGEPHASE)
{
$sError .= ActinicOrder::ValidateTax($bActuallyValidate);
}
elsif ($nPhase == $::GENERALPHASE)
{
$sError .= ValidateGeneral($bActuallyValidate);
}
elsif ($nPhase == $::PAYMENTPHASE)
{
$sError .= ValidatePayment($bActuallyValidate);
}
elsif ($nPhase == $::COMPLETEPHASE) # applet page
{
# no-op
# here when returning from a remote OCC site (SEQUENCE number is 3)
}
elsif ($nPhase == $::RECEIPTPHASE) # receipt page
{
# no-op
}
elsif ($nPhase == $::PRELIMINARYINFOPHASE)
{
$sError .= ActinicOrder::ValidatePreliminaryInfo($bActuallyValidate);
}
}
if ($sError ne '') # if an error occured
{
@Response = DisplayPage($sError, $::g_nCurrentSequenceNumber, $eDirection); # redisplay this page with the error messages
if ($Response[0] != $::SUCCESS)
{
return (@Response);
}
$Response[0] = $::BADDATA;
$Response[1] = $Response[2];
return (@Response);
}
}
return (UpdateCheckoutRecord());
}
#######################################################
#
# ValidateStart - validate the beginning of the order
# process
#
# Params: 0 - $::TRUE if the data should be validated
#
# Returns: 0 - status ($::BADDATA if the validation
# fails)
# 1 - error message (HTML of error page
# if status is $::BADDATA)
#
#######################################################
sub ValidateStart
{
if ($#_ != 0)
{
return ($::FAILURE, ACTINIC::GetPhrase(-1, 12, 'ValidateStart'), 0, 0);
}
my ($bActuallyValidate) = @_;
#
# validate the input (if necessary)
#
if (!$bActuallyValidate)
{
return ($::SUCCESS, "", 0, 0);
}
my ($nLineCount, @Response, $Status, $Message);
@Response = ActinicOrder::CountCartItems($::g_sCartId, $::g_InputHash{'PATH'}); # count the items in the cart
($Status, $Message, $nLineCount) = @Response;
if ($Status == $::FAILURE) # error out
{
return (@Response);
}
if ($nLineCount <= 0) # if the cart is empty
{
my ($sLocalPage, $sHTML);
$sLocalPage = pop @::g_PageList; # get the last item in the list
push (@::g_PageList, $sLocalPage); # put the item back
push (@::g_PageList, $sLocalPage); # dup the item (this allows us to bounce properly using ReturnToLastPage)
@Response = ACTINIC::ReturnToLastPage(5, "" .
ACTINIC::GetPhrase(-1, 44, $::g_sCart, $::g_sCart) . "",
$$::g_pSetupBlob{CHECKOUT_DESCRIPTION}, \@::g_PageList, $::g_sWebSiteUrl,
$::g_sContentUrl, $::g_pSetupBlob, %::g_InputHash); # bounce back in the broswer
($Status, $Message, $sHTML) = @Response; # parse the response
if ($Status != $::SUCCESS) # error out
{
return (@Response);
}
return ($::BADDATA, $sHTML, 0, 0); # return the goods
}
return ($::SUCCESS, "", 0, 0);
}
#######################################################
#
# ValidateBill - validate the billing contact data
#
# Params: 0 - $::TRUE if the data should be validated
#
# Returns: 0 - error message
#
#######################################################
sub ValidateBill
{
if ($#_ != 0)
{
ACTINIC::ReportError(ACTINIC::GetPhrase(-1, 12, 'ValidateBill'));
}
my ($bActuallyValidate) = @_;
#
# gather the data
#
$::g_BillContact{'SALUTATION'} = $::g_InputHash{'INVOICESALUTATION'};
$::g_BillContact{'NAME'} = $::g_InputHash{'INVOICENAME'};
$::g_BillContact{'JOBTITLE'} = $::g_InputHash{'INVOICEJOBTITLE'};
$::g_BillContact{'COMPANY'} = $::g_InputHash{'INVOICECOMPANY'};
$::g_BillContact{'ADDRESS1'} = $::g_InputHash{'INVOICEADDRESS1'};
$::g_BillContact{'ADDRESS2'} = $::g_InputHash{'INVOICEADDRESS2'};
$::g_BillContact{'ADDRESS3'} = $::g_InputHash{'INVOICEADDRESS3'};
$::g_BillContact{'ADDRESS4'} = $::g_InputHash{'INVOICEADDRESS4'};
$::g_BillContact{'POSTALCODE'} = $::g_InputHash{'INVOICEPOSTALCODE'};
$::g_BillContact{'COUNTRY'} = $::g_InputHash{'INVOICECOUNTRY'};
$::g_BillContact{'PHONE'} = $::g_InputHash{'INVOICEPHONE'};
$::g_BillContact{'FAX'} = $::g_InputHash{'INVOICEFAX'};
$::g_BillContact{'EMAIL'} = $::g_InputHash{'INVOICEEMAIL'};
$::g_BillContact{'USERDEFINED'} = $::g_InputHash{'INVOICEUSERDEFINED'};
$::g_BillContact{'MOVING'} = ($::g_InputHash{'INVOICEMOVING'} ne "") ? $::TRUE : $::FALSE;
$::g_BillContact{'PRIVACY'} = ($::g_InputHash{'INVOICEPRIVACY'} ne "") ? $::TRUE : $::FALSE;
$::g_BillContact{'SEPARATE'} = ($::g_InputHash{'SEPARATESHIP'} ne "") ? $::TRUE : $::FALSE;
#
# clean up the input
#
ACTINIC::TrimHashEntries(\%::g_BillContact);
#
# validate field input
#
my ($sError);
if (!$bActuallyValidate)
{
return ($sError);
}
#
# validate field requirement status
#
my (@Response);
if (ACTINIC::IsPromptRequired(0, 0) &&
$::g_BillContact{'SALUTATION'} eq "")
{
$sError .= ACTINIC::GetRequiredMessage(0, 0);
}
if (ACTINIC::IsPromptRequired(0, 1) &&
$::g_BillContact{'NAME'} eq "")
{
$sError .= ACTINIC::GetRequiredMessage(0, 1);
}
if (ACTINIC::IsPromptRequired(0, 2) &&
$::g_BillContact{'JOBTITLE'} eq "")
{
$sError .= ACTINIC::GetRequiredMessage(0, 2);
}
if (ACTINIC::IsPromptRequired(0, 3) &&
$::g_BillContact{'COMPANY'} eq "")
{
$sError .= ACTINIC::GetRequiredMessage(0, 3);
}
if (ACTINIC::IsPromptRequired(0, 4) &&
$::g_BillContact{'ADDRESS1'} eq "")
{
$sError .= ACTINIC::GetRequiredMessage(0, 4);
}
if (ACTINIC::IsPromptRequired(0, 5) &&
$::g_BillContact{'ADDRESS2'} eq "")
{
$sError .= ACTINIC::GetRequiredMessage(0, 5);
}
if (ACTINIC::IsPromptRequired(0, 6) &&
$::g_BillContact{'ADDRESS3'} eq "")
{
$sError .= ACTINIC::GetRequiredMessage(0, 6);
}
if (ACTINIC::IsPromptRequired(0, 7) &&
$::g_BillContact{'ADDRESS4'} eq "")
{
$sError .= ACTINIC::GetRequiredMessage(0, 7);
}
if (ACTINIC::IsPromptRequired(0, 8) &&
$::g_BillContact{'POSTALCODE'} eq "")
{
$sError .= ACTINIC::GetRequiredMessage(0, 8);
}
if (ACTINIC::IsPromptRequired(0, 9) &&
$::g_BillContact{'COUNTRY'} eq "")
{
$sError .= ACTINIC::GetRequiredMessage(0, 9);
}
if (ACTINIC::IsPromptRequired(0, 10) &&
$::g_BillContact{'PHONE'} eq "")
{
$sError .= ACTINIC::GetRequiredMessage(0, 10);
}
if (ACTINIC::IsPromptRequired(0, 11) &&
$::g_BillContact{'FAX'} eq "")
{
$sError .= ACTINIC::GetRequiredMessage(0, 11);
}
if (ACTINIC::IsPromptRequired(0, 12) &&
$::g_BillContact{'EMAIL'} eq "")
{
$sError .= ACTINIC::GetRequiredMessage(0, 12);
}
if (ACTINIC::IsPromptRequired(0, 14) &&
$::g_BillContact{'USERDEFINED'} eq "")
{
$sError .= ACTINIC::GetRequiredMessage(0, 14);
}
if ($sError ne "") # if there are any errors
{ # indicate the problem phase
$sError = "" . ACTINIC::GetPhrase(-1, 147) . "
" . $sError . "
";
}
return ($sError);
}
#######################################################
#
# ValidateShipContact - validate the shipping contact data
#
# Params: 0 - $::TRUE if the data should be validated
#
# Returns: 0 - error message
#
#######################################################
sub ValidateShipContact
{
if ($#_ != 0)
{
ACTINIC::ReportError(ACTINIC::GetPhrase(-1, 12, 'ValidateShipContact'));
}
my ($bActuallyValidate) = @_;
#
# If the ship separate flag has been disabled, then assume that the shipping address is required
#
my ($bDeliverAddressRequired) = ACTINIC::IsPromptHidden(0, 16);
#
# gather the data
#
#
# if they indicated that they are shipping to the same address, set the shipping address to the billing address
# and mark it as finished. Otherwise mark it as unfinished
#
# Presnet: handle reversal of check box action - start of un-comment
#
my $bCheckReversed = (defined $$::g_pSetupBlob{'REVERSE_ADDRESS_CHECK'} &&
$$::g_pSetupBlob{'REVERSE_ADDRESS_CHECK'});
if (((!$bCheckReversed && !$::g_BillContact{'SEPARATE'}) ||
($bCheckReversed && $::g_BillContact{'SEPARATE'})) && # ship address = bill address
!$bDeliverAddressRequired)
#
# Presnet: end of un-comment / start of comment-out
#
# if (!$::g_BillContact{'SEPARATE'}) ||
# !$bDeliverAddressRequired)
#
# Presnet: end of comment-out
#
{
$::g_ShipContact{'SALUTATION'} = $::g_BillContact{'SALUTATION'};
$::g_ShipContact{'NAME'} = $::g_BillContact{'NAME'};
$::g_ShipContact{'JOBTITLE'} = $::g_BillContact{'JOBTITLE'};
$::g_ShipContact{'COMPANY'} = $::g_BillContact{'COMPANY'};
$::g_ShipContact{'ADDRESS1'} = $::g_BillContact{'ADDRESS1'};
$::g_ShipContact{'ADDRESS2'} = $::g_BillContact{'ADDRESS2'};
$::g_ShipContact{'ADDRESS3'} = $::g_BillContact{'ADDRESS3'};
$::g_ShipContact{'ADDRESS4'} = $::g_BillContact{'ADDRESS4'};
$::g_ShipContact{'POSTALCODE'} = $::g_BillContact{'POSTALCODE'};
$::g_ShipContact{'COUNTRY'} = $::g_BillContact{'COUNTRY'};
$::g_ShipContact{'PHONE'} = $::g_BillContact{'PHONE'};
$::g_ShipContact{'FAX'} = $::g_BillContact{'FAX'};
$::g_ShipContact{'EMAIL'} = $::g_BillContact{'EMAIL'};
$::g_ShipContact{'USERDEFINED'} = $::g_BillContact{'USERDEFINED'};
}
else
{
$::g_ShipContact{'SALUTATION'} = $::g_InputHash{'DELIVERSALUTATION'};
$::g_ShipContact{'NAME'} = $::g_InputHash{'DELIVERNAME'};
$::g_ShipContact{'JOBTITLE'} = $::g_InputHash{'DELIVERJOBTITLE'};
$::g_ShipContact{'COMPANY'} = $::g_InputHash{'DELIVERCOMPANY'};
$::g_ShipContact{'ADDRESS1'} = $::g_InputHash{'DELIVERADDRESS1'};
$::g_ShipContact{'ADDRESS2'} = $::g_InputHash{'DELIVERADDRESS2'};
$::g_ShipContact{'ADDRESS3'} = $::g_InputHash{'DELIVERADDRESS3'};
$::g_ShipContact{'ADDRESS4'} = $::g_InputHash{'DELIVERADDRESS4'};
$::g_ShipContact{'POSTALCODE'} = $::g_InputHash{'DELIVERPOSTALCODE'};
$::g_ShipContact{'COUNTRY'} = $::g_InputHash{'DELIVERCOUNTRY'};
$::g_ShipContact{'PHONE'} = $::g_InputHash{'DELIVERPHONE'};
$::g_ShipContact{'FAX'} = $::g_InputHash{'DELIVERFAX'};
$::g_ShipContact{'EMAIL'} = $::g_InputHash{'DELIVEREMAIL'};
$::g_ShipContact{'USERDEFINED'} = $::g_InputHash{'DELIVERUSERDEFINED'};
}
$::g_ShipContact{'PRIVACY'} = $::g_BillContact{'PRIVACY'}; # the privacy setting is always the same for delivery and invoice contacts
#
# clean up the input
#
ACTINIC::TrimHashEntries(\%::g_ShipContact);
#
# validate field input
#
my ($sError);
if (!$bActuallyValidate || # if we are not validating, or
!$::g_BillContact{'SEPARATE'}) # if the delivery address is ignored
{
return ($sError); # don't do the validation
}
#
# validate field requirement status
#
my (@Response);
if (ACTINIC::IsPromptRequired(1, 0) &&
$::g_ShipContact{'SALUTATION'} eq "")
{
$sError .= ACTINIC::GetRequiredMessage(1, 0);
}
if (ACTINIC::IsPromptRequired(1, 1) &&
$::g_ShipContact{'NAME'} eq "")
{
$sError .= ACTINIC::GetRequiredMessage(1, 1);
}
if (ACTINIC::IsPromptRequired(1, 2) &&
$::g_ShipContact{'JOBTITLE'} eq "")
{
$sError .= ACTINIC::GetRequiredMessage(1, 2);
}
if (ACTINIC::IsPromptRequired(1, 3) &&
$::g_ShipContact{'COMPANY'} eq "")
{
$sError .= ACTINIC::GetRequiredMessage(1, 3);
}
if (ACTINIC::IsPromptRequired(1, 4) &&
$::g_ShipContact{'ADDRESS1'} eq "")
{
$sError .= ACTINIC::GetRequiredMessage(1, 4);
}
if (ACTINIC::IsPromptRequired(1, 5) &&
$::g_ShipContact{'ADDRESS2'} eq "")
{
$sError .= ACTINIC::GetRequiredMessage(1, 5);
}
if (ACTINIC::IsPromptRequired(1, 6) &&
$::g_ShipContact{'ADDRESS3'} eq "")
{
$sError .= ACTINIC::GetRequiredMessage(1, 6);
}
if (ACTINIC::IsPromptRequired(1, 7) &&
$::g_ShipContact{'ADDRESS4'} eq "")
{
$sError .= ACTINIC::GetRequiredMessage(1, 7);
}
if (ACTINIC::IsPromptRequired(1, 8) &&
$::g_ShipContact{'POSTALCODE'} eq "")
{
$sError .= ACTINIC::GetRequiredMessage(1, 8);
}
if (ACTINIC::IsPromptRequired(1, 9) &&
$::g_ShipContact{'COUNTRY'} eq "")
{
$sError .= ACTINIC::GetRequiredMessage(1, 9);
}
if (ACTINIC::IsPromptRequired(1, 10) &&
$::g_ShipContact{'PHONE'} eq "")
{
$sError .= ACTINIC::GetRequiredMessage(1, 10);
}
if (ACTINIC::IsPromptRequired(1, 11) &&
$::g_ShipContact{'FAX'} eq "")
{
$sError .= ACTINIC::GetRequiredMessage(1, 11);
}
if (ACTINIC::IsPromptRequired(1, 12) &&
$::g_ShipContact{'EMAIL'} eq "")
{
$sError .= ACTINIC::GetRequiredMessage(1, 12);
}
if (ACTINIC::IsPromptRequired(1, 13) &&
$::g_ShipContact{'USERDEFINED'} eq "")
{
$sError .= ACTINIC::GetRequiredMessage(1, 13);
}
if ($sError ne "") # if there are any errors
{ # indicate the problem phase
$sError = "" . ACTINIC::GetPhrase(-1, 148) . "
" . $sError . "
";
}
return ($sError);
}
#######################################################
#
# ValidateShipCharge - validate the shipping charge data
#
# Params: 0 - $::TRUE if the data should be validated
#
# Returns: 0 - error message
#
# Expects: $::g_ShipInfo to be defined
#
#######################################################
sub ValidateShipCharge
{
if ($#_ != 0)
{
ACTINIC::ReportError(ACTINIC::GetPhrase(-1, 12, 'ValidateShipCharge'));
}
my ($bActuallyValidate) = @_;
#
# retrieve and validate the shipping values
#
my ($sError);
if ($$::g_pSetupBlob{MAKE_SHIPPING_CHARGE} && # shipping is enabled and
!ActinicOrder::IsPhaseHidden($::SHIPCHARGEPHASE)) # it is not hidden
{
#
# do advanced shipping validation - only report validation problems if we are actually validating
#
my @Response = ActinicOrder::CallShippingPlugIn();
if ($bActuallyValidate) # if we are actually validating the input and
{
if ($Response[0] != $::SUCCESS) # the script failed
{
$sError .= "" . ACTINIC::GetPhrase(-1, 102) . " - ". $Response[1] . " \n";
}
elsif (${$Response[2]}{ValidateFinalInput} != $::SUCCESS) # the validation failed
{ # return the error
$sError .= "" . ACTINIC::GetPhrase(-1, 102) . " - ". ${$Response[3]}{ValidateFinalInput} . " \n";
}
}
}
#
# retrieve and validate the user defined shipping
#
$::g_ShipInfo{'USERDEFINED'} = $::g_InputHash{'SHIPUSERDEFINED'};
#
# clean up the input
#
ACTINIC::TrimHashEntries(\%::g_ShipInfo);
if ($bActuallyValidate &&
ACTINIC::IsPromptRequired(2, 1) &&
$::g_ShipInfo{'USERDEFINED'} eq "")
{
$sError .= ACTINIC::GetRequiredMessage(2, 1);
}
if ($sError ne "") # if there are any errors
{ # indicate the problem phase
$sError = "" . ACTINIC::GetPhrase(-1, 149) . "
" . $sError . "
";
}
return ($sError);
}
#######################################################
#
# ValidateGeneral - validate the general info data
#
# Params: 0 - $::TRUE if the data should be validated
#
# Returns: 0 - error message
#
#######################################################
sub ValidateGeneral
{
if ($#_ != 0)
{
ACTINIC::ReportError(ACTINIC::GetPhrase(-1, 12, 'ValidateGeneral'));
}
my ($bActuallyValidate) = @_;
#
# gather the data
#
$::g_GeneralInfo{'HOWFOUND'} = $::g_InputHash{'GENERALHOWFOUND'};
$::g_GeneralInfo{'WHYBUY'} = $::g_InputHash{'GENERALWHYBUY'};
$::g_GeneralInfo{'USERDEFINED'} = $::g_InputHash{'GENERALUSERDEFINED'};
#
# clean up the input
#
ACTINIC::TrimHashEntries(\%::g_GeneralInfo);
#
# validate field input
#
my ($sError);
if (!$bActuallyValidate)
{
return ($sError);
}
#
# validate field requirement status
#
my (@Response);
if (ACTINIC::IsPromptRequired(4, 0) &&
$::g_GeneralInfo{'HOWFOUND'} eq "")
{
$sError .= ACTINIC::GetRequiredMessage(4, 0);
}
if (ACTINIC::IsPromptRequired(4, 1) &&
$::g_GeneralInfo{'WHYBUY'} eq "")
{
$sError .= ACTINIC::GetRequiredMessage(4, 1);
}
if (ACTINIC::IsPromptRequired(4, 2) &&
$::g_GeneralInfo{'USERDEFINED'} eq "")
{
$sError .= ACTINIC::GetRequiredMessage(4, 2);
}
if ($sError ne "") # if there are any errors
{ # indicate the problem phase
$sError = "" . ACTINIC::GetPhrase(-1, 151) . "
" . $sError . "
";
}
return ($sError);
}
#######################################################
#
# ValidatePayment - validate the payment info data
#
# Params: 0 - $::TRUE if the data should be validated
#
# Returns: 0 - error message
#
#######################################################
sub ValidatePayment
{
if ($#_ != 0)
{
ACTINIC::ReportError(ACTINIC::GetPhrase(-1, 12, 'ValidatePayment'));
}
my ($bActuallyValidate) = @_;
#
# gather the data
#
$::g_PaymentInfo{'METHOD'} = $::g_InputHash{'PAYMENTMETHOD'};
$::g_PaymentInfo{'USERDEFINED'} = $::g_InputHash{'PAYMENTUSERDEFINED'};
$::g_PaymentInfo{'PONO'} = $::g_InputHash{'PAYMENTPONO'};
$::g_PaymentInfo{'CARDTYPE'} = $::g_InputHash{'PAYMENTCARDTYPE'};
$::g_PaymentInfo{'CARDNUMBER'} = $::g_InputHash{'PAYMENTCARDNUMBER'};
$::g_PaymentInfo{'CARDISSUE'} = $::g_InputHash{'PAYMENTCARDISSUE'};
$::g_PaymentInfo{'EXPMONTH'} = $::g_InputHash{'PAYMENTEXPMONTH'};
$::g_PaymentInfo{'EXPYEAR'} = $::g_InputHash{'PAYMENTEXPYEAR'};
$::g_PaymentInfo{'STARTMONTH'} = $::g_InputHash{'PAYMENTSTARTMONTH'};
$::g_PaymentInfo{'STARTYEAR'} = $::g_InputHash{'PAYMENTSTARTYEAR'};
#
# clean up the input
#
ACTINIC::TrimHashEntries(\%::g_PaymentInfo);
#
# if there is only one payment option, take it.
# if there are no payment options, assume pre-pay
#
EnsurePaymentSelection();
#
# validate field input
#
my ($sError);
if (!$bActuallyValidate)
{
return ($sError);
}
#
# validate field requirement status
#
my (@Response);
if (ACTINIC::IsPromptRequired(5, 6) &&
$::g_PaymentInfo{'PONO'} eq "")
{
$sError .= ACTINIC::GetRequiredMessage(5, 6);
}
if (ACTINIC::IsPromptRequired(5, 7) &&
$::g_PaymentInfo{'USERDEFINED'} eq "")
{
$sError .= ACTINIC::GetRequiredMessage(5, 7);
}
#
# validate credit card fields if they exist
#
my ($ePaymentMethod) = ActinicOrder::PaymentStringToEnum($::g_PaymentInfo{'METHOD'}); # the payment method is stored as "ENUMERATEDID:DESCRIPTION"
if ($ePaymentMethod == $::PAYMENT_CREDIT_CARD && # only validate the cc info if they paid with a CC and
!$$::g_pSetupBlob{USE_DH} && # the Java encryption is off and
$$::g_pSetupBlob{OCC} == -1) # we are not in on-line CC mode
{
#
# validation rules
#
# CARDTYPE - required
# CARDNUMBER - required and checksum
# CARDISSUE - required? (depends are card type) and 1-255
# EXPMONTH - required and combined with EXPYEAR must be > this month
# EXPYEAR - required
# STARTMONTH - required? (depends are card type) and combined with STARTYEAR must be <= this month
# STARTYEAR - required? (depends are card type)
#
if ($::g_PaymentInfo{'CARDTYPE'} eq "") # the card type is required
{
$sError .= ACTINIC::GetRequiredMessage(5, 1);
}
#
# locate the information for the card in question
#
my ($nIndex, $sCCID, $bFound);
$bFound = $::FALSE;
for ($nIndex = 0; $nIndex < 12; $nIndex++) # search for the selected card in the stack
{
$sCCID = sprintf('CC%d', $nIndex); # format the card key name
if ($$::g_pSetupBlob{$sCCID} eq
$::g_PaymentInfo{'CARDTYPE'}) # if this was the card of interest, use it
{
$bFound = $::TRUE; # note that the card was found
last; # break out
}
}
if (!$bFound) # if the matching card was found, report the error
{
$sError .= "" .
ACTINIC::GetPhrase(5, 1) . "" .
ACTINIC::GetPhrase(-1, 107, $::g_PaymentInfo{'CARDTYPE'}) . " \n"
}
#
# check the credit card number
#
my ($nNumber) = $::g_PaymentInfo{'CARDNUMBER'};
$nNumber =~ s/\s//g; # remove any white space
$nNumber =~ s/-//g; # remove any dashes
if ($nNumber eq "") # the card number is required
{
$sError .= ACTINIC::GetRequiredMessage(5, 2);
}
if ($nNumber =~ /[^0-9]/) # the card number should only contain numbers
{
$sError .= "" .
ACTINIC::GetPhrase(5, 2) . "" .
ACTINIC::GetPhrase(-1, 108) . " \n"
}
my ($nCheckSum, $nDigitCount) = (0, 0);
my ($nDigit, $nCheck);
for($nIndex = (length $nNumber) - 1; $nIndex >= 0; $nIndex--)
{
$nDigit = substr($nNumber, $nIndex, 1); # get this digit
$nCheck = (1 + $nDigitCount++ % 2) * # calculate the checksum
$nDigit;
if ( $nCheck >= 10)
{
$nCheck++;
}
$nCheckSum += $nCheck;
}
if (($nCheckSum % 10) != 0) # if the checksum failed
{
$sError .= "" .
ACTINIC::GetPhrase(5, 2) . "" .
ACTINIC::GetPhrase(-1, 109) . " \n"
}
#
# validate the issue number
#
if ($$::g_pSetupBlob{$sCCID . '_ISSUENUMBERFLAG'}) # this credit card requires an issue number
{
if ($::g_PaymentInfo{'CARDISSUE'} eq "" || # the issue number must exist and be between 1-255
$::g_PaymentInfo{'CARDISSUE'} < 1 ||
$::g_PaymentInfo{'CARDISSUE'} > 255)
{
$sError .= ACTINIC::GetPhrase(-1, 110, "" .
ACTINIC::GetPhrase(5, 5) . "", $::g_PaymentInfo{'CARDTYPE'}) . " \n"
}
}
else # the issue number is not required, make sure it is blank
{
$::g_PaymentInfo{'CARDISSUE'} = "";
}
#
# validate the start date
#
my ($sec, $min, $hour, $mday, $mon, $year, $wday, $yday, $isdst, $sDate);
($sec, $min, $hour, $mday, $mon, $year, $wday, $yday, $isdst) = localtime(time); # platform independent time
$mon++; # make month 1 based
$year += 1900; # make year AD based
if ($$::g_pSetupBlob{$sCCID . '_STARTDATEFLAG'}) # this credit card requires a start date
{
if ($::g_PaymentInfo{'STARTMONTH'} eq "" || # if the start month or year are blank
$::g_PaymentInfo{'STARTYEAR'} eq "")
{
$sError .= ACTINIC::GetRequiredMessage(5, 3); #point out that they are required
}
if ($::g_PaymentInfo{'STARTYEAR'} == $year && # if the card has not started yet
$::g_PaymentInfo{'STARTMONTH'} > $mon)
{
$sError .= "" .
ACTINIC::GetPhrase(5, 3) . "" .
ACTINIC::GetPhrase(-1, 111) . " \n"
}
}
else # the start date is not required, make sure it is blank
{
$::g_PaymentInfo{'STARTMONTH'} = "";
$::g_PaymentInfo{'STARTYEAR'} = "";
}
#
# validate the expiration date
#
if ($::g_PaymentInfo{'EXPMONTH'} eq "" || # if the expiration month or year are blank
$::g_PaymentInfo{'EXPYEAR'} eq "")
{
$sError .= ACTINIC::GetRequiredMessage(5, 4); # point out that they are required
}
if ($::g_PaymentInfo{'EXPYEAR'} == $year && # if the card has expired
$::g_PaymentInfo{'EXPMONTH'} < $mon)
{
$sError .= "" .
ACTINIC::GetPhrase(5, 4) . "" .
ACTINIC::GetPhrase(-1, 112) . " \n"
}
}
else
{
$::g_PaymentInfo{'CARDTYPE'} = "";
$::g_PaymentInfo{'CARDNUMBER'} = "";
$::g_PaymentInfo{'CARDISSUE'} = "";
$::g_PaymentInfo{'EXPMONTH'} = "";
$::g_PaymentInfo{'EXPYEAR'} = "";
$::g_PaymentInfo{'STARTMONTH'} = "";
$::g_PaymentInfo{'STARTYEAR'} = "";
}
if ($sError ne "") # if there are any errors
{ # indicate the problem phase
$sError = "" . ACTINIC::GetPhrase(-1, 152) . "
" . $sError . "
";
}
return ($sError);
}
#######################################################
#
# DisplayPage - display the specified page with the
# optional error message
#
# Params: 0 - error message if any
# 1 - page number to display
# 2 - advance direction ($::FORWARD, $::BACKWARD)
#
# Returns: 0 - status
# 1 - error message
# 2 - HTML
#
#######################################################
sub DisplayPage
{
if ($#_ != 2)
{
return ($::FAILURE, ACTINIC::GetPhrase(-1, 12, 'DisplayPage'), 0, 0);
}
my (%VariableTable);
my ($sError, $nPageNumber, $eDirection) = @_;
my (@Response, $sPath);
$sPath = $::g_InputHash{"PATH"}; # get the path to the web site
#
# Read the shopping cart - this has to be done before the call to ProcessPage since
# process page kills the cart when receipt is called.
#
my ($pCartList);
@Response = ActinicOrder::ReadCart($::g_sCartId, $sPath); # read the shopping cart
if ($Response[0] != $::SUCCESS) # general error
{
return (@Response);
}
$pCartList = $Response[2];
#
# make sure there are no "deleted" items in the cart
#
my $nLineCount = CountValidCartItems($pCartList);
my $sMessage;
if ($nLineCount != scalar @$pCartList &&
$::g_bFirstError)
{
$::g_bFirstError = $::FALSE;
$sMessage = "
" .
ACTINIC::GetPhrase(-1, 175) . " \n";
return(DisplayPage($sMessage, $::g_nCurrentSequenceNumber, $eDirection)); # redisplay the incoming page with the error messages
}
#
# Process the phases in this page
#
my (@DeleteDelimiters, @KeepDelimiters, $nInc, $status);
my ($pVarTable, $pDeleteDelimiters, $pKeepDelimiters, @keys);
$nInc = ($eDirection == $::FORWARD) ? 1 : -1;
while ($#keys == -1 && # as long as the page is not used
$nPageNumber >= 0) # and the page is a valid number
{
($status, $sMessage, $pVarTable, $pDeleteDelimiters, $pKeepDelimiters) =
ProcessPage($nPageNumber); # process the current page
if ($status != $::SUCCESS) # if an error occured creating the pages, display the previous page
{ # with the error message
if ($::g_bFirstError) # make sure we don't run into recursion problems
{
$::g_bFirstError = $::FALSE;
$sMessage = "
$sMessage \n";
return(DisplayPage($sMessage, $::g_nCurrentSequenceNumber, $eDirection)); # redisplay the incoming page with the error messages
}
else # unfortunate error that can be recovered
{
return($status, $sMessage, 0, 0);
}
}
@keys = keys %$pVarTable;
$nPageNumber += $nInc; # try the next/previous page
}
$nPageNumber -= $nInc; # roll back the page number since it was unnecessarily incremented
#
# Handle the special case when the back button takes us back to the catalog rather than a previous order page
#
if ($#keys == -1) # we wound back too far (never found a valid page)
{
if (length $sError > 0) # if an error message exists, we still need to display it
{
my ($sRefPage) = $::g_PageList[0]; # find the original referencing page
my @Response = ACTINIC::BounceToPageEnhanced(-1, $sError, ACTINIC::GetPhrase(-1, 25),
\@::g_PageList, $::g_sWebSiteUrl, $::g_sContentUrl, $::g_pSetupBlob, $sRefPage, \%::g_InputHash);
if ($Response[0] != $::SUCCESS)
{
ACTINIC::ReportError($sError, $::g_InputHash{'PATH'});
}
return ($::SUCCESS, '', $Response[2]);
}
else
{
return ($::SUCCESS, "", GetCancelPage()); # go back to the catalog
}
}
#
# Now display a summary of the shopping cart - this must be post page-specific formatting
# since the hidden status of the shipping phases may update the data
#
@Response = ActinicOrder::GenerateShoppingCartLines($pCartList);
if ($Response[0] != $::SUCCESS)
{
return (@Response);
}
$VariableTable{$::VARPREFIX.'THEORDERDETAILS'} = $Response[2]; # add the order lines to the reciept
#
# combine the variable tables - build the total page
#
my (@a1, @a2);
@a1 = %VariableTable;
@a2 = %$pVarTable;
push (@a1, @a2);
%VariableTable = @a1; # get easier-to-handle copies
@DeleteDelimiters = @$pDeleteDelimiters;
@KeepDelimiters = @$pKeepDelimiters;
#
# By here, we have all of the phase specific values. Now generate the generic values.
#
$sError = GroomError($sError); # make the error look nice for the HTML
$VariableTable{$::VARPREFIX.'SEQUENCE'} = $nPageNumber; # add the sequence number to the var list
$VariableTable{$::VARPREFIX.'ERROR'} = $sError; # add the error message to the var list
#
# build the file
#
my ($sFileName);
$sFileName = sprintf('order%2.2d.html', $nPageNumber);
@Response = ACTINIC::TemplateFile($sPath.$sFileName, \%VariableTable); # make the substitutions
if ($Response[0] != $::SUCCESS)
{
return (@Response);
}
#
# clean up the links
#
@Response = ACTINIC::MakeLinksAbsolute($Response[2], $::g_sWebSiteUrl, $::g_sContentUrl);
if ($Response[0] != $::SUCCESS)
{
return (@Response);
}
my ($sHTML) = $Response[2];
#
# remove unused form blocks
#
my ($sDelimiter);
foreach $sDelimiter (@DeleteDelimiters) # for each delimited section that is to be deleted
{
$sHTML =~ s/$::DELPREFIX$sDelimiter(.*?)$::DELPREFIX$sDelimiter//gs; # delete it (/s removes the \n limitation of .)
}
#
# remove unused delimiters
#
foreach $sDelimiter (@KeepDelimiters) # for each delimiter that is not used
{
$sHTML =~ s/$::DELPREFIX$sDelimiter//gs; # delete it
}
return ($::SUCCESS, "", $sHTML, 0);
}
#######################################################
#
# ProcessPage - process the page specific variable
# lists
#
# Params: 0 - page number
#
# Returns: 0 - status
# 1 - error message if any
# 2 - a pointer to the substitution variable table
# 3 - a pointer to the list of delimiters of areas to delete
# 4 - a pointer to the list of delimiters of areas to keep
#
# Affects: %s_LargeVariableTable, @s_LargeDeleteDelimiters,
# @s_LargeKeepDelimiters
#
#######################################################
sub ProcessPage
{
if ($#_ != 0)
{
return($::SUCCESS, ACTINIC::GetPhrase(-1, 12, 'ProcessPage'), undef, undef, undef);
}
my ($nPageNumber) = $_[0];
my @scratch = keys %$::g_pPhaseList;
my $nPhaseCount = $#scratch - 1;
if ($nPageNumber > $nPhaseCount)
{
return($::SUCCESS, ACTINIC::GetPhrase(-1, 146, $nPageNumber, $nPhaseCount), undef, undef, undef);
}
#
# get the phase list for this page
#
my ($sPhaseList) = $$::g_pPhaseList{$nPageNumber};
#
# process each phase in the current block
#
my ($pVarTable, $pDeleteDelimiters, $pKeepDelimiters);
my (@Phases) = split (//, $sPhaseList);
my ($nPhase, $status, $sMessage);
foreach $nPhase (@Phases)
{
if ($nPhase == $::BILLCONTACTPHASE)
{
($pVarTable, $pDeleteDelimiters, $pKeepDelimiters) = DisplayBillContactPhase();
}
elsif ($nPhase == $::SHIPCONTACTPHASE)
{
($pVarTable, $pDeleteDelimiters, $pKeepDelimiters) = DisplayShipContactPhase();
}
elsif ($nPhase == $::SHIPCHARGEPHASE)
{
($status, $sMessage, $pVarTable, $pDeleteDelimiters, $pKeepDelimiters) =
DisplayShipChargePhase();
if ($status != $::SUCCESS) # on error - bail
{
#
# since displaying the shipping charge phase failed, unselect the default
# country since it may change. It may have been erroneously entered.
#
my @Response = ActinicOrder::CallShippingPlugIn(); # get the country
if ($Response[0] == $::SUCCESS && # no errors - use the country
${$Response[2]}{GetCountryDescription} == $::SUCCESS)
{
my $sCountry = $Response[7];
if ($::g_BillContact{COUNTRY} eq $sCountry) # if the bill contact country had been defaulted to the one selected in the preliminary phase
{
undef $::g_BillContact{COUNTRY}; # unselect it
}
if ($::g_ShipContact{COUNTRY} eq $sCountry) # same for the destination country
{
undef $::g_BillContact{COUNTRY};
}
}
return ($status, $sMessage, $pVarTable, $pDeleteDelimiters, $pKeepDelimiters);
}
UpdateCheckoutRecord(); # update the checkout record since the plugin is free to change it
}
elsif ($nPhase == $::TAXCHARGEPHASE)
{
($status, $sMessage, $pVarTable, $pDeleteDelimiters, $pKeepDelimiters) = ActinicOrder::DisplayTaxPhase();
if ($status != $::SUCCESS) # on error - bail
{
return ($status, $sMessage, $pVarTable, $pDeleteDelimiters, $pKeepDelimiters);
}
}
elsif ($nPhase == $::GENERALPHASE)
{
($pVarTable, $pDeleteDelimiters, $pKeepDelimiters) = DisplayGeneralPhase();
}
elsif ($nPhase == $::PAYMENTPHASE)
{
($status, $sMessage, $pVarTable, $pDeleteDelimiters, $pKeepDelimiters) = DisplayPaymentPhase();
if ($status != $::SUCCESS) # on error - bail
{
return ($status, $sMessage, $pVarTable, $pDeleteDelimiters, $pKeepDelimiters);
}
}
elsif ($nPhase == $::COMPLETEPHASE)
{
if (length $::g_PaymentInfo{'METHOD'} == 0) # if the payment method is undefined at this point
{ # it is because the payment information was hidden
EnsurePaymentSelection();
}
my ($ePaymentMethod) = ActinicOrder::PaymentStringToEnum($::g_PaymentInfo{'METHOD'}); # the payment method is stored as "ENUMERATEDID:DESCRIPTION"
#
# complete the order based on the payment method
#
if ($ePaymentMethod == $::PAYMENT_CREDIT_CARD && # if they are paying with a credit card and
$$::g_pSetupBlob{USE_DH} && # Java encryption is enabled and
$$::g_pSetupBlob{OCC} == -1) # we are not in OCC mode
{ # use java encryption
($status, $sMessage, $pVarTable, $pDeleteDelimiters, $pKeepDelimiters) = DisplayApplet();
if ($status != $::SUCCESS) # on error - bail
{
return ($status, $sMessage, $pVarTable, $pDeleteDelimiters, $pKeepDelimiters);
}
}
#
# this is an on-line credit card transaction
#
elsif ($ePaymentMethod == $::PAYMENT_CREDIT_CARD && # if this is a credit card transaction and
$$::g_pSetupBlob{OCC} != -1) # we are in on-line mode
{
#
# call the plug in
#
my (@Response) = CallOCCPlugIn();
#
# of the CC was accepted, there is no UI to display, so continue to the receipt
#
if ($Response[0] == $::ACCEPTED) # card was accepted
{
@Response = CompleteOrder(); # record the order
if ($Response[0] != $::SUCCESS)
{
return(@Response);
}
#
# this call does not return any variables. this causes the next page to be loaded (the receipt)
#
undef %::s_VariableTable;
undef @::s_DeleteDelimiters;
undef @::s_KeepDelimiters;
($pVarTable, $pDeleteDelimiters, $pKeepDelimiters) =
(\%::s_VariableTable, \@::s_DeleteDelimiters, \@::s_KeepDelimiters);
}
#
# the credit card acceptance is pending, record the order and display the plug-in UI so
# it can complete the transaction
#
elsif ($Response[0] == $::PENDING)
{
my ($sHTML) = $Response[2];
@Response = CompleteOrder(); # record the order
if ($Response[0] != $::SUCCESS)
{
return (@Response);
}
#
# display the plug-in UI to complete the transaction
#
ACTINIC::PrintPage($sHTML, undef, $::FALSE);
exit;
}
#
# credit card rejected
#
elsif ($Response[0] == $::REJECTED)
{
#
# display the plug-in error page
#
ACTINIC::PrintPage($Response[2], undef, $::FALSE);
exit;
}
else
{
return (@Response);
}
}
else # use script encryption
{
my (@Response) = CompleteOrder();
if ($Response[0] != $::SUCCESS)
{
return (@Response);
}
#
# this call does not return any variables. this causes the next page to be loaded (the receipt)
#
undef %::s_VariableTable;
undef @::s_DeleteDelimiters;
undef @::s_KeepDelimiters;
($pVarTable, $pDeleteDelimiters, $pKeepDelimiters) =
(\%::s_VariableTable, \@::s_DeleteDelimiters, \@::s_KeepDelimiters);
}
}
elsif ($nPhase == $::RECEIPTPHASE) # here when order is done
{
my ($ePaymentMethod);
if (length $::g_PaymentInfo{METHOD} == 0) # if we used Java encryption, this field is undefined - but should be CC's
{
$ePaymentMethod = $::PAYMENT_CREDIT_CARD; # the : is to help parsing
}
else
{
($ePaymentMethod) = ActinicOrder::PaymentStringToEnum($::g_PaymentInfo{METHOD}); # the payment method is stored as "ENUMERATEDID:DESCRIPTION"
}
#
# If this is a OCC response, record the authorization - we no longer display the reciept at this point
#
if ($ePaymentMethod == $::PAYMENT_CREDIT_CARD &&
$$::g_pSetupBlob{OCC} != -1 &&
$::g_InputHash{'ACTION'} =~ m/AUTHORIZE/i)
{
my $sText;
my $sError = RecordAuthorization();
if (length $sError != 0) # if there were any errors,
{
ACTINIC::RecordErrors($sError, $::g_InputHash{PATH}); # record the error to error.err
$sText = "0" . $sError;
}
else
{
$sText = "1";
}
ACTINIC::PrintText($sText);
#
# processing is complete at this point
#
exit;
}
#
# if this is a request from the applet to record the order, then do it.
#
elsif ($ePaymentMethod == $::PAYMENT_CREDIT_CARD &&
$$::g_pSetupBlob{OCC} == -1 &&
$::g_InputHash{'ACTION'} =~ m/RECORDORDER/i)
{
my $sText;
my $sError = RecordOrder($::g_InputHash{ORDERNUMBER}, \$::g_InputHash{BLOB});
if (length $sError != 0) # if there were any errors,
{
ACTINIC::RecordErrors($sError, $::g_InputHash{PATH}); # record the error to error.err
$sText = "0" . $sError;
}
else
{
$sText = "1";
}
ACTINIC::PrintText($sText);
#
# processing is complete at this point
#
exit;
}
else
{
#
# Display the receipt
#
($status, $sMessage, $pVarTable, $pDeleteDelimiters, $pKeepDelimiters) = DisplayReceiptPhase($::g_InputHash{ORDERNUMBER}, $ePaymentMethod);
if ($status != $::SUCCESS) # on error - bail
{
return ($status, $sMessage, $pVarTable, $pDeleteDelimiters, $pKeepDelimiters);
}
#
# clean up the cart and checkout file
#
my (@ClearResponse);
@ClearResponse = ActinicOrder::ClearFiles($::g_InputHash{PATH}, $::g_sCartId);
if ($ClearResponse[0] != $::SUCCESS) # on error
{
ACTINIC::RecordErrors($ClearResponse[1]); # just record the problem - there is no good way to report it to the customer
}
}
}
elsif ($nPhase == $::PRELIMINARYINFOPHASE)
{
($status, $sMessage, $pVarTable, $pDeleteDelimiters, $pKeepDelimiters) = ActinicOrder::DisplayPreliminaryInfoPhase();
if ($status != $::SUCCESS) # on error - bail
{
return ($status, $sMessage, $pVarTable, $pDeleteDelimiters, $pKeepDelimiters);
}
UpdateCheckoutRecord(); # update the checkout record since the plugin is free to change it
}
my (@Array1, @Array2);
@Array1 = %$pVarTable;
@Array2 = %::s_LargeVariableTable;
push (@Array1, @Array2);
%::s_LargeVariableTable = @Array1;
push (@::s_LargeDeleteDelimiters, @$pDeleteDelimiters);
push (@::s_LargeKeepDelimiters, @$pKeepDelimiters);
#
# now find the bulk of the delimit stats
#
($pDeleteDelimiters, $pKeepDelimiters) = ActinicOrder::ParseDelimiterStatus($nPhase);
push (@::s_LargeDeleteDelimiters, @$pDeleteDelimiters);
push (@::s_LargeKeepDelimiters, @$pKeepDelimiters);
}
return ($::SUCCESS, '', \%::s_LargeVariableTable, \@::s_LargeDeleteDelimiters, \@::s_LargeKeepDelimiters);
}
#######################################################
#
# DisplayBillContactPhase - display the bill contact
# page
#
# Returns: 0 - pointer to variable table
# 1 - pointer to list of delimited regions
# to remove
# 2 - pointer to list of unused delimiters
#
# Affects: %::s_VariableTable, @::s_DeleteDelimiters,
# @::s_KeepDelimiters
#
#######################################################
sub DisplayBillContactPhase
{
undef %::s_VariableTable;
undef @::s_DeleteDelimiters;
undef @::s_KeepDelimiters;
#
# if the phase is done, don't display it
#
if (ActinicOrder::IsPhaseComplete($::BILLCONTACTPHASE) ||
ActinicOrder::IsPhaseHidden($::BILLCONTACTPHASE))
{
push (@::s_DeleteDelimiters, 'INVOICEPHASE');
return (\%::s_VariableTable, \@::s_DeleteDelimiters, \@::s_KeepDelimiters);
}
else
{
push (@::s_KeepDelimiters, 'INVOICEPHASE');
}
#
# if the country is not defined, but the shipping country has been selected, default
# to the shipping country.
#
if (0 == length $::g_BillContact{'COUNTRY'})
{
my @Response = ActinicOrder::CallShippingPlugIn();
if ($Response[0] == $::SUCCESS && # no errors - use the country
${$Response[2]}{GetCountryDescription} == $::SUCCESS)
{
$::g_BillContact{'COUNTRY'} = $Response[7];
}
}
#
# restore the default values from the table
#
$::s_VariableTable{$::VARPREFIX.'INVOICESALUTATION'} = ACTINIC::EncodeText2($::g_BillContact{'SALUTATION'});
$::s_VariableTable{$::VARPREFIX.'INVOICENAME'} = ACTINIC::EncodeText2($::g_BillContact{'NAME'});
$::s_VariableTable{$::VARPREFIX.'INVOICEJOBTITLE'} = ACTINIC::EncodeText2($::g_BillContact{'JOBTITLE'});
$::s_VariableTable{$::VARPREFIX.'INVOICECOMPANY'} = ACTINIC::EncodeText2($::g_BillContact{'COMPANY'});
$::s_VariableTable{$::VARPREFIX.'INVOICEADDRESS1'} = ACTINIC::EncodeText2($::g_BillContact{'ADDRESS1'});
$::s_VariableTable{$::VARPREFIX.'INVOICEADDRESS2'} = ACTINIC::EncodeText2($::g_BillContact{'ADDRESS2'});
$::s_VariableTable{$::VARPREFIX.'INVOICEADDRESS3'} = ACTINIC::EncodeText2($::g_BillContact{'ADDRESS3'});
$::s_VariableTable{$::VARPREFIX.'INVOICEADDRESS4'} = ACTINIC::EncodeText2($::g_BillContact{'ADDRESS4'});
$::s_VariableTable{$::VARPREFIX.'INVOICEPOSTALCODE'} = ACTINIC::EncodeText2($::g_BillContact{'POSTALCODE'});
$::s_VariableTable{$::VARPREFIX.'INVOICECOUNTRY'} = ACTINIC::EncodeText2($::g_BillContact{'COUNTRY'});
$::s_VariableTable{$::VARPREFIX.'INVOICEPHONE'} = ACTINIC::EncodeText2($::g_BillContact{'PHONE'});
$::s_VariableTable{$::VARPREFIX.'INVOICEFAX'} = ACTINIC::EncodeText2($::g_BillContact{'FAX'});
$::s_VariableTable{$::VARPREFIX.'INVOICEEMAIL'} = ACTINIC::EncodeText2($::g_BillContact{'EMAIL'});
$::s_VariableTable{$::VARPREFIX.'INVOICEUSERDEFINED'} = ACTINIC::EncodeText2($::g_BillContact{'USERDEFINED'});
$::s_VariableTable{$::VARPREFIX.'INVOICETITLE'} = ACTINIC::GetPhrase(-1, 147);
#
# handle check boxes
#
if ($::g_BillContact{'MOVING'}) # if the moving check is on, message the data a bit
{
$::s_VariableTable{$::VARPREFIX.'INVOICEMOVINGCHECKSTATUS'} = 'CHECKED';
}
else
{
$::s_VariableTable{$::VARPREFIX.'INVOICEMOVINGCHECKSTATUS'} = '';
}
if ($::g_BillContact{'PRIVACY'}) # if the privacy check is on, message the data a bit
{
$::s_VariableTable{$::VARPREFIX.'INVOICEPRIVACYCHECKSTATUS'} = 'CHECKED';
}
else
{
$::s_VariableTable{$::VARPREFIX.'INVOICEPRIVACYCHECKSTATUS'} = '';
}
if ($::g_BillContact{'SEPARATE'}) # if the ship separate flag is on, turn on the check box
{
$::s_VariableTable{$::VARPREFIX.'INVOICESEPARATECHECKSTATUS'} = 'CHECKED';
}
else
{
$::s_VariableTable{$::VARPREFIX.'INVOICESEPARATECHECKSTATUS'} = '';
}
return (\%::s_VariableTable, \@::s_DeleteDelimiters, \@::s_KeepDelimiters);
}
#######################################################
#
# DisplayShipContactPhase - display the ship contact
# page
#
# Returns: 0 - pointer to variable table
# 1 - pointer to list of delimited regions
# to remove
# 2 - pointer to list of unused delimiters
#
# Affects: %::s_VariableTable, @::s_DeleteDelimiters,
# @::s_KeepDelimiters
#
#######################################################
sub DisplayShipContactPhase
{
undef %::s_VariableTable;
undef @::s_DeleteDelimiters;
undef @::s_KeepDelimiters;
#
# if the phase is done, don't display it
#
if (ActinicOrder::IsPhaseComplete($::SHIPCONTACTPHASE) ||
ActinicOrder::IsPhaseHidden($::SHIPCONTACTPHASE))
{
push (@::s_DeleteDelimiters, 'DELIVERPHASE');
return (\%::s_VariableTable, \@::s_DeleteDelimiters, \@::s_KeepDelimiters);
}
#
# Presnet: start of un-comment
#
elsif (defined $$::g_pSetupBlob{'REVERSE_ADDRESS_CHECK'} && $$::g_pSetupBlob{'REVERSE_ADDRESS_CHECK'})
{
#
# Presnet: handle reversing the meaning of the check box
#
if ($::g_BillContact{'SEPARATE'})
{
push (@::s_DeleteDelimiters, 'DELIVERPHASE');
return (\%::s_VariableTable, \@::s_DeleteDelimiters, \@::s_KeepDelimiters);
}
else
{
push (@::s_KeepDelimiters, 'DELIVERPHASE');
}
}
#
# Presnet: end of un-comment
#
else
{
if (!$::g_BillContact{'SEPARATE'})
{
push (@::s_DeleteDelimiters, 'DELIVERPHASE');
return (\%::s_VariableTable, \@::s_DeleteDelimiters, \@::s_KeepDelimiters);
}
else
{
push (@::s_KeepDelimiters, 'DELIVERPHASE');
}
}
#
# if the country is not defined, but the shipping country has been selected, default
# to the shipping country.
#
if (0 == length $::g_ShipContact{'COUNTRY'})
{
my @Response = ActinicOrder::CallShippingPlugIn();
if ($Response[0] == $::SUCCESS && # no errors - use the country
${$Response[2]}{GetCountryDescription} == $::SUCCESS)
{
$::g_ShipContact{'COUNTRY'} = $Response[7];
}
}
#
# restore the default values from the table
#
$::s_VariableTable{$::VARPREFIX.'DELIVERSALUTATION'} = ACTINIC::EncodeText2($::g_ShipContact{'SALUTATION'});
$::s_VariableTable{$::VARPREFIX.'DELIVERNAME'} = ACTINIC::EncodeText2($::g_ShipContact{'NAME'});
$::s_VariableTable{$::VARPREFIX.'DELIVERJOBTITLE'} = ACTINIC::EncodeText2($::g_ShipContact{'JOBTITLE'});
$::s_VariableTable{$::VARPREFIX.'DELIVERCOMPANY'} = ACTINIC::EncodeText2($::g_ShipContact{'COMPANY'});
$::s_VariableTable{$::VARPREFIX.'DELIVERADDRESS1'} = ACTINIC::EncodeText2($::g_ShipContact{'ADDRESS1'});
$::s_VariableTable{$::VARPREFIX.'DELIVERADDRESS2'} = ACTINIC::EncodeText2($::g_ShipContact{'ADDRESS2'});
$::s_VariableTable{$::VARPREFIX.'DELIVERADDRESS3'} = ACTINIC::EncodeText2($::g_ShipContact{'ADDRESS3'});
$::s_VariableTable{$::VARPREFIX.'DELIVERADDRESS4'} = ACTINIC::EncodeText2($::g_ShipContact{'ADDRESS4'});
$::s_VariableTable{$::VARPREFIX.'DELIVERPOSTALCODE'} = ACTINIC::EncodeText2($::g_ShipContact{'POSTALCODE'});
$::s_VariableTable{$::VARPREFIX.'DELIVERCOUNTRY'} = ACTINIC::EncodeText2($::g_ShipContact{'COUNTRY'});
$::s_VariableTable{$::VARPREFIX.'DELIVERPHONE'} = ACTINIC::EncodeText2($::g_ShipContact{'PHONE'});
$::s_VariableTable{$::VARPREFIX.'DELIVERFAX'} = ACTINIC::EncodeText2($::g_ShipContact{'FAX'});
$::s_VariableTable{$::VARPREFIX.'DELIVEREMAIL'} = ACTINIC::EncodeText2($::g_ShipContact{'EMAIL'});
$::s_VariableTable{$::VARPREFIX.'DELIVERUSERDEFINED'} = ACTINIC::EncodeText2($::g_ShipContact{'USERDEFINED'});
$::s_VariableTable{$::VARPREFIX.'DELIVERTITLE'} = ACTINIC::GetPhrase(-1, 148);
return (\%::s_VariableTable, \@::s_DeleteDelimiters, \@::s_KeepDelimiters);
}
#######################################################
#
# DisplayShipChargePhase - display the ship charge
# page
#
# Returns: 0 - status
# 1 - error if any
# 2 - pointer to variable table
# 3 - pointer to list of delimited regions
# to remove
# 4 - pointer to list of unused delimiters
#
# Affects: %s_::s_VariableTable, @::s_DeleteDelimiters,
# @::s_KeepDelimiters
#
#######################################################
sub DisplayShipChargePhase
{
undef %::s_VariableTable;
undef @::s_DeleteDelimiters;
undef @::s_KeepDelimiters;
#
# if the phase is done, don't display it
#
if (ActinicOrder::IsPhaseComplete($::SHIPCHARGEPHASE) || # the shipping is already completed or
ActinicOrder::IsPhaseHidden($::SHIPCHARGEPHASE)) # is hidden
{
push (@::s_DeleteDelimiters, 'SHIPANDHANDLEPHASE'); # hide the shipping stuff
return ($::SUCCESS, '', \%::s_VariableTable, \@::s_DeleteDelimiters, \@::s_KeepDelimiters);
}
else
{
push (@::s_KeepDelimiters, 'SHIPANDHANDLEPHASE');
}
#
# restore the advanced shipping settings
#
if ($$::g_pSetupBlob{MAKE_SHIPPING_CHARGE})
{
my @Response = ActinicOrder::CallShippingPlugIn();
if ($Response[0] != $::SUCCESS)
{
return (@Response);
}
elsif (${$Response[2]}{RestoreFinalUI} != $::SUCCESS)
{
return (${$Response[2]}{RestoreFinalUI}, ${$Response[3]}{RestoreFinalUI});
}
%::s_VariableTable = %{$Response[10]};# save the var table
}
$::s_VariableTable{$::VARPREFIX.'SHIPUSERDEFINED'} = ACTINIC::EncodeText2($::g_ShipInfo{'USERDEFINED'});
return ($::SUCCESS, '', \%::s_VariableTable, \@::s_DeleteDelimiters, \@::s_KeepDelimiters);
}
#######################################################
#
# DisplayGeneralPhase - display the ship charge
# page
#
# Returns: 0 - pointer to variable table
# 1 - pointer to list of delimited regions
# to remove
# 2 - pointer to list of unused delimiters
#
# Affects: %s_::s_VariableTable, @::s_DeleteDelimiters,
# @::s_KeepDelimiters
#
#######################################################
sub DisplayGeneralPhase
{
undef %::s_VariableTable;
undef @::s_DeleteDelimiters;
undef @::s_KeepDelimiters;
#
# if the phase is done, don't display it
#
if (ActinicOrder::IsPhaseComplete($::GENERALPHASE) ||
ActinicOrder::IsPhaseHidden($::GENERALPHASE))
{
push (@::s_DeleteDelimiters, 'GENERALPHASE');
return (\%::s_VariableTable, \@::s_DeleteDelimiters, \@::s_KeepDelimiters);
}
else
{
push (@::s_KeepDelimiters, 'GENERALPHASE');
}
#
# restore the default values from the table
#
$::s_VariableTable{$::VARPREFIX.'GENERALHOWFOUND'} = ACTINIC::EncodeText2($::g_GeneralInfo{'HOWFOUND'});
$::s_VariableTable{$::VARPREFIX.'GENERALWHYBUY'} = ACTINIC::EncodeText2($::g_GeneralInfo{'WHYBUY'});
$::s_VariableTable{$::VARPREFIX.'GENERALUSERDEFINED'} = ACTINIC::EncodeText2($::g_GeneralInfo{'USERDEFINED'});
$::s_VariableTable{$::VARPREFIX.'GENERALTITLE'} = ACTINIC::GetPhrase(-1, 151);
return (\%::s_VariableTable, \@::s_DeleteDelimiters, \@::s_KeepDelimiters);
}
#######################################################
#
# DisplayPaymentPhase - display the ship charge
# page
#
# Returns: 0 - status
# 1 - error if any
# 2 - pointer to variable table
# 3 - pointer to list of delimited regions
# to remove
# 4 - pointer to list of unused delimiters
#
# Affects: %s_::s_VariableTable, @::s_DeleteDelimiters,
# @::s_KeepDelimiters
#
#######################################################
sub DisplayPaymentPhase
{
undef %::s_VariableTable;
undef @::s_DeleteDelimiters;
undef @::s_KeepDelimiters;
#
# if the phase is done, don't display it
#
if (ActinicOrder::IsPhaseComplete($::PAYMENTPHASE) ||
ActinicOrder::IsPhaseHidden($::PAYMENTPHASE))
{
push (@::s_DeleteDelimiters, 'PAYMENTPHASE');
return ($::SUCCESS, '', \%::s_VariableTable, \@::s_DeleteDelimiters, \@::s_KeepDelimiters);
}
my ($Status, $Message, $pCartList, @Response);
@Response = ActinicOrder::ReadCart($::g_sCartId, $::g_InputHash{'PATH'}); # read the shopping cart
($Status, $Message, $pCartList) = @Response;
if ($Status != $::SUCCESS) # general error
{
return (@Response);
}
my (@SummaryResponse, $nTotal);
@SummaryResponse = ActinicOrder::SummarizeOrder($pCartList); # get the real order total
if ($SummaryResponse[0] != $::SUCCESS) # if we were successful
{
return (@SummaryResponse);
}
$nTotal = $SummaryResponse[6];
#
# 1) If (total == 0 || prices are off)
# If (user defined field is hidden)
#
# mark payment complete
# mark method pre-pay
# skip processing
#
# else If (user defined is not hidden)
#
# mark method pre-pay
# hide payment stuff
#
my ($bPaymentHidden) = ($nTotal == 0 || !$$::g_pSetupBlob{'PRICES_DISPLAYED'});
if ($bPaymentHidden)
{
EnsurePaymentSelection();
}
if ( $bPaymentHidden && # there are no prompts in this phase,
ACTINIC::IsPromptHidden(5, 7)) # skip it
{
push (@::s_DeleteDelimiters, 'PAYMENTPHASE');
return ($::SUCCESS, '', \%::s_VariableTable, \@::s_DeleteDelimiters, \@::s_KeepDelimiters);
}
else # if we've made it this far, the phase is here to stay
{
push (@::s_KeepDelimiters, 'PAYMENTPHASE');
}
#
# restore the default values from the table
#
$::s_VariableTable{$::VARPREFIX.'PAYMENTUSERDEFINED'} = ACTINIC::EncodeText2($::g_PaymentInfo{'USERDEFINED'});
$::s_VariableTable{$::VARPREFIX.'PAYMENTPONO'} = ACTINIC::EncodeText2($::g_PaymentInfo{'PONO'});
#
# add the CC info if it exists
#
$::s_VariableTable{$::VARPREFIX.'PAYMENTCARDNUMBER'} = ACTINIC::EncodeText2($::g_PaymentInfo{'CARDNUMBER'});
$::s_VariableTable{$::VARPREFIX.'PAYMENTCARDISSUE'} = ACTINIC::EncodeText2($::g_PaymentInfo{'CARDISSUE'});
#
# add the CC dates
#
my ($sec, $min, $hour, $mday, $mon, $year, $wday, $yday, $isdst, $sDate);
($sec, $min, $hour, $mday, $mon, $year, $wday, $yday, $isdst) = localtime(time); # platform independent time
$mon++; # make month 1 based
$year += 1900; # make year AD based
my ($nYear, $nMonth);
for ($nMonth = 1; $nMonth < 13; $nMonth++) # first process the months
{
#
# populate the start date month field
#
if ($::g_PaymentInfo{'STARTMONTH'} eq '' && # if there is no pre-defined date
$nMonth == $mon) # use the current month as the default value
{
$::s_VariableTable{$::VARPREFIX.'PAYMENTSTARTMONTHS'} .= '