projects
/
freeside.git
/ blobdiff
commit
grep
author
committer
pickaxe
?
search:
re
summary
|
shortlog
|
log
|
commit
|
commitdiff
|
tree
raw
|
inline
| side by side
71513: Card tokenization [refactor only tokenize cards; job critical error handling]
[freeside.git]
/
FS
/
FS
/
cust_main
/
Billing_Realtime.pm
diff --git
a/FS/FS/cust_main/Billing_Realtime.pm
b/FS/FS/cust_main/Billing_Realtime.pm
index
59792e7
..
c2cb2e3
100644
(file)
--- 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);
# 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'})) {
# 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 $@;
###
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
###
# check for term discount validity
###
@@
-1587,12
+1584,6
@@
sub realtime_refund_bop {
$content{'name'} = $self->get('first'). ' '. $self->get('last');
}
}
$content{'name'} = $self->get('first'). ' '. $self->get('last');
}
}
- if ( $cust_pay->payby eq 'CARD'
- && !$content{'card_number'}
- && $cust_pay->tokenized
- ) {
- $content{'card_token'} = $cust_pay->payinfo;
- }
$void->content( 'action' => 'void', %content );
$void->test_transaction(1)
if $conf->exists('business-onlinepayment-test_transaction');
$void->content( 'action' => 'void', %content );
$void->test_transaction(1)
if $conf->exists('business-onlinepayment-test_transaction');
@@
-1799,6
+1790,13
@@
sub realtime_verify_bop {
return "No cust_payby" unless $options{'cust_payby'};
_bop_cust_payby_options(\%options);
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'})) {
# 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'})) {
@@
-1819,16
+1817,6
@@
sub realtime_verify_bop {
die $@ if $@;
###
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
###
# massage data
###
@@
-2236,6
+2224,13
@@
sub realtime_tokenize {
return '' unless $options{method} eq 'CC';
return '' if $self->tokenized($options{payinfo}); #already tokenized
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
###
###
# select a gateway
###
@@
-2264,16
+2259,6
@@
sub realtime_tokenize {
&& grep /^Tokenize$/, @{$supported_actions{'CC'}};
###
&& 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
###
# massage data
###
@@
-2388,7
+2373,7
@@
is set, this will instead cause a critical error to be recorded in the log,
and any other tokenizable records will still be committed.
If the I<daily> flag is also set, detection of existing untokenized records will
and any other tokenizable records will still be committed.
If the I<daily> flag is also set, detection of existing untokenized records will
-record a
critical error
in the system log (because they should have never appeared
+record a
n info message
in the system log (because they should have never appeared
in the first place.) Tokenization will still be attempted.
If any configured gateways do NOT have the ability to tokenize, or if a
in the first place.) Tokenization will still be attempted.
If any configured gateways do NOT have the ability to tokenize, or if a
@@
-2401,6
+2386,7
@@
sub token_check {
#acts on all customers
my %opt = @_;
my $debug = !$opt{'quiet'} || $DEBUG;
#acts on all customers
my %opt = @_;
my $debug = !$opt{'quiet'} || $DEBUG;
+ my $hascritical = 0;
warn "token_check called with opts\n".Dumper(\%opt) if $debug;
warn "token_check called with opts\n".Dumper(\%opt) if $debug;
@@
-2414,8
+2400,9
@@
sub token_check {
my $cache = {}; #cache for module info
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 $require_tokenized = 1;
+ my $someone_tokenizing = 0;
foreach my $gateway (
FS::payment_gateway->all_gateways(
'method' => 'CC',
foreach my $gateway (
FS::payment_gateway->all_gateways(
'method' => 'CC',
@@
-2427,18
+2414,26
@@
sub token_check {
# no default gateway, no promise to tokenize
# can just load other gateways as-needeed below
$require_tokenized = 0;
# 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
}
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;
# 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,
warn "REQUIRE TOKENIZED" if $require_tokenized && $debug;
# upgrade does not call this with autocommit turned on,
@@
-2469,7
+2464,7
@@
CUSTLOOP:
}
if ($require_tokenized && $opt{'daily'}) {
}
if ($require_tokenized && $opt{'daily'}) {
- $log->
critical("Untokenized card number detected in cust_payby ".$cust_payby->custpaybynum
);
+ $log->
info("Untokenized card number detected in cust_payby ".$cust_payby->custpaybynum. '; tokenizing'
);
$dbh->commit or die $dbh->errstr; # commit log message
}
$dbh->commit or die $dbh->errstr; # commit log message
}
@@
-2488,6
+2483,7
@@
CUSTLOOP:
}
my $error = "No gateway found for custnum ".$cust_main->custnum;
if ($opt{'queue'}) {
}
my $error = "No gateway found for custnum ".$cust_main->custnum;
if ($opt{'queue'}) {
+ $hascritical = 1;
$log->critical($error);
$dbh->commit or die $dbh->errstr; # commit error message
next; # not next CUSTLOOP, want to record error for every cust_payby
$log->critical($error);
$dbh->commit or die $dbh->errstr; # commit error message
next; # not next CUSTLOOP, want to record error for every cust_payby
@@
-2524,6
+2520,7
@@
CUSTLOOP:
if ($error) {
$error = "Error tokenizing cust_payby ".$cust_payby->custpaybynum.": ".$error;
if ($opt{'queue'}) {
if ($error) {
$error = "Error tokenizing cust_payby ".$cust_payby->custpaybynum.": ".$error;
if ($opt{'queue'}) {
+ $hascritical = 1;
$log->critical($error);
$dbh->commit or die $dbh->errstr; # commit log message, release mutex
next; # not next CUSTLOOP, want to record error for every cust_payby
$log->critical($error);
$dbh->commit or die $dbh->errstr; # commit log message, release mutex
next; # not next CUSTLOOP, want to record error for every cust_payby
@@
-2556,6
+2553,10
@@
CUSTLOOP:
while (my $recnum = _token_check_next_recnum($dbh,$table,$step,\$offset,\@recnums)) {
my $record = $tclass->by_key($recnum);
while (my $recnum = _token_check_next_recnum($dbh,$table,$step,\$offset,\@recnums)) {
my $record = $tclass->by_key($recnum);
+ unless ($record->payby eq 'CARD') {
+ warn "Skipping non-card record for $table ".$record->get($record->primary_key) if $debug;
+ next;
+ }
if (FS::cust_main::Billing_Realtime->tokenized($record->payinfo)) {
warn "Skipping tokenized record for $table ".$record->get($record->primary_key) if $debug;
next;
if (FS::cust_main::Billing_Realtime->tokenized($record->payinfo)) {
warn "Skipping tokenized record for $table ".$record->get($record->primary_key) if $debug;
next;
@@
-2570,7
+2571,7
@@
CUSTLOOP:
}
if ($require_tokenized && $opt{'daily'}) {
}
if ($require_tokenized && $opt{'daily'}) {
- $log->
critical("Untokenized card number detected in $table ".$record->get($record->primary_key)
);
+ $log->
info("Untokenized card number detected in $table ".$record->get($record->primary_key). ';tokenizing'
);
$dbh->commit or die $dbh->errstr; # commit log message
}
$dbh->commit or die $dbh->errstr; # commit log message
}
@@
-2586,6
+2587,7
@@
CUSTLOOP:
} else {
my $error = "Could not load cust_main for $table ".$record->get($record->primary_key);
if ($opt{'queue'}) {
} else {
my $error = "Could not load cust_main for $table ".$record->get($record->primary_key);
if ($opt{'queue'}) {
+ $hascritical = 1;
$log->critical($error);
$dbh->commit or die $dbh->errstr; # commit log message
next;
$log->critical($error);
$dbh->commit or die $dbh->errstr; # commit log message
next;
@@
-2688,6
+2690,7
@@
CUSTLOOP:
if ($error) {
$error = "Error tokenizing $table ".$record->get($record->primary_key).": ".$error;
if ($opt{'queue'}) {
if ($error) {
$error = "Error tokenizing $table ".$record->get($record->primary_key).": ".$error;
if ($opt{'queue'}) {
+ $hascritical = 1;
$log->critical($error);
$dbh->commit or die $dbh->errstr; # commit log message, release mutex
next;
$log->critical($error);
$dbh->commit or die $dbh->errstr; # commit log message, release mutex
next;
@@
-2703,7
+2706,7
@@
CUSTLOOP:
$dbh->commit or die $dbh->errstr if $oldAutoCommit;
$dbh->commit or die $dbh->errstr if $oldAutoCommit;
- return '';
+ return
$hascritical ? 'Critical errors occurred on some records, see system log' :
'';
}
# not a method!
}
# not a method!
@@
-2712,7
+2715,13
@@
sub _token_check_next_recnum {
my $recnum = shift @$recnums;
return $recnum if $recnum;
my $tclass = 'FS::'.$table;
my $recnum = shift @$recnums;
return $recnum if $recnum;
my $tclass = 'FS::'.$table;
- my $sth = $dbh->prepare('SELECT '.$tclass->primary_key.' FROM '.$table.' ORDER BY '.$tclass->primary_key.' LIMIT '.$step.' OFFSET '.$$offset) or die $dbh->errstr;
+ my $sth = $dbh->prepare(
+ 'SELECT '.$tclass->primary_key.
+ ' FROM '.$table.
+ ' ORDER BY '.$tclass->primary_key.
+ ' LIMIT '.$step.
+ ' OFFSET '.$$offset
+ ) or die $dbh->errstr;
$sth->execute() or die $sth->errstr;
my @recnums;
while (my $rec = $sth->fetchrow_hashref) {
$sth->execute() or die $sth->errstr;
my @recnums;
while (my $rec = $sth->fetchrow_hashref) {