[IC] surepay integration part II

ben schlaver interchange-users@lists.akopia.com
Wed May 9 12:57:01 2001


This seems to be a question "how do i get my custom globalsub to read from
the shopping cart each line item's description, price, color etc"! but in
this case, integrating SurePay XML gateway and SDK into a global sub.

well it took some time and a lot of work on the Order.pm but below is a
globalsub for SurePay that will comminicate to the provided SDK and then
surepay's servers.

the problem: surepay requires line item variables to be passed from the
cart... which works except item price, color, size... so from lines 226~240
there are logdebugs that we've used to see if the variables are making it,
right now the price is hardcoded in at a $1 and it follow thru fine with the
order from there... the logdebug's are commmented with "works" and "doesn't
work"... so any help to this one last hump would be great!

ben schlaver
chris fulton
chris@closetgenius.com


# Connection routine for Surepay
#


Variable SUREPAY_HELP <<EOV

 1. Modify interchange.cfg to use this file.

 #include globalsub/surepay



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

 # Username and password
 Variable MV_PAYMENT_ID      Your Surepay ID
 Variable MV_PAYMENT_SECRET  Your Surepay Password
 # Use xml.surepay.com for testing
 Variable MV_PAYMENT_SERVER  xml.surepay.com
Variable         MV_PAYMENT_PORT     443
Variable         MV_PAYMENT_PATH     /

 3. Set the payment mode in catalog.cfg:

 Variable MV_PAYMENT_MODE    custom surepay


 4. You must have the following modules installed
	LWP::UserAgent
        HTTP::Request
        HTTP::Request::Common
        Crypt::SSLeay
 5. Modify the Order.pm (/usr/local/interchange/lib/Vend/Order.pm) to add
the 'email' and 'phone_day' mappings.

 6. Restart Interchange.

EOV

GlobalSub <<EOS
sub surepay {

use PurePaymentsSDK;


my $gtype = 'https';  # (http|https|test)
my $numitems = 10;        # Max number of line items to allow
my $securitytype = '07';

###timeout defaults -- see alarm below
#local($timeout)   = 15;
#local($SIG{ALRM}) = sub { die "$timeout sec timeout"; };

###end config

##get environment stuff
    my ($user, $secret, $amount) = @_;

    my (%actual) = Vend::Order::map_actual();

    if(! $user  ) {
        $user    =  $::Variable->{MV_PAYMENT_ID}
                    or return undef;
    }
#::logDebug("surepay user $user");
    if(! $secret) {
        $secret  =  $::Variable->{MV_PAYMENT_SECRET}
                    or return undef;
    }
#::logDebug("surepay secret $secret");

    my $server  =   $::Variable->{MV_PAYMENT_SERVER} ||
                    'xml.surepay.com';

    my $port    =   $::Variable->{MV_PAYMENT_PORT} ||
                    443;

    my $path    =   $::Variable->{MV_PAYMENT_PATH} ||
                    '/';

    my $precision = $::Variable->{MV_PAYMENT_PRECISION} ||
                    2;






    $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%s%02d',
                        $actual{mv_credit_card_exp_month}, "/",
                        $actual{mv_credit_card_exp_year};

        $actual{cyber_mode} = 'S'
        unless $actual{cyber_mode};



    my %type_map = (
        qw/
                        mauthcapture  S
                        mauthonly     C
                        mauthdelay    D
                        mauthreturn   V
                        S             S
                        C             C
                        D             D
                        V             V
        /
    );




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

    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);

$orderID=Vend::Interpolate::tag_counter('etc/order.number');

::logDebug("surepay orderID= $orderID");



        # Join first and last name
        my($fullname);
        $fullname = sprintf($actual{b_fname} . " " . $actual{b_lname});




eval {


my $reqManager = RequestManager::new($gtype,$server,$port,$path,'0','');
my $billAddress = Address::new('billing',
                               'fullname' => $fullname,
                               'email'    => $actual{email},
                               'eveningphone' => $actual{b_phone},
                               'fax'      => $actual{b_fax},
                               'address1' => $actual{b_address1},
                               'address2' => $actual{b_address2},
                               'address3' => $actual{b_address3},
                               'city'     => $actual{b_city},
                               'state'    => $actual{b_state},
                               'country'  => $actual{b_country},
                               'zip'      => $actual{b_zip});
my $shipAddress = Address::new('shipping',
                               'fullname' => $fullname,
                               'email'    => $actual{email},
                               'eveningphone' => $actual{phone_day},
                               'fax'      => $actual{fax},
                               'address1' => $actual{address1},
                               'address2' => $actual{address2},
                               'address3' => $actual{address3},
                               'city'     => $actual{city},
                               'state'    => $actual{state},
                               'country'  => $actual{country},
                               'zip'      => $actual{zip});


#::logDebug("surepay billAddress= $billAddress");
#::logDebug("surepay shipAddress= $shipAddress");
#::logDebug("surepay city= $actual{city}");
#::logDebug("surepay fullname= $fullname");
#::logDebug("surepay email= $actual{email}");
#::logDebug("surepay phone= $actual{phone_day}");


my ($pi,$id);
  $pi =
CreditCard::new($actual{mv_credit_card_number},$exp,'','1',$billAddress);

my $ptype = $pi->getPaymentType;



my ($i,$lineitem,@lineitems);

#::logDebug("surepay items $actual{items}");

#my $numlineitems = return scalar @{$Carts->{main}};
#my $numlineitems = return scalar @{$Vend::Session->{carts}{main}};

#::logDebug("surepay carthash= $Carts->{main}[1]{code}");
#::logDebug("surepay item0code= $Vend::Session->{carts}{main}[1]{code}");
#::logDebug("surepay item1code= $Vend::Session->{carts}{main}[0]{code}");
#::logDebug("surepay item0title= $Vend::Session->{carts}{main}[0]{title}");
#::logDebug("surepay item0price= $Vend::Session->{carts}{main}[0]{price}");
#::logDebug("surepay item0desc=
$Vend::Session->{carts}{main}[0]{description}");
#::logDebug("surepay item0weight=
$Vend::Session->{carts}{main}[0]{weight}");
#::logDebug("surepay item1qty= $Vend::Session->{carts}{main}[1]{quantity}");
#::logDebug("surepay item0qty= $Vend::Session->{carts}{main}[0]{quantity}");
#::logDebug("surepay numlineitems= $numlineitems");
#::logDebug("surepay mv_cartname= $actual{mv_cartname}");

my ($temdesc);



foreach $i (0..(@{$Vend::Session->{carts}{main}}-1))
{

####these work

::logDebug("surepay itemicode= $Vend::Session->{carts}{main}[$i]{code}");
::logDebug("surepay itemtotalcost= $amount");
::logDebug("surepay item1mvib= $Vend::Session->{carts}{main}[$i]{mv_ib}");
::logDebug("surepay itemiqty= $Vend::Session->{carts}{main}[$i]{quantity}");

###these dont work

#$temdesc=Vend::Tags::item_description('R02298-035', 'description');
#::logDebug("surepay temdesc1= $temdesc");
::logDebug("surepay itemdesc1= $Vend::Tags->tag_data('products',
'description', 'R02298-035')");
::logDebug("surepay itemidescr2=
$Vend::Data::item_description->{('R02298-035', 'description')}");
::logDebug("surepay itemidesc2= $Vend::Parse::do_tag('data', 'products',
'description', 'R02298-035')");
::logDebug("surepay itemidescz=
$Vend::Data->{products}{description}{'R02298-035'}");
::logDebug("surepay itemidesczt=
$Vend::Data->{products}{description}{$Vend::Session->{carts}{main}[$i]{code}
}");
#::logDebug("surepay itemicode=
$Vend::Tag->{data}{products}{description}{R02298-035}");
#::logDebug("surepay itemicode= $Vend::Data->{data('products',
'description', $Vend::Session->{carts}{main}[$i]{code})}");
::logDebug("surepay itemidesc=
$Vend::Session->{carts}{main}[$i]{product_description}");
::logDebug("surepay itemisize= $Vend::Session->{carts}{main}[$i]{size}");
::logDebug("surepay item1color= $Vend::Session->{carts}{main}[$i]{color}");
::logDebug("surepay item1price=
$Vend::Session->{carts}{main}[1]{item_field_price}");
::logDebug("surepay item1price=
$Vend::Session->{carts}{main}[1]{item_fi1}");
::logDebug("surepay itemititle= $Vend::Session->{carts}{main}[$i]{title}");
#  next unless $actual{sku.$i} && $actual{quantity.$i};
  $lineitem =
LineItem::new($Vend::Session->{carts}{main}[$i]{code},'description',$Vend::S
ession->{carts}{main}[$i]{quantity},0,'1.00');
#  $extAmt += $lineitem->getQuantity * $lineitem->getUnitPrice;
  push(@lineitems,$lineitem);
}

#::logDebug("surepay quantity1 $actual{quantity1}");

my $obj;


  $obj = Auth::new($orderID,$orderID,'','','','','','',
                   '','', 'E-Commerce',$securitytype,
                   $shipAddress,$pi);

my $totalAmt = $amount;
foreach $lineitem (@lineitems) { $obj->addLineItem($lineitem); }
if ($amount && $amount != $totalAmt) { $obj->setTotal($amount); }
my $total = $obj->getTotal;
#my $numlineitems   = return scalar @{$Carts->{main}};


my $req  = Request::new('','','',$user,$secret,$obj);

#alarm $timeout;
my $res  = $reqManager->submit($req);
#alarm 0;


my $ores = $res->getFirstResponse;
my $pres = ref $ores;
my $failure    = $ores->getFailure;        # true/false
my $failureMsg = $ores->getFailureMsg;     # message if failure=true


my($status,$authCode,$avs,$cvv2result,$tid,$fee,$due,$exc,$pid);

if ($pres eq 'AuthResponse')
{
  $status   = $ores->getAuthStatus;     # status  if failure=false
  $authCode = $ores->getAuthCode;       # authorization code if transaction
approved
  $avs      = $ores->getAVS;            # avs
  $cvv2result = $ores->getcvv2result;   # CVV2 result
  $tid      = $ores->getTransactionID;  # transaction id
  $status ||= 'ERROR';
  $status  .= ": " . $failureMsg if $failure eq 'true';
}
elsif ($pres eq 'ComputeFeeResponse')
{
  $fee = $ores->getFeeAmount;
  $due = $ores->getDueAmount;
  $exp = $ores->getExpirationDate;
  $exc = $ores->getExchangeRate;
  $pid = '';
  $tid = 'compute fee only';
  $status  = ($failure eq 'true')? $failureMsg : '';
}
elsif ($pres eq 'InitiatePaymentResponse')
{
  $fee = $ores->getFeeAmount;
  $due = $ores->getDueAmount;
  $exp = $ores->getExpirationDate;
  $exc = $ores->getExchangeRate;
  $pid = $ores->getPayID;
  $tid = $ores->getTransactionID;
  $status  = ($failure eq 'true')? $failureMsg : '';
}



::logDebug("surepay failureMsg=$failureMsg");
::logDebug("surepay pres=$pres");



};
##end the eval statement

##pick up any errors returned by eval

$@ =~ s/ at .*//;

my $status = "ERROR: $@\n" if $@;


###end of it i think




::logDebug("surepay status=$status");










    # Minivend names are on the  left, Surepay on the right
    my %result_map = ( qw/

            MStatus               status
            pop.status            status
            MErrMsg               failureMSG
            pop.error-message     failureMSG
            order-id              tid
            pop.order-id          tid
            pop.auth-code         authCode
    /
    );



    my %result;

    for (keys %result_map) {
        $result{$_} = $result{$result_map{$_}}
            if defined $result{$result_map{$_}};
    }

    $Vend::Session->{cybercash_result} =
    $Vend::Session->{payment_result} = \%result;

    delete $Vend::Session->{cybercash_error};
    delete $Vend::Session->{payment_error};



::logDebug("surepay MStatus=$result{MStatus}");
::logDebug("surepay responsemsg=$result{RESPMSG}");
::logDebug("surepay authcode=$result{authCode}");



    if ($result{'pop.auth-code'} eq "") {
        $result{'pop.status'} =
        $result{'MStatus'} = 'failed';

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

                my $msg = errmsg("Surepay error: %s %s. Please call in your
order or try again.",
                        $result{RESULT} ,
                        $result{RESPMSG},
                );

                $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->{cybercash_error}   =
            $Vend::Session->{payment_error} = $result{RESPMSG};
    }






	return %result;






}

EOS




also here is the tail of the logdebug...:

Start DEBUG at Tue May  8 23:57:38 2001
Vend::Order:debug: called _charge: ref=HASH(0x83fee6c) params=custom surepay
message=
Vend::Order:debug: cyber_charge, mode val= cgi= actual=
Vend::Config:debug: surepay orderID= 000121
Vend::Config:debug: surepay mv_cartname=
Vend::Config:debug: surepay itemicode= case001
Vend::Config:debug: surepay itemtotalcost= 128.58
Vend::Config:debug: surepay itemdesc1= ->tag_data('products', 'description',
'R02298-035')
Vend::Config:debug: surepay itemidescr2=
Vend::Config:debug: surepay itemidesc2= ('data', 'products', 'description',
'R02298-035')
Vend::Config:debug: surepay itemidescz=
Vend::Config:debug: surepay itemidesczt=
Vend::Config:debug: surepay itemiqty= 1
Vend::Config:debug: surepay itemidesc=
Vend::Config:debug: surepay itemisize=
Vend::Config:debug: surepay item1color=
Vend::Config:debug: surepay item1mvib= products
Vend::Config:debug: surepay item1price=
Vend::Config:debug: surepay item1price=
Vend::Config:debug: surepay itemicode= B02298-032
Vend::Config:debug: surepay itemtotalcost= 128.58
Vend::Config:debug: surepay itemdesc1= ->tag_data('products', 'description',
'R02298-035')
Vend::Config:debug: surepay itemidescr2=
Vend::Config:debug: surepay itemidesc2= ('data', 'products', 'description',
'R02298-035')
Vend::Config:debug: surepay itemidescz=
Vend::Config:debug: surepay itemidesczt=
Vend::Config:debug: surepay itemiqty= 2
Vend::Config:debug: surepay itemidesc=
Vend::Config:debug: surepay itemisize=
Vend::Config:debug: surepay item1color=
Vend::Config:debug: surepay item1mvib= products
Vend::Config:debug: surepay item1price=
Vend::Config:debug: surepay item1price=
Text:debug: surepay xml ordertext <pp.ordertext
type="description"><![CDATA[000121]]></pp.ordertext>
Vend::Config:debug: surepay failureMsg=Card declined
Vend::Config:debug: surepay pres=AuthResponse
Vend::Config:debug: surepay status=
Vend::Config:debug: surepay MStatus=
Vend::Config:debug: surepay responsemsg=
Vend::Config:debug: surepay authcode=
Vend::Order:debug: charge result: result= params=custom surepay
message=Charge operation '' failed