don't credit-card-surcharge-percentage to ACH, RT#34815
[freeside.git] / FS / FS / cust_main / Billing_Realtime.pm
index 6e89f71..d973896 100644 (file)
@@ -3,6 +3,7 @@ package FS::cust_main::Billing_Realtime;
 use strict;
 use vars qw( $conf $DEBUG $me );
 use vars qw( $realtime_bop_decline_quiet ); #ugh
+use Carp;
 use Data::Dumper;
 use Business::CreditCard 0.28;
 use FS::UID qw( dbh );
@@ -44,6 +45,36 @@ These methods are available on FS::cust_main objects.
 
 =over 4
 
+=item realtime_cust_payby
+
+=cut
+
+sub realtime_cust_payby {
+  my( $self, %options ) = @_;
+
+  local($DEBUG) = $FS::cust_main::DEBUG if $FS::cust_main::DEBUG > $DEBUG;
+
+  $options{amount} = $self->balance unless exists( $options{amount} );
+
+  my @cust_payby = qsearch({
+    'table'     => 'cust_payby',
+    'hashref'   => { 'custnum' => $self->custnum, },
+    'extra_sql' => " AND payby IN ( 'CARD', 'CHEK' ) ",
+    'order_by'  => 'ORDER BY weight ASC',
+  });
+                                                   
+  my $error;
+  foreach my $cust_payby (@cust_payby) {
+    $error = $cust_payby->realtime_bop( %options, );
+    last unless $error;
+  }
+
+  #XXX what about the earlier errors?
+
+  $error;
+
+}
+
 =item realtime_collect [ OPTION => VALUE ... ]
 
 Attempt to collect the customer's current balance with a realtime credit 
@@ -300,10 +331,6 @@ sub _bop_content {
                         ? $options->{country}
                         : $self->country;
 
-  #3.0 is a good a time as any to get rid of this... add a config to pass it
-  # if anyone still needs it
-  #$content{referer} = 'http://cleanwhisker.420.am/';
-
   $content{phone} = $self->daytime || $self->night;
 
   my $currency =    $conf->exists('business-onlinepayment-currency')
@@ -323,6 +350,10 @@ my %bop_method2payby = (
 sub realtime_bop {
   my $self = shift;
 
+  confess "Can't call realtime_bop within another transaction ".
+          '($FS::UID::AutoCommit is false)'
+    unless $FS::UID::AutoCommit;
+
   local($DEBUG) = $FS::cust_main::DEBUG if $FS::cust_main::DEBUG > $DEBUG;
  
   my %options = ();
@@ -343,8 +374,9 @@ sub realtime_bop {
   my $cc_surcharge = 0;
   my $cc_surcharge_pct = 0;
   $cc_surcharge_pct = $conf->config('credit-card-surcharge-percentage') 
-    if $conf->config('credit-card-surcharge-percentage');
-  
+    if $conf->config('credit-card-surcharge-percentage')
+    && $options{method} eq 'CC';
+
   # always add cc surcharge if called from event 
   if($options{'cc_surcharge_from_event'} && $cc_surcharge_pct > 0) {
       $cc_surcharge = $options{'amount'} * $cc_surcharge_pct / 100;
@@ -364,6 +396,8 @@ sub realtime_bop {
   if ( $DEBUG ) {
     warn "$me realtime_bop (new): $options{method} $options{amount}\n";
     warn " cc_surcharge = $cc_surcharge\n";
+  }
+  if ( $DEBUG > 2 ) {
     warn "  $_ => $options{$_}\n" foreach keys %options;
   }
 
@@ -546,7 +580,9 @@ sub realtime_bop {
                   ? $options{'balance'}
                   : $self->balance;
 
+  warn "claiming mutex on customer ". $self->custnum. "\n" if $DEBUG > 1;
   $self->select_for_update; #mutex ... just until we get our pending record in
+  warn "obtained mutex on customer ". $self->custnum. "\n" if $DEBUG > 1;
 
   #the checks here are intended to catch concurrent payments
   #double-form-submission prevention is taken care of in cust_pay_pending::check
@@ -597,9 +633,16 @@ sub realtime_bop {
   };
   $cust_pay_pending->payunique( $options{payunique} )
     if defined($options{payunique}) && length($options{payunique});
+
+  warn "inserting cust_pay_pending record for customer ". $self->custnum. "\n"
+    if $DEBUG > 1;
   my $cpp_new_err = $cust_pay_pending->insert; #mutex lost when this is inserted
   return $cpp_new_err if $cpp_new_err;
 
+  warn "inserted cust_pay_pending record for customer ". $self->custnum. "\n"
+    if $DEBUG > 1;
+  warn Dumper($cust_pay_pending) if $DEBUG > 2;
+
   my( $action1, $action2 ) =
     split( /\s*\,\s*/, $payment_gateway->gateway_action );
 
@@ -1010,8 +1053,9 @@ sub _realtime_bop_result {
 
   } else {
 
-    my $perror = $payment_gateway->gateway_module. " error: ".
-      $transaction->error_message;
+    my $perror = $transaction->error_message;
+    #$payment_gateway->gateway_module. " error: ".
+    # removed for conciseness
 
     my $jobnum = $cust_pay_pending->jobnum;
     if ( $jobnum ) {
@@ -1096,7 +1140,7 @@ sub _realtime_bop_result {
         };
 
         my $error = send_email(
-          'from'    => $conf->config('invoice_from', $self->agentnum ),
+          'from'    => $conf->invoice_from_full( $self->agentnum ),
           'to'      => [ grep { $_ ne 'POST' } $self->invoicing_list ],
           'subject' => 'Your payment could not be processed',
           'body'    => [ $template->fill_in(HASH => $templ_hash) ],
@@ -1109,7 +1153,11 @@ sub _realtime_bop_result {
     }
 
     $cust_pay_pending->status('done');
-    $cust_pay_pending->statustext("declined: $perror");
+    $cust_pay_pending->statustext($perror);
+    #'declined:': no, that's failure_status
+    if ( $transaction->can('failure_status') ) {
+      $cust_pay_pending->failure_status( $transaction->failure_status );
+    }
     my $cpp_done_err = $cust_pay_pending->replace;
     if ( $cpp_done_err ) {
       my $e = "WARNING: $options{method} declined but pending payment not ".
@@ -1227,11 +1275,6 @@ sub realtime_botpp_capture {
     'amount'         => $cust_pay_pending->paid,
     #'invoice_number' => $options{'invnum'},
     'customer_id'    => $self->custnum,
-
-    #3.0 is a good a time as any to get rid of this... add a config to pass it
-    # if anyone still needs it
-    #'referer'        => 'http://cleanwhisker.420.am/',
-
     'reference'      => $cust_pay_pending->paypendingnum,
     'email'          => $email,
     'phone'          => $self->daytime || $self->night,
@@ -1441,10 +1484,6 @@ sub realtime_refund_bop {
     'password'       => $password,
     'order_number'   => $order_number,
     'amount'         => $amount,
-
-    #3.0 is a good a time as any to get rid of this... add a config to pass it
-    # if anyone still needs it
-    #'referer'        => 'http://cleanwhisker.420.am/',
   );
   $content{authorization} = $auth
     if length($auth); #echeck/ACH transactions have an order # but no auth