Akopia Akopia Services

[Date Prev][Date Next][Thread Prev][Thread Next][Minivend by date ][Minivend by thread ]

[mv] code submission: authorize.net global sub




Hello,

  I'd like to redeem myself after asking you all a number of pesky
questions today. :) 
Just a bit ago I finished and tested a globalsub for minivend 4.x that
adds authorizenet compatibility. Some brief documentation is included
with it. 
  I had it very close a while ago, but recently Paul Delys nudged me
over the edge by seeing a detail that I was missing. We were both
excited that we solved our job a little faster. I call this a success
for open source software. :)
  Thanks to Mike Heins for making a interface to credit card processors
that was fairly easy to plug into. 
  Some barebones documentation is included inside the document to get
you started. 

Good luck and have fun!

   -mark

  <<-------------------------------------------------------------->>
personal website                <    Summersault Website Design
   http://mark.stosberg.com/     >       http://www.summersault.com/
# Connection routine for AuthorizeNet version 3 using the 'ADC Direct Response' method.
# by mark@summersault.com with code reused and inspired by 
#	Mike Heins <mike@minivend.com>
#	webmaster@nameastar.net
#   Jeff Nappi <brage@cyberhighway.net>
#   Paul Delys <paul@gi.alaska.edu>

Variable AUTHORIZENET_HELP <<EOV

 1. Modify minivend.cfg to use this file.
 
	#include globalsub/authorizenet

 2. Modify catalog.cfg to set the server and your Authorize.Net account info

 # Username and password
 Variable MV_PAYMENT_ID      YourAuthorizeNetID
 Variable MV_PAYMENT_SECRET  YourAuthorizeNetPassword
 Variable MV_PAYMENT_MODE    custom authorizenet
 Variable MV_PAYMENT_REFERER A valid referering url (match this with your setting on secure.authorize.net
 
 3. Make sure CreditCardAuto is off (default in MV4)

 4. Restart Minivend.

EOV

GlobalSub <<EOS
sub authorizenet {
	my ($user, $secret, $amount) = @_;
	 
	my (%actual) = Vend::Order::map_actual();
	 
	if (! $user ) {
		$user    =  $::Variable->{MV_PAYMENT_ID} ||
                    $::Variable->{CYBER_ID}
                    or return undef;
	}
	
	if(! $secret) {
        $secret  =  $::Variable->{MV_PAYMENT_SECRET} ||
                    $::Variable->{CYBER_SECRET}
                    or return undef;
    }
    
    my $server  =   $::Variable->{MV_PAYMENT_SERVER} ||
                    $::Variable->{CYBER_SERVER} ||
                    'secure.authorize.net';
                    
    my $script 	=   $::Variable->{MV_PAYMENT_SCRIPT} ||
                    $::Variable->{CYBER_SCRIPT} ||
                    '/gateway/transact.dll';
                    
    my $port    =   $::Variable->{MV_PAYMENT_PORT} ||
                    $::Variable->{CYBER_PORT} ||
                    443;
                    
	my $precision = $::Variable->{MV_PAYMENT_PRECISION} ||
                    $::Variable->{CYBER_PRECISION} ||
                    2;
	my $referer   = $::Variable->{MV_PAYMENT_REFERER};                    
                                        
	$actual{mv_credit_card_exp_month} =~ s/\D//g;
    $actual{mv_credit_card_exp_month} =~ s/^0+//;
    $actual{mv_credit_card_exp_year} =~ s/\D//g;
    $actual{mv_credit_card_exp_year} =~ s/\d\d(\d\d)/$1/;

    $actual{mv_credit_card_number} =~ s/\D//g;

    my $exp = sprintf '%02d%02d',
                        $actual{mv_credit_card_exp_month},
                        $actual{mv_credit_card_exp_year};                    
                        
	 $actual{cyber_mode} = 'AUTH_CAPTURE'
        unless $actual{cyber_mode};
	
	my %type_map = (
		mauth_capture 			=>	'AUTH_CAPTURE',
		mauthonly				=>	'AUTH_ONLY',
		CAPTURE_ONLY			=>  'CAPTURE_ONLY',
		CREDIT					=>	'CREDIT',
		VOID					=>	'VOID',
		PRIOR_AUTH_CAPTURE		=>	'PRIOR_AUTH_CAPTURE',

	);                       
	
	if (defined $type_map{$actual{cyber_mode}}) {
        $actual{cyber_mode} = $type_map{$actual{cyber_mode}};
    }
    else {
        $actual{cyber_mode} = 'AUTH_CAPTURE';
    }

    if(! $amount) {
        $amount = Vend::Interpolate::total_cost();
        $amount = sprintf("%.${precision}f", $amount);
    } 
    
    my($orderID);
    my($sec,$min,$hour,$mday,$mon,$year,$wday,$yday,$isdst) = gmtime(time());

    # We'll make an order ID based on date, time, and MiniVend session

    # $mon is the month index where Jan=0 and Dec=11, so we use
    # $mon+1 to get the more familiar Jan=1 and Dec=12
    $orderID = sprintf("%02d%02d%02d%02d%02d%05d%s",
            $year + 1900,$mon + 1,$mday,$hour,$min,$Vend::SessionName);
            
    my %query = (
                    x_Card_Num			=> $actual{mv_credit_card_number},
                    x_Zip				=> $actual{zip},
                    x_Address			=> $actual{address},
                    x_Type				=> $actual{mv_payment_mode},
                    x_Amount    		=> $amount,
                    x_Exp_Date  		=> $exp,
                    x_Method    		=> 'CC',
                    x_Invoice_Num      	=> $orderID,
                    x_Password  		=> $secret,
                    x_Login     		=> $user,
                    x_Version   		=> '3.0',
                    x_ADC_URL   		=> 'FALSE',
                    x_ADC_Delim_Data	=> 'TRUE',


    );
    
    my @query;

    for (keys %query) {
        my $key = $_;
        my $val = $query{$key};
        $val =~ s/["\$\n\r]//g;
        $val =~ s/\$//g;
        my $len = length($val);
        if($val =~ /[&=]/) {
            $key .= "[$len]";
        }
        push @query, "$key=$val";
    }
    my $string = join '&', @query;
    
    use Net::SSLeay qw(post_https make_form make_headers);
    
    my ($page, $response, %reply_headers)
                = post_https($server, $port, $script, 
                	   make_headers( Referer => $referer), 
                       make_form(
                               %query
                       ));
	
    # Minivend names are on the  left, Authorize.Net on the right
    my %result_map = ( qw/
            MStatus               x_response_code
            pop.status            x_response_code
            MErrMsg               x_response_reason_text
            pop.error-message     x_response_reason_text
            order-id              x_trans_id
            pop.order-id          x_trans_id
            pop.auth-code         x_auth_code
            pop.avs_code          x_avs_code
            pop.avs_zip           x_zip
            pop.avs_addr          x_address
    /
    );          
    

#::logError(qq{\nauthorizenet page: $page response: $response\n}); 

    my ($response_code,
    	$response_subcode,
    	$response_reason_code,
    	$response_reason_text,
    	$auth_code,
    	$avs_code,
    	$trans_id) = split (/,/,$page);
    	
#::logError(qq{authorizenet response_reason_text=$response_reason_text response_code: $response_code});    	

    my %result;
    if ($response_code == 1) {
    	$result{MStatus} = 'success';
    	$result{'order-id'} = 1; # ? Why this this set to 1? -mark
    } else {
    	$result{MStatus} = 'failure';

		# NOTE: A lot more AVS codes could be checked for here. 
    	if ($avs_code eq 'N') {
    		$result{MErrMsg} = "You must enter the correct billing address of your credit card. The bank returned the following error: " . $response_reason_text;
    	} else {
    		$result{MErrMsg} = "$response_reason_text"
    	}
    }
    
    return (%result);

}
EOS

Search for: Match: Format: Sort by: