X-Git-Url: http://git.freeside.biz/gitweb/?p=freeside.git;a=blobdiff_plain;f=fs_selfservice%2FFS-SelfService%2Fcgi%2Fselfservice.cgi;h=d23e6ba68aa680e7951be559c9764943b50efd46;hp=0816758fb62b4b37616e03176e3c4d8c5524b489;hb=d7eafc9c9aae2bf47ea19a56cc5bb1380c5874e4;hpb=5fc8c5edf574ab024d4646914b6432d458e2ffbd diff --git a/fs_selfservice/FS-SelfService/cgi/selfservice.cgi b/fs_selfservice/FS-SelfService/cgi/selfservice.cgi index 0816758fb..d23e6ba68 100644 --- a/fs_selfservice/FS-SelfService/cgi/selfservice.cgi +++ b/fs_selfservice/FS-SelfService/cgi/selfservice.cgi @@ -1,27 +1,37 @@ #!/usr/bin/perl -Tw use strict; -use vars qw($cgi $session_id $form_max $template_dir); +use vars qw($DEBUG $cgi $session_id $form_max $template_dir); use subs qw(do_template); use CGI; use CGI::Carp qw(fatalsToBrowser); use Text::Template; use HTML::Entities; -use FS::SelfService qw( login customer_info invoice - payment_info process_payment - list_pkgs - part_svc_info provision_acct provision_external - unprovision_svc - ); +use Date::Format; +use Number::Format 1.50; +use FS::SelfService qw( + access_info login_info login customer_info edit_info invoice + payment_info process_payment realtime_collect process_prepay + list_pkgs order_pkg signup_info order_recharge + part_svc_info provision_acct provision_external + unprovision_svc change_pkg suspend_pkg domainselector + list_svcs list_svc_usage list_cdr_usage list_support_usage + myaccount_passwd + mason_comp +); $template_dir = '.'; +$DEBUG = 1; + $form_max = 255; $cgi = new CGI; unless ( defined $cgi->param('session') ) { - do_template('login',{}); + my $login_info = login_info( 'agentnum' => scalar($cgi->param('agentnum')) ); + + do_template('login', $login_info ); exit; } @@ -45,10 +55,12 @@ if ( $cgi->param('session') eq 'login' ) { 'password' => $password, ); if ( $rv->{error} ) { + my $login_info = login_info( 'agentnum' => $cgi->param('agentnum') ); do_template('login', { 'error' => $rv->{error}, 'username' => $username, 'domain' => $domain, + %$login_info, } ); exit; } else { @@ -61,30 +73,120 @@ $session_id = $cgi->param('session'); #order|pw_list XXX ??? $cgi->param('action') =~ - /^(myaccount|view_invoice|make_payment|payment_results|logout|change_bill|change_ship|provision|provision_svc|process_svc_acct|process_svc_external|delete_svc)$/ + /^(myaccount|view_invoice|make_payment|make_ach_payment|make_term_payment|make_thirdparty_payment|payment_results|ach_payment_results|recharge_prepay|recharge_results|logout|change_bill|change_ship|change_pay|process_change_bill|process_change_ship|process_change_pay|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|view_cdr_details|view_support_details|change_password|process_change_password|customer_suspend_pkg|process_suspend_pkg)$/ or die "unknown action ". $cgi->param('action'); my $action = $1; +warn "calling $action sub\n" + if $DEBUG; +$FS::SelfService::DEBUG = $DEBUG; my $result = eval "&$action();"; die $@ if $@; -if ( $result->{error} eq "Can't resume session" ) { #ick - do_template('login',{}); +if ( $result->{error} eq "Can't resume session" + || $result->{error} eq "Expired session" ) { #ick + + my $login_info = login_info(); + do_template('login', $login_info); exit; } #warn $result->{'open_invoices'}; #warn scalar(@{$result->{'open_invoices'}}); -warn "processing template $action\n"; +warn "processing template $action\n" + if $DEBUG; do_template($action, { 'session_id' => $session_id, + 'action' => $action, #so the menu knows what tab we're on... + #%{ payment_info( 'session_id' => $session_id ) }, # cust_paybys for the menu %{$result} }); #-- -sub myaccount { customer_info( 'session_id' => $session_id ); } +use Data::Dumper; +sub myaccount { my $result = customer_info( 'session_id' => $session_id ); warn Dumper($result); $result;} + +sub change_bill { my $payment_info = + payment_info( 'session_id' => $session_id ); + return $payment_info if ( $payment_info->{'error'} ); + my $customer_info = + customer_info( 'session_id' => $session_id ); + return { + %$payment_info, + %$customer_info, + }; + } +sub change_ship { change_bill(@_); } +sub change_pay { change_bill(@_); } + +sub _process_change_info { + my ($erroraction, @fields) = @_; + + my $results = ''; + + $results ||= edit_info ( + 'session_id' => $session_id, + map { ($_ => $cgi->param($_)) } grep { defined($cgi->param($_)) } @fields, + ); + + + if ( $results->{'error'} ) { + no strict 'refs'; + $action = $erroraction; + return { + $cgi->Vars, + %{&$action()}, + 'error' => ''. $results->{'error'}. '', + }; + } else { + return $results; + } +} + +sub process_change_bill { + _process_change_info( 'change_bill', + qw( first last company address1 address2 city state + county zip country daytime night fax ) + ); +} + +sub process_change_ship { + my @list = map { "ship_$_" } + qw( first last company address1 address2 city state + county zip country daytime night fax + ); + if ($cgi->param('same') eq 'Y') { + foreach (@list) { $cgi->param($_, '') } + } + + _process_change_info( 'change_ship', @list ); +} + +sub process_change_pay { + my $postal = $cgi->param( 'postal_invoicing' ); + my $payby = $cgi->param( 'payby' ); + my @list = + qw( payby payinfo payinfo1 payinfo2 month year payname + address1 address2 city county state zip country auto paytype + paystate ss stateid stateid_state invoicing_list + ); + push @list, 'postal_invoicing' if $postal; + unless ( $payby ne 'BILL' + || $postal + || $cgi->param( 'invoicing_list' ) + ) + { + $action = 'change_pay'; + return { + %{&change_pay()}, + $cgi->Vars, + 'error' => 'Postal or email required.', + }; + } + _process_change_info( 'change_pay', @list ); +} sub view_invoice { @@ -97,30 +199,217 @@ sub view_invoice { } +sub customer_order_pkg { + my $init_data = signup_info( 'customer_session_id' => $session_id ); + return $init_data if ( $init_data->{'error'} ); + + my $customer_info = customer_info( 'session_id' => $session_id ); + return $customer_info if ( $customer_info->{'error'} ); + + my $pkgselect = mason_comp( + 'session_id' => $session_id, + 'comp' => '/edit/cust_main/first_pkg/select-part_pkg.html', + 'args' => [ 'password_verify' => 1, + 'onchange' => 'enable_order_pkg()', + 'relurls' => 1, + 'empty_label' => 'Select package', + ], + ); + + $pkgselect = $pkgselect->{'error'} || $pkgselect->{'output'}; + + return { + ( map { $_ => $init_data->{$_} } + qw( part_pkg security_phrase svc_acct_pop ), + ), + %$customer_info, + 'pkg_selector' => $pkgselect, + }; +} + +sub customer_change_pkg { + my $init_data = signup_info( 'customer_session_id' => $session_id ); + return $init_data if ( $init_data->{'error'} ); + + my $customer_info = customer_info( 'session_id' => $session_id ); + return $customer_info if ( $customer_info->{'error'} ); + + return { + ( map { $_ => $init_data->{$_} } + qw( part_pkg security_phrase svc_acct_pop ), + ), + ( map { $_ => $cgi->param($_) } + qw( pkgnum pkg ) + ), + %$customer_info, + }; +} + +sub process_order_pkg { + + my $results = ''; + + my @params = (qw( custnum pkgpart )); + my $svcdb = ''; + if ( $cgi->param('pkgpart_svcpart') =~ /^(\d+)_(\d+)$/ ) { + $cgi->param('pkgpart', $1); + $cgi->param('svcpart', $2); + push @params, 'svcpart'; + $svcdb = $cgi->param('svcdb'); + push @params, 'domsvc' if $svcdb eq 'svc_acct'; + } else { + $svcdb = 'svc_acct'; + } + + if ( $svcdb eq 'svc_acct' ) { + + push @params, qw( username _password _password2 sec_phrase popnum ); + + unless ( length($cgi->param('_password')) ) { + my $init_data = signup_info( 'customer_session_id' => $session_id ); + $results = { 'error' => $init_data->{msgcat}{empty_password} }; + $results = { 'error' => $init_data->{error} } if($init_data->{error}); + } + if ( $cgi->param('_password') ne $cgi->param('_password2') ) { + my $init_data = signup_info( 'customer_session_id' => $session_id ); + $results = { 'error' => $init_data->{msgcat}{passwords_dont_match} }; + $results = { 'error' => $init_data->{error} } if($init_data->{error}); + $cgi->param('_password', ''); + $cgi->param('_password2', ''); + } + + } elsif ( $svcdb eq 'svc_phone' ) { + + push @params, qw( phonenum sip_password pin phone_name ); + + } else { + die "$svcdb not handled on process_order_pkg yet"; + } + + $results ||= order_pkg ( + 'session_id' => $session_id, + map { $_ => $cgi->param($_) } @params + ); + + + if ( $results->{'error'} ) { + $action = 'customer_order_pkg'; + return { + $cgi->Vars, + %{customer_order_pkg()}, + 'error' => ''. $results->{'error'}. '', + }; + } else { + return $results; + } + +} + +sub process_change_pkg { + + my $results = ''; + + $results ||= change_pkg ( + 'session_id' => $session_id, + map { $_ => $cgi->param($_) } + qw( pkgpart pkgnum ) + ); + + + if ( $results->{'error'} ) { + $action = 'customer_change_pkg'; + return { + $cgi->Vars, + %{customer_change_pkg()}, + 'error' => ''. $results->{'error'}. '', + }; + } else { + return $results; + } + +} + +sub process_suspend_pkg { + my $results = ''; + $results = suspend_pkg ( + 'session_id' => $session_id, + map { $_ => $cgi->param($_) } + qw( pkgnum ) + ); + if ( $results->{'error'} ) { + $action = 'provision'; + return { + 'error' => ''. $results->{'error'}. '', + } + } + else { + return $results; + } +} + +sub process_order_recharge { + + my $results = ''; + + $results ||= order_recharge ( + 'session_id' => $session_id, + map { $_ => $cgi->param($_) } + qw( svcnum ) + ); + + + if ( $results->{'error'} ) { + $action = 'view_usage'; + if ($results->{'error'} eq '_decline') { + $results->{'error'} = "There has been an error processing your account. Please contact customer support." + } + return { + $cgi->Vars, + %{view_usage()}, + 'error' => ''. $results->{'error'}. '', + }; + } else { + return $results; + } + +} + sub make_payment { payment_info( 'session_id' => $session_id ); } sub payment_results { - use Business::CreditCard; + use Business::CreditCard 0.30; + + #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"; #!!! + or die "Illegal amount: ". $cgi->param('amount'); #!!! my $amount = $1; my $payinfo = $cgi->param('payinfo'); - $payinfo =~ s/\D//g; - $payinfo =~ /^(\d{13,16})$/ + $payinfo =~ s/[^\dx]//g; + $payinfo =~ /^([\dx]{13,16})$/ #or $error ||= $init_data->{msgcat}{invalid_card}; #. $self->payinfo; or die "illegal card"; #!!! $payinfo = $1; - validate($payinfo) - #or $error ||= $init_data->{msgcat}{invalid_card}; #. $self->payinfo; - or die "invalid card"; #!!! - cardtype($payinfo) eq $cgi->param('card_type') - #or $error ||= $init_data->{msgcat}{not_a}. $cgi->param('CARD_type'); - or die "not a ". $cgi->param('card_type'); + unless ( $payinfo =~ /x/ ) { + validate($payinfo) + #or $error ||= $init_data->{msgcat}{invalid_card}; #. $self->payinfo; + or die "invalid card"; #!!! + } + + if ( $cgi->param('card_type') ) { + cardtype($payinfo) eq $cgi->param('card_type') + #or $error ||= $init_data->{msgcat}{not_a}. $cgi->param('CARD_type'); + or die "not a ". $cgi->param('card_type'); + } + + $cgi->param('paycvv') =~ /^\s*(.{0,4})\s*$/ or die "illegal CVV2"; + my $paycvv = $1; $cgi->param('month') =~ /^(\d{2})$/ or die "illegal month"; my $month = $1; @@ -139,12 +428,15 @@ sub payment_results { $cgi->param('city') =~ /^(.{0,80})$/ or die "illegal city"; my $city = $1; - $cgi->param('state') =~ /^(.{2})$/ or die "illegal state"; + $cgi->param('state') =~ /^(.{0,80})$/ or die "illegal state"; my $state = $1; $cgi->param('zip') =~ /^(.{0,10})$/ or die "illegal zip"; my $zip = $1; + $cgi->param('country') =~ /^(.{0,2})$/ or die "illegal country"; + my $country = $1; + my $save = 0; $save = 1 if $cgi->param('save'); @@ -154,10 +446,16 @@ sub payment_results { $cgi->param('paybatch') =~ /^([\w\-\.]+)$/ or die "illegal paybatch"; my $paybatch = $1; + $cgi->param('discount_term') =~ /^(\d*)$/ or die "illegal discount_term"; + my $discount_term = $1; + + process_payment( 'session_id' => $session_id, + 'payby' => 'CARD', 'amount' => $amount, 'payinfo' => $payinfo, + 'paycvv' => $paycvv, 'month' => $month, 'year' => $year, 'payname' => $payname, @@ -166,6 +464,82 @@ sub payment_results { 'city' => $city, 'state' => $state, 'zip' => $zip, + 'country' => $country, + 'save' => $save, + 'auto' => $auto, + 'paybatch' => $paybatch, + 'discount_term' => $discount_term, + ); + +} + +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 =~ s/[^\dx]//g; + $payinfo1 =~ /^([\dx]+)$/ + or die "illegal account"; #!!! + $payinfo1 = $1; + + my $payinfo2 = $cgi->param('payinfo2'); + $payinfo2 =~ s/[^\dx]//g; + $payinfo2 =~ /^([\dx]+)$/ + 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, @@ -173,6 +547,42 @@ sub payment_results { } +sub make_thirdparty_payment { + $cgi->param('payby_method') =~ /^(CC|ECHECK)$/ + or die "illegal payby method"; + realtime_collect( 'session_id' => $session_id, 'method' => $1 ); +} + +sub make_term_payment { + $cgi->param('amount') =~ /^(\d+\.\d{2})$/ + or die "illegal payment amount"; + my $balance = $1; + $cgi->param('discount_term') =~ /^(\d+)$/ + or die "illegal discount term"; + my $discount_term = $1; + $action = 'make_payment'; + ({ %{payment_info( 'session_id' => $session_id )}, + 'balance' => $balance, + 'discount_term' => $discount_term, + }) +} + +sub recharge_prepay { + customer_info( 'session_id' => $session_id ); +} + +sub recharge_results { + + my $prepaid_cardnum = $cgi->param('prepaid_cardnum'); + $prepaid_cardnum =~ s/\W//g; + $prepaid_cardnum =~ /^(\w*)$/ or die "illegal prepaid card number"; + $prepaid_cardnum = $1; + + process_prepay ( 'session_id' => $session_id, + 'prepaid_cardnum' => $prepaid_cardnum, + ); +} + sub logout { FS::SelfService::logout( 'session_id' => $session_id ); } @@ -204,7 +614,7 @@ sub process_svc_acct { my $result = provision_acct ( 'session_id' => $session_id, map { $_ => $cgi->param($_) } qw( - pkgnum svcpart username _password _password2 sec_phrase popnum ) + pkgnum svcpart username domsvc _password _password2 sec_phrase popnum ) ); if ( exists $result->{'error'} && $result->{'error'} ) { @@ -239,6 +649,76 @@ sub delete_svc { ); } +sub view_usage { + list_svcs( + 'session_id' => $session_id, + 'svcdb' => [ 'svc_acct', 'svc_phone' ], + 'ncancelled' => 1, + ); +} + +sub view_usage_details { + list_svc_usage( + 'session_id' => $session_id, + 'svcnum' => $cgi->param('svcnum'), + 'beginning' => $cgi->param('beginning') || '', + 'ending' => $cgi->param('ending') || '', + ); +} + +sub view_cdr_details { + list_cdr_usage( + 'session_id' => $session_id, + 'svcnum' => $cgi->param('svcnum'), + 'beginning' => $cgi->param('beginning') || '', + 'ending' => $cgi->param('ending') || '', + ); +} + +sub view_support_details { + list_support_usage( + 'session_id' => $session_id, + 'svcnum' => $cgi->param('svcnum'), + 'beginning' => $cgi->param('beginning') || '', + 'ending' => $cgi->param('ending') || '', + ); +} + +sub change_password { + list_svcs( + 'session_id' => $session_id, + 'svcdb' => 'svc_acct', + ); +}; + +sub process_change_password { + + my $result = myaccount_passwd( + 'session_id' => $session_id, + map { $_ => $cgi->param($_) } qw( svcnum new_password new_password2 ) + ); + + if ( exists $result->{'error'} && $result->{'error'} ) { + + $action = 'change_password'; + return { + $cgi->Vars, + %{ list_svcs( 'session_id' => $session_id, + 'svcdb' => 'svc_acct', + ) + }, + #'svcnum' => $cgi->param('svcnum'), + 'error' => $result->{'error'} + }; + + } else { + + return $result; + + } + +} + #-- sub do_template { @@ -249,12 +729,21 @@ sub do_template { $fill_in->{'selfurl'} = $cgi->self_url; $fill_in->{'cgi'} = \$cgi; - my $template = new Text::Template( TYPE => 'FILE', - SOURCE => "$template_dir/$name.html", + my $access_info = $session_id + ? access_info( 'session_id' => $session_id ) + : {}; + $fill_in->{$_} = $access_info->{$_} foreach keys %$access_info; + + my $source = "$template_dir/$name.html"; + #warn "creating template for $source\n"; + my $template = new Text::Template( TYPE => 'FILE', + SOURCE => $source, DELIMITERS => [ '<%=', '%>' ], - UNTAINT => 1, ) + UNTAINT => 1, + ) or die $Text::Template::ERROR; + #warn "filling in $template with $fill_in\n"; print $cgi->header( '-expires' => 'now' ), $template->fill_in( PACKAGE => 'FS::SelfService::_selfservicecgi', HASH => $fill_in @@ -267,11 +756,15 @@ package FS::SelfService::_selfservicecgi; #use FS::SelfService qw(regionselector expselect popselector); use HTML::Entities; -use FS::SelfService qw(popselector); +use FS::SelfService qw(regionselector popselector domainselector location_form); #false laziness w/agent.cgi +use vars qw(@INCLUDE_ARGS); sub include { my $name = shift; + + @INCLUDE_ARGS = @_; + my $template = new Text::Template( TYPE => 'FILE', SOURCE => "$main::template_dir/$name.html", DELIMITERS => [ '<%=', '%>' ], @@ -285,3 +778,4 @@ sub include { } +1;