[freeside-commits] branch master updated. a1a0800de7c69fe5ee414b79e408ceacd4a1c2c3

Mark Wells mark at 420.am
Thu Apr 25 14:46:40 PDT 2013


The branch, master has been updated
       via  a1a0800de7c69fe5ee414b79e408ceacd4a1c2c3 (commit)
      from  f3e0ac2b009c4edd5692cb587ff709dac2223ebe (commit)

Those revisions listed above that are new to this repository have
not appeared on any other notification email; so we list those
revisions in full, below.

- Log -----------------------------------------------------------------
commit a1a0800de7c69fe5ee414b79e408ceacd4a1c2c3
Author: Mark Wells <mark at freeside.biz>
Date:   Thu Apr 25 14:45:49 2013 -0700

    changes to support PayPal, #22395

diff --git a/FS/FS/ClientAPI/Signup.pm b/FS/FS/ClientAPI/Signup.pm
index 1dbb20b..c3beb69 100644
--- a/FS/FS/ClientAPI/Signup.pm
+++ b/FS/FS/ClientAPI/Signup.pm
@@ -946,15 +946,27 @@ sub capture_payment {
   }
 
   my $cust_main = $cust_pay_pending->cust_main;
-  my $bill_error =
-    $cust_main->realtime_botpp_capture( $cust_pay_pending, 
-      %{$packet->{data}},
-      apply => 1,
-  );
+  if ( $packet->{cancel} ) {
+    # the user has chosen not to make this payment
+    # (probably should be a separate API call, but I don't want to duplicate
+    # all of the above...which should eventually go away)
+    my $error = $cust_pay_pending->delete;
+    # don't show any errors related to this; they're not meaningful
+    warn "error canceling pending payment $paypendingnum: $error\n" if $error;
+    return { 'error'      => '_cancel',
+             'session_id' => $cust_pay_pending->session_id };
+  } else {
+    # create the payment
+    my $bill_error =
+      $cust_main->realtime_botpp_capture( $cust_pay_pending, 
+        %{$packet->{data}},
+        apply => 1,
+    );
 
-  return { 'error'      => ( $bill_error->{bill_error} ? '_decline' : '' ),
-           %$bill_error,
-         };
+    return { 'error'      => ( $bill_error->{bill_error} ? '_decline' : '' ),
+             %$bill_error,
+           };
+  }
 
 }
 
diff --git a/FS/FS/Conf.pm b/FS/FS/Conf.pm
index 6a19ff4..8dbc070 100644
--- a/FS/FS/Conf.pm
+++ b/FS/FS/Conf.pm
@@ -2098,7 +2098,7 @@ and customer address. Include units.',
     'section'     => 'self-service',
     'description' => 'Acceptable payment types for the signup server',
     'type'        => 'selectmultiple',
-    'select_enum' => [ qw(CARD DCRD CHEK DCHK LECB PREPAY BILL COMP) ],
+    'select_enum' => [ qw(CARD DCRD CHEK DCHK LECB PREPAY PPAL BILL COMP) ],
   },
 
   {
@@ -2472,7 +2472,7 @@ and customer address. Include units.',
     'section'     => 'billing',
     'description' => 'Available payment types.',
     'type'        => 'selectmultiple',
-    'select_enum' => [ qw(CARD DCRD CHEK DCHK LECB BILL CASH WEST MCRD COMP) ],
+    'select_enum' => [ qw(CARD DCRD CHEK DCHK LECB BILL CASH WEST MCRD PPAL COMP) ],
   },
 
   {
@@ -2480,7 +2480,7 @@ and customer address. Include units.',
     'section'     => 'UI',
     'description' => 'Default payment type.  HIDE disables display of billing information and sets customers to BILL.',
     'type'        => 'select',
-    'select_enum' => [ '', qw(CARD DCRD CHEK DCHK LECB BILL CASH WEST MCRD COMP HIDE) ],
+    'select_enum' => [ '', qw(CARD DCRD CHEK DCHK LECB BILL CASH WEST MCRD PPAL COMP HIDE) ],
   },
 
   {
diff --git a/FS/FS/Schema.pm b/FS/FS/Schema.pm
index eb73ccb..4f395f2 100644
--- a/FS/FS/Schema.pm
+++ b/FS/FS/Schema.pm
@@ -3267,7 +3267,8 @@ sub tables_hashref {
         'gateway_username', 'varchar',  'NULL', $char_d, '', '', 
         'gateway_password', 'varchar',  'NULL', $char_d, '', '', 
         'gateway_action',   'varchar',  'NULL', $char_d, '', '', 
-        'gateway_callback_url', 'varchar',  'NULL', $char_d, '', '', 
+        'gateway_callback_url', 'varchar',  'NULL', 255, '', '', 
+        'gateway_cancel_url',   'varchar',  'NULL', 255, '', '',
         'disabled',   'char',  'NULL',   1, '', '', 
       ],
       'primary_key' => 'gatewaynum',
diff --git a/FS/FS/agent.pm b/FS/FS/agent.pm
index 3794d3f..9b32209 100644
--- a/FS/FS/agent.pm
+++ b/FS/FS/agent.pm
@@ -216,7 +216,7 @@ an attempt will be made to select a gateway suited for the taxes paid on
 the invoice.
 
 The I<method> and I<payinfo> options can be used to influence the choice
-as well.  Presently only 'CC' and 'ECHECK' methods are meaningful.
+as well.  Presently only 'CC', 'ECHECK', and 'PAYPAL' methods are meaningful.
 
 When the I<method> is 'CC' then the card number in I<payinfo> can direct
 this routine to route to a gateway suited for that type of card.
@@ -246,13 +246,17 @@ sub payment_gateway {
   }
 
   #look for an agent gateway override first
-  my $cardtype;
-  if ( $options{method} && $options{method} eq 'CC' && $options{payinfo} ) {
-    $cardtype = cardtype($options{payinfo});
-  } elsif ( $options{method} && $options{method} eq 'ECHECK' ) {
-    $cardtype = 'ACH';
-  } else {
-    $cardtype = $options{method} || '';
+  my $cardtype = '';
+  if ( $options{method} ) {
+    if ( $options{method} eq 'CC' && $options{payinfo} ) {
+      $cardtype = cardtype($options{payinfo});
+    } elsif ( $options{method} eq 'ECHECK' ) {
+      $cardtype = 'ACH';
+    } elsif ( $options{method} eq 'PAYPAL' ) {
+      $cardtype = 'PayPal';
+    } else {
+      $cardtype = $options{method}
+    }
   }
 
   my $override =
diff --git a/FS/FS/cust_main.pm b/FS/FS/cust_main.pm
index 2a4602e..1cf0365 100644
--- a/FS/FS/cust_main.pm
+++ b/FS/FS/cust_main.pm
@@ -390,7 +390,7 @@ sub insert {
 
     $payby = 'PREP' if $amount;
 
-  } elsif ( $self->payby =~ /^(CASH|WEST|MCRD)$/ ) {
+  } elsif ( $self->payby =~ /^(CASH|WEST|MCRD|PPAL)$/ ) {
 
     $payby = $1;
     $self->payby('BILL');
@@ -2021,7 +2021,8 @@ sub check {
 
   if ( $self->paydate eq '' || $self->paydate eq '-' ) {
     return "Expiration date required"
-      unless $self->payby =~ /^(BILL|PREPAY|CHEK|DCHK|LECB|CASH|WEST|MCRD)$/;
+      # shouldn't payinfo_check do this?
+      unless $self->payby =~ /^(BILL|PREPAY|CHEK|DCHK|LECB|CASH|WEST|MCRD|PPAL)$/;
     $self->paydate('');
   } else {
     my( $m, $y );
diff --git a/FS/FS/cust_main/Billing_Realtime.pm b/FS/FS/cust_main/Billing_Realtime.pm
index 804969b..1caa3e5 100644
--- a/FS/FS/cust_main/Billing_Realtime.pm
+++ b/FS/FS/cust_main/Billing_Realtime.pm
@@ -111,7 +111,7 @@ L<http://420.am/business-onlinepayment> for supported gateways.
 
 Required arguments in the hashref are I<method>, and I<amount>
 
-Available methods are: I<CC>, I<ECHECK> and I<LEC>
+Available methods are: I<CC>, I<ECHECK>, I<LEC>, and I<PAYPAL>
 
 Available optional arguments are: I<description>, I<invnum>, I<apply>, I<quiet>, I<paynum_ref>, I<payunique>, I<session_id>
 
@@ -317,6 +317,7 @@ my %bop_method2payby = (
   'CC'     => 'CARD',
   'ECHECK' => 'CHEK',
   'LEC'    => 'LECB',
+  'PAYPAL' => 'PPAL',
 );
 
 sub realtime_bop {
@@ -612,6 +613,7 @@ sub realtime_bop {
     %$bop_content,
     'reference'      => $cust_pay_pending->paypendingnum, #for now
     'callback_url'   => $payment_gateway->gateway_callback_url,
+    'cancel_url'     => $payment_gateway->gateway_cancel_url,
     'email'          => $email,
     %content, #after
   );
diff --git a/FS/FS/payby.pm b/FS/FS/payby.pm
index d1961a5..e223a05 100644
--- a/FS/FS/payby.pm
+++ b/FS/FS/payby.pm
@@ -208,6 +208,7 @@ sub longname {
   'CARD' => 'CC',
   'CHEK' => 'ECHECK',
   'MCRD' => 'CC',
+  'PPAL' => 'PAYPAL',
 );
 
 sub payby2bop {
diff --git a/FS/FS/payinfo_Mixin.pm b/FS/FS/payinfo_Mixin.pm
index 9879a3a..8263252 100644
--- a/FS/FS/payinfo_Mixin.pm
+++ b/FS/FS/payinfo_Mixin.pm
@@ -44,26 +44,18 @@ For Refunds (cust_refund):
 For Payments (cust_pay):
 'CARD' (credit cards), 'CHEK' (electronic check/ACH),
 'LECB' (phone bill billing), 'BILL' (billing), 'PREP' (prepaid card),
-'CASH' (cash), 'WEST' (Western Union), or 'MCRD' (Manual credit card)
+'CASH' (cash), 'WEST' (Western Union), 'MCRD' (Manual credit card),
+'PPAL' (PayPal)
 'COMP' (free) is depricated as a payment type in cust_pay
 
 =cut 
 
-# was this supposed to do something?
- 
-#sub payby {
-#  my($self,$payby) = @_;
-#  if ( defined($payby) ) {
-#    $self->setfield('payby', $payby);
-#  } 
-#  return $self->getfield('payby')
-#}
-
 =item payinfo
 
 Payment information (payinfo) can be one of the following types:
 
-Card Number, P.O., comp issuer (4-8 lowercase alphanumerics; think username) or prepayment identifier (see L<FS::prepay_credit>)
+Card Number, P.O., comp issuer (4-8 lowercase alphanumerics; think username) 
+prepayment identifier (see L<FS::prepay_credit>), PayPal transaction ID
 
 =cut
 
@@ -267,6 +259,8 @@ sub payby_payinfo_pretty {
     'Western Union'; #. $self->payinfo;
   } elsif ( $self->payby eq 'MCRD' ) {
     'Manual credit card'; #. $self->payinfo;
+  } elsif ( $self->payby eq 'PPAL' ) {
+    'PayPal transaction#' . $self->order_number;
   } else {
     $self->payby. ' '. $self->payinfo;
   }
diff --git a/FS/FS/payment_gateway.pm b/FS/FS/payment_gateway.pm
index 4a7585e..e94a62c 100644
--- a/FS/FS/payment_gateway.pm
+++ b/FS/FS/payment_gateway.pm
@@ -41,7 +41,7 @@ currently supported:
 
 =item gateway_namespace - Business::OnlinePayment, Business::OnlineThirdPartyPayment, or Business::BatchPayment
 
-=item gateway_module - Business::OnlinePayment:: module name
+=item gateway_module - Business::OnlinePayment:: (or other) module name
 
 =item gateway_username - payment gateway username
 
@@ -51,6 +51,14 @@ currently supported:
 
 =item disabled - Disabled flag, empty or 'Y'
 
+=item gateway_callback_url - For ThirdPartyPayment only, set to the URL that 
+the user should be redirected to on a successful payment.  This will be sent
+as a transaction parameter (named "callback_url").
+
+=item gateway_cancel_url - For ThirdPartyPayment only, set to the URL that 
+the user should be redirected to if they cancel the transaction.  PayPal
+requires this; other gateways ignore it.
+
 =item auto_resolve_status - For BatchPayment only, set to 'approve' to 
 auto-approve unresolved payments after some number of days, 'reject' to 
 auto-decline them, or null to do nothing.
@@ -128,6 +136,7 @@ sub check {
     || $self->ut_textn('gateway_username')
     || $self->ut_anything('gateway_password')
     || $self->ut_textn('gateway_callback_url')  # a bit too permissive
+    || $self->ut_textn('gateway_cancel_url')
     || $self->ut_enum('disabled', [ '', 'Y' ] )
     || $self->ut_enum('auto_resolve_status', [ '', 'approve', 'reject' ])
     || $self->ut_numbern('auto_resolve_days')
@@ -152,8 +161,8 @@ sub check {
   }
 
   # this little kludge mimics FS::CGI::popurl
-  $self->gateway_callback_url($self->gateway_callback_url. '/')
-    if ( $self->gateway_callback_url && $self->gateway_callback_url !~ /\/$/ );
+  #$self->gateway_callback_url($self->gateway_callback_url. '/')
+  #  if ( $self->gateway_callback_url && $self->gateway_callback_url !~ /\/$/ );
 
   $self->SUPER::check;
 }
diff --git a/fs_selfservice/FS-SelfService/cgi/make_thirdparty_payment.html b/fs_selfservice/FS-SelfService/cgi/make_thirdparty_payment.html
index b5b9eea..59ee93b 100755
--- a/fs_selfservice/FS-SelfService/cgi/make_thirdparty_payment.html
+++ b/fs_selfservice/FS-SelfService/cgi/make_thirdparty_payment.html
@@ -8,7 +8,7 @@ onSubmit="document.OneTrueForm.process.disabled=true">
 <INPUT TYPE="hidden" NAME="session" VALUE="<%=$session_id%>">
 <INPUT TYPE="hidden" NAME="action" VALUE="post_thirdparty_payment">
 <INPUT TYPE="hidden" NAME="payby_method" VALUE="<%= 
-$cgi->param('payby_method') =~ /(CC|ECHECK)/;
+$cgi->param('payby_method') =~ /(CC|ECHECK|PAYPAL)/;
 $1 %>">
 <TABLE BGCOLOR="#cccccc">
 <TR>
diff --git a/fs_selfservice/FS-SelfService/cgi/myaccount.html b/fs_selfservice/FS-SelfService/cgi/myaccount.html
index 9ab2622..a6352e0 100644
--- a/fs_selfservice/FS-SelfService/cgi/myaccount.html
+++ b/fs_selfservice/FS-SelfService/cgi/myaccount.html
@@ -6,18 +6,13 @@ Hello <%= $name %>!<BR><BR>
 <%= include('small_custview') %>
 
 <BR>
-<%= unless ( $access_pkgnum ) {
-      $OUT .= qq!Balance: <B>\$$balance</B><BR><BR>!;
-    }
-    '';
-%>
 
 <%=
   $OUT .= qq! <B><A HREF="${url}invoices">View All Invoices</A></B>     !;
 %>
 
 <%= if ( $balance > 0 ) {
-  if (scalar(grep $_, @hide_payment_fields)) {
+  if (scalar(grep $_, @hide_payment_fields)) { # this sucks
     $OUT .= qq! <B><A HREF="${url}make_thirdparty_payment&payby_method=CC">Make a payment</A></B><BR><BR>!;
   } else {
     $OUT .= qq! <B><A HREF="${url}make_payment">Make a payment</A></B><BR>!;
diff --git a/fs_selfservice/FS-SelfService/cgi/myaccount_menu.html b/fs_selfservice/FS-SelfService/cgi/myaccount_menu.html
index 4a31b12..cf719e8 100644
--- a/fs_selfservice/FS-SelfService/cgi/myaccount_menu.html
+++ b/fs_selfservice/FS-SelfService/cgi/myaccount_menu.html
@@ -23,37 +23,44 @@ unless ( $access_pkgnum ) {
       url=>'customer_order_pkg', 'indent'=>2 };
 }
 
+my %payby_mode;
+ at payby_mode{@cust_paybys} = @hide_payment_fields;
+# $payby_mode{FOO} is true if FOO is thirdparty, false if it's B::OP,
+# nonexistent if it's not supported
+
 if ( $balance > 0 ) { #XXXFIXME "enable selfservice prepay features" flag or something, eventually per-pkg or something really fancy
 
-  #XXXFIXME still a bit sloppy for multi-gateway of differing namespace
-  my $i = 0;
-  while($i < scalar(@cust_paybys)) { last if $cust_paybys[$i] =~ /^CARD/; $i++ }
-  if ( $cust_paybys[$i] && $cust_paybys[$i] =~ /^CARD/ ) {
+  if ( exists( $payby_mode{CARD} ) ) {
     push @menu, { title  => 'Recharge my account with a credit card',
-                  url    => $hide_payment_fields[$i]
+                  url    => $payby_mode{CARD}
                               ? 'make_thirdparty_payment&payby_method=CC'
                               : 'make_payment',
                   indent => 2,
                  }
   }
 
-  $i = 0;
-  while($i < scalar(@cust_paybys)) { last if $cust_paybys[$i] =~ /^CHEK/; $i++ }
-  if ( $cust_paybys[$i] && $cust_paybys[$i] =~ /^CHEK/ ) {
+  if ( exists( $payby_mode{CHEK} ) ) {
     push @menu, { title  => 'Recharge my account with a check',
-                  url    => $hide_payment_fields[$i]
+                  url    => $payby_mode{CHEK}
                               ? 'make_thirdparty_payment&payby_method=ECHECK'
                               : 'make_ach_payment',
                   indent => 2,
                 }
   }
 
-  push @menu, { title  => 'Recharge my account with a prepaid card',
-                url    => 'recharge_prepay',
-                indent => 2,
-              }
-    if grep(/^PREP/, @cust_paybys);
+  if ( exists( $payby_mode{PREP} ) ) {
+    push @menu, { title  => 'Recharge my account with a prepaid card',
+                  url    => 'recharge_prepay',
+                  indent => 2,
+                }
+  }
 
+  if ( exists( $payby_mode{PPAL} ) ) {
+    push @menu, { title  => 'Recharge my account with PayPal',
+                  url    => 'make_thirdparty_payment&payby_method=PAYPAL',
+                  indent => 2,
+                }
+  }
 }
 
 push @menu,
diff --git a/fs_selfservice/FS-SelfService/cgi/selfservice.cgi b/fs_selfservice/FS-SelfService/cgi/selfservice.cgi
index f7fe308..40fe98a 100755
--- a/fs_selfservice/FS-SelfService/cgi/selfservice.cgi
+++ b/fs_selfservice/FS-SelfService/cgi/selfservice.cgi
@@ -667,12 +667,15 @@ sub make_thirdparty_payment {
 }
 
 sub post_thirdparty_payment {
-  $cgi->param('payby_method') =~ /^(CC|ECHECK)$/
+  $cgi->param('payby_method') =~ /^(CC|ECHECK|PAYPAL)$/
     or die "illegal payby method";
   my $method = $1;
   $cgi->param('amount') =~ /^(\d+(\.\d*)?)$/
     or die "illegal amount";
   my $amount = $1;
+  # realtime_collect() returns the result from FS::cust_main->realtime_collect
+  # which returns realtime_bop()
+  # which returns a hashref of popup_url, collectitems, and reference
   my $result = realtime_collect( 
     'session_id' => $session_id,
     'method' => $method, 
diff --git a/fs_selfservice/FS-SelfService/cgi/verify.cgi b/fs_selfservice/FS-SelfService/cgi/verify.cgi
index d9346b8..ff209d2 100755
--- a/fs_selfservice/FS-SelfService/cgi/verify.cgi
+++ b/fs_selfservice/FS-SelfService/cgi/verify.cgi
@@ -87,11 +87,14 @@ my $rv = capture_payment(
                      map { $_ => scalar($cgi->param($_)) } $cgi->param
                    },
            url  => $cgi->self_url,
+           cancel => ($cgi->param('cancel') ? 1 : 0),
 );
 
 $error = $rv->{error};
-  
-if ( $error eq '_decline' ) {
+
+if ( $error eq '_cancel' ) {
+  print_okay(%$rv);
+} elsif ( $error eq '_decline' ) {
   print_decline();
 } elsif ( $error ) {
   print_verify();
@@ -133,8 +136,14 @@ sub print_okay {
     $success_url .= '/signup.cgi?action=success';
   }
 
-  print $cgi->header( '-expires' => 'now' ),
-        $success_template->fill_in( HASH => { success_url => $success_url } );
+  if ( $param{error} eq '_cancel' ) {
+    # then the payment was canceled, so don't show a message, just redirect
+    # (during signup, you really need a separate landing page for this case)
+    print $cgi->redirect($success_url);
+  } else {
+    print $cgi->header( '-expires' => 'now' ),
+          $success_template->fill_in( HASH => { success_url => $success_url } );
+  }
 }
 
 sub success_default { #html to use if you don't specify a success file
diff --git a/httemplate/edit/agent_payment_gateway.html b/httemplate/edit/agent_payment_gateway.html
index 4a7cedf..41a9f3e 100644
--- a/httemplate/edit/agent_payment_gateway.html
+++ b/httemplate/edit/agent_payment_gateway.html
@@ -34,6 +34,7 @@ for <SELECT NAME="cardtype" MULTIPLE>
 %  "Switch",
 %  "Solo",
 %  'ACH',
+%  'PayPal',
 %) { 
 
   <OPTION VALUE="<% $cardtype %>"><% $cardtype || '(Default fallback)' %>
diff --git a/httemplate/edit/payment_gateway.html b/httemplate/edit/payment_gateway.html
index a469beb..7cfab71 100644
--- a/httemplate/edit/payment_gateway.html
+++ b/httemplate/edit/payment_gateway.html
@@ -13,15 +13,16 @@
                                   'gateway_action'       => 'Action',
                                   'gateway_options'      => 'Options (Name/Value pairs, <BR>one element per line)',
                                   'gateway_callback_url' => 'Callback URL',
+                                  'gateway_cancel_url'   => 'Cancel URL',
                                 },
           )
 %>
 
 
 <SCRIPT TYPE="text/javascript">
-  var modulesForNamespace = <% encode_json(\%modules_for_namespace, {canonical=>1}) %>;
-  function changeNamespace(what) {
-    var ns = what.value;
+  var modulesForNamespace = <% $json->encode(\%modules) %>;
+  function changeNamespace() {
+    var ns = document.getElementById('gateway_namespace').value;
     var select_module = document.getElementById('gateway_module');
     select_module.options.length = 0;
     for (var x in modulesForNamespace[ns]) {
@@ -30,6 +31,7 @@
       select_module.add(o, null);
     }
   }
+  window.onload = changeNamespace;
 </SCRIPT>
 
 <%init>
@@ -37,69 +39,71 @@
 die "access denied"
   unless $FS::CurrentUser::CurrentUser->access_right('Configuration');
 
-my %modules =  (
-  '2CheckOut'             => 'Business::OnlinePayment',
-  'AuthorizeNet'          => 'Business::OnlinePayment',
-  'BankOfAmerica'         => 'Business::OnlinePayment', #deprecated?
-  'Beanstream'            => 'Business::OnlinePayment',
-  'Capstone'              => 'Business::OnlinePayment',
-  'Cardstream'            => 'Business::OnlinePayment',
-  'CashCow'               => 'Business::OnlinePayment',
-  'CyberSource'           => 'Business::OnlinePayment',
-  'eSec'                  => 'Business::OnlinePayment',
-  'eSelectPlus'           => 'Business::OnlinePayment',
-  'eWayShared'            => 'Business::OnlineThirdPartyPayment',
-  'ElavonVirtualMerchant' => 'Business::OnlinePayment',
-  'Exact'                 => 'Business::OnlinePayment',
-  'iAuthorizer'           => 'Business::OnlinePayment',
-  'Ingotz'                => 'Business::OnlinePayment',
-  'InternetSecure'        => 'Business::OnlinePayment',
-  'Interswitchng'         => 'Business::OnlineThirdPartyPayment',
-  'IPaymentTPG'           => 'Business::OnlinePayment',
-  'IPPay'                 => 'Business::OnlinePayment',
-  'Iridium'               => 'Business::OnlinePayment',
-  'Jettis'                => 'Business::OnlinePayment',
-  'Jety'                  => 'Business::OnlinePayment',
-  'LinkPoint'             => 'Business::OnlinePayment',
-  'MerchantCommerce'      => 'Business::OnlinePayment',
-  'Network1Financial'     => 'Business::OnlinePayment',
-  'OCV'                   => 'Business::OnlinePayment',
-  'OpenECHO'              => 'Business::OnlinePayment',
-  'PayConnect'            => 'Business::OnlinePayment',
-  'PayflowPro'            => 'Business::OnlinePayment',
-  'PaymenTech'            => 'Business::OnlinePayment',
-  'PaymentsGateway'       => 'Business::OnlinePayment',
-  'PayPal'                => 'Business::OnlinePayment',
-  #'PaySystems'            => 'Business::OnlinePayment',
-  'PlugnPay'              => 'Business::OnlinePayment',
-  'PPIPayMover'           => 'Business::OnlinePayment',
-  'Protx'                 => 'Business::OnlinePayment', #now SagePay
-  'PXPost'                => 'Business::OnlinePayment',
-  'SagePay'               => 'Business::OnlinePayment',
-  'SecureHostingUPG'      => 'Business::OnlinePayment',
-  'Skipjack'              => 'Business::OnlinePayment',
-  'StGeorge'              => 'Business::OnlinePayment',
-  'SurePay'               => 'Business::OnlinePayment',
-  'TCLink'                => 'Business::OnlinePayment',
-  'TransactionCentral'    => 'Business::OnlinePayment',
-  'TransFirsteLink'       => 'Business::OnlinePayment',
-  'Vanco'                 => 'Business::OnlinePayment',
-  'viaKLIX'               => 'Business::OnlinePayment',
-  'VirtualNet'            => 'Business::OnlinePayment',
-  'WesternACH'            => 'Business::OnlinePayment',
-  'WorldPay'              => 'Business::OnlinePayment',
-
-  'KeyBank'               => 'Business::BatchPayment',
-  'Paymentech'            => 'Business::BatchPayment',
-  'TD_EFT'                => 'Business::BatchPayment',
+my $json = JSON::XS->new;
+$json->canonical(1);
+my %modules = (
+  'Business::OnlinePayment' => [
+    '2CheckOut',
+    'AuthorizeNet',
+    'BankOfAmerica', #deprecated?
+    'Beanstream',
+    'Capstone',
+    'Cardstream',
+    'CashCow',
+    'CyberSource',
+    'eSec',
+    'eSelectPlus',
+    'ElavonVirtualMerchant',
+    'Exact',
+    'iAuthorizer',
+    'Ingotz',
+    'InternetSecure',
+    'IPaymentTPG',
+    'IPPay',
+    'Iridium',
+    'Jettis',
+    'Jety',
+    'LinkPoint',
+    'MerchantCommerce',
+    'Network1Financial',
+    'OCV',
+    'OpenECHO',
+    'PayConnect',
+    'PayflowPro',
+    'PaymenTech',
+    'PaymentsGateway',
+    'PayPal',
+    #'PaySystems',
+    'PlugnPay',
+    'PPIPayMover',
+    'Protx', #now SagePay
+    'PXPost',
+    'SagePay',
+    'SecureHostingUPG',
+    'Skipjack',
+    'StGeorge',
+    'SurePay',
+    'TCLink',
+    'TransactionCentral',
+    'TransFirsteLink',
+    'Vanco',
+    'viaKLIX',
+    'VirtualNet',
+    'WesternACH',
+    'WorldPay',
+  ],
+  'Business::OnlineThirdPartyPayment' => [
+    'eWayShared',
+    'Interswitchng',
+    'PayPal',
+  ],
+  'Business::BatchPayment' => [
+    'KeyBank',
+    'Paymentech',
+    'TD_EFT',
+  ],
 );
 
-my %modules_for_namespace;
-for (keys %modules) {
-  $modules_for_namespace{$modules{$_}} ||= [];
-  push @{ $modules_for_namespace{$modules{$_}} }, $_;
-}
-
 my @actions = (
                 'Normal Authorization',
                 'Authorization Only',
@@ -125,7 +129,9 @@ my $fields = [
                {
                  field    => 'gateway_module',
                  type     => 'select',
-                 options  => [ sort { lc($a) cmp lc ($b) } keys %modules ],
+                 # does it even make sense to list all modules here?
+                 options  => [ sort { lc($a) cmp lc ($b) }
+                               map { @$_ } values %modules ],
                },
                'gateway_username',
                'gateway_password',
@@ -140,6 +146,11 @@ my $fields = [
                  size     => 40,
                },
                {
+                 field    => 'gateway_cancel_url',
+                 type     => 'text',
+                 size     => 40,
+               },
+               {
                  field               => 'gateway_options',
                  type                => 'textarea',
                  rows                => '12',
diff --git a/httemplate/edit/process/payment_gateway.html b/httemplate/edit/process/payment_gateway.html
index 812c988..157449e 100644
--- a/httemplate/edit/process/payment_gateway.html
+++ b/httemplate/edit/process/payment_gateway.html
@@ -15,6 +15,7 @@ my $args_callback = sub {
   my @options = split(/\r?\n/, $cgi->param('gateway_options') );
   pop @options
     if scalar(@options) % 2 && $options[-1] =~ /^\s*$/;
+  @options = ( {} ) if !@options;
   (@options)
 };
 

-----------------------------------------------------------------------

Summary of changes:
 FS/FS/ClientAPI/Signup.pm                          |   28 +++-
 FS/FS/Conf.pm                                      |    6 +-
 FS/FS/Schema.pm                                    |    3 +-
 FS/FS/agent.pm                                     |   20 ++-
 FS/FS/cust_main.pm                                 |    5 +-
 FS/FS/cust_main/Billing_Realtime.pm                |    4 +-
 FS/FS/payby.pm                                     |    1 +
 FS/FS/payinfo_Mixin.pm                             |   18 +--
 FS/FS/payment_gateway.pm                           |   15 ++-
 .../cgi/make_thirdparty_payment.html               |    2 +-
 fs_selfservice/FS-SelfService/cgi/myaccount.html   |    7 +-
 .../FS-SelfService/cgi/myaccount_menu.html         |   35 +++--
 fs_selfservice/FS-SelfService/cgi/selfservice.cgi  |    5 +-
 fs_selfservice/FS-SelfService/cgi/verify.cgi       |   17 ++-
 httemplate/edit/agent_payment_gateway.html         |    1 +
 httemplate/edit/payment_gateway.html               |  141 +++++++++++---------
 httemplate/edit/process/payment_gateway.html       |    1 +
 17 files changed, 180 insertions(+), 129 deletions(-)




More information about the freeside-commits mailing list