X-Git-Url: http://git.freeside.biz/gitweb/?a=blobdiff_plain;f=FS%2FFS%2Fcust_main%2FBilling_Realtime.pm;h=d96b8ba99790d0d128d41de07e4c76d66f260648;hb=b843454941061c79410d2b0efc8da5124e1021e2;hp=3a3947b9cdf88f2539f3d3e041e1b20dd0fb85c9;hpb=9a8399783bb9d87ef662b4371bebe983d2781dce;p=freeside.git diff --git a/FS/FS/cust_main/Billing_Realtime.pm b/FS/FS/cust_main/Billing_Realtime.pm index 3a3947b9c..d96b8ba99 100644 --- a/FS/FS/cust_main/Billing_Realtime.pm +++ b/FS/FS/cust_main/Billing_Realtime.pm @@ -416,6 +416,13 @@ sub realtime_bop { # set fields from passed cust_payby _bop_cust_payby_options(\%options); + # check for banned credit card/ACH + my $ban = FS::banned_pay->ban_search( + 'payby' => $bop_method2payby{$options{method}}, + 'payinfo' => $options{payinfo}, + ); + return "Banned credit card" if $ban && $ban->bantype ne 'warn'; + # possibly run a separate transaction to tokenize card number, # so that we never store tokenized card info in cust_pay_pending if (($options{method} eq 'CC') && !$self->tokenized($options{'payinfo'})) { @@ -502,16 +509,6 @@ sub realtime_bop { die $@ if $@; ### - # check for banned credit card/ACH - ### - - my $ban = FS::banned_pay->ban_search( - 'payby' => $bop_method2payby{$options{method}}, - 'payinfo' => $options{payinfo}, - ); - return "Banned credit card" if $ban && $ban->bantype ne 'warn'; - - ### # check for term discount validity ### @@ -1454,9 +1451,10 @@ sub realtime_refund_bop { ( $gatewaynum, $processor, $auth, $order_number ) = ( $2, $3, $4, $6 ); } + my $payment_gateway; if ( $gatewaynum ) { #gateway for the payment to be refunded - my $payment_gateway = + $payment_gateway = qsearchs('payment_gateway', { 'gatewaynum' => $gatewaynum } ); die "payment gateway $gatewaynum not found" unless $payment_gateway; @@ -1470,7 +1468,7 @@ sub realtime_refund_bop { } else { #try the default gateway my $conf_processor; - my $payment_gateway = + $payment_gateway = $self->agent->payment_gateway('method' => $options{method}); ( $conf_processor, $login, $password, $namespace ) = @@ -1487,8 +1485,27 @@ sub realtime_refund_bop { unless ($processor eq $conf_processor) || (($conf_processor eq 'CardFortress') && ($processor eq $bop_options{'gateway'})); + $processor = $conf_processor; + } + # if gateway has switched to CardFortress but token_check hasn't run yet, + # tokenize just this record now, so that token gets passed/set appropriately + if ($cust_pay->payby eq 'CARD' && !$cust_pay->tokenized) { + my %tokenopts = ( + 'payment_gateway' => $payment_gateway, + 'method' => 'CC', + 'payinfo' => $cust_pay->payinfo, + 'paydate' => $cust_pay->paydate, + ); + my $error = $self->realtime_tokenize(\%tokenopts); # no-op unless gateway can tokenize + if ($self->tokenized($tokenopts{'payinfo'})) { # implies no error + warn " tokenizing cust_pay\n" if $DEBUG > 1; + $cust_pay->payinfo($tokenopts{'payinfo'}); + $error = $cust_pay->replace; + } + return $error if $error; + } } else { # didn't specify a paynum, so look for agent gateway overrides # like a normal transaction @@ -1773,6 +1790,13 @@ sub realtime_verify_bop { return "No cust_payby" unless $options{'cust_payby'}; _bop_cust_payby_options(\%options); + # check for banned credit card/ACH + my $ban = FS::banned_pay->ban_search( + 'payby' => $bop_method2payby{'CC'}, + 'payinfo' => $options{payinfo}, + ); + return "Banned credit card" if $ban && $ban->bantype ne 'warn'; + # possibly run a separate transaction to tokenize card number, # so that we never store tokenized card info in cust_pay_pending if (($options{method} eq 'CC') && !$self->tokenized($options{'payinfo'})) { @@ -1793,16 +1817,6 @@ sub realtime_verify_bop { die $@ if $@; ### - # check for banned credit card/ACH - ### - - my $ban = FS::banned_pay->ban_search( - 'payby' => $bop_method2payby{'CC'}, - 'payinfo' => $options{payinfo}, - ); - return "Banned credit card" if $ban && $ban->bantype ne 'warn'; - - ### # massage data ### @@ -2210,6 +2224,13 @@ sub realtime_tokenize { return '' unless $options{method} eq 'CC'; return '' if $self->tokenized($options{payinfo}); #already tokenized + # check for banned credit card/ACH + my $ban = FS::banned_pay->ban_search( + 'payby' => $bop_method2payby{'CC'}, + 'payinfo' => $options{payinfo}, + ); + return "Banned credit card" if $ban && $ban->bantype ne 'warn'; + ### # select a gateway ### @@ -2238,16 +2259,6 @@ sub realtime_tokenize { && grep /^Tokenize$/, @{$supported_actions{'CC'}}; ### - # check for banned credit card/ACH - ### - - my $ban = FS::banned_pay->ban_search( - 'payby' => $bop_method2payby{'CC'}, - 'payinfo' => $options{payinfo}, - ); - return "Banned credit card" if $ban && $ban->bantype ne 'warn'; - - ### # massage data ### @@ -2388,8 +2399,9 @@ sub token_check { my $cache = {}; #cache for module info - # look for a gateway that can't tokenize + # look for a gateway that can and can't tokenize my $require_tokenized = 1; + my $someone_tokenizing = 0; foreach my $gateway ( FS::payment_gateway->all_gateways( 'method' => 'CC', @@ -2401,18 +2413,26 @@ sub token_check { # no default gateway, no promise to tokenize # can just load other gateways as-needeed below $require_tokenized = 0; - last; + last if $someone_tokenizing; + next; } my $info = _token_check_gateway_info($cache,$gateway); die $info unless ref($info); # means it's an error message - unless ($info->{'can_tokenize'}) { + if ($info->{'can_tokenize'}) { + $someone_tokenizing = 1; + } else { # a configured gateway can't tokenize, that's all we need to know right now # can just load other gateways as-needeed below $require_tokenized = 0; - last; + last if $someone_tokenizing; } } + unless ($someone_tokenizing) { #no need to check, if no one can tokenize + warn "no gateways tokenize\n" if $debug; + return; + } + warn "REQUIRE TOKENIZED" if $require_tokenized && $debug; # upgrade does not call this with autocommit turned on, @@ -2553,7 +2573,11 @@ CUSTLOOP: # might happen for cust_pay_pending from failed verify records, # in which case we attempt tokenization without cust_main # everything else should absolutely have a cust_main - unless ($table eq 'cust_pay_pending' && $record->{'custnum_pending'}) { + if ($table eq 'cust_pay_pending' and !$record->custnum ) { + # override the usual safety check and allow the record to be + # updated even without a custnum. + $record->set('custnum_pending', 1); + } else { my $error = "Could not load cust_main for $table ".$record->get($record->primary_key); if ($opt{'queue'}) { $log->critical($error); @@ -2635,7 +2659,7 @@ CUSTLOOP: warn "ATTEMPTING GATEWAY-ONLY TOKENIZE" if $debug && !$cust_main; # if we got this far, time to mutex - $record = $record->select_for_update; + $record->select_for_update; # no clear record of name/address/etc used for transaction, # but will load name/phone/id from customer if run as an object method,