#!/usr/bin/perl -w
use strict;
-use vars qw($DEBUG $cgi $session_id $form_max $template_dir);
+use vars qw($DEBUG $cgi $session_id $pw_session_id $form_max $template_dir);
use subs qw(do_template);
use CGI;
use CGI::Carp qw(fatalsToBrowser);
use Date::Parse 'str2time';
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
+ access_info login_info login customer_info edit_info insert_payby update_payby
+ invoice payment_info process_payment realtime_collect process_prepay
list_pkgs order_pkg signup_info order_recharge
- part_svc_info provision_acct provision_external provision_phone
+ part_svc_info provision_acct provision_external provision_phone provision_forward
unprovision_svc change_pkg suspend_pkg domainselector
list_svcs list_svc_usage list_cdr_usage list_support_usage
myaccount_passwd list_invoices create_ticket get_ticket did_report
mason_comp port_graph
start_thirdparty finish_thirdparty
reset_passwd check_reset_passwd process_reset_passwd
+ validate_passwd
+ billing_history
);
$template_dir = '.';
$form_max = 255;
$cgi = new CGI;
-my %cookies = CGI::Cookie->fetch;
-
-my $login_rv;
-
-if ( exists($cookies{'session'}) ) {
-
- $session_id = $cookies{'session'}->value;
-
- if ( $session_id eq 'login' ) {
- # then we've just come back from the login page
-
- $cgi->param('password') =~ /^(.{0,$form_max})$/;
- my $password = $1;
-
- if ( $cgi->param('email') =~ /^\s*([a-z0-9_\-\.\@]{1,$form_max})\s*$/i ) {
-
- my $email = $1;
- $login_rv = login(
- 'email' => $email,
- 'password' => $password
- );
- $session_id = $login_rv->{'session_id'};
-
- } else {
-
- $cgi->param('username') =~ /^\s*([a-z0-9_\-\.\&]{0,$form_max})\s*$/i;
- my $username = $1;
-
- $cgi->param('domain') =~ /^\s*([\w\-\.]{0,$form_max})\s*$/;
- my $domain = $1;
-
- if ( $username and $domain and $password ) {
-
- # authenticate
- $login_rv = login(
- 'username' => $username,
- 'domain' => $domain,
- 'password' => $password,
- );
- $session_id = $login_rv->{'session_id'};
-
- } elsif ( $username or $domain or $password ) {
-
- my $error = 'Illegal '; #XXX localization...
- my $count = 0;
- if ( !$username ) {
- $error .= 'username';
- $count++;
- }
- if ( !$domain ) {
- $error .= ', ' if $count;
- $error .= 'domain';
- $count++;
- }
- if ( !$password ) {
- $error .= ', ' if $count;
- $error .= 'and ' if $count > 1;
- $error .= 'password';
- $count++;
- }
- $error .= '.';
- $login_rv = {
- 'username' => $username,
- 'domain' => $domain,
- 'password' => $password,
- 'error' => $error,
- };
- $session_id = undef; # attempt login again
-
- }
-
- } # else there was no input, so show no error message
-
- } # else session_id ne 'login'
-
-} else {
- # there is no session cookie
- $login_rv = {};
-}
-
-if ( !$session_id ) {
- # XXX why are we getting agentnum from a CGI param? surely it should
- # be some kind of configuration option.
- #
- # show the login page
- $session_id = 'login'; # set state
- my $login_info = login_info( 'agentnum' => scalar($cgi->param('agentnum')) );
-
- do_template('login', { %$login_rv, %$login_info });
- exit;
-}
-
-# at this point $session_id is a real session
#order|pw_list XXX ???
my @actions = ( qw(
change_bill
change_ship
change_pay
+ change_creditcard_pay
+ change_check_pay
+ process_change_creditcard_pay
+ process_change_check_pay
process_change_bill
process_change_ship
process_change_pay
process_svc_acct
process_svc_phone
process_svc_external
+ process_svc_forward
delete_svc
view_usage
view_usage_details
real_port_graph
change_password
process_change_password
+ customer_suspend_pkg
+ process_suspend_pkg
+ switch_cust
+ history
+ validate_password
+));
+
+my @nologin_actions = (qw(
forgot_password
do_forgot_password
process_forgot_password
do_process_forgot_password
- customer_suspend_pkg
- process_suspend_pkg
+ process_forgot_password_session
+ validate_password_nologin
));
+push @actions, @nologin_actions;
+my %nologin_actions = map { $_=>1 } @nologin_actions;
my $action = 'myaccount'; # sensible default
-if ( $cgi->param('action') =~ /^(\w+)$/ ) {
+
+if ( $cgi->param('action') =~ /^process_forgot_password_session_(\w+)$/ ) {
+ $action = 'process_forgot_password_session';
+ $pw_session_id = $1;
+} elsif ( $cgi->param('action') =~ /^(\w+)$/ ) {
if (grep {$_ eq $1} @actions) {
$action = $1;
} else {
warn "WARNING: unrecognized action '$1'\n";
}
}
+unless ( $nologin_actions{$action} ) {
+
+ my %cookies = CGI::Cookie->fetch;
+
+ my $login_rv = {};
+
+ if ( exists($cookies{'session'}) ) {
+
+ $session_id = $cookies{'session'}->value;
+
+ if ( $session_id eq 'login' ) {
+ # then we've just come back from the login page
+
+ $cgi->param('password') =~ /^(.{0,$form_max})$/;
+ my $password = $1;
+
+ if ( $cgi->param('email') =~ /^\s*([a-z0-9_\-\.\+\@]{1,$form_max})\s*$/i ) {
+
+ my $email = $1;
+ $login_rv = login(
+ 'email' => $email,
+ 'password' => $password
+ );
+
+ if ( $login_rv->{'error'} ) {
+ my $ip = $cgi->remote_addr();
+ warn("login failure [email $email] [ip $ip] [error $login_rv->{error}]");
+ } else {
+ #successful login
+ }
+
+ $session_id = $login_rv->{'session_id'};
+
+ } else {
+
+ $cgi->param('username') =~ /^\s*([a-z0-9_\-\.\&]{0,$form_max})\s*$/i;
+ my $username = $1;
+
+ $cgi->param('domain') =~ /^\s*([\w\-\.]{0,$form_max})\s*$/;
+ my $domain = $1;
+
+ if ( $username and $domain and $password ) {
+
+ # authenticate
+ $login_rv = login(
+ 'username' => $username,
+ 'domain' => $domain,
+ 'password' => $password,
+ );
+ $session_id = $login_rv->{'session_id'};
+
+ } elsif ( $username or $domain or $password ) {
+
+ my $error = 'Illegal '; #XXX localization...
+ my $count = 0;
+ if ( !$username ) {
+ $error .= 'username';
+ $count++;
+ }
+ if ( !$domain ) {
+ $error .= ', ' if $count;
+ $error .= 'domain';
+ $count++;
+ }
+ if ( !$password ) {
+ $error .= ', ' if $count;
+ $error .= 'and ' if $count > 1;
+ $error .= 'password';
+ $count++;
+ }
+ $error .= '.';
+ $login_rv = {
+ 'username' => $username,
+ 'domain' => $domain,
+ 'password' => $password,
+ 'error' => $error,
+ };
+ $session_id = undef; # attempt login again
+
+ }
+
+ } # else there was no input, so show no error message
+
+ } # else session_id ne 'login'
+
+ } # else there is no session cookie
+
+ if ( !$session_id ) {
+ # show the login page
+ $session_id = 'login'; # set state
+ my $login_info = login_info( 'agentnum' => scalar($cgi->param('agentnum')) );
+
+ do_template('login', { %$login_rv, %$login_info });
+ exit;
+ }
+
+ # at this point $session_id is a real session
+
+ if ( ! $login_rv->{'custnum'} && ! $login_rv->{'svcnum'} && $login_rv->{'customers'} ) {
+ #select a customer if we're a multi-contact customer
+ do_template('select_cust', { %$login_rv } );
+ exit;
+ }
+
+}
warn "calling $action sub\n"
if $DEBUG;
my $result = eval "&$action();";
die $@ if $@;
+use Data::Dumper;
warn Dumper($result) if $DEBUG;
if ( $result->{error} && ( $result->{error} eq "Can't resume session"
|| $result->{error} eq "Expired session") ) { #ick
$session_id = 'login';
- my $login_info = login_info();
+ my $login_info = login_info( 'agentnum' => scalar($cgi->param('agentnum')) );
do_template('login', $login_info);
exit;
}
#--
-use Data::Dumper;
+sub switch_cust {
+ $action = 'myaccount';
+ FS::SelfService::switch_cust( 'session_id' => $session_id,
+ 'custnum' => scalar($cgi->param('custnum')),
+ );
+}
+
sub myaccount {
customer_info( 'session_id' => $session_id );
}
-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_bill {
+ my $payby = shift;
+ my $payment_info;
+ if ($payby) {
+ $payment_info = payment_info( 'session_id' => $session_id, 'payment_payby' => $payby, );
+ }
+ else {
+ $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 change_creditcard_pay { change_bill('CARD'); }
+sub change_check_pay { change_bill('CHEK'); }
+
sub _process_change_info {
my ($erroraction, @fields) = @_;
}
}
+sub _process_change_payby {
+ my ($erroraction, @fields) = @_;
+
+ my $results = '';
+
+ $results ||= update_payby (
+ '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' => '<FONT COLOR="#FF0000">'. $results->{'error'}. '</FONT>',
+ };
+ } else {
+ return $results;
+ }
+}
+
+sub _process_insert_payby {
+ my ($erroraction, @fields) = @_;
+
+ my $results = '';
+
+ $results ||= insert_payby (
+ 'session_id' => $session_id,
+ map { ($_ => $cgi->param($_)) } grep { defined($cgi->param($_)) } @fields,
+ );
+
+ ## check error
+
+
+ if ( $results->{'error'} ) {
+ no strict 'refs';
+ $action = $erroraction;
+ return {
+ $cgi->Vars,
+ %{&$action()},
+ 'error' => '<FONT COLOR="#FF0000">'. $results->{'error'}. '</FONT>',
+ };
+ } else {
+ return $results;
+ }
+}
+
sub process_change_bill {
_process_change_info( 'change_bill',
qw( first last company address1 address2 city state
'error' => '<FONT COLOR="#FF0000">Postal or email required.</FONT>',
};
}
+
_process_change_info( 'change_pay', @list );
}
+sub process_change_creditcard_pay {
+ my $payby = $cgi->param( 'payby' );
+ $cgi->param('paydate', $cgi->param('year') . '-' . $cgi->param('month') . '-01');
+ my @list =
+ qw( payby payinfo payinfo1 payinfo2 paydate payname custpaybynum
+ address1 address2 city county state zip country auto paytype
+ paystate ss stateid stateid_state invoicing_list
+ );
+ if ($cgi->param( 'custpaybynum' )) { _process_change_payby( 'change_creditcard_pay', @list ); }
+ else { _process_insert_payby( 'change_creditcard_pay', @list ); }
+}
+
+sub process_change_check_pay {
+ my $payby = $cgi->param( 'payby' );
+ #$cgi->param('paydate', '2039-12-01');
+ my @list =
+ qw( payby payinfo payinfo1 payinfo2 paydate payname custpaybynum
+ address1 address2 city county state zip country auto paytype
+ paystate ss stateid stateid_state invoicing_list
+ );
+ if ($cgi->param( 'custpaybynum' )) { _process_change_payby( 'change_check_pay', @list ); }
+ else { _process_insert_payby( 'change_check_pay', @list ); }
+}
+
sub view_invoice {
$cgi->param('invnum') =~ /^(\d+)$/ or die "illegal invnum";
list_invoices( 'session_id' => $session_id, );
}
+sub history {
+ billing_history( 'session_id' => $session_id, );
+}
+
sub tktcreate {
my $customer_info = customer_info( 'session_id' => $session_id );
return $customer_info if ( $customer_info->{'error'} );
sub make_payment {
- my $payment_info = payment_info( 'session_id' => $session_id );
+ my $payment_info = payment_info( 'session_id' => $session_id, 'payment_payby' => 'CARD' );
+
+ my $amount =
+ ($payment_info->{'balance'} && ($payment_info->{'balance'} > 0))
+ ? $payment_info->{'balance'}
+ : '';
my $tr_amount_fee = mason_comp(
'session_id' => $session_id,
'comp' => '/elements/tr-amount_fee.html',
- 'args' => [ 'amount' => $payment_info->{'balance'},
+ 'args' => [ 'amount' => $amount,
],
);
sub payment_results {
- use Business::CreditCard 0.30;
+ use Business::CreditCard 0.35;
#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: ". $cgi->param('amount'); #!!!
+ or return { 'error' => "Illegal amount: ". $cgi->param('amount') }; #!!!
my $amount = $1;
my $payinfo = $cgi->param('payinfo');
$payinfo =~ s/[^\dx]//g;
- $payinfo =~ /^([\dx]{13,16}|[\dx]{8,9})$/
+ $payinfo =~ /^([\dx]{13,19}|[\dx]{8,9})$/
#or $error ||= $init_data->{msgcat}{invalid_card}; #. $self->payinfo;
- or die "illegal card"; #!!!
+ or return { 'error' => "illegal card" }; #!!!
$payinfo = $1;
unless ( $payinfo =~ /x/ ) {
validate($payinfo)
#or $error ||= $init_data->{msgcat}{invalid_card}; #. $self->payinfo;
- or die "invalid card"; #!!!
+ or return { 'error' => "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');
+ or return { 'error' => "not a ". $cgi->param('card_type') };
}
$cgi->param('paycvv') =~ /^\s*(.{0,4})\s*$/ or die "illegal CVV2";
my $auto = 0;
$auto = 1 if $cgi->param('auto');
- $cgi->param('paybatch') =~ /^([\w\-\.]+)$/ or die "illegal paybatch";
+ $cgi->param('payunique') =~ /^([\w\-\.]*)$/ or die "illegal payunique";
+ my $payunique = $1;
+
+ $cgi->param('paybatch') =~ /^([\w\-\.]*)$/ or die "illegal paybatch";
my $paybatch = $1;
$cgi->param('discount_term') =~ /^(\d*)$/ or die "illegal discount_term";
'country' => $country,
'save' => $save,
'auto' => $auto,
+ 'payunique' => $payunique,
'paybatch' => $paybatch,
'discount_term' => $discount_term,
);
}
sub make_ach_payment {
- payment_info( 'session_id' => $session_id );
+ payment_info( 'session_id' => $session_id, 'payment_payby' => 'CHEK' );
}
sub ach_payment_results {
my $result = part_svc_info(
'session_id' => $session_id,
- map { $_ => $cgi->param($_) } qw( pkgnum svcpart svcnum ),
+ map { $_ => ($cgi->param($_) || '') } qw( pkgnum svcpart svcnum ),
);
die $result->{'error'} if exists $result->{'error'} && $result->{'error'};
);
}
+sub process_svc_forward {
+
+ my $result = provision_forward (
+ 'session_id' => $session_id,
+ map { $_ => $cgi->param($_) || '' } qw(
+ pkgnum svcpart srcsvc src dstsvc dst )
+ );
+
+ if ( exists $result->{'error'} && $result->{'error'} ) {
+ #warn "$result $result->{'error'}";
+ $action = 'provision_svc_forward';
+ return {
+ $cgi->Vars,
+ %{ part_svc_info( 'session_id' => $session_id,
+ map { $_ => $cgi->param($_) } qw( svcnum pkgnum svcpart )
+ )
+ },
+ 'error' => $result->{'error'},
+ };
+ } else {
+ #just go to setup services page, results will be visible there
+ $action = 'provision';
+ return provision();
+ }
+
+}
+
sub delete_svc {
unprovision_svc(
'session_id' => $session_id,
}
sub view_usage {
- list_svcs(
+ my $res = list_svcs(
'session_id' => $session_id,
- 'svcdb' => [ 'svc_acct', 'svc_phone', 'svc_port', ],
+ 'svcdb' => [ 'svc_acct', 'svc_broadband', 'svc_phone', 'svc_port', 'svc_pbx' ],
'ncancelled' => 1,
);
+ if ($res->{hide_usage}) {
+ $action = 'myaccount';
+ return myaccount();
+ } else {
+ return $res;
+ }
}
sub real_port_graph {
}
sub forgot_password {
- login_info( 'agentnum' => scalar($cgi->param('agentnum')) ); #skin_info
+ login_info( 'agentnum' => scalar($cgi->param('agentnum')) );
}
sub do_forgot_password {
reset_passwd(
map { $_ => scalar($cgi->param($_)) }
- qw( email username domain )
+ qw( agentnum email username domain )
);
}
);
}
+sub process_forgot_password_session {
+ $action = 'process_forgot_password';
+ check_reset_passwd(
+ 'session_id' => $pw_session_id,
+ );
+}
+
sub do_process_forgot_password {
process_reset_passwd(
map { $_ => scalar($cgi->param($_)) }
);
}
+sub validate_password {
+ validate_passwd(
+ 'session_id' => $session_id,
+ map { $_ => scalar($cgi->param($_)) }
+ qw( fieldid svcnum check_password )
+ )
+}
+
+sub validate_password_nologin {
+ $action = 'validate_password'; #use same landing page
+ validate_passwd(
+ map { $_ => scalar($cgi->param($_)) }
+ qw( fieldid check_password )
+ )
+}
+
#--
sub do_template {
$fill_in->{$_} = $access_info->{$_} foreach keys %$access_info;
# update the user's authentication
- my $timeout = $access_info->{'timeout'} || '60';
+ my $timeout = $access_info->{'timeout'} || '3600';
my $cookie = CGI::Cookie->new('-name' => 'session',
'-value' => $session_id,
- '-expires' => '+'.$timeout,
+ '-expires' => '+'.$timeout.'s',
#'-secure' => 1, # would be a good idea...
);
if ( $name eq 'logout' ) {
use HTML::Entities;
use FS::SelfService qw(
- regionselector popselector domainselector location_form didselector
+ regionselector popselector domainselector location_form didselector mason_comp
);
#false laziness w/agent.cgi