[interchange-cvs] interchange - markj modified lib/Vend/Payment.pm

interchange-cvs at icdevgroup.org interchange-cvs at icdevgroup.org
Fri Mar 20 16:40:34 UTC 2009


User:      markj
Date:      2009-03-20 16:40:34 GMT
Modified:  lib/Vend Payment.pm
Log:
New Global Timeout feature for payment gateways.

The different payment gateways all tend to implement their own timeout features
with varying degrees of success. In particular, LWP-based clients do not appear
to have any capability of passing a timeout by the developer whenever it uses
the https protocol. Thus, the use of LWP's timeout feature is illusory and
forces any activity to a 180s timeout.

The new feature completely separates out the gateway activity with a fork,
giving it reliable control over the duration of the gateway request. It also
eliminates the need for each gateway module to implement its own timeout,
either because the developer chose not to, didn't consider it, or because the
developer discovered it was hopeless to do so using LWP.

The feature is invoked using the "global_timeout" option in the payment route,
or as an opt passed to [charge]. global_timeout should be any positive integer,
which will define the number of seconds until the timeout is triggered. If this
new option is not used, the effect is a no-op, with behavior identical to that
prior to the feature. No changes in config means completely backward
compatible.

Additionally, a new "global_timeout_msg" option is available so that the
message produced if the alarm fires can be customized within the payment route.

E.g.:

    Route   payflowpro    id                 "__PAYFLOWPRO_ID__"
    Route   payflowpro    secret             "__PAYFLOWPRO_SECRET__"
    Route   payflowpro    partner            "__PAYFLOWPRO_PARTNER__"
    Route   payflowpro    vendor             "__PAYFLOWPRO_VENDOR__"
    Route   payflowpro    host               "__PAYFLOWPRO_SERVER__"
    Route   payflowpro    transaction        A
    Route   payflowpro    global_timeout     20
    Route   payflowpro    global_timeout_msg "We're sorry, but due to a system error, we are unable to process online orders at this time. Please call __TOLLFREE__ and let one of our customer-service specialists assist you. We apologize for the inconvenience."

Revision  Changes    Path
2.22                 interchange/lib/Vend/Payment.pm


rev 2.22, prev_rev 2.21
Index: Payment.pm
===================================================================
RCS file: /var/cvs/interchange/lib/Vend/Payment.pm,v
retrieving revision 2.21
retrieving revision 2.22
diff -u -r2.21 -r2.22
--- Payment.pm	16 Mar 2009 19:34:00 -0000	2.21
+++ Payment.pm	20 Mar 2009 16:40:34 -0000	2.22
@@ -1,6 +1,6 @@
 # Vend::Payment - Interchange payment processing routines
 #
-# $Id: Payment.pm,v 2.21 2009-03-16 19:34:00 jon Exp $
+# $Id: Payment.pm,v 2.22 2009-03-20 16:40:34 markj Exp $
 #
 # Copyright (C) 2002-2009 Interchange Development Group
 # Copyright (C) 1996-2002 Red Hat, Inc.
@@ -23,7 +23,7 @@
 package Vend::Payment;
 require Exporter;
 
-$VERSION = substr(q$Revision: 2.21 $, 10);
+$VERSION = substr(q$Revision: 2.22 $, 10);
 
 @ISA = qw(Exporter);
 
@@ -39,6 +39,7 @@
 use Vend::Util;
 use Vend::Interpolate;
 use Vend::Order;
+use IO::Pipe;
 use strict;
 
 use vars qw/$Have_LWP $Have_Net_SSLeay/;
@@ -389,15 +390,61 @@
 #::logDebug("Charge sub");
 		# Calling a defined GlobalSub payment mode
 		# Arguments are the passed option hash (if any) and the route hash
-		eval {
-			%result = $sub->($pay_opt);
-		};
+
+        my $pid;
+        my $timeout = $pay_opt->{global_timeout} || charge_param('global_timeout');
+
+        %result = eval {
+            if ($timeout > 0) {
+
+                my $pipe = IO::Pipe->new;
+
+                unless ($pid = fork) {
+
+                    $pipe->writer;
+
+                    eval {
+                        my %d = DBI->installed_drivers;
+                        for my $h (values %d) {
+                            $_->{InactiveDestroy} = 1
+                                for grep { defined } @{ $h->{ChildHandles} };
+                        }
+                    };
+
+                    my %rv = $sub->($pay_opt);
+
+                    $pipe->print( ::uneval(\%rv) );
+                    exit;
+                }
+
+                $pipe->reader;
+
+                my $to_msg = $pay_opt->{global_timeout_msg}
+                    || 'Due to technical difficulties, your order could not be processed.';
+                local $SIG{ALRM} = sub { die $to_msg };
+
+                alarm $timeout;
+                wait;
+                alarm 0;
+
+                $pid = undef;
+
+                my $rv = eval join ('', $pipe->getlines);
+
+                return %$rv;
+            }
+
+            return $sub->($pay_opt);
+        };
+
 		if($@) {
 			my $msg = errmsg(
 						"payment routine '%s' returned error: %s",
 						$charge_type,
 						$@,
 			);
+            kill (KILL => $pid)
+                if $pid && kill (0 => $pid);
 			::logError($msg);
 			$result{MStatus} = 'died';
 			$result{MErrMsg} = $msg;







More information about the interchange-cvs mailing list