X-Git-Url: http://git.freeside.biz/gitweb/?a=blobdiff_plain;f=FS%2FFS%2Fpayinfo_Mixin.pm;h=23d24a88de714973db293754c2c91088f85690db;hb=c8fcbf5ff7dde3f2bf826a9a9098d8c046f0cff4;hp=fb56371e3c53d2b2d2895715cd13754d099b6373;hpb=978fea1c303551f90c95ae852b6463951b78246b;p=freeside.git diff --git a/FS/FS/payinfo_Mixin.pm b/FS/FS/payinfo_Mixin.pm index fb56371e3..23d24a88d 100644 --- a/FS/FS/payinfo_Mixin.pm +++ b/FS/FS/payinfo_Mixin.pm @@ -3,6 +3,7 @@ package FS::payinfo_Mixin; use strict; use Business::CreditCard; use FS::payby; +use FS::Record qw(qsearch); =head1 NAME @@ -18,12 +19,6 @@ use vars qw(@ISA); This is a mixin class for records that contain payinfo. -This class handles the following functions for payinfo... - -Payment Mask (Generation and Storage) -Data Validation (parent checks need to be sure to call this) -Pretty printing - =head1 FIELDS =over 4 @@ -72,12 +67,12 @@ Card Number, P.O., comp issuer (4-8 lowercase alphanumerics; think username) or sub payinfo { my($self,$payinfo) = @_; + if ( defined($payinfo) ) { - $self->setfield('payinfo', $payinfo); # This is okay since we are the 'setter' - $self->paymask($self->mask_payinfo()); + $self->setfield('payinfo', $payinfo); + $self->paymask($self->mask_payinfo) unless $payinfo =~ /^99\d{14}$/; #token } else { - $payinfo = $self->getfield('payinfo'); # This is okay since we are the 'getter' - return $payinfo; + $self->getfield('payinfo'); } } @@ -110,25 +105,11 @@ sub paycvv { sub paymask { my($self, $paymask) = @_; - if ( defined($paymask) && $paymask ne '' ) { - # I hate this little bit of magic... I don't expect it to cause a problem, - # but who knows... If the payinfo is passed in masked then ignore it and - # set it based on the payinfo. The only guy that should call this in this - # way is... $self->payinfo - $self->setfield('paymask', $self->mask_payinfo()); - + if ( defined($paymask) ) { + $self->setfield('paymask', $paymask); } else { - - $paymask=$self->getfield('paymask'); - if (!defined($paymask) || $paymask eq '') { - # Generate it if it's blank - Note that we're not going to set it - just - # generate - $paymask = $self->mask_payinfo(); - } - + $self->getfield('paymask') || $self->mask_payinfo; } - - return $paymask; } =back @@ -152,32 +133,54 @@ sub mask_payinfo { my $payinfo = scalar(@_) ? shift : $self->payinfo; # Check to see if it's encrypted... - my $paymask; - if ( $self->is_encrypted($payinfo) ) { - $paymask = 'N/A'; - } else { - # if not, mask it... + if ( ref($self) && $self->is_encrypted($payinfo) ) { + return 'N/A'; + } elsif ( $payinfo =~ /^99\d{14}$/ || $payinfo eq 'N/A' ) { #token + return 'N/A (tokenized)'; #? + } else { # if not, mask it... + if ($payby eq 'CARD' || $payby eq 'DCRD' || $payby eq 'MCRD') { + # Credit Cards + + # special handling for Local Isracards: always show last 4 + if ( $payinfo =~ /^(\d{8,9})$/ ) { + + return 'x'x(length($payinfo)-4). + substr($payinfo,(length($payinfo)-4)); + + } + my $conf = new FS::Conf; my $mask_method = $conf->config('card_masking_method') || 'first6last4'; $mask_method =~ /^first(\d+)last(\d+)$/ or die "can't parse card_masking_method $mask_method"; my($first, $last) = ($1, $2); - $paymask = substr($payinfo,0,$first). - 'x'x(length($payinfo)-$first-$last). - substr($payinfo,(length($payinfo)-$last)); + return substr($payinfo,0,$first). + 'x'x(length($payinfo)-$first-$last). + substr($payinfo,(length($payinfo)-$last)); + } elsif ($payby eq 'CHEK' || $payby eq 'DCHK' ) { + # Checks (Show last 2 @ bank) my( $account, $aba ) = split('@', $payinfo ); - $paymask = 'x'x(length($account)-2). - substr($account,(length($account)-2))."@".$aba; + return 'x'x(length($account)-2). + substr($account,(length($account)-2)). + ( length($aba) ? "@".$aba : ''); + + } elsif ($payby eq 'EDI') { + # EDI. + # These numbers have been seen anywhere from 8 to 30 digits, and + # possibly more. Lacking any better idea I'm going to mask all but + # the last 4 digits. + return 'x' x (length($payinfo) - 4) . substr($payinfo, -4); + } else { # Tie up loose ends - $paymask = $payinfo; + return $payinfo; } } - return $paymask; + #die "shouldn't be reached"; } =item payinfo_check @@ -214,11 +217,12 @@ sub payinfo_check { $payinfo =~ s/\D//g; $self->payinfo($payinfo); if ( $self->payinfo ) { - $self->payinfo =~ /^(\d{13,16})$/ + $self->payinfo =~ /^(\d{13,16}|\d{8,9})$/ or return "Illegal (mistyped?) credit card number (payinfo)"; $self->payinfo($1); validate($self->payinfo) or return "Illegal credit card number"; - return "Unknown card type" if cardtype($self->payinfo) eq "Unknown"; + return "Unknown card type" if $self->payinfo !~ /^99\d{14}$/ #token + && cardtype($self->payinfo) eq "Unknown"; } else { $self->payinfo('N/A'); #??? } @@ -237,7 +241,7 @@ sub payinfo_check { } -=item payby_payinfo_pretty +=item payby_payinfo_pretty [ LOCALE ] Returns payment method and information (suitably masked, if applicable) as a human-readable string, such as: @@ -252,31 +256,68 @@ or sub payby_payinfo_pretty { my $self = shift; + my $locale = shift; + my $lh = FS::L10N->get_handle($locale); if ( $self->payby eq 'CARD' ) { - 'Card #'. $self->paymask; + $lh->maketext('Card #') . $self->paymask; } elsif ( $self->payby eq 'CHEK' ) { - 'E-check acct#'. $self->payinfo; + + #false laziness w/view/cust_main/payment_history.html::translate_payinfo + my( $account, $aba ) = split('@', $self->paymask ); + + if ( $aba =~ /^(\d{5})\.(\d{3})$/ ) { #blame canada + my($branch, $routing) = ($1, $2); + $lh->maketext("Routing [_1], Branch [_2], Acct [_3]", + $routing, $branch, $account); + } else { + $lh->maketext("Routing [_1], Acct [_2]", $aba, $account); + } + } elsif ( $self->payby eq 'BILL' ) { - 'Check #'. $self->payinfo; + $lh->maketext('Check #') . $self->payinfo; } elsif ( $self->payby eq 'PREP' ) { - 'Prepaid card #'. $self->payinfo; + $lh->maketext('Prepaid card #') . $self->payinfo; } elsif ( $self->payby eq 'CASH' ) { - 'Cash '. $self->payinfo; + $lh->maketext('Cash') . ' ' . $self->payinfo; } elsif ( $self->payby eq 'WEST' ) { - 'Western Union'; #. $self->payinfo; + # does Western Union localize their name? + $lh->maketext('Western Union'); } elsif ( $self->payby eq 'MCRD' ) { - 'Manual credit card'; #. $self->payinfo; + $lh->maketext('Manual credit card'); + } elsif ( $self->payby eq 'EDI' ) { + $lh->maketext('EDI') . ' ' . $self->paymask; } else { $self->payby. ' '. $self->payinfo; } } -=head1 BUGS +=item payinfo_used [ PAYINFO ] + +Returns 1 if there's an existing payment using this payinfo. This can be +used to set the 'recurring payment' flag required by some processors. -Future items? - Encryption - In the Future (Pull from Record.pm) - Bad Card Stuff - In the Future (Integrate Banned Pay) - Currency - In the Future +=cut + +sub payinfo_used { + my $self = shift; + my $payinfo = shift || $self->payinfo; + my %hash = ( + 'custnum' => $self->custnum, + 'payby' => 'CARD', + ); + + return 1 + if qsearch('cust_pay', { %hash, 'payinfo' => $payinfo } ) + || qsearch('cust_pay', + { %hash, 'paymask' => $self->mask_payinfo('CARD', $payinfo) } ) + ; + + return 0; +} + +=back + +=head1 BUGS =head1 SEE ALSO