From f63c0e821610c885f9f49d301eeccf804e1ca6d3 Mon Sep 17 00:00:00 2001 From: ivan Date: Fri, 24 Oct 2003 19:30:44 +0000 Subject: [PATCH] cvv! --- FS/FS/ClientAPI/Signup.pm | 5 ++- FS/FS/cust_main.pm | 51 +++++++++++++++++++++++++--- FS/bin/freeside-setup | 1 + fs_signup/FS-SignupClient/SignupClient.pm | 2 ++ fs_signup/FS-SignupClient/cgi/cvv2.html | 25 ++++++++++++++ fs_signup/FS-SignupClient/cgi/cvv2.png | Bin 0 -> 3854 bytes fs_signup/FS-SignupClient/cgi/cvv2_amex.png | Bin 0 -> 4573 bytes fs_signup/FS-SignupClient/cgi/signup.cgi | 8 +++-- fs_signup/FS-SignupClient/cgi/signup.html | 27 ++++++++++++++- httemplate/docs/cvv2.html | 25 ++++++++++++++ httemplate/docs/schema.html | 1 + httemplate/docs/upgrade10.html | 4 ++- httemplate/edit/cust_main.cgi | 37 ++++++++++++++++++-- httemplate/edit/process/cust_main.cgi | 8 +++++ 14 files changed, 182 insertions(+), 12 deletions(-) create mode 100644 fs_signup/FS-SignupClient/cgi/cvv2.html create mode 100644 fs_signup/FS-SignupClient/cgi/cvv2.png create mode 100644 fs_signup/FS-SignupClient/cgi/cvv2_amex.png create mode 100644 httemplate/docs/cvv2.html diff --git a/FS/FS/ClientAPI/Signup.pm b/FS/FS/ClientAPI/Signup.pm index 5ca1f93ed..92fc6361d 100644 --- a/FS/FS/ClientAPI/Signup.pm +++ b/FS/FS/ClientAPI/Signup.pm @@ -60,6 +60,8 @@ sub signup_info { 'payby' => [ $conf->config('signup_server-payby') ], + 'cvv_enabled' => defined dbdef->table('cust_main')->column('paycvv'), + 'msgcat' => { map { $_=>gettext($_) } qw( passwords_dont_match invalid_card unknown_card_type not_a ) }, @@ -116,7 +118,8 @@ sub new_customer { map { $_ => $packet->{$_} } qw( last first ss company address1 address2 city county state zip country - daytime night fax payby payinfo paydate payname referral_custnum comments + daytime night fax payby payinfo paycvv paydate payname referral_custnum + comments ), } ); diff --git a/FS/FS/cust_main.pm b/FS/FS/cust_main.pm index 2ba0ff046..0ab2aa50d 100644 --- a/FS/FS/cust_main.pm +++ b/FS/FS/cust_main.pm @@ -172,6 +172,8 @@ FS::Record. The following fields are currently supported: =item payinfo - card number, P.O., comp issuer (4-8 lowercase alphanumerics; think username) or prepayment identifier (see L) +=item paycvv - Card Verification Value, "CVV2" (also known as CVC2 or CID), the 3 or 4 digit number on the back (or front, for American Express) of the credit card + =item paydate - expiration date, mm/yyyy, m/yyyy, mm/yy or m/yy =item payname - name on card or billing name @@ -773,6 +775,21 @@ sub check { or return gettext('invalid_card'); # . ": ". $self->payinfo; return gettext('unknown_card_type') if cardtype($self->payinfo) eq "Unknown"; + if ( defined $self->dbdef_table->column('paycvv') ) { + if ( length($self->paycvv) ) { + if ( cardtype($self->payinfo) eq 'American Express card' ) { + $self->paycvv =~ /^(\d{4})$/ + or return "CVV2 (CID) for American Express cards is four digits."; + $self->paycvv($1); + } else { + $self->paycvv =~ /^(\d{3})$/ + or return "CVV2 (CVC2/CID) is three digits."; + $self->paycvv($1); + } + } else { + $self->paycvv(''); + } + } } elsif ( $self->payby eq 'CHEK' || $self->payby eq 'DCHK' ) { @@ -781,6 +798,7 @@ sub check { $payinfo =~ /^(\d+)\@(\d{9})$/ or return 'invalid echeck account@aba'; $payinfo = "$1\@$2"; $self->payinfo($payinfo); + $self->paycvv('') if $self->dbdef_table->column('paycvv'); } elsif ( $self->payby eq 'LECB' ) { @@ -789,11 +807,13 @@ sub check { $payinfo =~ /^1?(\d{10})$/ or return 'invalid btn billing telephone number'; $payinfo = $1; $self->payinfo($payinfo); + $self->paycvv('') if $self->dbdef_table->column('paycvv'); } elsif ( $self->payby eq 'BILL' ) { $error = $self->ut_textn('payinfo'); return "Illegal P.O. number: ". $self->payinfo if $error; + $self->paycvv('') if $self->dbdef_table->column('paycvv'); } elsif ( $self->payby eq 'COMP' ) { @@ -804,6 +824,7 @@ sub check { $error = $self->ut_textn('payinfo'); return "Illegal comp account issuer: ". $self->payinfo if $error; + $self->paycvv('') if $self->dbdef_table->column('paycvv'); } elsif ( $self->payby eq 'PREPAY' ) { @@ -814,6 +835,7 @@ sub check { return "Illegal prepayment identifier: ". $self->payinfo if $error; return "Unknown prepayment identifier" unless qsearchs('prepay_credit', { 'identifier' => $self->payinfo } ); + $self->paycvv('') if $self->dbdef_table->column('paycvv'); } @@ -1666,15 +1688,20 @@ sub realtime_bop { my %content; if ( $method eq 'CC' ) { + $content{card_number} = $self->payinfo; $self->paydate =~ /^\d{2}(\d{2})[\/\-](\d+)[\/\-]\d+$/; $content{expiration} = "$2/$1"; - if ( qsearch('cust_pay', { 'custnum' => $self->custnum, + + $content{cvv2} = $self->paycvv + if defined $self->dbdef_table->column('paycvv') + && length($self->paycvv); + + $content{recurring_billing} = 'YES' + if qsearch('cust_pay', { 'custnum' => $self->custnum, 'payby' => 'CARD', - 'payinfo' => $self->payinfo, } ) - ) { - $content{recurring_billing} = 'YES'; - } + 'payinfo' => $self->payinfo, } ); + } elsif ( $method eq 'ECHECK' ) { my($account_number,$routing_code) = $self->payinfo; ( $content{account_number}, $content{routing_code} ) = @@ -1759,6 +1786,20 @@ sub realtime_bop { } + #remove paycvv after initial transaction + #make this disable-able via a config option if anyone insists? + # (though that probably violates cardholder agreements) + if ( defined $self->dbdef_table->column('paycvv') + && length($self->paycvv) + ) { + my $new = new FS::cust_main { $self->hash }; + $new->paycvv(''); + my $error = $new->replace($self); + if ( $error ) { + warn "error removing cvv: $error\n"; + } + } + #result handling if ( $transaction->is_success() ) { diff --git a/FS/bin/freeside-setup b/FS/bin/freeside-setup index 375a63c2f..80b74c1f1 100755 --- a/FS/bin/freeside-setup +++ b/FS/bin/freeside-setup @@ -502,6 +502,7 @@ sub tables_hash_hack { 'ship_fax', 'varchar', 'NULL', 12, 'payby', 'char', '', 4, 'payinfo', 'varchar', 'NULL', $char_d, + 'paycvv', 'varchar', 'NULL', 4, #'paydate', @date_type, 'paydate', 'varchar', 'NULL', 10, 'payname', 'varchar', 'NULL', $char_d, diff --git a/fs_signup/FS-SignupClient/SignupClient.pm b/fs_signup/FS-SignupClient/SignupClient.pm index 1d91a418f..fb2b12fb0 100644 --- a/fs_signup/FS-SignupClient/SignupClient.pm +++ b/fs_signup/FS-SignupClient/SignupClient.pm @@ -43,6 +43,7 @@ FS::SignupClient - Freeside signup client API 'fax' => $fax, 'payby' => $payby, 'payinfo' => $payinfo, + 'paycvv' => $paycvv, 'paydate' => $paydate, 'payname' => $payname, 'invoicing_list' => $invoicing_list, @@ -125,6 +126,7 @@ a paramater with the following keys: fax payby payinfo + paycvv paydate payname invoicing_list diff --git a/fs_signup/FS-SignupClient/cgi/cvv2.html b/fs_signup/FS-SignupClient/cgi/cvv2.html new file mode 100644 index 000000000..b178c8513 --- /dev/null +++ b/fs_signup/FS-SignupClient/cgi/cvv2.html @@ -0,0 +1,25 @@ + + + + CVV2 information + + + + The CVV2 number (also called CVC2 or CID) is a three- or four-digit + security code used to reduce credit card fraud.

+ + + + + + + + +
Visa / MasterCard / DiscoverAmerican Express
+ Visa/MasterCard/Discover + + American Express +
+
(close window)
+ + diff --git a/fs_signup/FS-SignupClient/cgi/cvv2.png b/fs_signup/FS-SignupClient/cgi/cvv2.png new file mode 100644 index 0000000000000000000000000000000000000000..4610dcbe62aa30a493a84265090f59ade25d83f8 GIT binary patch literal 3854 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 literal 0 HcmV?d00001 diff --git a/fs_signup/FS-SignupClient/cgi/cvv2_amex.png b/fs_signup/FS-SignupClient/cgi/cvv2_amex.png new file mode 100644 index 0000000000000000000000000000000000000000..21c36a0ab5eb9f9fe56bb994007ac2d5284d55c5 GIT binary patch literal 4573 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 Hu0mjf_HDMR literal 0 HcmV?d00001 diff --git a/fs_signup/FS-SignupClient/cgi/signup.cgi b/fs_signup/FS-SignupClient/cgi/signup.cgi index 2458bcf19..70facb570 100755 --- a/fs_signup/FS-SignupClient/cgi/signup.cgi +++ b/fs_signup/FS-SignupClient/cgi/signup.cgi @@ -1,6 +1,6 @@ #!/usr/bin/perl -Tw # -# $Id: signup.cgi,v 1.46 2003-10-14 17:00:00 ivan Exp $ +# $Id: signup.cgi,v 1.47 2003-10-24 19:28:49 ivan Exp $ use strict; use vars qw( @payby $cgi $locales $packages @@ -8,7 +8,7 @@ use vars qw( @payby $cgi $locales $packages $init_data $error $last $first $ss $company $address1 $address2 $city $state $county $country $zip $daytime $night $fax $invoicing_list $payby $payinfo - $paydate $payname $referral_custnum $init_popstate + $paycvv $paydate $payname $referral_custnum $init_popstate $pkgpart $username $password $password2 $sec_phrase $popnum $agentnum $ieak_file $ieak_template $cck_file $cck_template @@ -178,6 +178,9 @@ if ( defined $cgi->param('magic') ) { $paydate = $cgi->param( $payby. '_month' ). '-'. $cgi->param( $payby. '_year' ); $payname = $cgi->param( $payby. '_payname' ); + $paycvv = defined $cgi->param( $payby. '_paycvv' ) + ? $cgi->param( $payby. '_paycvv' ) + : ''; if ( $invoicing_list = $cgi->param('invoicing_list') ) { $invoicing_list .= ', POST' if $cgi->param('invoicing_list_POST'); @@ -252,6 +255,7 @@ if ( defined $cgi->param('magic') ) { 'fax' => $fax, 'payby' => $payby, 'payinfo' => $payinfo, + 'paycvv' => $paycvv, 'paydate' => $paydate, 'payname' => $payname, 'invoicing_list' => $invoicing_list, diff --git a/fs_signup/FS-SignupClient/cgi/signup.html b/fs_signup/FS-SignupClient/cgi/signup.html index 80774099c..dc4252c73 100755 --- a/fs_signup/FS-SignupClient/cgi/signup.html +++ b/fs_signup/FS-SignupClient/cgi/signup.html @@ -1,5 +1,18 @@ ISP Signup form -ISP Signup form

+ + +ISP Signup form

<%= $error %>
@@ -101,6 +114,12 @@ Contact Information 'PREPAY' => qq!Prepaid card
*!, ); + if ( $init_data->{'cvv_enabled'} ) { + foreach my $payby ( grep { exists $payby{$_} } qw(CARD DCRD) ) { #1.4/1.5 + $payby{$payby} .= qq!
CVV2 (help!; + } + } + my( $account, $aba ) = split('@', $payinfo); my %paybychecked = ( 'CARD' => qq!Credit card
*$cardselect
*Exp !. expselect("CARD", $paydate). qq!
*Name on card
!, @@ -113,6 +132,12 @@ Contact Information 'PREPAY' => qq!Prepaid card
*!, ); + if ( $init_data->{'cvv_enabled'} ) { + foreach my $payby ( grep { exists $payby{$_} } qw(CARD DCRD) ) { #1.4/1.5 + $paybychecked{$payby} .= qq!
CVV2 (help!; + } + } + for (@payby) { if ( scalar(@payby) == 1) { $OUT .= ''. diff --git a/httemplate/docs/cvv2.html b/httemplate/docs/cvv2.html new file mode 100644 index 000000000..fe8a17f6f --- /dev/null +++ b/httemplate/docs/cvv2.html @@ -0,0 +1,25 @@ + + + + CVV2 information + + + + The CVV2 number (also called CVC2 or CID) is a three- or four-digit + security code used to reduce credit card fraud.

+ + + + + + + + +
Visa / MasterCard / DiscoverAmerican Express
+ Visa/MasterCard/Discover + + American Express +
+
(close window)
+ + diff --git a/httemplate/docs/schema.html b/httemplate/docs/schema.html index bef567186..06be8960d 100644 --- a/httemplate/docs/schema.html +++ b/httemplate/docs/schema.html @@ -121,6 +121,7 @@
  • ship_fax
  • payby - CARD, DCHK, CHEK, DCHK, LECB, BILL, or COMP
  • payinfo - card number, P.O.#, or comp issuer +
  • paycvv - Card Verification Value, "CVV2" (also known as CVC2 or CID), the 3 or 4 digit number on the back (or front, for American Express) of the credit card
  • paydate - expiration date
  • payname - billing name (name on card)
  • tax - tax exempt, Y or null diff --git a/httemplate/docs/upgrade10.html b/httemplate/docs/upgrade10.html index 446090503..080528bac 100644 --- a/httemplate/docs/upgrade10.html +++ b/httemplate/docs/upgrade10.html @@ -1,7 +1,7 @@
     this is incomplete
     
    -install DBIx::DBSchema 0.21
    +install DBIx::DBSchema 0.22
     
     install NetAddr::IP and Chart::Base
     
    @@ -142,6 +142,8 @@ ALTER TABLE agent ADD username varchar(80) NULL;
     ALTER TABLE h_agent ADD username varchar(80) NULL;
     ALTER TABLE agent ADD _password varchar(80) NULL;
     ALTER TABLE h_agent ADD _password varchar(80) NULL;
    +ALTER TABLE cust_main ADD paycvv varchar(4) NULL;
    +ALTER TABLE h_cust_main ADD paycvv varchar(4) NULL;
     
     dump database, edit:
     - cust_main: increase otaker from 8 to 32
    diff --git a/httemplate/edit/cust_main.cgi b/httemplate/edit/cust_main.cgi
    index 73a0eef49..1909b5438 100755
    --- a/httemplate/edit/cust_main.cgi
    +++ b/httemplate/edit/cust_main.cgi
    @@ -39,6 +39,12 @@ if ( $cgi->param('error') ) {
       $query =~ /^(\d+)$/;
       $custnum=$1;
       $cust_main = qsearchs('cust_main', { 'custnum' => $custnum } );
    +  if ( $cust_main->dbdef_table->column('paycvv')
    +       && length($cust_main->paycvv)             ) {
    +    my $paycvv = $cust_main->paycvv;
    +    $paycvv =~ s/./*/g;
    +    $cust_main->paycvv($paycvv);
    +  }
       $saved_pkgpart = 0;
       $username = '';
       $password = '';
    @@ -61,7 +67,7 @@ my $action = $custnum ? 'Edit' : 'Add';
     # top
     
     my $p1 = popurl(1);
    -print header("Customer $action", '');
    +print header("Customer $action", '', ' onUnload="myclose()"');
     print qq!Error: !, $error, ""
       if $error;
     
    @@ -400,7 +406,19 @@ if ( $payby_default eq 'HIDE' ) {
       print qq!Email invoice !;
     
       print "Billing type",
    -        "",
    +        "", '',
             &table("#cccccc"), "";
     
       my($payinfo, $payname)=(
    @@ -418,6 +436,12 @@ if ( $payby_default eq 'HIDE' ) {
         'COMP' => qq!Complimentary
    ${r}Approved by
    ${r}Exp !. expselect("COMP"), ); + if ( $cust_main->dbdef_table->column('paycvv') ) { + foreach my $payby ( grep { exists $payby{$_} } qw(CARD DCRD) ) { #1.4/1.5 bs + $payby{$payby} .= qq!
    CVV2 (help!; + } + } + my( $account, $aba ) = split('@', $payinfo); my %paybychecked = ( @@ -430,6 +454,15 @@ if ( $payby_default eq 'HIDE' ) { 'COMP' => qq!Complimentary
    ${r}Approved by
    ${r}Exp !. expselect("COMP", $cust_main->paydate), ); + if ( $cust_main->dbdef_table->column('paycvv') ) { + my $paycvv = $cust_main->paycvv; + + foreach my $payby ( grep { exists $payby{$_} } qw(CARD DCRD) ) { #1.4/1.5 bs + $paybychecked{$payby} .= qq!
    CVV2 (help!; + } + } + + $cust_main->payby($payby_default) unless $cust_main->payby; for (qw(CARD DCRD CHEK DCHK LECB BILL COMP)) { print qq!param('paydate', $cgi->param( $payby. '_month' ). '-'. $cgi->param( $payby. '_year' ) ); $cgi->param('payname', $cgi->param( $payby. '_payname' ) ); + $cgi->param('paycvv', $cgi->param( $payby. '_paycvv' ) ) + if defined $cgi->param( $payby. '_paycvv' ); } $cgi->param('otaker', &getotaker ); @@ -27,6 +29,7 @@ my @invoicing_list = split( /\s*\,\s*/, $cgi->param('invoicing_list') ); push @invoicing_list, 'POST' if $cgi->param('invoicing_list_POST'); $cgi->param('invoicing_list', join(',', @invoicing_list) ); + #create new record object my $new = new FS::cust_main ( { @@ -113,6 +116,11 @@ if ( $new->custnum eq '' ) { } else { #create old record object my $old = qsearchs( 'cust_main', { 'custnum' => $new->custnum } ); $error ||= "Old record not found!" unless $old; + if ( defined dbdef->table('cust_main')->column('paycvv') + && length($old->paycvv) + && $new->paycvv =~ /^\s*\*+\s*$/ ) { + $new->paycvv($old->paycvv); + } $error ||= $new->replace($old, \@invoicing_list); } -- 2.11.0