[Date Prev][Date Next][Thread Prev][Thread Next][Minivend by date
][Minivend by thread
]
re: Payment Net (signio) Pains!! but IT WORKS!
Well after getting nowhere I finally decided to rewrite CCLib.pm to use the most
recect auth program from signio (pfpro).
Attached is my new updated CCLib.pm with some hacks in it based on signio's test.cgi
script.
You need the signio exe from their website. Download and tuck this away in the minivend
directory or anywhere.
Besides the documented parameters you should define
Variable CYBER_EXECUTABLE /path/to/pfpro
CYBER_EXECUTABLE is refernced in CCLib.pm, but appears NO WHERE in the documentation
The signio client returns different parameters so the status checks were all balled up.
Hope this helps someone out there!
Cordially,
George
____________________________________________________________________________
Customer Service Software Workshop Inc.
glaw@thebook.com 315.635-1968 (x213) "software that fits!" (TM)
http://www.thebook.com
#!/usr/bin/perl
=head1 NAME
CCLib.pm -- Compatibility module for PAYMENTNET.COM and CyberCash version 2
=cut
package CCLib;
use Carp;
use Exporter;
@EXPORT = qw/ SetServer sendmserver /;
use POSIX qw/tmpnam/;
$VERSION = '0.01';
use vars qw/$VERSION/;
my $Port = 1605;
my $Server = 'connect.seguesystems.com';
my $Password;
my $VendorID;
my $Executable;
=head1 VERSION
0.01
=head1 SYNOPSIS
use CCLib;
SetServer(
host => 'connect.sequesystems.com',
port => '1605',
secret => 'analyze',
vendor => 'sltest',
);
my $mode = 'mauthonly' || 'mauthcapture';
%result = sendmserver (
$mode,
# may be anything
'Order-ID' => $orderID,
# can be the Cybercash 'usd 33.44'
'Amount' => $amount,
# spaces OK
'Card-Number' => $ccnum,
'Card-Name' => $name,
'Card-Address' => $address,
'Card-City' => $city,
'Card-State' => $state,
'Card-Zip' => $zip,
'Card-Country' => $country,
# Can be cybercash style, must be
# one of MM/YY, M/YY, MYY, or MMYY
'Card-Exp' => $exp,
);
if($result{MStatus} !~ /^success/) {
$error = $result{MErrMsg};
return undef;
}
else {
return 1;
}
=head1 DESCRIPTION
This module interfaces PaymentNet.com 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{PAYMENTNET_VENDORID}.
The C<socklink> executable can either reside in the Perl @INC
libary include path, or can be in your $ENV{PATH}. They are used
in that order.
=head2 Example of use with MiniVend
Set the following variables in catalog.cfg:
# the paymentnet.com host
Variable CYBER_HOST connect.sequesystems.com
# the paymentnet.com port, defaults to 1605
#Variable CYBER_PORT 1605
# your password
Variable CYBER_SECRET analyze
# your password
Variable CYBER_VENDOR sltest
You can set your mv_cyber_mode variable to any valid PaymentNet
transaction type, or to the CyberCash:
CyberCash PaymentNet
------------------------------
mauthonly C1
mauthcapture C6
=head1 AUTHOR
Mike Heins, Internet Robotics, <mikeh@minivend.com>.
=head1 BUGS
Doesn't capture and log approval, AVS, and verify. That would be
easy to add.
=cut
#
# socklink <host> <port> <URL> <vendorID> <password> <transType> <ccNum> <ZIP> <expDate> <amount> <comment1> <comment2>
#
# <host> host name 'www2.onanalysis.com'
# <port> port number '443'
# <URL> local path on host to cgi '/socketlink/cc.cgi'
# <vendorID> user name for SocketLink account 'XYZcorp'
# <password> password for SocketLink account 'foobar'
# <transType> credit card transaction type 'C6'
# <ccNum> credit card number '1234234534564567'
# <ZIP> ZIP code for card (AVS) '94612'
# <expDate> credit card expiration date '0698'
# <amount> amount of transaction '49.95'
# <comment1> Comment #1 'SuperWidget (green)'
# <comment2> Comment #2 'Sales Agent: 4432'
#
sub SetServer {
#::logGlobal("Setserver called", @_);
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'};
#::logGlobal("vendor id assigned from hash");
}
elsif($ENV{PAYMENTNET_VENDORID}) {
#::logGlobal("vendor id assigned from PAYMENTNET env");
$VendorID = $ENV{PAYMENTNET_VENDORID};
}
elsif( defined $Vend::Cfg and
ref $Vend::Cfg->{Variable} and
$Vend::Cfg->{Variable}{CYBER_VENDOR}
)
{
#::logGlobal("vendor id assigned from CYBER_VENDOR");
$VendorID = $Vend::Cfg->{Variable}{CYBER_VENDOR};
}
else {
carp "No vendor id assigned.\n";
$VendorID = 'sltest';
}
my $ext = '';
my $joiner = "/";
if($^O =~ /win32/) {
$joiner = "\\";
$ext = '.exe';
}
$Executable = $Vend::Cfg->{Variable}{CYBER_EXECUTABLE};
$Executable = 'socklink' unless $Executable;
#::logGlobal("Vendor=$VendorID exec=$Executable pass=$Password\n");
return 1;
}
my %status_translate = (
-99 => 'Internal (unknown) error',
-8 => 'X509 cerification verification error',
-7 => 'SSL verify location error',
-6 => 'SSL verification policy error',
-5 => 'SSL context initialization failed',
-4 => 'Socket initialization error',
-2 => 'Hostname lookup failed',
-1 => 'Server socket unavailable',
0 => 'success',
1 => 'Invalid Vendor ID',
2 => 'Invalid password',
3 => 'Invalid transaction type',
4 => 'Invalid amount',
5 => 'Processor host connection error',
11 => 'Transaction timeout error',
12 => 'Transaction declined',
19 => 'Invalid authorization transaction ID',
21 => 'Recapture not allowed',
23 => 'Credit card number is invalid',
24 => 'Credit card expiration date is invalid',
);
my %mode_translate = ( qw/
C0 C0
C1 C1
C3 C3
C6 C6
C7 C7
mauthonly C1
mauthcapture C6
authonly C1
authcapture C6
/ );
sub sendmserver {
my $mode = shift;
my %opt = @_;
my $debug = "mode=$mode\n";
for(keys %opt) {
$debug .= "$_=$opt{$_}\n";
}
#::logGlobal("sendmserver called:\n$debug");
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;
#::logGlobal("error", @err_parms);
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.');
#::logGlobal("error", @err_parms);
return(@err_parms);
}
# The order of these params is documented in PaymentNet
# literature (and above from the socklink usage message).
# We use Order ID and customer name as the last two
# user-definable ones.
my (@param);
@param = (
$Server,
$Port,
$opt{'Card-Address'},
$VendorID,
$Password,
$mode_translate{$mode},
$opt{'Card-Number'},
$opt{'Card-Zip'},
$opt{'Card-Exp'},
$opt{'Amount'},
$opt{'Order-ID'},
$opt{'Card-Name'},
);
for(@param) {
next if /^[-\w.]+$/;
s/\s/ /g;
s/"/\\"/g;
$_ = qq{"$_"};
}
#$debug = "parms:\n" . join "\n", @param;
#::logGlobal($debug);
@err_parms = ( 'MStatus' , 'error_on_execution', 'MErrMsg' );
my $rfile = POSIX::tmpnam();
my $status_msg;
my $paramstring;
$paramstring = "TRXTYPE=S&TENDER=C&PWD=$Password&USER=$VendorID&ACCT=$opt{'Card-Number'}&EXPDATE=$opt{'Card-Exp'}&AMT=$opt{'Amount'}";
# do the authorization, results saved in the $rfile
open (TRANS, "| $Executable $Server $Port \"$paramstring\" 30 > $rfile");
close TRANS;
if($?) { # check the system status
my $status = $? >> 8;
@err_parms = ( 'MStatus', 'error_on_execution', 'MErrMsg' );
push @err_parms, "Status $status: $status_translate{$status}";
#::logGlobal("error", @err_parms);
return @err_parms if $status != 1;
}
open(RESULT, $rfile) or croak "read $rfile: $!\n";
my $status = <RESULT>; #signio file only has 1 line 0 see the format below
chomp $status;
my $result = <RESULT>;
chomp $result;
# Not using this at the moment
# my $process = <RESULT>;
# chomp $process;
close RESULT;
# payment net returns a string like :
#RESULT=1&PNREF=P789321897561RESPMSG=Approved&AUTHCODE=821PNI&AVSADDR=X&AVSZIP=X
# split this up, create a assoc array $results with keys
my @resultfields = split("&",$status);
my $resultline;
my $results;
my $key;
my $value;
foreach $resultline (@resultfields) {
($key,$value) = split ("=",$resultline);
$results{$key} = $value;
}
my $status1 = $results{'RESULT'};
if($?) {
my $code = $? >> 8;
@err_parms = ( 'MStatus', 'error_during_execution', 'MErrMsg' );
carp("Error running $Executable, error $code: $!\n");
push @err_parms, $status_translate{$status};
#::logGlobal("error", @err_parms);
unlink($rfile);
return @err_parms;
}
$result = $status_translate{$status1} unless $result;
my $success = ($status1 eq '0');
#if($status eq '0') {
# $status_msg = 'success';
#}
#elsif ($status < 0) {
# $status_msg = 'connection error';
#}
#else {
# $status_msg = 'transaction error';
#}
my %result;
if ($success) {
$result{MStatus} = 'success';
$result{'order-id'} = $result;
}
else {
$result{MStatus} = $status_translate{$status};
$result{MErrMsg} = $result;
}
unlink($rfile);
return (%result);
}
1;