use vars qw( $realtime_bop_decline_quiet ); #ugh
use Carp;
use Data::Dumper;
-use Business::CreditCard 0.28;
+use Business::CreditCard 0.35;
use FS::UID qw( dbh );
use FS::Record qw( qsearch qsearchs );
use FS::payby;
\%content;
}
+sub _tokenize_card {
+ my ($self,$transaction,$payinfo,$log) = @_;
+
+ if ( $transaction->can('card_token')
+ and $transaction->card_token
+ and $payinfo !~ /^99\d{14}$/ #not already tokenized
+ ) {
+
+ my @cust_payby = $self->cust_payby('CARD','DCRD');
+ @cust_payby = grep { $payinfo == $_->payinfo } @cust_payby;
+ if (@cust_payby > 1) {
+ $log->error('Multiple matching card numbers for cust '.$self->custnum.', could not tokenize card');
+ } elsif (@cust_payby) {
+ my $cust_payby = $cust_payby[0];
+ $cust_payby->payinfo($transaction->card_token);
+ my $error = $cust_payby->replace;
+ if ( $error ) {
+ $log->error('Error storing token for cust '.$self->custnum.', cust_payby '.$cust_payby->custpaybynum.': '.$error);
+ } else {
+ $log->debug('Tokenized card for cust '.$self->custnum.', cust_payby '.$cust_payby->custpaybynum);
+ }
+ } else {
+ $log->debug('No matching card numbers for cust '.$self->custnum.', could not tokenize card');
+ }
+
+ }
+
+}
+
my %bop_method2payby = (
'CC' => 'CARD',
'ECHECK' => 'CHEK',
unless $FS::UID::AutoCommit;
local($DEBUG) = $FS::cust_main::DEBUG if $FS::cust_main::DEBUG > $DEBUG;
+
+ my $log = FS::Log->new('FS::cust_main::Billing_Realtime::realtime_bop');
my %options = ();
if (ref($_[0]) eq 'HASH') {
$paydate =~ /^\d{2}(\d{2})[\/\-](\d+)[\/\-]\d+$/;
$content{expiration} = "$2/$1";
- my $paycvv = exists($options{'paycvv'})
- ? $options{'paycvv'}
- : $self->paycvv;
- $content{cvv2} = $paycvv
- if length($paycvv);
+ $content{cvv2} = $options{'paycvv'}
+ if length($options{'paycvv'});
my $paystart_month = exists($options{'paystart_month'})
? $options{'paystart_month'}
###
# compare to FS::cust_main::save_cust_payby - check both to make sure working correctly
- if ( length($self->paycvv)
+ if ( length($options{'paycvv'})
&& ! grep { $_ eq cardtype($options{payinfo}) } $conf->config('cvv-save')
) {
- my $error = $self->remove_cvv;
+ my $error = $self->remove_cvv_from_cust_payby($options{payinfo});
if ( $error ) {
warn "WARNING: error removing cvv: $error\n";
}
# Tokenize
###
-
- if ( $transaction->can('card_token') && $transaction->card_token ) {
-
- if ( $options{'payinfo'} eq $self->payinfo ) {
- $self->payinfo($transaction->card_token);
- my $error = $self->replace;
- if ( $error ) {
- warn "WARNING: error storing token: $error, but proceeding anyway\n";
- }
- }
-
- }
+ $self->_tokenize_card($transaction,$options{'payinfo'},$log);
###
# result handling
$paydate =~ /^\d{2}(\d{2})[\/\-](\d+)[\/\-]\d+$/;
$content{expiration} = "$2/$1";
- my $paycvv = exists($options{'paycvv'})
- ? $options{'paycvv'}
- : $self->paycvv;
- $content{cvv2} = $paycvv
- if length($paycvv);
+ $content{cvv2} = $options{'paycvv'}
+ if length($options{'paycvv'});
my $paystart_month = exists($options{'paystart_month'})
? $options{'paystart_month'}
}
}
+ my $log = FS::Log->new('FS::cust_main::Billing_Realtime::realtime_verify_bop');
+
if ( $transaction->is_success() ) {
$cust_pay_pending->status('authorized');
if ( $reverse->is_success ) {
$cust_pay_pending->status('done');
+ $cust_pay_pending->statustext('reversed');
my $cpp_authorized_err = $cust_pay_pending->replace;
return $cpp_authorized_err if $cpp_authorized_err;
my $e = "Authorization successful but reversal failed, custnum #".
$self->custnum. ': '. $reverse->result_code.
": ". $reverse->error_message;
+ $log->warning($e);
warn $e;
return $e;
# Neither address nor postal code matches N N N N
if (my $avscode = uc($transaction->avs_code)) {
+
# map codes to accept/warn/reject
my $avs = {
'American Express card' => {
my $cardtype = cardtype($content{card_number});
if ($avs->{$cardtype}) {
my $avsact = $avs->{$cardtype}->{$avscode};
+ my $warning = '';
if ($avsact eq 'r') {
return "AVS code verification failed, cardtype $cardtype, code $avscode";
} elsif ($avsact eq 'w') {
- warn "AVS code verification did not occur, cardtype $cardtype, code $avscode";
+ $warning = "AVS did not occur, cardtype $cardtype, code $avscode";
} elsif (!$avsact) {
- warn "AVS code verification did not occur, unknown avscode, cardtype $cardtype, code $avscode";
+ $warning = "AVS code unknown, cardtype $cardtype, code $avscode";
} # else $avsact eq 'a'
+ if ($warning) {
+ $log->warning($warning);
+ warn $warning;
+ }
} # else $cardtype avs handling not implemented
} # else !$transaction->avs_code
# Tokenize
###
- if ( $transaction->can('card_token') && $transaction->card_token ) {
-
- if ( $options{'payinfo'} eq $self->payinfo ) {
- $self->payinfo($transaction->card_token);
- my $error = $self->replace;
- if ( $error ) {
- warn "WARNING: error storing token: $error, but proceeding anyway\n";
- }
- }
-
- }
+ $self->_tokenize_card($transaction,$options{'payinfo'},$log);
###
# result handling