From 2a82381a976c22f2c0d85645e8b327713ddcbd88 Mon Sep 17 00:00:00 2001 From: Christopher Burger Date: Wed, 10 Oct 2018 12:53:53 -0400 Subject: [PATCH] RT# 39340 - created access to payment only via ip address, fixes security by creating a seperate session --- FS/FS/ClientAPI/MasonComponent.pm | 29 +- FS/FS/ClientAPI/PaymentOnly.pm | 472 +++++++++++++++++++++ FS/FS/ClientAPI_XMLRPC.pm | 8 + .../FS-SelfService/SelfService/XMLRPC.pm | 1 + fs_selfservice/FS-SelfService/cgi/change_pay.html | 2 +- fs_selfservice/FS-SelfService/cgi/selfservice.cgi | 6 +- ng_selfservice/elements/payment_only_menu.php | 101 +++++ ng_selfservice/payment_only.php | 52 +++ ng_selfservice/payment_only_error.php | 6 + ng_selfservice/payment_only_logout.php | 35 ++ ng_selfservice/payment_only_payment.php | 118 ++++++ 11 files changed, 824 insertions(+), 6 deletions(-) create mode 100644 FS/FS/ClientAPI/PaymentOnly.pm create mode 100644 ng_selfservice/elements/payment_only_menu.php create mode 100644 ng_selfservice/payment_only.php create mode 100644 ng_selfservice/payment_only_error.php create mode 100644 ng_selfservice/payment_only_logout.php create mode 100644 ng_selfservice/payment_only_payment.php diff --git a/FS/FS/ClientAPI/MasonComponent.pm b/FS/FS/ClientAPI/MasonComponent.pm index d615c271c..e216d919a 100644 --- a/FS/FS/ClientAPI/MasonComponent.pm +++ b/FS/FS/ClientAPI/MasonComponent.pm @@ -2,7 +2,7 @@ package FS::ClientAPI::MasonComponent; use strict; use vars qw( $cache $DEBUG $me ); -use subs qw( _cache ); +use subs qw( _cache _mason_comp ); use FS::Mason qw( mason_interps ); use FS::Conf; use FS::ClientAPI_SessionCache; @@ -138,8 +138,27 @@ my( $fs_interp, $rt_interp ) = mason_interps('standalone', 'outbuf'=>\$outbuf); sub mason_comp { my $packet = shift; + my $me = 'mason_comp'; + my $namespace = 'FS::ClientAPI::MyAccount'; - warn "$me mason_comp called on $packet\n" if $DEBUG; + _mason_comp($packet, $me, $namespace); + +} + +sub payment_only_mason_comp { + my $packet = shift; + my $me = 'payment_only_mason_comp'; + my $namespace = 'FS::ClientAPI::PaymentOnly'; + + _mason_comp($packet, $me, $namespace); +} + +sub _mason_comp { + my $packet = shift; + my $me = shift; + my $namespace = shift; + + warn "$me called on $packet\n" if $DEBUG; my $comp = $packet->{'comp'}; unless ( $allowed_comps{$comp} || $session_comps{$comp} ) { @@ -150,7 +169,7 @@ sub mason_comp { if ( $session_comps{$comp} ) { - my $session = _cache->get($packet->{'session_id'}) + my $session = _cache($namespace)->get($packet->{'session_id'}) or return ( 'error' => "Can't resume session" ); #better error message my $custnum = $session->{'custnum'}; @@ -175,8 +194,10 @@ sub mason_comp { #hmm sub _cache { + my $namespace = shift || 'FS::ClientAPI::MyAccount'; + $cache ||= new FS::ClientAPI_SessionCache( { - 'namespace' => 'FS::ClientAPI::MyAccount', + 'namespace' => $namespace, } ); } diff --git a/FS/FS/ClientAPI/PaymentOnly.pm b/FS/FS/ClientAPI/PaymentOnly.pm new file mode 100644 index 000000000..e1c59a91b --- /dev/null +++ b/FS/FS/ClientAPI/PaymentOnly.pm @@ -0,0 +1,472 @@ +package FS::ClientAPI::PaymentOnly; + +use 5.008; #require 5.8+ for Time::Local 1.05+ +use strict; +use vars qw( $cache $DEBUG $me ); +use subs qw( _cache _provision ); +use FS::ClientAPI_SessionCache; + +use IO::Scalar; +use Data::Dumper; +use Digest::MD5 qw(md5_hex); +use Digest::SHA qw(sha512_hex); +use Date::Format; +use Time::Duration; +use Time::Local qw(timelocal_nocheck); +use Business::CreditCard 0.35; +use HTML::Entities; +use Text::CSV_XS; +use Spreadsheet::WriteExcel; +use OLE::Storage_Lite; +use FS::UI::Web::small_custview qw(small_custview); #less doh +use FS::UI::Web; +use FS::UI::bytecount qw( display_bytecount ); +use FS::Conf; +#use FS::UID qw(dbh); +use FS::Record qw(qsearch qsearchs dbh); +use FS::Msgcat qw(gettext); +use FS::Misc qw(card_types money_pretty); +use FS::Misc::DateTime qw(parse_datetime); +use FS::TicketSystem; +use FS::ClientAPI_SessionCache; +use FS::cust_svc; +use FS::svc_acct; +use FS::svc_forward; +use FS::svc_domain; +use FS::svc_phone; +use FS::svc_external; +use FS::svc_dsl; +use FS::dsl_device; +use FS::part_svc; +use FS::cust_main; +use FS::cust_bill; +use FS::legacy_cust_bill; +use FS::cust_main_county; +use FS::part_pkg; +use FS::cust_pkg; +use FS::payby; +use FS::acct_rt_transaction; +use FS::msg_template; +use FS::contact; +use FS::cust_contact; +use FS::cust_location; +use FS::cust_payby; + +$DEBUG = 0; +$me = '[FS::ClientAPI::PaymentOnly]'; + +sub _cache { + $cache ||= new FS::ClientAPI_SessionCache( { + 'namespace' => 'FS::ClientAPI::PaymentOnly', + } ); +} + +sub payment_only_skin_info { + my $p = shift; + + my($context, $session, $custnum) = _custoragent_session_custnum($p); + #return { 'error' => $session } if $context eq 'error'; + + my $agentnum = ''; + if ( $context eq 'customer' && $custnum ) { + + my $sth = dbh->prepare('SELECT agentnum FROM cust_main WHERE custnum = ?') + or die dbh->errstr; + + $sth->execute($custnum) or die $sth->errstr; + + $agentnum = $sth->fetchrow_arrayref->[0] + or die "no agentnum for custnum $custnum"; + + #} elsif ( $context eq 'agent' ) { + } elsif ( defined($p->{'agentnum'}) and $p->{'agentnum'} =~ /^(\d+)$/ ) { + $agentnum = $1; + } + $p->{'agentnum'} = $agentnum; + + my $conf = new FS::Conf; + + #false laziness w/Signup.pm + + my $skin_info_cache_agent = _cache->get("skin_info_cache_agent$agentnum"); + + if ( $skin_info_cache_agent ) { + + warn "$me loading cached skin info for agentnum $agentnum\n" + if $DEBUG > 1; + + } else { + + warn "$me populating skin info cache for agentnum $agentnum\n" + if $DEBUG > 1; + + $skin_info_cache_agent = { + 'agentnum' => $agentnum, + ( map { $_ => scalar( $conf->config($_, $agentnum) ) } + qw( company_name date_format ) ), + ( map { $_ => scalar( $conf->config("selfservice-$_", $agentnum ) ) } + qw( body_bgcolor box_bgcolor stripe1_bgcolor stripe2_bgcolor + text_color link_color vlink_color hlink_color alink_color + font title_color title_align title_size menu_bgcolor menu_fontsize + ) + ), + 'menu_disable' => [ $conf->config('selfservice-menu_disable',$agentnum) ], + ( map { $_ => $conf->exists("selfservice-$_", $agentnum ) } + qw( menu_skipblanks menu_skipheadings menu_nounderline no_logo enable_payment_without_balance ) + ), + ( map { $_ => scalar($conf->config_binary("selfservice-$_", $agentnum)) } + qw( title_left_image title_right_image + menu_top_image menu_body_image menu_bottom_image + ) + ), + 'logo' => scalar($conf->config_binary('logo.png', $agentnum )), + ( map { $_ => join("\n", $conf->config("selfservice-$_", $agentnum ) ) } + qw( head body_header body_footer company_address ) ), + 'money_char' => $conf->config("money_char") || '$', + 'menu' => 'payment_only_payment.php Make Payment + + payment_only_logout.php Logout + ', + }; + + _cache->set("skin_info_cache_agent$agentnum", $skin_info_cache_agent); + + } + + #{ %$skin_info_cache_agent }; + $skin_info_cache_agent; + +} + +sub ip_login { + my $p = shift; + + my $conf = new FS::Conf; + + my $svc_x = ''; + my $session = {}; + my $cust_main; + + return { error => 'MAC address empty '.$p->{'mac'} } + unless $p->{'mac'}; + + my $mac_address = $p->{'mac'}; + $mac_address =~ s/[\:\,\-\. ]//g; + $mac_address =~ tr/[a-z]/[A-Z/; + + my $svc_broadband = qsearchs( 'svc_broadband', { 'mac_addr' => $mac_address } ); + return { error => 'MAC address not found $mac_address '.$p->{'mac'} } + unless $svc_broadband; + $svc_x = $svc_broadband; + + if ( $svc_x ) { + + $session->{'svcnum'} = $svc_x->svcnum; + + my $cust_svc = $svc_x->cust_svc; + my $cust_pkg = $cust_svc->cust_pkg; + if ( $cust_pkg ) { + $cust_main = $cust_pkg->cust_main; + $session->{'custnum'} = $cust_main->custnum; + if ( $conf->exists('pkg-balances') ) { + my @cust_pkg = grep { $_->part_pkg->freq !~ /^(0|$)/ } + $cust_main->ncancelled_pkgs; + $session->{'pkgnum'} = $cust_pkg->pkgnum + if scalar(@cust_pkg) > 1; + } + } + + #my $pkg_svc = $svc_acct->cust_svc->pkg_svc; + #return { error => 'Only primary user may log in.' } + # if $conf->exists('selfservice_server-primary_only') + # && ( ! $pkg_svc || $pkg_svc->primary_svc ne 'Y' ); + my $part_pkg = $cust_pkg->part_pkg; + return { error => 'Only primary user may log in.' } + if $conf->exists('selfservice_server-primary_only') + && $cust_svc->svcpart != $part_pkg->svcpart([qw( svc_acct svc_phone )]); + + } + else { + return { error => "No Service Found with Mac Address ".$p->{'mac'} }; + } + + ## get account information + my ($cust_payby_card) = $cust_main->cust_payby('CARD', 'DCRD'); + if ($cust_payby_card) { + $session->{'CARD'} = $cust_payby_card->custpaybynum; + } + my ($cust_payby_check) = $cust_main->cust_payby('CHEK', 'DCHK'); + if ($cust_payby_check) { + $session->{'CHEK'} = $cust_payby_check->custpaybynum; + } + + my $session_id; + do { + $session_id = sha512_hex(time(). {}. rand(). $$) + } until ( ! defined _cache->get($session_id) ); #just in case + + my $timeout = $conf->config('selfservice-session_timeout') || '1 hour'; + _cache->set( $session_id, $session, $timeout ); + + return { 'error' => '', + 'session_id' => $session_id, + %$session, + }; +} + +sub ip_logout { + my $p = shift; + my $skin_info = skin_info($p); + if ( $p->{'session_id'} ) { + _cache->remove($p->{'session_id'}); + return { %$skin_info, 'error' => '' }; + } else { + return { %$skin_info, 'error' => "Can't resume session" }; #better error message + } +} + +sub get_mac_address { + my $p = shift; + +## access radius exports acct tables to get mac + my @part_export = (); + @part_export = ( + qsearch( 'part_export', { 'exporttype' => 'sqlradius' } ), + qsearch( 'part_export', { 'exporttype' => 'sqlradius_withdomain' } ), + qsearch( 'part_export', { 'exporttype' => 'broadband_sqlradius' } ), + ); + + my @sessions; + foreach my $part_export (@part_export) { + push @sessions, ( @{ $part_export->usage_sessions( { + 'ip' => $p->{'ip'}, + 'session_status' => 'open', + } ) } ); + } + + return { 'mac_address' => $sessions[0]->{'callingstationid'}, }; +} + +sub payment_only_payment_info { + my $p = shift; + my $session = _cache->get($p->{'session_id'}) + or return { 'error' => "Can't resume session today" }; #better error message + + my $custnum = $session->{'custnum'}; + my $cust_main = qsearchs('cust_main', { 'custnum' => $custnum } ) + or return { 'error' => "unknown custnum $custnum" }; + + my $payment_info = { + 'balance' => $cust_main->balance, + }; + + #doubleclick protection + my $_date = time; + $payment_info->{'payunique'} = "webui-PaymentOnly-$_date-$$-". rand() * 2**32; #new + $payment_info->{'paybatch'} = $payment_info->{'payunique'}; #back compat + + if ($session->{'CARD'}) { + my $card_payby = qsearchs('cust_payby', { 'custpaybynum' => $session->{'CARD'} }); + if ($card_payby) { + $payment_info->{'CARD'} = $session->{'CARD'}; + $payment_info->{'card_mask'} = $card_payby->paymask; + $payment_info->{'card_type'} = $card_payby->paycardtype; + } + } + + if ($session->{'CHEK'}) { + my $check_payby = qsearchs('cust_payby', { 'custpaybynum' => $session->{'CHEK'} }); + if ($check_payby) { + my ($payaccount, $payaba) = split /\@/, $check_payby->paymask; + $payment_info->{'CHEK'} = $session->{'CHEK'}; + $payment_info->{'check_mask'} = $payaccount; + $payment_info->{'check_type'} = $check_payby->paytype; + } + } + + return $payment_info; + +} + +sub payment_only_process_payment { + my $p = shift; + + my $payment_info = _validate_payment($p); + return $payment_info if $payment_info->{'error'}; + + FS::ClientAPI::MyAccount::do_process_payment($payment_info); + + #return; +} + +sub _validate_payment { + my $p = shift; + + my $session = _cache->get($p->{'session_id'}) + or return { 'error' => "Can't resume session" }; #better error message + + my $custnum = $session->{'custnum'}; + + my $cust_main = qsearchs('cust_main', { 'custnum' => $custnum } ) + or return { 'error' => "unknown custnum $custnum" }; + + $p->{'amount'} =~ /^\s*(\d+(\.\d{2})?)\s*$/ + or return { 'error' => gettext('illegal_amount') }; + my $amount = $1; + return { error => 'Amount must be greater than 0' } unless $amount > 0; + + #false laziness w/tr-amount_fee.html, but we don't want selfservice users + #changing the hidden form values + my $conf = new FS::Conf; + my $fee_display = $conf->config('selfservice_process-display') || 'add'; + my $fee_pkgpart = $conf->config('selfservice_process-pkgpart', $cust_main->agentnum); + my $fee_skip_first = $conf->exists('selfservice_process-skip_first'); + if ( $fee_display eq 'add' + and $fee_pkgpart + and ! $fee_skip_first || scalar($cust_main->cust_pay) + ) + { + my $fee_pkg = qsearchs('part_pkg', { pkgpart=>$fee_pkgpart } ); + $amount = sprintf('%.2f', $amount + $fee_pkg->option('setup_fee') ); + } + + #$p->{'payby'} ||= 'CARD'; + $p->{'payby'} =~ /^([A-Z]{4})$/ + or return { 'error' => "illegal_payby " . $p->{'payby'} }; + my $payby = $1; + + ## get info from custpaybynum. + my $custpayby = qsearchs('cust_payby', { custpaybynum => $session->{$p->{'payby'}} } ) + or return { 'error' => 'No payment information found' }; + + $p->{'discount_term'} =~ /^\s*(\d*)\s*$/ + or return { 'error' => gettext('illegal_discount_term'). ': '. $p->{'discount_term'} }; + my $discount_term = $1; + + $p->{'payunique'} =~ /^([\w \!\@\#\$\%\&\(\)\-\+\;\:\'\"\,\.\?\/\=]*)$/ + or return { 'error' => gettext('illegal_text'). " payunique: ". $p->{'payunique'} }; + my $payunique = $1; + + $p->{'paybatch'} =~ /^([\w \!\@\#\$\%\&\(\)\-\+\;\:\'\"\,\.\?\/\=]*)$/ + or return { 'error' => gettext('illegal_text'). " paybatch: ". $p->{'paybatch'} }; + my $paybatch = $1; + + $payunique = $paybatch if ! length($payunique) && length($paybatch); + my $payname = $custpayby->payname; + + #false laziness w/process/payment.cgi + my $payinfo = $custpayby->payinfo; + my $onfile = 1; + my $paycvv = ''; + my $replace_cust_payby; + + if ( $payby eq 'CHEK' || $payby eq 'DCHK' ) { + + my ($payinfo1, $payinfo2) = split /\@/, $payinfo; + $payinfo1 =~ /^([\dx]+)$/ + or return { 'error' => "illegal account number " }; + $payinfo2 =~ /^([\dx]+)$/ + or return { 'error' => "illegal ABA/routing number " }; + + } elsif ( $payby eq 'CARD' || $payby eq 'DCRD' ) { + + $payinfo =~ s/\D//g; + $payinfo =~ /^(\d{13,19}|\d{8,9})$/ + or return { 'error' => gettext('invalid_card') }; # . ": ". $self->payinfo + $payinfo = $1; + + validate($payinfo) + or return { 'error' => gettext('invalid_card') }; # . ": ". $self->payinfo + return { 'error' => gettext('unknown_card_type') } + if !$cust_main->tokenized($payinfo) && cardtype($payinfo) eq "Unknown"; + + if ( length($p->{'paycvv'}) && $p->{'paycvv'} !~ /^\s*$/ ) { + if ( cardtype($payinfo) eq 'American Express card' ) { + $p->{'paycvv'} =~ /^\s*(\d{4})\s*$/ + or return { 'error' => "CVV2 (CID) for American Express cards is four digits." }; + $paycvv = $1; + } else { + $p->{'paycvv'} =~ /^\s*(\d{3})\s*$/ + or return { 'error' => "CVV2 (CVC2/CID) is three digits." }; + $paycvv = $1; + } + } elsif ( $conf->exists('selfservice-onfile_require_cvv') ) { + return { 'error' => 'CVV2 is required' }; + } elsif ( !$onfile && $conf->exists('selfservice-require_cvv') ) { + return { 'error' => 'CVV2 is required' }; + } + + } else { + die "unknown payby $payby"; + } + + $p->{$_} = $cust_main->bill_location->get($_) + for qw(address1 address2 city state zip); + + my %payby2fields = ( + 'CARD' => [ qw( paystart_month paystart_year payissue payip + address1 address2 city state zip country ) ], + 'CHEK' => [ qw( ss paytype paystate stateid stateid_state payip ) ], + ); + + my $card_type = ''; + $card_type = cardtype($payinfo) if $payby eq 'CARD'; + + my ($year, $month, $day) = split /-/, $custpayby->{Hash}->{paydate}; + + my $return = { + 'cust_main' => $cust_main, #XXX or just custnum?? + 'amount' => sprintf('%.2f', $amount), + 'payby' => $payby, + 'payinfo' => $payinfo, + 'paymask' => $custpayby->paymask, + 'card_type' => $card_type, + 'paydate' => $custpayby->paydate, + 'paydate_pretty' => $month. ' / '. $year, + 'month' => $month, + 'year' => $year, + 'payname' => $custpayby->{HASH}->{payname}, + 'payunique' => $payunique, + 'paybatch' => $paybatch, + 'paycvv' => $paycvv, + 'payname' => $payname, + 'discount_term' => $discount_term, + 'pkgnum' => $session->{'pkgnum'}, + map { $_ => $p->{$_} } ( @{ $payby2fields{$payby} } ) + }; + + return $return; + +} + +sub _custoragent_session_custnum { + my $p = shift; + + my($context, $session, $custnum); + if ( $p->{'session_id'} ) { + + $context = 'customer'; + $session = _cache->get($p->{'session_id'}) + or return ( 'error' => "Can't resume session" ); #better error message + $custnum = $session->{'custnum'}; + + } elsif ( $p->{'agent_session_id'} ) { + + $context = 'agent'; + my $agent_cache = new FS::ClientAPI_SessionCache( { + 'namespace' => 'FS::ClientAPI::Agent', + } ); + $session = $agent_cache->get($p->{'agent_session_id'}) + or return ( 'error' => "Can't resume session" ); #better error message + $custnum = $p->{'custnum'}; + + } else { + $context = 'error'; + return ( 'error' => "Can't resume session" ); #better error message + } + + ($context, $session, $custnum); + +} + +1; \ No newline at end of file diff --git a/FS/FS/ClientAPI_XMLRPC.pm b/FS/FS/ClientAPI_XMLRPC.pm index dcf34fdaa..430edfe36 100644 --- a/FS/FS/ClientAPI_XMLRPC.pm +++ b/FS/FS/ClientAPI_XMLRPC.pm @@ -50,6 +50,7 @@ our %typefix = ( 'invoice_pdf' => { 'invoice_pdf' => 'base64', }, 'legacy_invoice_pdf' => { 'invoice_pdf' => 'base64', }, 'skin_info' => \%typefix_skin_info, + 'payment_only_skin_info' => \%typefix_skin_info, 'login_info' => \%typefix_skin_info, 'logout' => \%typefix_skin_info, 'access_info' => \%typefix_skin_info, @@ -215,6 +216,7 @@ sub ss2clientapi { 'suspend_username' => 'Agent/suspend_username', 'unsuspend_username' => 'Agent/unsuspend_username', 'mason_comp' => 'MasonComponent/mason_comp', + 'payment_only_mason_comp' => 'MasonComponent/payment_only_mason_comp', 'call_time' => 'PrepaidPhone/call_time', 'call_time_nanpa' => 'PrepaidPhone/call_time_nanpa', 'phonenum_balance' => 'PrepaidPhone/phonenum_balance', @@ -227,6 +229,12 @@ sub ss2clientapi { 'quotation_add_pkg' => 'MyAccount/quotation/quotation_add_pkg', 'quotation_remove_pkg' => 'MyAccount/quotation/quotation_remove_pkg', 'quotation_order' => 'MyAccount/quotation/quotation_order', + 'ip_login' => 'PaymentOnly/ip_login', + 'ip_logout' => 'PaymentOnly/ip_logout', + 'get_mac_address' => 'PaymentOnly/get_mac_address', + 'payment_only_skin_info' => 'PaymentOnly/payment_only_skin_info', + 'payment_only_payment_info' => 'PaymentOnly/payment_only_payment_info', + 'payment_only_process_payment' => 'PaymentOnly/payment_only_process_payment', 'freesideinc_service' => 'Freeside/freesideinc_service', }; diff --git a/fs_selfservice/FS-SelfService/SelfService/XMLRPC.pm b/fs_selfservice/FS-SelfService/SelfService/XMLRPC.pm index 506dce1de..58ce6a801 100644 --- a/fs_selfservice/FS-SelfService/SelfService/XMLRPC.pm +++ b/fs_selfservice/FS-SelfService/SelfService/XMLRPC.pm @@ -45,6 +45,7 @@ our %typefix = ( 'invoice_pdf' => { 'invoice_pdf' => 'base64', }, 'legacy_invoice_pdf' => { 'invoice_pdf' => 'base64', }, 'skin_info' => \%typefix_skin_info, + 'payment_only_skin_info' => \%typefix_skin_info, 'login_info' => \%typefix_skin_info, 'logout' => \%typefix_skin_info, 'access_info' => \%typefix_skin_info, diff --git a/fs_selfservice/FS-SelfService/cgi/change_pay.html b/fs_selfservice/FS-SelfService/cgi/change_pay.html index f90f6d92b..bd64907e2 100644 --- a/fs_selfservice/FS-SelfService/cgi/change_pay.html +++ b/fs_selfservice/FS-SelfService/cgi/change_pay.html @@ -68,7 +68,7 @@ selected_layer => $payby, # form_name => 'dummy', # form_action => 'dummy.cgi', - layer_callback => sub { my $layer = shift; return ''.$paybychecked{$layer}.qq!$tail!; }, + layer_callback => sub { my $layer = shift; use MyLog; use Data::Dumper; MyLog->mylog("my layer $layer\n"); return '
'.$paybychecked{$layer}.qq!$tail!; }, )->html; %> diff --git a/fs_selfservice/FS-SelfService/cgi/selfservice.cgi b/fs_selfservice/FS-SelfService/cgi/selfservice.cgi index 3dc69e142..999b812d9 100755 --- a/fs_selfservice/FS-SelfService/cgi/selfservice.cgi +++ b/fs_selfservice/FS-SelfService/cgi/selfservice.cgi @@ -284,7 +284,11 @@ sub change_bill { }; } sub change_ship { change_bill(@_); } -sub change_pay { change_bill(@_); } +sub change_pay { + my @payby = ('CARD', 'CHEK', 'DCHK'); + use MyLog; use Data::Dumper; MyLog->mylog("my change pay at\n".Dumper(@_)); + change_bill(@_); +} sub change_creditcard_pay { change_bill('CARD'); } sub change_check_pay { change_bill('CHEK'); } diff --git a/ng_selfservice/elements/payment_only_menu.php b/ng_selfservice/elements/payment_only_menu.php new file mode 100644 index 000000000..8fb9331e3 --- /dev/null +++ b/ng_selfservice/elements/payment_only_menu.php @@ -0,0 +1,101 @@ +payment_only_skin_info( array( + 'session_id' => $_COOKIE['session_id'], +) ); + + +if ( isset($skin_info['error']) && $skin_info['error'] ) { + $error = $skin_info['error']; + header('Location:payment_only_error.php?error='. urlencode($error)); + die(); +} + +extract($skin_info); + +?> + + + + +
+
+ +
\ No newline at end of file diff --git a/ng_selfservice/payment_only.php b/ng_selfservice/payment_only.php new file mode 100644 index 000000000..d348b9cbc --- /dev/null +++ b/ng_selfservice/payment_only.php @@ -0,0 +1,52 @@ +get_mac_address( array('ip' => $ip, ) ); + +$response = $freeside->ip_login( array( + 'mac' => $mac['mac_address'], +) ); + +$error = $response['error']; + +if ( $error ) { + + $title ='Login'; include('elements/header.php'); + include('elements/error.php'); + echo "Sorry "+$error; + + // header('Location:index.php?username='. urlencode($mac). + // '&domain='. urlencode($domain). + // '&email='. urlencode($email). + // '&error='. urlencode($error) + // ); + +} +else { + // sucessful login + + $session_id = $response['session_id']; + $mac = $mac['mac_address']; + + error_log("[login] logged into freeside with ip=$ip and mac=$mac, setting cookie"); + + setcookie('session_id', $session_id); + + $title ='IP Login'; + + if ( $response['custnum'] || $response['svcnum'] ) { + + header("Location:payment_only_payment.php"); + die(); + + } + +} //successfull login + +?> + + \ No newline at end of file diff --git a/ng_selfservice/payment_only_error.php b/ng_selfservice/payment_only_error.php new file mode 100644 index 000000000..2ee9f53fa --- /dev/null +++ b/ng_selfservice/payment_only_error.php @@ -0,0 +1,6 @@ + + +There was in issue processing your payment. +

+ + \ No newline at end of file diff --git a/ng_selfservice/payment_only_logout.php b/ng_selfservice/payment_only_logout.php new file mode 100644 index 000000000..e172680cb --- /dev/null +++ b/ng_selfservice/payment_only_logout.php @@ -0,0 +1,35 @@ +ip_logout( array( + 'session_id' => $_COOKIE['session_id'], +) ); + +setcookie('session_id', '', time() - 3600); + +$error = $response['error']; + +if ( $error ) { + error_log("Logout error: $error "); +} + +?> + + + + + + Logged Out + + + + + + + Logged Out +

+ You have been logged out. + + \ No newline at end of file diff --git a/ng_selfservice/payment_only_payment.php b/ng_selfservice/payment_only_payment.php new file mode 100644 index 000000000..baed422d1 --- /dev/null +++ b/ng_selfservice/payment_only_payment.php @@ -0,0 +1,118 @@ + + + +payment_only_process_payment(array( + 'session_id' => $_COOKIE['session_id'], + 'payby' => $_POST['payby'], + 'amount' => $_POST['amount'], + 'paybatch' => $_POST['paybatch'], + //'discount_term' => $discount_term, + )); + + if ( $payment_results['error'] ) { + $error = $payment_results['error']; + } else { + $receipt_html = $payment_results['receipt_html']; + } + +} + +#echo print_r($payment_results); + +if ( $receipt_html ) { +?> + + Your payment was processed successfully. Thank you.

+ + +payment_only_payment_info( array( + 'session_id' => $_COOKIE['session_id'], + ) ); + + if ( isset($payment_info['error']) && $payment_info['error'] ) { + $error = $payment_info['error']; + // possible to just keep on this page + header('Location:payment_only_error.php?error='. urlencode($error)); + die(); + } + + extract($payment_info); + + $tr_amount_fee = $freeside->payment_only_mason_comp(array( + 'session_id' => $_COOKIE['session_id'], + 'comp' => '/elements/tr-amount_fee.html', + 'args' => [ 'amount', $balance ], + )); + //$tr_amount_fee = $tr_amount_fee->{'error'} || $tr_amount_fee->{'output'}; + $tr_amount_fee = $tr_amount_fee['output']; + + ?> + + + + + +

+ + + + + + + + + + + + + + + +
Payment account + +
Amount Due +
+ $ + " > +
+
+
+ + +
+ + + + \ No newline at end of file -- 2.11.0