#!/usr/bin/perl

=head1 NAME

CCLib.pm -- Compatibility module for AUTHORIZE.NET and CyberCash version 2

=cut

package CCLib;

use Net::SSLeay;
use Carp;
use Exporter;
@EXPORT = qw/ SetServer sendmserver /;

use POSIX qw/tmpnam/;
$VERSION = '0.03';

use vars qw/$VERSION/;

my $Port   = 443;
my $Server = 'www.authorize.net';
my $Path   = '/scripts/authnet25/AuthRequest.asp';
my $Password;
my $VendorID;
my $Reqavs;

=head1 VERSION

0.04

=head1 SYNOPSIS

#not used for minivend :)

use CCLib;

SetServer( 
            host     => 'www.authorize.net',
            port     => '443',                    
            secret   => 'test',                 
            vendor   => 'test',                  
            );

my $mode = 'mauthonly' || 'mauthcapture';

    %result = sendmserver(
            $actual{cyber_mode},
            'Order-ID'     => $orderID,
            'Amount'       => $amount,
            'Card-Number'  => $actual{mv_credit_card_number}

            'Card-Name'    => $actual{b_name},
            'Card-Address' => $actual{b_address},
            'Card-City'    => $actual{b_city},
            'Card-State'   => $actual{b_state},
            'Card-Zip'     => $actual{b_zip},
            'Card-Country' => $actual{b_country},
            'Card-Exp'     => $exp,
            );
    if($result{MStatus} !~ /^success/) {
        $error = $result{MErrMsg};
        return undef;
    }
    else {
        return 1;
    }
=head1 PREREQUISITES

This package requires the Net::SSLeay perl library which requires the 
SSLeay or OpenSSL package as well.

You can download these packages from http://phear.cyberhighway.net/minivend,
These packages are guarenteed to work with this library but may not be
the most recent versions.


=head1 DESCRIPTION

This module interfaces Authorize.net servers to software
designed for CyberCash 2. It is also quite suitable for standalone use
with Perl.

This module was designed to work with MiniVend, so if you see
references to $Vend::Cfg that is the reason. You may ignore
those references; they should not cause problems.

If you want to set your Vendor ID in the environment, use 
$ENV{AUTHORIZENET_VENDORID}.

=head2 Example of use with MiniVend

Set the following variables in catalog.cfg:

    # the authorize.net host
    Variable CYBER_HOST   www.authorize.net

    # the authorize.net port, defaults to 443
    #Variable CYBER_PORT   443

    # your password
    Variable CYBER_VENDOR vendor_login

    # your password
    Variable CYBER_SECRET vendor_passwd
 
    # Do you want to deny transactions with an AVS mismatch?
    Variable CYBER_AVS TRUE/FALSE

You can set your mv_cyber_mode variable to any valid Authorize.net
transaction type, or to the CyberCash:

    CyberCash       AuthorizeNet
    ------------------------------
    mauthonly           AO
    mauthcapture        NA

=head1 AUTHOR

Jeff Nappi, Cyberhighway Internet Services <brage@cyberhighway.net>

Based on paymentnet CyberCash 2 interface by Mike Heins of
Internet Robotics <mikeh@minivend.com>

=head1 BUGS

Doesn't capture and log approval. That would be easy to add.

=cut

sub SetServer {
        my (%hash) = @_;
        $Server = $hash{'host'}
                    if  $hash{'host'} and
                        $hash{'host'} ne 'localhost';
        $Port   = $hash{'port'}
                    if  $hash{'port'} and
                    $hash{'port'} ne '8000';
        $Password = $hash{'secret'}
                    if $hash{'secret'};

        if ($hash{'vendor'}) {
            $VendorID = $hash{'vendor'};
        }
        elsif($ENV{AUTHORIZENET_VENDORID}) {
            $VendorID = $ENV{AUTHORIZENET_VENDORID};
        }
        elsif(  defined $Vend::Cfg and
                ref     $Vend::Cfg->{Variable} and 
                $Vend::Cfg->{Variable}{CYBER_VENDOR}
                )
        {
            $VendorID = $Vend::Cfg->{Variable}{CYBER_VENDOR};
        }
        else {
            carp "No vendor id assigned.\n";
            $VendorID = 'test';
        }

   return 1;
}

my %mode_translate = ( qw/
                        NA NA
                        AO AO
                        CR CR
                        PA PA
                        mauthonly       AO
                        mauthcapture    NA
                        authonly        AO
                        authcapture     NA
                        / );

sub sendmserver {
        my $mode = shift;
        my %opt = @_;

if ($Vend::Cfg->{Variable}{CYBER_AVS} =~ "TRUE")
  {
    $Reqavs = "TRUE";
  } else {
    $Reqavs = "FALSE";
  }

my $debug = "mode=$mode\n";
for(keys %opt) {
    $debug .= "$_=$opt{$_}\n";
}

        my (@err_parms);
        unless( $Server && $Password && $VendorID && $Port ) {
            @err_parms = ( 'MStatus' , 'error_before_connect', 'MErrMsg' );
            my $err = '';
            $err .= "No server set.\n" unless $Server;
            $err .= "No password given.\n" unless $Password;
            $err .= "No port set.\n" unless $Port;
            $err .= "No Vendor ID given.\n" unless $VendorID;
            push @err_parms, $err;
            return(@err_parms);
        }

        $opt{'Card-Number'} =~ tr/0-9//cd;
        $opt{'Card-Exp'} =~ tr/0-9//cd;
        $opt{'Card-Exp'} = "0" .  $opt{'Card-Exp'}
            if length   $opt{'Card-Exp'} < 4;
        $opt{'Amount'} =~ tr/.0-9//cd;
        unless ($mode_translate{$mode}) {
            @err_parms = ('MStatus', 'error_before_connect',
                            'MErrMsg', 'No mode set.');
            return(@err_parms);
        }
         my ($page,$server_response,%headers,$response,
             $authcode,$text,$avs,$transid);

#Call Net::SSLeay::post_https
#function and read back data.
#########################

	 ($page, $server_response, %headers)
         = &Net::SSLeay::post_https($Server, $Port, $Path, '',
                &Net::SSLeay::make_form(
                        'TESTREQUEST'   => 'FALSE',
                        'LOGIN'         => $VendorID,
                        'PASSWORD'      => $Password,
                        'AMOUNT'        => $opt{'Amount'},
                        'METHOD'        => $CGI::values{METHOD},
                        'TYPE'          => $mode_translate{$mode},
                        'CARDNUM'       => $opt{'Card-Number'},
                        'EXPDATE'       => $opt{'Card-Exp'},
                        'NAME'          => $opt{'Card-Name'},
                        'ADDRESS'       => $opt{'Card-Address'},
                        'CITY'          => $opt{'Card-City'},
                        'STATE'         => $opt{'Card-State'},
                        'ZIP'           => $opt{'Card-Zip'},
                        'COUNTRY'       => $opt{'Card-Country'},
                        'REJECTAVSMISMATCH' => $Reqavs));

        ($response,$authcode,$text,$avs,$transid) = split (/,/,$page);
        my %result;
        if ($response eq 'A' || $reponse eq 'P')
         {
            $result{MStatus} = 'success';
            $result{'order-id'} = 1;
         } else {
            $result{MStatus} = 'failure';
            if (grep(/AVS/, $text))
              {
                $result{MErrMsg} = "You must enter the correct billing address of your credit card. The bank returned the following error: " . $text;
              } else {
                $result{MErrMsg} = $text;
              }
        }
  return (%result);
}
1;
