From: jeff Date: Sun, 29 Apr 2007 22:55:14 +0000 (+0000) Subject: ticket 1568 config options for new echeck fields and addition to selfservice interface X-Git-Tag: TRIXBOX_2_6~527 X-Git-Url: http://git.freeside.biz/gitweb/?p=freeside.git;a=commitdiff_plain;h=7cdcb8d249f66efdbd5eb4efdd6e07f0f7948b49 ticket 1568 config options for new echeck fields and addition to selfservice interface --- diff --git a/FS/FS/ClientAPI/MyAccount.pm b/FS/FS/ClientAPI/MyAccount.pm index c24917749..9ee770b20 100644 --- a/FS/FS/ClientAPI/MyAccount.pm +++ b/FS/FS/ClientAPI/MyAccount.pm @@ -23,6 +23,7 @@ use FS::cust_main; use FS::cust_bill; use FS::cust_main_county; use FS::cust_pkg; +use FS::payby; use HTML::Entities; #false laziness with FS::cust_main @@ -237,6 +238,14 @@ sub payment_info { 'card_types' => card_types(), + 'paytypes' => [ @FS::cust_main::paytypes ], + + 'stateid_label' => FS::Msgcat::_gettext('stateid'), + 'stateid_state_label' => FS::Msgcat::_gettext('stateid_state'), + + 'show_ss' => $conf->exists('show_ss'), + 'show_stateid' => $conf->exists('show_stateid'), + 'show_paystate' => $conf->exists('show_bankstate'), }; } @@ -260,6 +269,7 @@ sub payment_info { $return{$_} = $cust_main->get($_) for qw(address1 address2 city state zip); $return{payby} = $cust_main->payby; + $return{stateid_state} = $cust_main->stateid_state; if ( $cust_main->payby =~ /^(CARD|DCRD)$/ ) { $return{card_type} = cardtype($cust_main->payinfo); @@ -269,6 +279,15 @@ sub payment_info { } + if ( $cust_main->payby =~ /^(CHEK|DCHK)$/ ) { + my ($payinfo1, $payinfo2) = split '@', $cust_main->payinfo; + $return{payinfo1} = $payinfo1; + $return{payinfo2} = $payinfo2; + $return{paytype} = $cust_main->paytype; + $return{paystate} = $cust_main->paystate; + + } + #doubleclick protection my $_date = time; $return{paybatch} = "webui-MyAccount-$_date-$$-". rand() * 2**32; @@ -303,19 +322,23 @@ sub process_payment { or return { 'error' => gettext('illegal_text'). " paybatch: ". $p->{'paybatch'} }; my $paybatch = $1; + $p->{'payby'} =~ /^([A-Z]{4})$/ + or return { 'error' => "illegal_payby " . $p->{'payby'} }; + my $payby = $1; + my $payinfo; my $paycvv = ''; - #if ( $payby eq 'CHEK' ) { - # - # $p->{'payinfo1'} =~ /^(\d+)$/ - # or return { 'error' => "illegal account number ". $p->{'payinfo1'} }; - # my $payinfo1 = $1; - # $p->{'payinfo2'} =~ /^(\d+)$/ - # or return { 'error' => "illegal ABA/routing number ". $p->{'payinfo2'} }; - # my $payinfo2 = $1; - # $payinfo = $payinfo1. '@'. $payinfo2; - # - #} elsif ( $payby eq 'CARD' ) { + if ( $payby eq 'CHEK' || $payby eq 'DCHK' ) { + + $p->{'payinfo1'} =~ /^(\d+)$/ + or return { 'error' => "illegal account number ". $p->{'payinfo1'} }; + my $payinfo1 = $1; + $p->{'payinfo2'} =~ /^(\d+)$/ + or return { 'error' => "illegal ABA/routing number ". $p->{'payinfo2'} }; + my $payinfo2 = $1; + $payinfo = $payinfo1. '@'. $payinfo2; + + } elsif ( $payby eq 'CARD' || $payby eq 'DCRD' ) { $payinfo = $p->{'payinfo'}; $payinfo =~ s/\D//g; @@ -339,19 +362,23 @@ sub process_payment { } } - #} else { - # die "unknown payby $payby"; - #} + } else { + die "unknown payby $payby"; + } - my $error = $cust_main->realtime_bop( 'CC', $p->{'amount'}, + my %payby2fields = ( + 'CARD' => [ qw( paystart_month paystart_year payissue address1 address2 city state zip payip ) ], + 'CHEK' => [ qw( ss paytype paystate stateid stateid_state payip ) ], + ); + + my $error = $cust_main->realtime_bop( $FS::payby::payby2bop{$payby}, $p->{'amount'}, 'quiet' => 1, 'payinfo' => $payinfo, 'paydate' => $p->{'year'}. '-'. $p->{'month'}. '-01', 'payname' => $payname, 'paybatch' => $paybatch, 'paycvv' => $paycvv, - map { $_ => $p->{$_} } qw( paystart_month paystart_year payissue payip - address1 address2 city state zip ) + map { $_ => $p->{$_} } @{ $payby2fields{$payby} } ); return { 'error' => $error } if $error; @@ -359,11 +386,19 @@ sub process_payment { if ( $p->{'save'} ) { my $new = new FS::cust_main { $cust_main->hash }; - $new->set( $_ => $p->{$_} ) - foreach qw( payname paystart_month paystart_year payissue payip - address1 address2 city state zip payinfo ); + if ($payby eq 'CARD' || $payby eq 'DCRD') { + $new->set( $_ => $p->{$_} ) + foreach qw( payname paystart_month paystart_year payissue payip + address1 address2 city state zip payinfo ); + $new->set( 'payby' => $p->{'auto'} ? 'CARD' : 'DCRD' ); + } elsif ($payby eq 'CHEK' || $payby eq 'DCHK') { + $new->set( $_ => $p->{$_} ) + foreach qw( payname payip paytype paystate + stateid stateid_state ); + $new->set( 'payinfo' => $payinfo ); + $new->set( 'payby' => $p->{'auto'} ? 'CHEK' : 'DCHK' ); + } $new->set( 'paydate' => $p->{'year'}. '-'. $p->{'month'}. '-01' ); - $new->set( 'payby' => $p->{'auto'} ? 'CARD' : 'DCRD' ); my $error = $new->replace($cust_main); return { 'error' => $error } if $error; $cust_main = $new; diff --git a/FS/FS/ClientAPI/Signup.pm b/FS/FS/ClientAPI/Signup.pm index 1f5a2ec1c..6dded4ccf 100644 --- a/FS/FS/ClientAPI/Signup.pm +++ b/FS/FS/ClientAPI/Signup.pm @@ -67,14 +67,24 @@ sub signup_info { 'card_types' => card_types(), + 'paytypes' => [ @FS::cust_main::paytypes ], + 'cvv_enabled' => defined dbdef->table('cust_main')->column('paycvv'), # 1, + 'stateid_enabled' => $conf->exists('show_stateid'), + + 'paystate_enabled' => $conf->exists('show_bankstate'), + 'ship_enabled' => defined dbdef->table('cust_main')->column('ship_last'),#1, 'msgcat' => { map { $_=>gettext($_) } qw( passwords_dont_match invalid_card unknown_card_type not_a empty_password illegal_or_empty_text ) }, + 'label' => { map { $_ => FS::Msgcat::_gettext($_) } qw( + stateid stateid_state + ) }, + 'statedefault' => $conf->config('statedefault') || 'CA', 'countrydefault' => $conf->config('countrydefault') || 'US', @@ -259,14 +269,14 @@ sub new_customer { last first ss company address1 address2 city county state zip country - daytime night fax + daytime night fax stateid stateid_state ship_last ship_first ship_ss ship_company ship_address1 ship_address2 ship_city ship_county ship_state ship_zip ship_country ship_daytime ship_night ship_fax payby - payinfo paycvv paydate payname + payinfo paycvv paydate payname paystate paytype paystart_month paystart_year payissue payip diff --git a/FS/FS/Conf.pm b/FS/FS/Conf.pm index b54d6f54f..a86764846 100644 --- a/FS/FS/Conf.pm +++ b/FS/FS/Conf.pm @@ -925,6 +925,13 @@ httemplate/docs/config.html 'type' => 'checkbox', }, + { + 'key' => 'show_bankstate', + 'section' => 'UI', + 'description' => "Turns on display/collection of state for bank accounts in the web interface. Sometimes required by electronic check (ACH) processors.", + 'type' => 'checkbox', + }, + { 'key' => 'agent_defaultpkg', 'section' => 'UI', diff --git a/fs_selfservice/FS-SelfService/cgi/ach_payment_results.html b/fs_selfservice/FS-SelfService/cgi/ach_payment_results.html new file mode 100644 index 000000000..9fe400faf --- /dev/null +++ b/fs_selfservice/FS-SelfService/cgi/ach_payment_results.html @@ -0,0 +1,16 @@ +MyAccount +MyAccount

+<%= $url = "$selfurl?session=$session_id;action="; ''; %> +<%= include('myaccount_menu') %> + +Payment results

+<%= if ( $error ) { + $OUT .= qq!Error processing your payment: $error!; +} else { + $OUT .= 'Your payment was processed successfully. Thank you.'; +} %> + +
+powered by freeside + + diff --git a/fs_selfservice/FS-SelfService/cgi/make_ach_payment.html b/fs_selfservice/FS-SelfService/cgi/make_ach_payment.html new file mode 100644 index 000000000..83d36b9b9 --- /dev/null +++ b/fs_selfservice/FS-SelfService/cgi/make_ach_payment.html @@ -0,0 +1,111 @@ +MyAccount + + +MyAccount

+<%= $url = "$selfurl?session=$session_id;action="; ''; %> +<%= include('myaccount_menu') %> + +Make a payment

+
+ + + + + + + + + + + + + + + + + + + + + + + + <%= + $OUT = ''; + if ($show_paystate) { + $OUT .= qq!'; + } + %> + <%= + $OUT = ''; + if ($show_ss) { + $OUT .= ''; + } + %> + <%= + $OUT = ''; + if ($show_stateid) { + $OUT .= '!; + $OUT .= qq!!; + $OUT .= ''; + } + %> + + + + +
Amount Due +
+ $<%=sprintf("%.2f",$balance)%> +
+
Payment amount +
+ $"> +
+
Account type + +
Account number
ABA/Routing number
Bank name
Bank state
Account holder
Social '; + $OUT .= 'security or tax ID #
'; + $OUT .= qq!!; + $OUT .= '
'; + $OUT .= qq!Account holder
$stateid_label
!; + $OUT .= qq!$stateid_state_label
+ + Remember this information +
+ NAME="auto" VALUE="1" onClick="if (this.checked) { document.OneTrueForm.save.checked=true; }"> + Charge future payments to this account automatically +
+
+ + +
+ +
+powered by freeside + + diff --git a/fs_selfservice/FS-SelfService/cgi/myaccount_menu.html b/fs_selfservice/FS-SelfService/cgi/myaccount_menu.html index 47fcfc127..095d59cce 100644 --- a/fs_selfservice/FS-SelfService/cgi/myaccount_menu.html +++ b/fs_selfservice/FS-SelfService/cgi/myaccount_menu.html @@ -21,6 +21,8 @@ if ( 1 ) { #XXXFIXME "enable selfservice prepay features" flag or something, eve push @menu, ( { title=>'Recharge my account with a credit card', url=>'make_payment', indent=>2 }, + { title=>'Recharge my account with a check', + url=>'make_ach_payment', indent=>2 }, { title=>'Recharge my account with a prepaid card', url=>'recharge_prepay', indent=>2 }, ); diff --git a/fs_selfservice/FS-SelfService/cgi/selfservice.cgi b/fs_selfservice/FS-SelfService/cgi/selfservice.cgi index 975203dc8..2e1da4168 100644 --- a/fs_selfservice/FS-SelfService/cgi/selfservice.cgi +++ b/fs_selfservice/FS-SelfService/cgi/selfservice.cgi @@ -66,7 +66,7 @@ $session_id = $cgi->param('session'); #order|pw_list XXX ??? $cgi->param('action') =~ - /^(myaccount|view_invoice|make_payment|payment_results|recharge_prepay|recharge_results|logout|change_bill|change_ship|customer_order_pkg|process_order_pkg|customer_change_pkg|process_change_pkg|process_order_recharge|provision|provision_svc|process_svc_acct|process_svc_external|delete_svc|view_usage|view_usage_details|change_password|process_change_password)$/ + /^(myaccount|view_invoice|make_payment|make_ach_payment|payment_results|ach_payment_results|recharge_prepay|recharge_results|logout|change_bill|change_ship|customer_order_pkg|process_order_pkg|customer_change_pkg|process_change_pkg|process_order_recharge|provision|provision_svc|process_svc_acct|process_svc_external|delete_svc|view_usage|view_usage_details|change_password|process_change_password)$/ or die "unknown action ". $cgi->param('action'); my $action = $1; @@ -299,6 +299,7 @@ sub payment_results { process_payment( 'session_id' => $session_id, + 'payby' => 'CARD', 'amount' => $amount, 'payinfo' => $payinfo, 'paycvv' => $paycvv, @@ -317,6 +318,78 @@ sub payment_results { } +sub make_ach_payment { + payment_info( 'session_id' => $session_id ); +} + +sub ach_payment_results { + + #we should only do basic checking here for DoS attacks and things + #that couldn't be constructed by the web form... let process_payment() do + #the rest, it gives better error messages + + $cgi->param('amount') =~ /^\s*(\d+(\.\d{2})?)\s*$/ + or die "illegal amount"; #!!! + my $amount = $1; + + my $payinfo1 = $cgi->param('payinfo1'); + $payinfo1=~ /^(\d+)$/ + or die "illegal account"; #!!! + $payinfo1= $1; + + my $payinfo2 = $cgi->param('payinfo2'); + $payinfo2=~ /^(\d+)$/ + or die "illegal ABA/routing code"; #!!! + $payinfo2= $1; + + $cgi->param('payname') =~ /^(.{0,80})$/ or die "illegal payname"; + my $payname = $1; + + $cgi->param('paystate') =~ /^(.{0,2})$/ or die "illegal paystate"; + my $paystate = $1; + + $cgi->param('paytype') =~ /^(.{0,80})$/ or die "illegal paytype"; + my $paytype = $1; + + $cgi->param('ss') =~ /^(.{0,80})$/ or die "illegal ss"; + my $ss = $1; + + $cgi->param('stateid') =~ /^(.{0,80})$/ or die "illegal stateid"; + my $stateid = $1; + + $cgi->param('stateid_state') =~ /^(.{0,2})$/ or die "illegal stateid_state"; + my $stateid_state = $1; + + my $save = 0; + $save = 1 if $cgi->param('save'); + + my $auto = 0; + $auto = 1 if $cgi->param('auto'); + + $cgi->param('paybatch') =~ /^([\w\-\.]+)$/ or die "illegal paybatch"; + my $paybatch = $1; + + process_payment( + 'session_id' => $session_id, + 'payby' => 'CHEK', + 'amount' => $amount, + 'payinfo1' => $payinfo1, + 'payinfo2' => $payinfo2, + 'month' => '12', + 'year' => '2037', + 'payname' => $payname, + 'paytype' => $paytype, + 'paystate' => $paystate, + 'ss' => $ss, + 'stateid' => $stateid, + 'stateid_state' => $stateid_state, + 'save' => $save, + 'auto' => $auto, + 'paybatch' => $paybatch, + ); + +} + sub recharge_prepay { customer_info( 'session_id' => $session_id ); } diff --git a/fs_selfservice/FS-SelfService/cgi/signup.cgi b/fs_selfservice/FS-SelfService/cgi/signup.cgi index 227f05f7b..e07b6ee5a 100755 --- a/fs_selfservice/FS-SelfService/cgi/signup.cgi +++ b/fs_selfservice/FS-SelfService/cgi/signup.cgi @@ -149,6 +149,14 @@ if ( ( defined($cgi->param('magic')) && $cgi->param('magic') eq 'process' ) ? $cgi->param( $payby. '_paycvv' ) : '' ); + $cgi->param('paytype' => defined $cgi->param( $payby. '_paytype' ) + ? $cgi->param( $payby. '_paytype' ) + : '' + ); + $cgi->param('paystate' => defined $cgi->param( $payby. '_paystate' ) + ? $cgi->param( $payby. '_paystate' ) + : '' + ); if ( $cgi->param('invoicing_list') ) { $cgi->param('invoicing_list' => $cgi->param('invoicing_list'). ', POST') @@ -185,15 +193,15 @@ if ( ( defined($cgi->param('magic')) && $cgi->param('magic') eq 'process' ) ( map { $_ => scalar($cgi->param($_)) } qw( last first ss company address1 address2 city county state zip country - daytime night fax + daytime night fax stateid stateid_state ship_last ship_first ship_company ship_address1 ship_address2 ship_city ship_county ship_state ship_zip ship_country ship_daytime ship_night ship_fax - payby payinfo paycvv paydate payname invoicing_list - referral_custnum promo_code reg_code + payby payinfo paycvv paydate payname paystate paytype + invoicing_list referral_custnum promo_code reg_code pkgpart username sec_phrase _password popnum refnum agentnum ), diff --git a/fs_selfservice/FS-SelfService/cgi/signup.html b/fs_selfservice/FS-SelfService/cgi/signup.html index c2c5d700a..42334eade 100755 --- a/fs_selfservice/FS-SelfService/cgi/signup.html +++ b/fs_selfservice/FS-SelfService/cgi/signup.html @@ -21,7 +21,7 @@ <%= - $OUT = join("\n",map { my $method = $_ ; map { qq|| } qw / payinfo payinfo1 payinfo2 payname paycvv month year type / } @payby); + $OUT = join("\n",map { my $method = $_ ; map { qq|| } qw / payinfo payinfo1 payinfo2 payname paystate paytype paycvv month year type / } @payby); %> <%= @@ -94,6 +94,22 @@ Contact Information Fax +<%= + $OUT = ''; + if ( $stateid_enabled ) { + my ($county_html, $state_html, $country_html) = + regionselector( { + prefix => 'stateid_', + default_state => $statedefault, + default_country => $countrydefault, + locales => \@cust_main_county, + } ); + $OUT .= qq!!. $label{stateid}.''; + $OUT .= qq!!; + $OUT .= qq!!. $label{stateid_state} .''; + $OUT .="$county_html $state_html"; + } +%> * required fields

Billing information!; } } + if ( $paystate_enabled ) { + foreach my $payby ( grep { exists $payby{$_} } qw(CHEK DCHK) ) { + my ($county_html, $state_html, $country_html) = + regionselector( { + prefix => "${payby}_pay", + default_state => $statedefault, + default_country => $countrydefault, + locales => \@cust_main_county, + } ); + $payby{$payby} .= "
${r}Bank state $county_html $state_html"; + } + } my( $account, $aba ) = split('@', $payinfo); my %paybychecked = ( 'CARD' => qq!
@@ -129,8 +145,8 @@ Contact Information my %payby = ( 'CARD' => qq!Credit card
*$cardselect
*Exp !. expselect("CARD"). qq!
*Name on card
!, 'DCRD' => qq!Credit card
*$cardselect
*Exp !. expselect("DCRD"). qq!
*Name on card
!, - 'CHEK' => qq!Electronic check
${r}Account number
${r}ABA/Routing code
${r}Bank name !, - 'DCHK' => qq!Electronic check
${r}Account number
${r}ABA/Routing code
${r}Bank name !, + 'CHEK' => qq!Electronic check
${r}Account number
${r}ABA/Routing code Type
{$r}Bank State
${r}Bank name !, + 'DCHK' => qq!Electronic check
${r}Account number Type
${r}ABA/Routing code
{$r}Bank State
${r}Bank name !, 'LECB' => qq!Phone bill billing
${r}Phone number !, 'BILL' => qq!Billing
P.O.
*Exp !. expselect("BILL", "12-2037"). qq!
*Attention
!, 'COMP' => qq!Complimentary
*Approved by
*Exp !. expselect("COMP"), @@ -142,13 +158,25 @@ Contact Information $payby{$payby} .= qq!
CVV2 (help)
!, 'DCRD' => qq!Credit card
*$cardselect
*Exp !. expselect("DCRD", $paydate). qq!
*Name on card
!, - 'CHEK' => qq!Electronic check
${r}Account number
${r}ABA/Routing code
${r}Bank name !, - 'DCHK' => qq!Electronic check
${r}Account number
${r}ABA/Routing code
${r}Bank name !, + 'CHEK' => qq!Electronic check
${r}Account number Type
${r}ABA/Routing code
${r}Bank name !, + 'DCHK' => qq!Electronic check
${r}Account number Type
${r}ABA/Routing code
${r}Bank name !, 'LECB' => qq!Phone bill billing
${r}Phone number !, 'BILL' => qq!Billing
P.O.
*Exp !. expselect("BILL", $paydate). qq!
*Attention
!, 'COMP' => qq!Complimentary
*Approved by
*Exp !. expselect("COMP", $paydate), @@ -160,6 +188,22 @@ Contact Information $paybychecked{$payby} .= qq!!; } } + if ( $paystate_enabled ) { + foreach my $payby ( grep { exists $payby{$_} } qw(CHEK DCHK) ) { + my ($county_html, $state_html, $country_html) = + regionselector( { + prefix => "${payby}_pay", + selected_county => $county, + selected_state => $state, + selected_country => $country, + default_state => $statedefault, + default_country => $countrydefault, + locales => \@cust_main_county, + } ); + $paybychecked{$payby} .= "
${r}Bank state $county_html $state_html"; + } + } + use Tie::IxHash; use HTML::Widgets::SelectLayers; @@ -282,7 +326,7 @@ function fixup_form() { // copy payment method data up to OneTrueForm - var payment_method_elements = new Array( 'payinfo', 'payinfo1', 'payinfo2', 'payname', 'paycvv' , 'month', 'year','type' ); + var payment_method_elements = new Array( 'payinfo', 'payinfo1', 'payinfo2', 'payname', 'paycvv' , 'paystate', 'paytype', 'month', 'year','type' ); var payment_method_form_name = document.OneTrueForm.select.options[document.OneTrueForm.select.selectedIndex].value; document.OneTrueForm.elements['payby'].value = payment_method_form_name; var payment_method_form = document.forms[payment_method_form_name]; diff --git a/httemplate/view/cust_main/billing.html b/httemplate/view/cust_main/billing.html index 42467bb31..3fcb5d460 100644 --- a/httemplate/view/cust_main/billing.html +++ b/httemplate/view/cust_main/billing.html @@ -90,10 +90,12 @@ Billing information +% if ( $conf->exists('show_bankstate') ) { +% } % } elsif ( $cust_main->payby eq 'LECB' ) { % $cust_main->payinfo =~ /^(\d{3})(\d{3})(\d{4})$/; % my $payinfo = "$1-$2-$3";
* Card type$cardselect
* Card number
* Expration!. expselect("CARD", $paydate). qq!
* Name on card
CVV2 (help)
Bank name <% $cust_main->payname %>
<% $paystate_label %> <% $cust_main->paystate || '   ' %>