[ic] RE: Payment module failure
Boyer, Jim
boyerj at wsu.edu
Tue Nov 29 16:40:05 EST 2005
Here is a little more info on the payment module failure I am getting
IC version 5.2.0
Perl 5.8.5
OS RHEL 2.4.21-37.ELsmp
Here is the module I am running
=============================
# Vend::Payment::WSU - Interchange WSU support
#
# $Id: WSU.pm,v 2.7 2002/12/17 02:39:04 kwalsh Exp $
#
# Copyright (C) 1999-2003 Perusion, Inc. <info at perusion.net>
#
# This program is free software; you can redistribute it and/or modify
# it under the terms of the GNU General Public License as published by
# the Free Software Foundation; either version 2 of the License, or
# (at your option) any later version.
#
# This program is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
# GNU General Public License for more details.
#
# You should have received a copy of the GNU General Public
# License along with this program; if not, write to the Free
# Software Foundation, Inc., 59 Temple Place, Suite 330, Boston,
# MA 02111-1307 USA.
# Connection routine for WSU custom payment server
package Vend::Payment::WSU;
use Vend::Util;
=head1 Interchange WSU Custom Payment Server Support
Vend::Payment::WSU $Revision: 1.0 $
=head1 SYNOPSIS
&charge=wsu
or
[charge mode=wsu param1=value1 param2=value2]
=head1 PREREQUISITES
This module is required:
Frontier::Client
It implements the RPC calls via HTTP.
One of these:
Net::SSLeay OR LWP::UserAgent and Crypt::SSLeay
Only one of these need be present and working.
=head1 DESCRIPTION
The Vend::Payment::WSU module implements the wsu() routine
for use with Interchange. It is compatible on a call level with the
other
Interchange payment modules -- in theory (and even usually in practice)
you
could switch from WSU to Authorize.net with a few configuration
file changes.
To enable this module, place this directive in C<interchange.cfg>:
Require module Vend::Payment::WSU
This I<must> be in interchange.cfg or a file included from it.
Make sure CreditCardAuto is off (default in Interchange demos).
The mode can be named anything, but the C<gateway> parameter must be set
to C<wsu>. To make it the default payment gateway for all credit
card transactions in a specific catalog, you can set in C<catalog.cfg>:
Variable MV_PAYMENT_MODE wsu
It uses several of the standard settings from Interchange payment. Any
time
we speak of a setting, it is obtained either first from the tag/call
options,
then from an Interchange order Route named for the mode, then finally a
default global payment variable, For example, the C<id> parameter would
be specified by:
[charge mode=wsu id=YourWSUID]
or
Route wsu id YourWSUID
or
Variable MV_PAYMENT_ID YourWSUID
The active settings are:
=over 4
=item id
Your WSU account ID, supplied by WSU IT. Global parameter is
MV_PAYMENT_ID.
Example:
Route wsu id CAHE
=item
=item payment_opt
The WSU payment option. Default is 201.
Route wsu payment_opt 201
=item remap
This remaps the form variable names to the ones needed by WSU. See
the C<Payment Settings> heading in the Interchange documentation for
use.
=item transaction
The default type of transaction to be run. Valid values are:
Interchange WSU
---------------- -----------------
auth AUTH
reverse REVERSAL
sale AUTHCAP
settle CAPTURE
You can set the default in catalog.cfg:
Route wsu transaction AUTH
To change the type for one particular charge operation, you would
pass it in the [charge ...] or $Tag->charge():
[charge transaction=AUTHCAP mode=wsu]
or
$Tag->charge({ transaction => 'AUTHCAP', mode => 'wsu' });
The Interchange UI can be used for CAPTURE and REVERSAL operations.
REVERSAL
only will reverse the entire amount of the order in the UI, but using
the
amount flag can cause partial reversal (if the gateway supports it).
=back
=head2 Troubleshooting
Try the instructions above, then enable test mode. A test order should
complete.
Disable test mode, then test in various WSU error modes by
using the credit card number 4222 2222 2222 2222.
Then try a sale with the card number C<4111 1111 1111 1111>
and a valid expiration date. The sale should be denied, and the reason
should
be in [data session payment_error].
If nothing works:
=over 4
=item *
Make sure you "Require"d the module in interchange.cfg:
Require module Vend::Payment::WSU
=item *
Make sure either Net::SSLeay or Crypt::SSLeay and LWP::UserAgent are
installed
and working. You can test to see whether your Perl thinks they are:
perl -MNet::SSLeay -e 'print "It works\n"'
or
perl -MLWP::UserAgent -MCrypt::SSLeay -e 'print "It works\n"'
If either one prints "It works." and returns to the prompt you should be
OK
(presuming they are in working order otherwise).
=item *
Check the error logs, both catalog and global.
=item *
Make sure you set your payment parameters properly.
=item *
Try an order, then put this code in a page:
<XMP>
[calc]
my $string = $Tag->uneval( { ref => $Session->{payment_result}
});
$string =~ s/{/{\n/;
$string =~ s/,/,\n/g;
return $string;
[/calc]
</XMP>
That should show what happened.
=item *
If all else fails, Perusion and other consultants are available to help
with integration for a fee.
=back
=head1 BUGS
There is actually nothing *in* Vend::Payment::WSU. It changes packages
to Vend::Payment and places things there.
=head1 AUTHORS
Mike Heins, <mikeh at perusion.net>.
=cut
BEGIN {
my $selected;
eval {
package Vend::Payment;
require Net::SSLeay;
import Net::SSLeay qw(post_https make_form make_headers);
$selected = "Net::SSLeay";
};
$Vend::Payment::Have_Net_SSLeay = 1 unless $@;
unless ($Vend::Payment::Have_Net_SSLeay) {
eval {
package Vend::Payment;
require LWP::UserAgent;
require HTTP::Request::Common;
require Crypt::SSLeay;
import HTTP::Request::Common qw(POST);
$selected = "LWP and Crypt::SSLeay";
};
$Vend::Payment::Have_LWP = 1 unless $@;
}
unless ($Vend::Payment::Have_Net_SSLeay or
$Vend::Payment::Have_LWP) {
die __PACKAGE__ . " requires Net::SSLeay or Crypt::SSLeay";
}
eval {
package Vend::Payment;
require Frontier::Client;
import Frontier::Client;
};
if($@) {
die __PACKAGE__ . "requires Frontier::Client\n";
}
logGlobal("%s payment module initialized, using %s\n", __PACKAGE__,
$selected)
unless $Vend::Quiet or ! $Global::VendRoot;
}
package Vend::Payment;
sub wsu {
my ($user, $amount) = @_;
my $opt;
if(ref $user) {
$opt = $user;
$user = $opt->{id} || undef;
$secret = $opt->{secret} || undef;
}
else {
$opt = {};
}
my $actual;
if($opt->{actual}) {
$actual = $opt->{actual};
}
else {
my (%actual) = map_actual();
$actual = \%actual;
}
#::logDebug("actual map result: " . ::uneval($actual));
if (! $user ) {
$user = charge_param('id')
or return (
MStatus => 'failure-hard',
MErrMsg => errmsg('No account id'),
);
}
$secret = charge_param('secret') if ! $secret;
$opt->{host} ||= 'https://itnt104.it.wsu.edu';
$opt->{script} ||= '/xml-rpc/epay.asp';
$opt->{function} ||= 'epay_cc';
$opt->{port} ||= '';
$opt->{port} =~ s/^:*/:/ if $opt->{port};
$opt->{payment_opt} ||= charge_param('payment_opt') || '201';
my $precision = $opt->{precision}
|| 2;
my $referer = $opt->{referer}
|| charge_param('referer');
my @override = qw/
order_id
auth_code
mv_credit_card_exp_month
mv_credit_card_exp_year
mv_credit_card_number
/;
for(@override) {
next unless defined $opt->{$_};
$actual->{$_} = $opt->{$_};
}
## Format month
$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};
# Using mv_payment_mode for compatibility with older versions,
probably not
# necessary.
$opt->{transaction} ||= 'sale';
my $transtype = $opt->{transaction};
my %type_map = (
AUTH => 'AUTH',
REVERSAL => 'REVERSAL',
AUTHCAP => 'AUTHCAP',
CAPTURE => 'CAPTURE',
authorize => 'AUTH',
auth => 'AUTH',
mauthonly => 'AUTH',
return => 'REVERSAL',
sale => 'AUTHCAP',
settle => 'CAPTURE',
settle_prior => 'CAPTURE',
void => 'REVERSAL',
);
if (defined $type_map{$transtype}) {
$transtype = $type_map{$transtype};
}
$amount = $opt->{total_cost} if $opt->{total_cost};
if(! $amount) {
$amount = Vend::Interpolate::total_cost();
$amount = Vend::Util::round_to_frac_digits($amount,$precision);
}
$amount = int( $amount * 100 );
$order_id = gen_order_id($opt);
#::logDebug("auth_code=$actual->{auth_code} order_id=$opt->{order_id}");
my $cc = $actual->{mv_credit_card_number};
$cc =~ s/\D+//g;
my %ctype = (
visa => '001',
mc => '002',
mastercard => '002',
);
my $card_type = $ctype{$actual->{mv_credit_card_type}};
#::logDebug("card type=$actual->{mv_credit_card_type}
card_type=$card_type");
if(! $card_type) {
$actual->{mv_credit_card_number} =~ /^4/ and $card_type =
'001';
$actual->{mv_credit_card_number} =~ /^5/ and $card_type =
'002';
}
#::logDebug("card type=$actual->{mv_credit_card_type}
card_type=$card_type");
$card_type ||= '001';
if(! $card_type) {
$result{MStatus} = 'failure';
return (
MStatus => 'failure',
MErrMsg => "WSU doesn't accept
$actual->{mv_credit_card_type}",
);
}
my $name_and_phone = '';
if($actual->{b_name}) {
$name_and_phone .= $actual->{b_name};
}
elsif($actual->{name}) {
$name_and_phone .= $actual->{name};
}
else {
$name_and_phone .= "NO NAME";
}
if($actual->{phone_day}) {
$name_and_phone .= ", " . $actual->{phone_day};
}
elsif($actual->{phone_night}) {
$name_and_phone .= ", " . $actual->{phone_night};
}
else {
$name_and_phone .= " (NO PHONE)";
}
my $server_url = $opt->{host} . $opt->{port} . $opt->{script};
## Get Frontier object
my $server = Frontier::Client->new(url => $server_url)
or die "Unable to reach Frontier::Client\n";
## Stack parameters, formatted for Frontier
my %query = (
merchant => $server->string($user),
tran_type => $server->string($transtype),
card_num => $server->string($cc),
exp_date => $server->string($exp),
amount => $server->int($amount),
card_type => $server->string($card_type),
payment_opt =>
$server->string($opt->{payment_opt}),
t_type_id => $server->string($opt->{t_type_id}),
trans_id => $server->string($order_id),
sequence_num_in => $server->string($order_id),
ip_address =>
$server->string($Session->{ohost}),
additional_info => $server->string($name_and_phone),
cvv => $server->string($actual->{cvv2} ||
''),
);
#::logDebug(qq{\nwsu array to send: } . ::uneval(\%query));
my $return = $server->call($opt->{function}, \%query);
# Interchange names are on the left, WSU on the right
my %result_map = ( qw/
pop.status return_code
pop.error-message return_message
order-id sequence_num
pop.order-id sequence_num
pop.auth-code approval_code
pop.cvv_code cvv_result
/
);
::logDebug(qq{\nwsu hash result: } . ::uneval($return));
my %result = %{$return->[0]};
for (keys %result_map) {
$result{$_} = $result{$result_map{$_}}
if defined $result{$result_map{$_}};
}
::logDebug(qq{\nwsu hash result translated: } . ::uneval(\%result));
my $status = $result{return_code};
my $gwmsg = $result{return_message};
if(! defined $status or $status eq '') {
$result{MStatus} = 'failure-hard';
$result{MErrMsg} = $gwmsg || 'Gateway failure';
}
elsif($status == 0) {
$result{MStatus} = 'success';
}
elsif($status == 1) {
$result{MStatus} = 'failure';
$result{MErrMsg} = errmsg($gwmsg || 'Card declined.');
}
elsif($status == 2) {
$result{MStatus} = 'failure-hard';
$result{MErrMsg} = errmsg($gwmsg || 'Gateway processing
error.');
}
elsif($status == 3) {
$result{MStatus} = 'failure';
$result{MErrMsg} = errmsg("Bad input parameter: %s", $gwmsg ||
'unknown');
}
::logDebug(qq{\nwsu hash result: } . ::uneval(\%result));
return (%result);
}
package Vend::Payment::WSU;
1;
===============================================
And the error again:
I have a payment module written for us that uses XML to talk to our
credit card server. It has recently been receiving the following error
on a random basis:
==============================================================
- [28/November/2005:09:15:00 -0800] pestrecert
/cgi-bin/pestrecert/process Safe:
Real-time charge failed.
Reason: payment routine 'wsu' returned error: 500 read failed:
>
>
>
> die errmsg(
> "Real-time charge failed. Reason: %s\n",
> errmsg($Session->{cybercash_error}),
> );
>
>
==============================================================
I looked in the archives for LWP and I could not find anything about my
problem, maybe I am blind...
Any help would be greatly appreciated.
Thanks,
-------------------------------
Jim Boyer
Systems Programmer
College of Agriculture, Human, and Natural Resource Sciences
Washington State University
509.335.2838
More information about the interchange-users
mailing list