+ 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' => $amount,
+ ],
+ );
+
+ $tr_amount_fee = $tr_amount_fee->{'error'} || $tr_amount_fee->{'output'};
+
+ $payment_info->{'tr_amount_fee'} = $tr_amount_fee;
+
+ $payment_info;
+}
+
+sub payment_results {
+
+ 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 return { 'error' => "Illegal amount: ". $cgi->param('amount') }; #!!!
+ my $amount = $1;
+
+ my $payinfo = $cgi->param('payinfo');
+ $payinfo =~ s/[^\dx]//g;
+ $payinfo =~ /^([\dx]{13,19}|[\dx]{8,9})$/
+ #or $error ||= $init_data->{msgcat}{invalid_card}; #. $self->payinfo;
+ or return { 'error' => "illegal card" }; #!!!
+ $payinfo = $1;
+ unless ( $payinfo =~ /x/ ) {
+ validate($payinfo)
+ #or $error ||= $init_data->{msgcat}{invalid_card}; #. $self->payinfo;
+ 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 return { 'error' => "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;
+ $cgi->param('year') =~ /^(\d{4})$/ or die "illegal year";
+ my $year = $1;
+
+ $cgi->param('payname') =~ /^(.{0,80})$/ or die "illegal payname";
+ my $payname = $1;
+
+ $cgi->param('address1') =~ /^(.{0,80})$/ or die "illegal address1";
+ my $address1 = $1;
+
+ $cgi->param('address2') =~ /^(.{0,80})$/ or die "illegal address2";
+ my $address2 = $1;
+
+ $cgi->param('city') =~ /^(.{0,80})$/ or die "illegal city";
+ my $city = $1;
+
+ $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');
+
+ my $auto = 0;
+ $auto = 1 if $cgi->param('auto');
+
+ $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";
+ my $discount_term = $1;
+
+
+ process_payment(
+ 'session_id' => $session_id,
+ 'payby' => 'CARD',
+ 'amount' => $amount,
+ 'payinfo' => $payinfo,
+ 'paycvv' => $paycvv,
+ 'month' => $month,
+ 'year' => $year,
+ 'payname' => $payname,
+ 'address1' => $address1,
+ 'address2' => $address2,
+ 'city' => $city,
+ 'state' => $state,
+ 'zip' => $zip,
+ '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_payby' => 'CHEK' );
+}
+
+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,
+ );
+
+}
+
+sub make_thirdparty_payment {
+ my $payment_info = payment_info('session_id' => $session_id);
+ $cgi->param('payby_method') =~ /^(CC|ECHECK|PAYPAL)$/
+ or die "illegal payby method";
+ $payment_info->{'payby_method'} = $1;
+ $payment_info->{'error'} = $cgi->param('error');
+
+ $payment_info;
+}
+
+sub post_thirdparty_payment {
+ $cgi->param('payby_method') =~ /^(CC|ECHECK|PAYPAL)$/
+ or die "illegal payby method";
+ my $method = $1;
+ $cgi->param('amount') =~ /^(\d+(\.\d*)?)$/
+ or die "illegal amount";
+ my $amount = $1;
+ my $result = start_thirdparty(
+ 'session_id' => $session_id,
+ 'method' => $method,
+ 'amount' => $amount,
+ );
+ if ( $result->{error} ) {
+ $cgi->param('action', 'make_thirdparty_payment');
+ $cgi->param('error', $result->{error});
+ print $cgi->redirect( $cgi->self_url );
+ exit;
+ }
+
+ $result;
+}
+
+sub finish_thirdparty_payment {
+ my %param = $cgi->Vars;
+ finish_thirdparty( 'session_id' => $session_id, %param );
+ # result contains either 'error' => error message, or the payment details
+}
+
+sub cancel_thirdparty_payment {
+ $action = 'make_thirdparty_payment';
+ finish_thirdparty( 'session_id' => $session_id, '_cancel' => 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 );
+}
+
+sub didreport {
+ my $result = did_report( 'session_id' => $session_id,
+ 'format' => $cgi->param('type'),
+ 'recentonly' => $cgi->param('recentonly'),
+ );
+ die $result->{'error'} if exists $result->{'error'} && $result->{'error'};
+ $result;
+}
+
+sub provision {
+ my $result = list_pkgs( 'session_id' => $session_id );
+ die $result->{'error'} if exists $result->{'error'} && $result->{'error'};
+ $result->{'pkgpart'} = $cgi->param('pkgpart') if $cgi->param('pkgpart');
+ $result->{'filter'} = $cgi->param('filter') if $cgi->param('filter');
+ $result;
+}
+
+sub provision_svc {
+
+ my $result = part_svc_info(
+ 'session_id' => $session_id,
+ map { $_ => ($cgi->param($_) || '') } qw( pkgnum svcpart svcnum ),
+ );
+ die $result->{'error'} if exists $result->{'error'} && $result->{'error'};
+
+ $result->{'svcdb'} =~ /^svc_(.*)$/
+ #or return { 'error' => 'Unknown svcdb '. $result->{'svcdb'} };
+ or die 'Unknown svcdb '. $result->{'svcdb'};
+ $action .= "_$1";
+
+ $result->{'numavail'} = $cgi->param('numavail');
+ $result->{'lnp'} = $cgi->param('lnp');
+
+ $result;
+}
+
+sub process_svc_phone {
+ my @bulkdid = $cgi->param('bulkdid');
+ my $phonenum = $cgi->param('phonenum');
+ my $lnp = $cgi->param('lnp');
+
+ my $result;
+ if($lnp) {
+ $result = provision_phone (
+ 'session_id' => $session_id,
+ 'countrycode' => '1',
+ map { $_ => $cgi->param($_) } qw( pkgnum svcpart phonenum
+ lnp_desired_due_date lnp_other_provider
+ lnp_other_provider_account )
+ );
+ } else {
+ $result = provision_phone (
+ 'session_id' => $session_id,
+ 'bulkdid' => [ @bulkdid ],
+ 'countrycode' => '1',
+ map { $_ => $cgi->param($_) } qw( pkgnum svcpart phonenum svcnum email forwarddst )
+ );
+ }
+
+ if ( exists $result->{'error'} && $result->{'error'} ) {
+ $action = 'provision_svc_phone';
+ return {
+ $cgi->Vars,
+ %{ part_svc_info( 'session_id' => $session_id,
+ map { $_ => $cgi->param($_) } qw( pkgnum svcpart svcnum )
+ )
+ },
+ 'error' => $result->{'error'},
+ };
+ }
+
+ $result;
+}
+
+sub process_svc_acct {
+
+ my $result = provision_acct (
+ 'session_id' => $session_id,
+ map { $_ => $cgi->param($_) } qw(
+ pkgnum svcpart username domsvc _password _password2 sec_phrase popnum )
+ );
+
+ if ( exists $result->{'error'} && $result->{'error'} ) {
+ #warn "$result $result->{'error'}";
+ $action = 'provision_svc_acct';
+ return {
+ $cgi->Vars,
+ %{ part_svc_info( 'session_id' => $session_id,
+ map { $_ => $cgi->param($_) } qw( pkgnum svcpart )
+ )
+ },
+ 'error' => $result->{'error'},
+ };
+ } else {
+ #warn "$result $result->{'error'}";
+ return $result;
+ }
+
+}
+
+sub process_svc_external {
+ provision_external (
+ 'session_id' => $session_id,
+ map { $_ => $cgi->param($_) } qw( pkgnum svcpart )
+ );
+}
+
+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,
+ 'svcnum' => $cgi->param('svcnum'),
+ );
+}
+
+sub view_usage {
+ my $res = list_svcs(
+ 'session_id' => $session_id,
+ '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 {
+ my $svcnum = $cgi->param('svcnum');
+ my $res = port_graph(
+ 'session_id' => $session_id,
+ 'svcnum' => $svcnum,
+ 'beginning' => str2time($cgi->param('start')." 00:00:00"),
+ 'ending' => str2time($cgi->param('end') ." 23:59:59"),
+ );
+ my @usage = @{$res->{'usage'}};
+ my $png = $usage[0]->{'png'};
+ { 'content' => $png, 'format' => 'png' };
+}
+
+sub view_port_graph {
+ my $svcnum = $cgi->param('svcnum');
+ { 'svcnum' => $svcnum,
+ 'start' => $cgi->param($svcnum.'_start'),
+ 'end' => $cgi->param($svcnum.'_end'),
+ }
+}
+
+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') || '',
+ 'inbound' => $cgi->param('inbound') || 0,
+ );
+}
+
+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 forgot_password {
+ login_info( 'agentnum' => scalar($cgi->param('agentnum')) );
+}
+
+sub do_forgot_password {
+ reset_passwd(
+ map { $_ => scalar($cgi->param($_)) }
+ qw( agentnum email username domain )
+ );
+}
+
+sub process_forgot_password {
+ check_reset_passwd(
+ map { $_ => scalar($cgi->param($_)) }
+ qw( session_id )
+ );
+}
+
+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($_)) }
+ qw( session_id new_password new_password2 )
+ );
+}
+
+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 )
+ )