[ic] Trying to make new Payment Module for Card Services perl wrapper.

Boyd Lynn Gerber interchange-users@interchange.redhat.com
Mon Apr 15 07:59:00 2002


Hello,

How do I get interchange payment modules to find and load a perl module in
interchange_location/lib/LPERL/ lperl.pm .  What I am doing does not seem
to be working.  The test programs all work using lperl in the
interchange_location/lib/LPERL directory.

If I copy lperl.pm to my perl site_perl/5.6.1/ directory, interchange load
just fine, but when I try to place a CC order I get...

(linkpt): Charge failed, reason: payment routine 'linkpt' returned error:
Undefined subroutine &lperl::new called at
/linux/usr/local/interchange.new/lib/Vend/Payment/linkpt.pm line 324.

or

(linkpt): Charge failed, reason: payment routine 'linkpt' returned error:
Can't locate object method "new" via package "lperl" (perhaps you forgot
to load "lperl"?) at
/linux/usr/local/interchange.new/lib/Vend/Payment/linkpt.pm line 317.

The lperl.pm module can not be distributed in any form.

If I do not copy it to my perl site_perl/5.6.1 directory I get

Required Perl module Vend::Payment::linkpt not present. Aborting catalog.
In line 5 of the configuration file 'interchange.cfg':
Require module Vend::Payment::linkpt

So I know that when interchange starts and finds the lperl.pm module
interchange is able to start.  So now I need to some how make interchange
use the interchange_directory/lib/LPERL to do everything.  I missed
something going through the code and I am not sure exactly what.

Maybe one of you interchange and perl Guru's can quicly spot what I am
doing wrong.  Below is linkpt.pm that I put in the lib/Vend/Payment
directory.  This is a work in progress so please do not rely on it working
at this time.  When I finish this and passes all tests I will glady let
any one with interchange use it and if Red Hat wants to add it to their
Payment modules I think they will be able to use it.  Where I am requiring
people to purchase from Card Service the Perl Wrapper and I am not
distributing any part of it.

Thanks for any and all help.

--
Boyd Gerber <gerberb@zenez.com>
ZENEZ	3748 Valley Forge Road, Magna Utah  84044


---------------------------------linkpt.pm--------------------------
# Vend::Payment::linkpt - Interchange linkpt Support
#
# $Id: linkpt.pm,v 2.0 2002/04/13 02:23:16 jon Exp $
#
# Copyright (C) 1999-2001 Red Hat, Inc. <interchange@redhat.com>
#
# LinkPoint CardService using the lperl that must be purchased
# From Card Server.
# by Boyd Gerber <gerberb@zenez.com> inspired and resused by
# based on code by Mike Heins <mheins@redhat.com>

# 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.

package Vend::Payment::linkpt;

=head1 Interchange linkpt Support

Vend::Payment::linkpt $Revision: 2.0 $

=head1 SYNOPSIS

    &charge=linkpt

        or

    [charge mode=linkpt param1=value1 param2=value2]

=head1 PREREQUISITES

	lperl
	lbin

Purchase the perl wrapper from  Card Service.

=head1 DESCRIPTION

The Vend::Payment::linkpt module implements the linkpt() routine
for use with Interchange. It is compatible on a call level with the other
Interchange payment modules.

To enable this module, place this directive in C<interchange.cfg>:

    Require module Vend::Payment::linkpt

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<linkpt>. 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  linkpt

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=linkpt id=YourStoreName]

or

    Route linkpt id YourStoreName

or

    Variable MV_PAYMENT_ID      YourStoreName

The active settings are:

=over 4

=item id

Your Card Service store Name, supplied by Card Service when you sign up.
Global parameter is MV_PAYMENT_ID.

That should show what happened.

 Variable MV_PAYMENT_ID      YourStoreNymber
 # Use staging.linkpt.new for testing
 Variable MV_PAYMENT_SERVER  secure.linkpt.net

transactionresult needs to be set to GOOD for testing and LIVE for normal processing.

 3. Copy your Card Service Perl software to interchange/lib/LPERL.

 4. Copy your Digital certificate .pem file for LinkPoint API client:
    to YourStoreNumber.pem in the interchange/lib/LPERL directory.

 5. Create a temp directory in your interchange/lib/LPERL directory,
    mkdir temp

=item remap

This remaps the form variable names to the ones needed by linkpt. See
the C<Payment Settings> heading in the Interchange documentation for use.

=back

=head2 Troubleshooting

Try the instructions above, then enable test mode. A test order should complete.

Then move to live mode and 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::linkpt

=item *

Make sure you have installed your perl wrapper in the your interchange
directory in lib/LPERL.  Make sure it is working with the tests provided.
You can test to see whether your Perl can access lbin and lperl.  The commands
are:

Edit these programs to reflect your store name and cert and then run perl filename.

lptest_ApproveSale_VoidSale_Track.pl
lptest_ApproveSale_VoidSale_card.pl
lptest_BillOrder.pl
lptest_CalculateShipping.pl
lptest_CalculateTax.pl
lptest_PeriodicBilling.pl
lptest_ReturnCard.pl
lptest_Shipping_Tax_ApproveSale.pl
lptest_VirtualCheck.pl
lptest_minimum.pl


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 account ID 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, Red Hat and other consultants are available to help
with integration for a fee.

=back

=head1 BUGS

There is actually nothing *in* Vend::Payment::linkpt. It changes packages
to Vend::Payment and places things there.

=head1 AUTHORS

Boyd Gerber <gerberb@zenez.com>, based on original code by
Mike Heins <mheins@redhat.com> and other from the Payment directory.

=cut

BEGIN {
        my $selected;
        package Vend::Payment;
        eval {

                package LPERL::lperl;
                require lperl;
                import lperl qw($REVISION $VERSION @ISA @EXPORT);
@ISA = qw(Exporter);
@EXPORT = qw(&process &new &add_item &add_option @Items);
                $selected = "lperl";
         };
	$Vend::Payment::Have_LPERL_lperl = 1 unless $@;
        unless ($Vend::Payment::Have_LPERL_lperl) {
                die __PACKAGE__ . " requires lperl";
        }

	::logGlobal("%s payment module initialized, using %s", __PACKAGE__, $selected)
		unless $Vend::Quiet;

}

package Vend::Payment;
sub linkpt {
use lperl;
#::logDebug("linkpt called");

    my $exe;

        my @try = split /:/, $ENV{PATH};
        unshift @try,
                        "$Global::VendRoot/lib",
                        "$Global::VendRoot/bin",
                        "$Global::VendRoot",
                        ;

        my $stdin;
        for(@try) {
                if(-f "$_/lib/LPERL/lbin" and -x _) {
                        $exe = "$_/lib/LPERL/lbin";
                        $stdin = 1;
                        last;
                }
                next unless -f "$_/lib/LPERL/lbin" and -x _;
                $exe = "$_/lib/LPERL/lbin";
                last;
        }

    if(! $exe ) {
                return (
                        MStatus => 'failure-hard',
                        MErrMsg => errmsg('lbin executable not found.'),
                        );
    }

        # set loadable module path so not needed in /usr/lib
        @try = split /:/, (charge_param('library_path') || $ENV{LD_LIBRARY_PATH}
);
        unshift @try,
                        "$Global::VendRoot/lib",
                        "$Global::VendRoot/bin",
                        "$Global::VendRoot",
                        ;
        $ENV{LD_LIBRARY_PATH} = join ':', @try;

        # set certificat path for modern lbin
        $ENV{LINKPT_CERT_PATH} ||= charge_param('cert_path');
        if(! -d $ENV{LINKPT_CERT_PATH} ) {
                @try = (
                                        "$Global::VendRoot",
                                        "$Global::VendRoot/lib",
                                        "$Global::VendRoot/lib/LPERL",
                                        '/usr/local/ssl',
                                        '/usr/lib/ssl',
                                );
                for(@try) {
                        next unless  -d "$_/certs";
                        $ENV{LINKPT_CERT_PATH} = "$_/certs";
                        last;
                }
        }

        my %actual;
        if($opt->{actual}) {
                %actual = %{$opt->{actual}};
        }
        else {
                %actual = map_actual();
        }

    if(! $user  ) {
        $user    =  charge_param('id')
                                                or return (
                                                        MStatus => 'failure-hard
',
                                                        MErrMsg => errmsg('No ac
count id'),
                                                        );
    }
#::logDebug("linkpt user $user");

        my $server;
        my $port;
        if(! $opt->{host} and charge_param('test')) {
                $server = 'staging.linkpt.net';
                $port   = 1139;
        }
        else {
                # We won't read from MV_PAYMENT_SERVER because that would rarely
                # be right and might often be wrong
# this is normally secure.linkpt.net
                $server  =   $opt->{host}  || 'staging.linkpt.net';
                $port    =   $opt->{port}  || '1139';
        }


    my $exe  =  "$Global::VendRoot/lib/LPERL/lbin";

#my $lperl = new lperl("my$exe", "FILE", "/linux/usr/lib/interchange/lib/LPERL/temp/");
#
# use this just to make sure this is not where it is failing.
#
my $lperl = new lperl("/linux/usr/lib/interchange/lib/LPERL/lbin", "FILE", "/linux/usr/lib/interchange/lib/LPERL/temp/");

#::logDebug("linkpt srcipt $script");

#    my $server  =   $::Variable->{MV_PAYMENT_SERVER} ||
#                    $::Variable->{CYBER_SERVER} ||
#                    'staging.linkpt.net';
#                    'secure.linkpt.net';

   my $hostname = "$server";

#::logDebug("linkpt server $hostname");

#my $port             =  "$::Variable->{MV_PAYMENT_PORT}" ||
#                        "$::Variable->{CYBER_PORT}" ||
#                        "1139";

#::logDebug("linkpt port $port");

   if(! $storename  ) {
        $storename   =  "$::Variable->{MV_PAYMENT_ID}" ||
                    "$::Variable->{CYBER_ID}"
                    or return undef;
   }
#
# use this just to make sure this is not where it is faling.
#

my $storename="800153";
#::logDebug("linkpt store $storename");

#my $keyfile  = "$Global::VendRoot/lib/LPERL/800153.pem";
#
# use this just to make sure this is not where it is faling.
#

my $keyfile            = "/linux/usr/lib/interchange/lib/LPERL/800153.pem";

# Change to LIVE for normal processing
#
# use this just to make sure this is not where it is faling.
#

my $transactionresult  = "GOOD";
my $testip             = "127.0.0.1";

my %actual = Vend::Order::map_actual();
my $transaction_hash = {
                        hostname        => $hostname,
                        port            => $port,
                        storename       => $storename,
                        keyfile         => $keyfile,
                        # if this param is empty or missing
                        # a CSI order number will be assigned
                        orderID         => "",
                        amount          => Vend::Interpolate::total_cost(),
                        result          => $transactionresult,
                        cardNumber      => $actual{mv_credit_card_number},
                        cardExpMonth    => $actual{mv_credit_card_exp_month},
                        cardExpYear     => $actual{mv_credit_card_exp_year},
                        name            => "$actual{fname} $actual{lname}",
                        email           => $actual{email},
                        phone           => $actual{phone_day},
                        address         => $actual{address},
                        city            => $actual{city},
                        state           => $actual{state},
                        zip             => $actual{zip},
                        country         => $actual{country},
                        ip              => $testip,
                };

my %ret = $lperl->CapturePayment($transaction_hash);
# ---------------------------------------------
# capture the order ID so we can bill the order
# ---------------------------------------------

my $neworderID = $ret{'neworderID'};
my %result;

#::logDebug("linkpt CapturePayment: statusCode $statusCode");

if ( $ret{'statusCode'} eq 0 ) {

    # the transaction failed.  print the reason.
     $result{MStatus} = 'failure';
     $result{MErrMsg} = "$ret{'statusMessage'} ";
#::logDebug("linkpt failure:");
#::logDebug("linkpt CapturePayment: statusMessage $statusCode");
#::logDebug("linkpt ChargeTotal: $actual{'total-cost'}");
#::logDebug(qq{linkpt decline=$statusCode result: } . ::uneval( \%result));

 }
else
 {
    # the transaction succeeded.  print the results.
#::logDebug("linkpt CapturePayment: statusMessage:'AVSCode'");

# ------------------
# now bill the order
# ------------------

     $transaction_hash = {
            hostname        => $hostname,
            port            => $port,
            storename       => $storename,
            keyfile         => $keyfile,
            result          => $transactionresult,
            orders          => ([
                          # multiple entries could be used for more orders
              {orderID      => $neworderID,
               amount       => $actual{'total-cost'},
               backOrdered  => '0',
               }
            ])
        };

%ret = $lperl->BillOrders($transaction_hash);

#::logDebug("linkpt Successfully billed $ret of 1 order\n");
#::logDebug("Order statusMessage: $transaction_hash->{'orders'}[0]->{'statusMessage'}\n";
$result{MStatus} = 'success';
$result{'order-id'} = $neworderID;


 }
return %result;
}

package Vend::Payment::linkpt;

1;
-----------------------------------end_file--------------------------