Akopia Akopia Services

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

[ic] Updated Signio globalsub for PayflowPro Version 3.0 - DONE




Attached you will find the updated globalsub for Verisign's PayflowPro
verision 3.0.  This sub is also upgraded to work with Interchange 4.7.5.
In the sub I've documented my changes.  In short, I moved the variables
into the variable.txt file.  Plus, with the new version of PayflowPro some
additonal variables were added.  I'm sure it could use some more tweeking
if someone else would like to look at it and add to it.  

Michelle
michelle@wilant.com
# This is how you can use Verisign's PayflowPro (version 3.0) with Interchange.
# 
Variable SIGNIO_HELP <<EOV

 1. Modify interchange.cfg to use this file.
 
 #include globalsub/signio (your path to this signio file)  
	(with interchange 4.7 and above may be with (ConfigParseComments Yes) 
	or without # sign in front (ConfigParseComments No))

 2. Modify CATROOT/products/variable.txt to set the server and your PayflowPro (signio) account info

 Variable MV_PAYMENT_ID			YourPayflowProID (you create with verisign)
 Variable MV_PAYMENT_SECRET  		YourPayflowProPassword (you create with verisign)
 Variable MV_PAYMENT_SERVER  		payflow.verisign.com
 					# Use test-payflow.verisign.com for testing
 Variable MV_PAYMENT_VENDOR  		YourPayflowProVendor (or YourPayflowProID)
 Variable MV_PAYMENT_PARTNER 		YourPayflowProPartner (verisign provides)
 Variable MV_PAYMENT_MODE    		signio
 Variable MV_PAYMENT_TRANS_TYPE 	Transaction type (look at list below)
	Transaction Types:
                        sale  			S
                        credit     		C
                        authorization   	A
                        delayed capture 	D
                        void         		V
                        voice authorization     F
			inqury			I

 Variable MV_PAYMENT_PFPRO_AVS     	Y or N - Should AVS be used for U.S. Card holders
 Variable MV_PAYMENT_TENDER_TYPE 	C for credit - look in Payflow Pro's docs for others

 Variable MV_PAYMENT_PFPRO_CERT_PATH	Path to the cert that came with your download of Payflow Pro
 Variable MV_PAYMENT_PFPRO_EXE_PATH	Path to the pfpro executable
 Variable MV_PAYMENT_PFPRO_PORT		Port for pfpro - usually 443
 Variable MV_PAYMENT_PRECISION 		how many digits do you want after the decimal for the dollar amount - US=2

 3. Set CreditCardAuto is off (default) in the catalog.cfg file
	If not there add:
 CreditCardAuto no
 
 4. set subroutine in CATROOT/etc/profiles.order
	replace &charge=[var MV_PAYMENT_MODE][cgi mv_payment_test]
    with
	&charge=signio

 6. Restart Interchange.

 7. Strongly suggest to use the logDebug function to help with testing.  In interchange.cfg set Variable DEBUG to 1 then
	set DebugFile to where you want the output to go.  Default is /tmp/icdebug. Then uncomment the needed logDebugs
	below.

Changes:
	- PayflowPro 3.0 requires additonal values to be passed.  These are:  partner and vendor. 
		SOLUTION:  Added MV_PAYMENT_VENDOR and MV_PAYMENT_PARTNER to the catalog.cfg file.  
	- The use of a cert (included with PayflowPro) is also required.
		SOLUTION:  set variable in variable.txt to where the cert is located
	- Also added function to combine address1 or badddress1 for submission to PayflowPro as ADDRESS.
	- Also added AVS fuctionality as an option for submission for US customers. 
		NOTE:  AVS RESPONSE IS NOT USED IN THIS SCRIPT 
			- that functionality needs to be added for how you want to use the AVS response.
	- Updated the TRXTYPE codes below to PayfloPro's listing:
                        sale  			S
                        credit     		C
                        authorization   	A
                        delayed capture 	D
                        void         		V
                        voice authorization     F
			inquiry			I

	- Placed all variables in the variable.txt file.

*ANY ADDITONS/ROBUSTIFING/CLEANUP is greatly appreciated.
michelle\@wilant.com  
EOV
GlobalSub <<EOS
sub signio {

#::logDebug("\n\n***********\npayflow pro subroutine called - logDebug");
    my ($user, $secret, $amount, $vendor, 
	$partner, $exe, $cert, $mode, $trans_type, 
	$avs, $tender_type, $server,
	$precision, $port, $acct) = @_;
    $user = "";
    my %query = "";
	
    my (%actual) = Vend::Order::map_actual();

    if(! $user ) {
        $user    =  $::Variable->{MV_PAYMENT_ID}
                    or return undef;
    }
#::logDebug("pfpro user $user");
    if(! $secret ) {
        $secret  =  $::Variable->{MV_PAYMENT_SECRET}
                    or return undef;
    }
    if(! $server ) {
    	$server  =   $::Variable->{MV_PAYMENT_SERVER}
                    or return undef;
    }
    if(! $vendor ) {
        $vendor  =  $::Variable->{MV_PAYMENT_VENDOR}
                    or return undef;
    }
    if(! $partner ) {
        $partner  =  $::Variable->{MV_PAYMENT_PARTNER}
                     or return undef;
    }
    if(! $mode ) {
        $mode    =  $::Variable->{MV_PAYMENT_MODE}
                    or return undef;
    }
#::logDebug("pfpro payment mode $mode");
    if(! $tender_type ) {
        $tender_type    =  $::Variable->{MV_PAYMENT_TENDER_TYPE}
	                    or return undef;
    }
#::logDebug("pfpro tender type $tender_type");
    if(! $trans_type ) {
        $trans_type    =  $::Variable->{MV_PAYMENT_TRANS_TYPE}
        	            or return undef;
    }
#::logDebug("pfpro transaction type $trans_type");
    if(! $avs ) {
        $avs    =  $::Variable->{MV_PAYMENT_PFPRO_AVS}
                    or return undef;
    }
#::logDebug("pfpro avs being used: $avs");
    $ENV{"PFPRO_CERT_PATH"} = $::Variable->{MV_PAYMENT_PFPRO_CERT_PATH}
	or return undef;
#::logDebug("path for pfpro cert: $ENV{\"PFPRO_CERT_PATH\"}");
    if(! $exe ) {
        $exe    =  $::Variable->{MV_PAYMENT_PFPRO_EXE_PATH}
                    or return undef;
    }
#::logDebug("path for pfpro executable: $exe");
    if (! $port) {
	$port    =   $::Variable->{MV_PAYMENT_PFPRO_PORT}
                     or return undef;
    }
#::logDebug("port: $port");
    if (! $precision ){
    	$precision = $::Variable->{MV_PAYMENT_PRECISION}
                     or return undef;
    }
#::logDebug("precision: $precision");

    $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};

    my %type_map = (
        qw/
                        sale                    S
                        credit                  C
                        authorization           A
                        delayed_capture         D
                        void                    V
                        voice_authorization     F
			inqury			I
                        S                       S
                        C                       C
                        A                       A
                        D                       D
                        V                       V
                        F                       F
			I			I
        /
    );


    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 Interchange 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 %varmap = ( qw/
                            ACCT     mv_credit_card_number
                            ZIP      zip
                            STREET   address
                            STREET1  address1
                            STREET2  address2
                            BSTREET1 b_address1
                            BSTREET2 b_address2
                            COUNTRY  country
        /
    );


    my %query = (
                    USER        => $user,
                    VENDOR      => $vendor,
                    PARTNER     => $partner,
                    AMT         => $amount,
                    EXPDATE     => $exp,
                    TENDER      => $tender_type,
                    ORIGID      => $orderID,
                    PWD         => $secret,
                    TRXTYPE     => $trans_type
    );
	 


    if($avs eq "Y" && $actual{$varmap{'COUNTRY'}} eq "US"){
	if($actual{$varmap{'BSTREET1'}} ne ""){
        	$actual{$varmap{'STREET'}} = $actual{$varmap{'BSTREET1'}};
	}elsif($actual{$varmap{'STREET1'}} ne ""){
        	$actual{$varmap{'STREET'}} = $actual{$varmap{'STREET1'}};
        }
#::logDebug(qq{AVS LOOP WORKS\n});
    	for (keys %varmap) {
        	if($_ eq "STREET1"||$_ eq "STREET2"||$_ eq "BSTREET1"||$_ eq "BSTREET2"||$_ eq "COUNTRY"){
                	next;
        	}else{
                	$query{$_} = $actual{$varmap{$_}};
#::logDebug(qq{*$query{$_} = $actual{$varmap{$_}}\n});
        	}
    	}
     }else{
#::logDebug(qq{NON-AVS LOOP WORKS\n});
	for (keys %varmap) {
        	if($_ eq "STREET1"||$_ eq "STREET2"||$_ eq "BSTREET1"||$_ eq "BSTREET2"||
			$_ eq "STREET"||$_ eq "ZIP"||$_ eq "COUNTRY"){
                	next;
        	}else{
                	$query{$_} = $actual{$varmap{$_}};
#::logDebug(qq{*$query{$_} = $actual{$varmap{$_}}\n});
        	}
    	}
     }


     my @query;

    for (keys %query) {
        my $key = $_;
        my $val = $query{$key};
        $val =~ s/["\$\n\r]//g;
        $val =~ s/\$//g;
        $val =~ tr/ /+/;
        my $len = length($val);
        if($val =~ /[&=]/) {
            $key .= "[$len]";
	}
        push @query, "$key=$val";
#::logDebug("***\$key=$val\n");
    }
    my $string = join '&', @query;
#::logDebug(qq{***pfprosub call: $exe $server $port "$string" |\n});
    open(CONNECT, qq{$exe $server $port "$string" |})
    or die "can't fork: $!\n";
    my $msg = undef;

    local($/);
    my $result = <CONNECT>;
#::logDebug(qq{*** my $result = <CONNECT>\n\n});
    close CONNECT;

    my $decline = $?;

#::logDebug(qq{signio decline = $decline\n result: $result\n});

    my %result_map = ( qw/

            MStatus               RESULT
            pop.status            RESULT
            MErrMsg               RESPMSG
            pop.error-message     RESPMSG
            order-id              PNREF
            pop.order-id          PNREF
            pop.auth-code         AUTHCODE
            pop.avs_code          AVSZIP
            pop.avs_zip           AVSZIP
            pop.avs_addr          AVSADDR
            pop.cvv2match         CVV2MATCH
    /
    );

    my %result = split /[&=]/, $result;

    for (keys %result_map) {
        $result{$_} = $result{$result_map{$_}}
            if defined $result{$result_map{$_}};
#::logDebug(qq{ $_=$result{$result_map{$_}}\n});
    }

    $Vend::Session->{payment_result} = \%result;
#::logDebug(qq{payment_result:  $Vend::Session->{payment_result}\n}):

    delete $Vend::Session->{payment_error};
#::logDebug(qq{payment_error: $Vend::Session->{payment_error}\n});

    if ($decline) {
        $decline = $decline >> 8;
        $result{'pop.status'} =
        $result{'MStatus'} = 'failed';
#::logDebug(qq{decline = $decline\n});

        $Vend::Session->{payment_error} = $result{RESPMSG};
#::logDebug(qq{result{respmsg} = $result{RESPMSG}\n});

	my $msg = errmsg("Payment error: " . $result{RESULT} . " " . $result{RESPMSG} ." ". "Please call in your order or try again.");
#::logDebug(qq{$msg\n});
	$Vend::Session->{errors}{mv_credit_card_valid} = $msg;
    }else {
        $result{'pop.status'} =
        $result{'MStatus'} = 'success';

        $Vend::Session->{payment_id} = $result{'pop.order-id'};

        $Vend::Session->{payment_error} = $result{RESPMSG};
    }

#::logDebug(qq{signio decline=$decline result:\n } . ::uneval( \%result));

    return %result;

}
EOS

Search for: Match: Format: Sort by: