RT# 81183 Fix crash processing payment with new payment method
[freeside.git] / httemplate / misc / process / payment.cgi
index 852becb..d0e5896 100644 (file)
@@ -39,6 +39,8 @@ my $cust_main = qsearchs({
   'extra_sql' => ' AND '. $curuser->agentnums_sql,
 }) or die "unknown custnum $custnum";
 
+my $invoice = ($cgi->param('invoice') =~ /^(\d+)$/) ? $cgi->param('invoice') : '';
+
 $cgi->param('amount') =~ /^\s*(\d*(\.\d\d)?)\s*$/
   or errorpage("illegal amount ". $cgi->param('amount'));
 my $amount = $1;
@@ -72,7 +74,7 @@ $cgi->param('discount_term') =~ /^(\d*)$/
   or errorpage("illegal discount_term");
 my $discount_term = $1;
 
-my( $payinfo, $paycvv, $month, $year, $payname );
+my( $cust_payby, $payinfo, $paycvv, $month, $year, $payname );
 my $paymask = '';
 if ( (my $custpaybynum = scalar($cgi->param('custpaybynum'))) > 0 ) {
 
@@ -80,15 +82,17 @@ if ( (my $custpaybynum = scalar($cgi->param('custpaybynum'))) > 0 ) {
   # use stored cust_payby info
   ##
 
-  my $cust_payby = qsearchs('cust_payby', { custnum      => $custnum,
+  $cust_payby = qsearchs('cust_payby', { custnum      => $custnum,
                                             custpaybynum => $custpaybynum, } )
     or die "unknown custpaybynum $custpaybynum";
 
+  # not needed for realtime_bop, but still needed for batch_card
   $payinfo = $cust_payby->payinfo;
   $paymask = $cust_payby->paymask;
   $paycvv = $cust_payby->paycvv; # pass it if we got it, running a transaction will clear it
   ( $month, $year ) = $cust_payby->paydate_mon_year;
   $payname = $cust_payby->payname;
+  $cgi->param(-name=>"paytype", -value=>$cust_payby->paytype) unless $cgi->param("paytype");
 
 } else {
 
@@ -128,13 +132,13 @@ if ( (my $custpaybynum = scalar($cgi->param('custpaybynum'))) > 0 ) {
     $payinfo = $cgi->param('payinfo');
 
     $payinfo =~ s/\D//g;
-    $payinfo =~ /^(\d{13,16}|\d{8,9})$/
+    $payinfo =~ /^(\d{13,19}|\d{8,9})$/
       or errorpage(gettext('invalid_card'));
     $payinfo = $1;
     validate($payinfo)
       or errorpage(gettext('invalid_card'));
 
-    unless ( $payinfo =~ /^99\d{14}$/ ) { #token
+    unless ( $cust_main->tokenized($payinfo) ) { #token
 
       my $cardtype = cardtype($payinfo);
 
@@ -164,7 +168,7 @@ if ( (my $custpaybynum = scalar($cgi->param('custpaybynum'))) > 0 ) {
     die "unknown payby $payby";
   }
 
-  # save first, for proper tokenization later
+  # save first, for proper tokenization
   if ( $cgi->param('save') ) {
 
     my %saveopt;
@@ -181,6 +185,7 @@ if ( (my $custpaybynum = scalar($cgi->param('custpaybynum'))) > 0 ) {
     }
 
     my $error = $cust_main->save_cust_payby(
+      'saved_cust_payby' => \$cust_payby,
       'payment_payby' => $payby,
       'auto'          => scalar($cgi->param('auto')),
       'weight'        => scalar($cgi->param('weight')),
@@ -191,6 +196,11 @@ if ( (my $custpaybynum = scalar($cgi->param('custpaybynum'))) > 0 ) {
 
     errorpage("error saving info, payment not processed: $error")
       if $error;       
+
+  } elsif ( $payby eq 'CARD' ) { # not saving
+
+    $paymask = FS::payinfo_Mixin->mask_payinfo('CARD',$payinfo); # for untokenized but tokenizable payinfo
+
   }
 
 }
@@ -201,17 +211,28 @@ if ( (my $custpaybynum = scalar($cgi->param('custpaybynum'))) > 0 ) {
 
 my $error = '';
 my $paynum = '';
+
 if ( $cgi->param('batch') ) {
 
   $error = 'Prepayment discounts not supported with batched payments' 
     if $discount_term;
 
+  # Invalid payment expire dates are replaced with 2037-12-01 (why?)
+  my $paydate = "${year}-${month}-01";
+  {
+    use DateTime;
+    local $@;
+    eval { DateTime->new({ year => $year, month => $month, day => 1 }) };
+    $paydate = '2037-12-01' if $@;
+  }
+
   $error ||= $cust_main->batch_card(
                                      'payby'    => $payby,
                                      'amount'   => $amount,
                                      'payinfo'  => $payinfo,
-                                     'paydate'  => "$year-$month-01",
+                                     'paydate'  => $paydate,
                                      'payname'  => $payname,
+                                     'invnum'   => $invoice,
                                      map { $_ => scalar($cgi->param($_)) } 
                                        @{$payby2fields{$payby}}
                                    );
@@ -220,6 +241,7 @@ if ( $cgi->param('batch') ) {
 } else {
 
   $error = $cust_main->realtime_bop( $FS::payby::payby2bop{$payby}, $amount,
+    'cust_payby' => $cust_payby, # if defined, will override passed payinfo, etc 
     'quiet'      => 1,
     'manual'     => 1,
     'balance'    => $balance,
@@ -233,6 +255,7 @@ if ( $cgi->param('batch') ) {
     'discount_term' => $discount_term,
     'no_auto_apply' => ($cgi->param('apply') eq 'never') ? 'Y' : '',
     'no_invnum'     => 1,
+    'invnum'        => $invoice,
     map { $_ => scalar($cgi->param($_)) } @{$payby2fields{$payby}}
   );
   errorpage($error) if $error;
@@ -248,7 +271,7 @@ if ( $cgi->param('batch') ) {
 
     #and generate an invoice for it now too
     $error = $cust_main->bill( 'pkg_list' => [ $cust_pkg ] );
-    errorpage("payment processed and fee ordered sucessfully, but error billing fee: $error")
+    errorpage("payment processed and fee ordered successfully, but error billing fee: $error")
       if $error;
 
   }