new thirdparty payment framework, #23752, #23579, #22395
authorMark Wells <mark@freeside.biz>
Fri, 28 Jun 2013 23:42:17 +0000 (16:42 -0700)
committerMark Wells <mark@freeside.biz>
Fri, 28 Jun 2013 23:42:17 +0000 (16:42 -0700)
61 files changed:
FS/FS/ClientAPI/MyAccount.pm
FS/FS/Conf.pm
FS/FS/Schema.pm
FS/FS/agent.pm
FS/FS/cust_main.pm
FS/FS/cust_pay.pm
FS/FS/cust_pay_pending.pm
FS/FS/payment_gateway.pm
fs_selfservice/FS-SelfService/SelfService.pm
fs_selfservice/FS-SelfService/cgi/ach_payment_results.html
fs_selfservice/FS-SelfService/cgi/agent_customer_menu.html
fs_selfservice/FS-SelfService/cgi/change_bill.html
fs_selfservice/FS-SelfService/cgi/change_password.html
fs_selfservice/FS-SelfService/cgi/change_pay.html
fs_selfservice/FS-SelfService/cgi/change_pkg.html
fs_selfservice/FS-SelfService/cgi/change_ship.html
fs_selfservice/FS-SelfService/cgi/customer_change_pkg.html
fs_selfservice/FS-SelfService/cgi/customer_order_pkg.html
fs_selfservice/FS-SelfService/cgi/delete_svc.html
fs_selfservice/FS-SelfService/cgi/finish_thirdparty_payment.html [new file with mode: 0644]
fs_selfservice/FS-SelfService/cgi/invoices.html
fs_selfservice/FS-SelfService/cgi/list_customers.html
fs_selfservice/FS-SelfService/cgi/login.html
fs_selfservice/FS-SelfService/cgi/logout.html
fs_selfservice/FS-SelfService/cgi/make_ach_payment.html
fs_selfservice/FS-SelfService/cgi/make_payment.html
fs_selfservice/FS-SelfService/cgi/make_thirdparty_payment.html
fs_selfservice/FS-SelfService/cgi/myaccount.html
fs_selfservice/FS-SelfService/cgi/myaccount_menu.html
fs_selfservice/FS-SelfService/cgi/order_pkg.html
fs_selfservice/FS-SelfService/cgi/payment_results.html
fs_selfservice/FS-SelfService/cgi/post_thirdparty_payment.html
fs_selfservice/FS-SelfService/cgi/process_change_bill.html
fs_selfservice/FS-SelfService/cgi/process_change_password.html
fs_selfservice/FS-SelfService/cgi/process_change_pay.html
fs_selfservice/FS-SelfService/cgi/process_change_pkg.html
fs_selfservice/FS-SelfService/cgi/process_change_ship.html
fs_selfservice/FS-SelfService/cgi/process_order_pkg.html
fs_selfservice/FS-SelfService/cgi/process_order_recharge.html
fs_selfservice/FS-SelfService/cgi/process_suspend_pkg.html
fs_selfservice/FS-SelfService/cgi/process_svc_acct.html
fs_selfservice/FS-SelfService/cgi/process_svc_external.html
fs_selfservice/FS-SelfService/cgi/process_svc_phone.html
fs_selfservice/FS-SelfService/cgi/provision.html
fs_selfservice/FS-SelfService/cgi/provision_svc_acct.html
fs_selfservice/FS-SelfService/cgi/provision_svc_phone.html
fs_selfservice/FS-SelfService/cgi/recharge_prepay.html
fs_selfservice/FS-SelfService/cgi/recharge_results.html
fs_selfservice/FS-SelfService/cgi/selfservice.cgi
fs_selfservice/FS-SelfService/cgi/svc_acct.html
fs_selfservice/FS-SelfService/cgi/ticket_summary.html
fs_selfservice/FS-SelfService/cgi/tktcreate.html
fs_selfservice/FS-SelfService/cgi/tktview.html
fs_selfservice/FS-SelfService/cgi/view_cdr_details.html
fs_selfservice/FS-SelfService/cgi/view_customer.html
fs_selfservice/FS-SelfService/cgi/view_invoice.html
fs_selfservice/FS-SelfService/cgi/view_port_graph.html
fs_selfservice/FS-SelfService/cgi/view_support_details.html
fs_selfservice/FS-SelfService/cgi/view_usage.html
fs_selfservice/FS-SelfService/cgi/view_usage_details.html
httemplate/edit/payment_gateway.html

index 01e0ebc..b735958 100644 (file)
@@ -349,6 +349,8 @@ sub access_info {
       $conf->exists('ticket_system-selfservice_edit_subject') && 
       $cust_main->edit_subject;
 
+  $info->{'timeout'} = $conf->config('selfservice-timeout') || 3600;
+
   return { %$info,
            'custnum'       => $custnum,
            'access_pkgnum' => $session->{'pkgnum'},
@@ -845,7 +847,7 @@ sub payment_info {
 
       'save_unchecked' => $conf->exists('selfservice-save_unchecked'),
 
-      'credit_card_surcharge_percentage' => $conf->config('credit-card-surcharge-percentage'),
+      'credit_card_surcharge_percentage' => scalar($conf->config('credit-card-surcharge-percentage')),
     };
 
   }
@@ -1267,6 +1269,50 @@ sub realtime_collect {
   return { 'error' => '', amount => $amount, %$error };
 }
 
+sub start_thirdparty {
+  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 = FS::cust_main->by_key($custnum);
+  
+  my $amount = $p->{'amount'}
+    or return { error => 'no amount' };
+
+  my $result = $cust_main->create_payment(
+    'method'      => $p->{'method'},
+    'amount'      => $p->{'amount'},
+    'pkgnum'      => $session->{'pkgnum'},
+    'session_id'  => $p->{'session_id'},
+  );
+  
+  if ( ref($result) ) { # hashref or error
+    return $result;
+  } else {
+    return { error => $result };
+  }
+}
+
+sub finish_thirdparty {
+  my $p = shift;
+  my $session_id = delete $p->{'session_id'};
+  my $session = _cache->get($session_id)
+    or return { 'error' => "Can't resume session" };
+  my $custnum = $session->{'custnum'};
+  my $cust_main = FS::cust_main->by_key($custnum);
+
+  if ( $p->{_cancel} ) {
+    # customer backed out of making a payment
+    return $cust_main->cancel_payment( $session_id );
+  }
+  my $result = $cust_main->execute_payment( $session_id, %$p );
+  if ( ref($result) ) {
+    return $result;
+  } else {
+    return { error => $result };
+  }
+}
+
 sub process_payment_order_pkg {
   my $p = shift;
 
index b88aa11..5e70b40 100644 (file)
@@ -2272,6 +2272,12 @@ and customer address. Include units.',
   },
 
   {
+    'key'         => 'selfservice-timeout',
+    'section'     => 'self-service',
+    'description' => 'Timeout for the self-service login cookie, in seconds.  Defaults to 1 hour.',
+  },
+
+  {
     'key'         => 'backend-realtime',
     'section'     => 'billing',
     'description' => 'Run billing for backend signups immediately.',
index da3ddab..72412c2 100644 (file)
@@ -1576,6 +1576,9 @@ sub tables_hashref {
         #'cust_balance', @money_type,            '', '',
         'paynum',       'int',     'NULL',  '', '', '',
         'jobnum',    'bigint',     'NULL',  '', '', '', 
+        'invnum',       'int',     'NULL',  '', '', '',
+        'manual',       'char',    'NULL',   1, '', '',
+        'discount_term','int',     'NULL',  '', '', '',
       ],
       'primary_key' => 'paypendingnum',
       'unique'      => [ [ 'payunique' ] ],
index 109343a..57093e3 100644 (file)
@@ -230,7 +230,8 @@ sub ticketing_queue {
 
 Returns a payment gateway object (see L<FS::payment_gateway>) for this agent.
 
-Currently available options are I<nofatal>, I<invnum>, I<method>, and I<payinfo>.
+Currently available options are I<nofatal>, I<invnum>, I<method>, 
+I<payinfo>, and I<thirdparty>.
 
 If I<nofatal> is set, and no gateway is available, then the empty string
 will be returned instead of throwing a fatal exception.
@@ -245,10 +246,34 @@ as well.  Presently only 'CC', 'ECHECK', and 'PAYPAL' methods are meaningful.
 When the I<method> is 'CC' then the card number in I<payinfo> can direct
 this routine to route to a gateway suited for that type of card.
 
+If I<thirdparty> is set, the defined self-service payment gateway will 
+be returned.
+
 =cut
 
 sub payment_gateway {
   my ( $self, %options ) = @_;
+  
+  my $conf = new FS::Conf;
+
+  if ( $options{thirdparty} ) {
+    # still a kludge, but it gets the job done
+    # and the 'cardtype' semantics don't really apply to thirdparty
+    # gateways because we have to choose a gateway without ever 
+    # seeing the card number
+    my $gatewaynum =
+      $conf->config('selfservice-payment_gateway', $self->agentnum);
+    my $gateway = FS::payment_gateway->by_key($gatewaynum)
+      if $gatewaynum;
+
+    if ( $gateway ) {
+      return $gateway;
+    } elsif ( $options{'nofatal'} ) {
+      return '';
+    } else {
+      die "no third-party gateway configured\n";
+    }
+  }
 
   my $taxclass = '';
   if ( $options{invnum} ) {
@@ -276,8 +301,6 @@ sub payment_gateway {
       $cardtype = cardtype($options{payinfo});
     } elsif ( $options{method} eq 'ECHECK' ) {
       $cardtype = 'ACH';
-    } elsif ( $options{method} eq 'PAYPAL' ) {
-      $cardtype = 'PayPal';
     } else {
       $cardtype = $options{method}
     }
@@ -298,7 +321,6 @@ sub payment_gateway {
                                            taxclass => '',              } );
 
   my $payment_gateway;
-  my $conf = new FS::Conf;
   if ( $override ) { #use a payment gateway override
 
     $payment_gateway = $override->payment_gateway;
index 7e3e26a..04c2e22 100644 (file)
@@ -6,6 +6,7 @@ use base qw( FS::cust_main::Packages FS::cust_main::Status
              FS::cust_main::NationalID
              FS::cust_main::Billing FS::cust_main::Billing_Realtime
              FS::cust_main::Billing_Discount
+             FS::cust_main::Billing_ThirdParty
              FS::cust_main::Location
              FS::otaker_Mixin FS::payinfo_Mixin FS::cust_main_Mixin
              FS::geocode_Mixin FS::Quotable_Mixin
index f6954a4..69f4c39 100644 (file)
@@ -190,6 +190,15 @@ A hash of optional arguments may be passed.  Currently "manual" is supported.
 If true, a payment receipt is sent instead of a statement when
 'payment_receipt_email' configuration option is set.
 
+About the "manual" flag: Normally, if the 'payment_receipt' config option 
+is set, and the customer has an invoice email address, inserting a payment
+causes a I<statement> to be emailed to the customer.  If the payment is 
+considered "manual" (or if the customer has no invoices), then it will 
+instead send a I<payment receipt>.  "manual" should be true whenever a 
+payment is created directly from the web interface, from a user-initiated
+realtime payment, or from a third-party payment via self-service.  It should
+be I<false> when creating a payment from a billing event or from a batch.
+
 =cut
 
 sub insert {
index f03ed1f..8e29f08 100644 (file)
@@ -128,8 +128,24 @@ Additional status information.
 
 L<FS::payment_gateway> id.
 
-=item paynum - 
+=item paynum
 
+Payment number (L<FS::cust_pay>) of the completed payment.
+
+=item invnum
+
+Invoice number (L<FS::cust_bill>) to try to apply this payment to.
+
+=item manual
+
+Flag for whether this is a "manual" payment (i.e. initiated through 
+self-service or the back-office web interface, rather than from an event
+or a payment batch).  "Manual" payments will cause the customer to be 
+sent a payment receipt rather than a statement.
+
+=item discount_term
+
+Number of months the customer tried to prepay for.
 
 =back
 
@@ -203,6 +219,9 @@ sub check {
     || $self->ut_hexn('session_id')
     || $self->ut_foreign_keyn('paynum', 'cust_pay', 'paynum' )
     || $self->ut_foreign_keyn('pkgnum', 'cust_pkg', 'pkgnum')
+    || $self->ut_foreign_keyn('invnum', 'cust_bill', 'invnum')
+    || $self->ut_flag('manual')
+    || $self->ut_numbern('discount_term')
     || $self->payinfo_check() #payby/payinfo/paymask/paydate
   ;
   return $error if $error;
@@ -296,6 +315,116 @@ sub insert_cust_pay {
 
 }
 
+=item approve OPTIONS
+
+Sets the status of this pending payment to "done" and creates a completed 
+payment (L<FS::cust_pay>).  This should be called when a realtime or 
+third-party payment has been approved.
+
+OPTIONS may include any of 'processor', 'payinfo', 'discount_term', 'auth',
+and 'order_number' to set those fields on the completed payment, as well as 
+'apply' to apply payments for this customer after inserting the new payment.
+
+=cut
+
+sub approve {
+  my $self = shift;
+  my %opt = @_;
+
+  my $dbh = dbh;
+  my $oldAutoCommit = $FS::UID::AutoCommit;
+  local $FS::UID::AutoCommit = 0;
+
+  my $cust_pay = FS::cust_pay->new({
+      'custnum'     => $self->custnum,
+      'invnum'      => $self->invnum,
+      'pkgnum'      => $self->pkgnum,
+      'paid'        => $self->paid,
+      '_date'       => '',
+      'payby'       => $self->payby,
+      'payinfo'     => $self->payinfo,
+      'gatewaynum'  => $self->gatewaynum,
+  });
+  foreach my $opt_field (qw(processor payinfo auth order_number))
+  {
+    $cust_pay->set($opt_field, $opt{$opt_field}) if exists $opt{$opt_field};
+  }
+
+  my %insert_opt = (
+    'manual'        => $self->manual,
+    'discount_term' => $self->discount_term,
+  );
+  my $error = $cust_pay->insert( %insert_opt );
+  if ( $error ) {
+    # try it again without invnum or discount
+    # (both of those can make payments fail to insert, and at this point
+    # the payment is a done deal and MUST be recorded)
+    $self->invnum('');
+    my $error2 = $cust_pay->insert('manual' => $self->manual);
+    if ( $error2 ) {
+      # attempt to void the payment?
+      # no, we'll just stop digging at this point.
+      $dbh->rollback or die $dbh->errstr if $oldAutoCommit;
+      my $e = "WARNING: payment captured but not recorded - error inserting ".
+              "payment (". ($opt{processor} || $self->payby) . 
+              ": $error2\n(previously tried insert with invnum#".$self->invnum.
+              ": $error)\npending payment saved as paypendingnum#".
+              $self->paypendingnum."\n\n";
+      warn $e;
+      return $e;
+    }
+  }
+  if ( my $jobnum = $self->jobnum ) {
+    my $placeholder = FS::queue->by_key($jobnum);
+    my $error;
+    if (!$placeholder) {
+      $error = "not found";
+    } else {
+      $error = $placeholder->delete;
+    }
+
+    if ($error) {
+      $dbh->rollback or die $dbh->errstr if $oldAutoCommit;
+      my $e  = "WARNING: payment captured but could not delete job $jobnum ".
+               "for paypendingnum #" . $self->paypendingnum . ": $error\n\n";
+      warn $e;
+      return $e;
+    }
+  }
+
+  if ( $opt{'paynum_ref'} ) {
+    ${ $opt{'paynum_ref'} } = $cust_pay->paynum;
+  }
+
+  $self->status('done');
+  $self->statustext('captured');
+  $self->paynum($cust_pay->paynum);
+  my $cpp_done_err = $self->replace;
+
+  if ( $cpp_done_err ) {
+
+    $dbh->rollback or die $dbh->errstr if $oldAutoCommit;
+    my $e = "WARNING: payment captured but could not update pending status ".
+            "for paypendingnum ".$self->paypendingnum.": $cpp_done_err \n\n";
+    warn $e;
+    return $e;
+
+  } else {
+
+    # commit at this stage--we don't want to roll back if applying 
+    # payments fails
+    $dbh->commit or die $dbh->errstr if $oldAutoCommit;
+
+    if ( $opt{'apply'} ) {
+      my $apply_error = $self->apply_payments_and_credits;
+      if ( $apply_error ) {
+        warn "WARNING: error applying payment: $apply_error\n\n";
+      }
+    }
+  }
+  '';
+}
+
 =item decline [ STATUSTEXT ]
 
 Sets the status of this pending payment to "done" (with statustext
index e94a62c..68d8418 100644 (file)
@@ -53,11 +53,11 @@ currently supported:
 
 =item gateway_callback_url - For ThirdPartyPayment only, set to the URL that 
 the user should be redirected to on a successful payment.  This will be sent
-as a transaction parameter (named "callback_url").
+as a transaction parameter named "return_url".
 
 =item gateway_cancel_url - For ThirdPartyPayment only, set to the URL that 
-the user should be redirected to if they cancel the transaction.  PayPal
-requires this; other gateways ignore it.
+the user should be redirected to if they cancel the transaction.  This will 
+be sent as a transaction parameter named "cancel_url".
 
 =item auto_resolve_status - For BatchPayment only, set to 'approve' to 
 auto-approve unresolved payments after some number of days, 'reject' to 
@@ -277,10 +277,6 @@ sub batch_processor {
   eval "use Business::BatchPayment;";
   die "couldn't load Business::BatchPayment: $@" if $@;
 
-  my $conf = new FS::Conf;
-  my $test_mode = $conf->exists('business-batchpayment-test_transaction');
-  $opt{'test_mode'} = 1 if $test_mode;
-
   my $module = $self->gateway_module;
   my $processor = eval { 
     Business::BatchPayment->create($module, $self->options, %opt)
@@ -289,11 +285,46 @@ sub batch_processor {
     if $@;
 
   die "$module does not support test mode"
-    if $test_mode and not $processor->does('Business::BatchPayment::TestMode');
+    if $opt{'test_mode'}
+      and not $processor->does('Business::BatchPayment::TestMode');
 
   return $processor;
 }
 
+=item processor OPTIONS
+
+Loads the module for the processor and returns an instance of it.
+
+=cut
+
+sub processor {
+  local $@;
+  my $self = shift;
+  my %opt = @_;
+  foreach (qw(action username password)) {
+    if (length($self->get("gateway_$_"))) {
+      $opt{$_} = $self->get("gateway_$_");
+    }
+  }
+  $opt{'return_url'} = $self->gateway_callback_url;
+  $opt{'cancel_url'} = $self->gateway_cancel_url;
+
+  my $conf = new FS::Conf;
+  my $test_mode = $conf->exists('business-batchpayment-test_transaction');
+  $opt{'test_mode'} = 1 if $test_mode;
+
+  my $namespace = $self->gateway_namespace;
+  eval "use $namespace";
+  die "couldn't load $namespace: $@" if $@;
+
+  if ( $namespace eq 'Business::BatchPayment' ) {
+    # at some point we can merge these, but there's enough special behavior...
+    return $self->batch_processor(%opt);
+  } else {
+    return $namespace->new( $self->gateway_module, $self->options, %opt );
+  }
+}
+
 # _upgrade_data
 #
 # Used by FS::Upgrade to migrate to a new database.
index d44f978..9da40b9 100644 (file)
@@ -109,6 +109,9 @@ $socket .= '.'.$tag if defined $tag && length($tag);
   'call_time'                 => 'PrepaidPhone/call_time',
   'call_time_nanpa'           => 'PrepaidPhone/call_time_nanpa',
   'phonenum_balance'          => 'PrepaidPhone/phonenum_balance',
+
+  'start_thirdparty'          => 'MyAccount/start_thirdparty',
+  'finish_thirdparty'         => 'MyAccount/finish_thirdparty',
 );
 @EXPORT_OK = (
   keys(%autoload),
index 9cdb65e..9c60222 100644 (file)
@@ -1,4 +1,3 @@
-<%= $url = "$selfurl?session=$session_id;action="; ''; %>
 <%= include('header', 'Payment results') %>
 
 <%= if ( $error ) {
index 603fc0b..1e986e1 100644 (file)
@@ -1,4 +1,4 @@
-<%= $url = "$selfurl?session=$session_id;custnum=$custnum;action="; ''; %>
+<%= $url = "$selfurl?action="; ''; %>
 <TD VALIGN="top" HEIGHT=384 BGCOLOR="#dddddd">
 <A HREF="<%= $url %>agent_provision">Setup services</A><BR><BR>
 <A HREF="<%= $url %>agent_order_pkg">Purchase additional package</A><BR><BR>
index 7941971..06ea12b 100755 (executable)
@@ -1,4 +1,3 @@
-<%= $url = "$selfurl?session=$session_id;action="; ''; %>
 <%= include('header', 'Edit billing address') %>
 
 <%= if ( $error ) { 
@@ -6,7 +5,6 @@
 }  ''; %>
 
 <FORM NAME="ChangeBillForm" ACTION="<%= $selfurl %>" METHOD=POST onSubmit="document.bottomform.submit.disabled=true;">
-<INPUT TYPE="hidden" NAME="session" VALUE="<%= $session_id %>">
 <INPUT TYPE="hidden" NAME="action" VALUE="process_change_bill">
 <TABLE BGCOLOR="#cccccc" BORDER=0 CELLSPACING=0>
 
index 68b6fd8..22d8973 100644 (file)
@@ -1,4 +1,3 @@
-<%= $url = "$selfurl?session=$session_id;action="; ''; %>
 <%= include('header', 'Change password') %>
 
 <%= if ( $error ) {
@@ -6,7 +5,6 @@
 } ''; %>
 
 <FORM ACTION="<%= $selfurl %>" METHOD="POST">
-<INPUT TYPE="hidden" NAME="session" VALUE="<%= $session_id %>">
 <INPUT TYPE="hidden" NAME="action" VALUE="process_change_password">
 
 <TABLE BGCOLOR="#cccccc">
index 9633e89..6898dc7 100644 (file)
@@ -1,4 +1,3 @@
-<%= $url = "$selfurl?session=$session_id;action="; ''; %>
 <%= include('header', 'Change payment information') %>
 
 <%= if ( $error ) { 
@@ -13,7 +12,7 @@
   my $preauto = '<TR><TD COLSPAN=3><INPUT TYPE="checkbox" NAME="auto" VALUE="1"';
   my $postauto = '>Charge future payments to this card automatically</TD></TR>';
 
-  my $tail = qq(</TABLE><INPUT TYPE="hidden" NAME="session" VALUE="$session_id">). 
+  my $tail = qq(</TABLE>).
              qq(<INPUT TYPE="hidden" NAME="action" VALUE="process_change_pay">).
              qq(<BR>).
              qq(<INPUT TYPE="submit" NAME="process" ).
index 2d7b488..5006706 100644 (file)
@@ -12,7 +12,6 @@ function enable_change_pkg () {
   $OUT .= qq!<FONT SIZE="+1" COLOR="#ff0000">$error</FONT><BR><BR>!;
 } ''; %>
 <FORM NAME="ChangePkgForm" ACTION="<%= $selfurl %>" METHOD=POST>
-<INPUT TYPE="hidden" NAME="session" VALUE="<%= $session_id %>">
 <INPUT TYPE="hidden" NAME="action" VALUE="process_change_pkg">
 <INPUT TYPE="hidden" NAME="pkgnum" VALUE="<%= encode_entities($pkgnum) %>">
 <INPUT TYPE="hidden" NAME="pkg" VALUE="<%= encode_entities($pkg) %>">
index 59f9176..ecd20dc 100755 (executable)
@@ -1,4 +1,3 @@
-<%= $url = "$selfurl?session=$session_id;action="; ''; %>
 <%= include('header', 'Edit service address') %>
 
 <%= if ( $error ) { 
@@ -6,7 +5,6 @@
 }  ''; %>
 
 <FORM NAME="OneTrueForm" ACTION="<%= $selfurl %>" METHOD=POST onSubmit="document.bottomform.submit.disabled=true;">
-<INPUT TYPE="hidden" NAME="session" VALUE="<%= $session_id %>">
 <INPUT TYPE="hidden" NAME="action" VALUE="process_change_ship">
 <TABLE BGCOLOR="#cccccc" BORDER=0 CELLSPACING=0>
 
index 37dccaa..047f880 100644 (file)
@@ -1,4 +1,3 @@
-<%= $url = "$selfurl?session=$session_id;action="; ''; %>
 <%= include('header', 'Change package') %>
 
 <%= include('change_pkg') %>
index 192c29f..5fcf77f 100755 (executable)
@@ -1,4 +1,3 @@
-<%= $url = "$selfurl?session=$session_id;action="; ''; %>
 <%= include('header', 'Purchase additional package') %>
 
 <%= include('order_pkg') %>
index 80a14f8..e2b2678 100644 (file)
@@ -1,4 +1,3 @@
-<%= $url = "$selfurl?session=$session_id;action="; ''; %>
 <%= include('header', 'Remove service') %>
 
 <%= if ( $error ) {
diff --git a/fs_selfservice/FS-SelfService/cgi/finish_thirdparty_payment.html b/fs_selfservice/FS-SelfService/cgi/finish_thirdparty_payment.html
new file mode 100644 (file)
index 0000000..79c02cc
--- /dev/null
@@ -0,0 +1,22 @@
+<%= include('header', 'Payment confirmation') %>
+
+<TABLE BGCOLOR="#cccccc">
+<%= if ( $error ) {
+  $OUT .= '<FONT SIZE=+1><B>Payment processing error</B></FONT><BR>'.$error;
+} else {
+  $OUT .= '
+<TR><TH COLSPAN=2><FONT SIZE=+1><B>Your payment details</B></FONT></TH></TR>
+<TR>
+  <TD ALIGN="right">Payment&nbsp;#</TD>
+  <TD BGCOLOR="#ffffff"><B>' . $paynum . '</B></TD>
+</TR>
+<TR>
+  <TD ALIGN="right">Payment&nbsp;amount</TH>
+  <TD BGCOLOR="#ffffff"><B>' . sprintf('$%.2f', $paid) . '</B></TD>
+</TR>
+<TR>
+  <TD ALIGN="right">Processing&nbsp;#</TD>
+  <TD BGCOLOR="#ffffff"><B>' . $order_number . '</B></TD>
+</TR>';
+} %>
+<%= include('footer') %>
index d155b93..7528051 100644 (file)
@@ -1,4 +1,4 @@
-<%= $url = "$selfurl?session=$session_id;action="; ''; %>
+<%= $url = "$selfurl?action="; ''; %>
 <%= include('header', 'All Invoices') %>
 
 <%=
index 7fe7fa4..9746347 100644 (file)
@@ -1,6 +1,6 @@
 <HTML><HEAD><TITLE>Reseller</TITLE></HEAD>
 <BODY BGCOLOR="#eeeeee"><FONT SIZE=5>Reseller</FONT><BR><BR>
-<%= $url = "$selfurl?session=$session_id;action="; ''; %>
+<%= $url = "$selfurl?action="; ''; %>
 <TABLE BORDER=0 CELLPADDING=4><TR>
 <%= include('agent_menu') %>
 <TD VALIGN="top">
index f7473b1..68f3ae4 100644 (file)
@@ -10,7 +10,7 @@
 <FONT SIZE="+1" COLOR="#ff0000"><%= $error %></FONT>
 
 <FORM ACTION="<%= $self_url %>" METHOD=POST>
-<INPUT TYPE="hidden" NAME="session" VALUE="login">
+<INPUT TYPE="hidden" NAME="action" VALUE="myaccount">
 <INPUT TYPE="hidden" NAME="agentnum" VALUE="<%= $agentnum %>">
 
 <TABLE BGCOLOR="<%= $box_bgcolor || '#c0c0c0' %>" BORDER=0 CELLSPACING=2 CELLPADDING=0>
@@ -65,7 +65,6 @@ if ( $phone_login ) {
     <B>OR</B><BR><BR>
     
     <FORM ACTION="$self_url" METHOD=POST>
-    <INPUT TYPE="hidden" NAME="session" VALUE="login">
     <TABLE BGCOLOR="$box_bgcolor" BORDER=0 CELLSPACING=2 CELLPADDING=0>
     <TR>
       <TH ALIGN="right">Phone number </TH>
index 5e22ad8..834ef13 100644 (file)
@@ -1,5 +1,6 @@
 <HTML>
   <HEAD>
+    <META HTTP-EQUIV="refresh" CONTENT="5;URL=<%= $cgi->url(-absolute => 1) %>">
     <TITLE>MyAccount</TITLE>
     <%= $head %>
   </HEAD>
index 5b81b00..e33ad57 100644 (file)
@@ -1,8 +1,6 @@
-<%= $url = "$selfurl?session=$session_id;action="; ''; %>
 <%= include('header', 'Make a payment') %>
 
 <FORM NAME="OneTrueForm" METHOD="POST" ACTION="<%=$selfurl%>" onSubmit="document.OneTrueForm.process.disabled=true">
-<INPUT TYPE="hidden" NAME="session" VALUE="<%=$session_id%>">
 <INPUT TYPE="hidden" NAME="action" VALUE="ach_payment_results">
 <TABLE BGCOLOR="#cccccc">
 <TR>
index defd4a5..915714c 100644 (file)
@@ -1,8 +1,6 @@
-<%= $url = "$selfurl?session=$session_id;action="; ''; %>
 <%= include('header', 'Make a payment') %>
 
 <FORM NAME="OneTrueForm" METHOD="POST" ACTION="<%=$selfurl%>" onSubmit="document.OneTrueForm.process.disabled=true">
-<INPUT TYPE="hidden" NAME="session" VALUE="<%=$session_id%>">
 <INPUT TYPE="hidden" NAME="action" VALUE="payment_results">
 <TABLE BGCOLOR="#cccccc">
 <TR>
index 59ee93b..9a5678e 100755 (executable)
@@ -1,15 +1,12 @@
-<%= $url = "$selfurl?session=$session_id;action="; 
-  $cgi = new CGI;
-  ''; %>
 <%= include('header', 'Make a payment') %>
+<%= if ( $error ) {
+  $OUT .= qq!<FONT SIZE="+1" COLOR="#ff0000">$error</FONT><BR><BR>!;
+} ''; %>
 
 <FORM NAME="OneTrueForm" METHOD="POST" ACTION="<%=$selfurl%>" 
 onSubmit="document.OneTrueForm.process.disabled=true">
-<INPUT TYPE="hidden" NAME="session" VALUE="<%=$session_id%>">
 <INPUT TYPE="hidden" NAME="action" VALUE="post_thirdparty_payment">
-<INPUT TYPE="hidden" NAME="payby_method" VALUE="<%= 
-$cgi->param('payby_method') =~ /(CC|ECHECK|PAYPAL)/;
-$1 %>">
+<INPUT TYPE="hidden" NAME="payby_method" VALUE="<%= $payby_method %>">
 <TABLE BGCOLOR="#cccccc">
 <TR>
   <TH ALIGN="right">Balance&nbsp;due</TH>
index a6352e0..66e2c69 100644 (file)
@@ -1,4 +1,4 @@
-<%= $url = "$selfurl?session=$session_id;action="; ''; %>
+<%= $url = "$selfurl?action="; ''; %>
 <%= include('header', 'My Account') %>
 
 Hello <%= $name %>!<BR><BR>
index cf719e8..7d1a5f7 100644 (file)
@@ -1,4 +1,4 @@
-<%= $url = "$selfurl?session=$session_id;action="; ''; %>
+<%= $url = "$selfurl?action="; ''; %>
 <TABLE BORDER=0><TR>
 <TD VALIGN="top" BGCOLOR="<%= $menu_bgcolor || $box_bgcolor || '#c0c0c0' %>">
 
index 79335a0..84a10ab 100644 (file)
@@ -12,7 +12,6 @@ function enable_order_pkg () {
   $OUT .= qq!<FONT SIZE="+1" COLOR="#ff0000">$error</FONT><BR><BR>!;
 } ''; %>
 <FORM NAME="OrderPkgForm" ACTION="<%= $selfurl %>" METHOD=POST>
-<INPUT TYPE="hidden" NAME="session" VALUE="<%= $session_id %>">
 <INPUT TYPE="hidden" NAME="action" VALUE="process_order_pkg">
 <INPUT TYPE="hidden" NAME="custnum" VALUE="<%= $custnum %>">
 <TABLE BGCOLOR="#cccccc" BORDER=0 CELLSPACING=0>
index be727cb..04a0611 100644 (file)
@@ -1,4 +1,3 @@
-<%= $url = "$selfurl?session=$session_id;action="; ''; %>
 <%= include('header', 'Payment results') %>
 
 <%= if ( $error ) {
index 17710b2..ed7c2a3 100644 (file)
@@ -1,42 +1,21 @@
-<%= $url = "$selfurl?session=$session_id;action="; ''; %>
-<%= include('header', 'Pay now') %>
-
-<SCRIPT TYPE="text/javascript" SRC="overlibmws.js"></SCRIPT>
-<SCRIPT TYPE="text/javascript" SRC="overlibmws_iframe.js"></SCRIPT>
-<SCRIPT TYPE="text/javascript" SRC="overlibmws_draggable.js"></SCRIPT>
-<SCRIPT TYPE="text/javascript" SRC="overlibmws_crossframe.js"></SCRIPT>
-<SCRIPT TYPE="text/javascript" SRC="iframecontentmws.js"></SCRIPT>
-
-<%= if ( $error ) {
-  $OUT .= qq!<FONT SIZE="+1" COLOR="#ff0000">$error</FONT><BR><BR>!;
-}else{
-  $OUT .= <<EOF;
-    You are about to contact our payment processor to pay $amount.<BR><BR>
-    Your transaction reference number is $reference <BR><BR>
-    <FORM METHOD="POST" ACTION="$popup_url">
-EOF
-    
-#<FORM NAME="collect_popper" method="post" action="javascript:void(0)" onSubmit="popcollect()">
-  my %itemhash = @collectitems;
-#  my $query = join(';', 
-#    map { uri_escape($_) . '=' . uri_escape($itemhash{$_}) }
-#    keys(%itemhash)
-#  );
-  foreach my $input (keys(%itemhash)) {
-    $OUT .= qq!<INPUT NAME="$input" TYPE="hidden" VALUE="$itemhash{$input}">\n!;
-  }
-  $OUT .= qq!<INPUT NAME="submit" TYPE="submit" VALUE="Pay now"></FORM>!
+<HTML>
+  <HEAD>
+    <TITLE>Redirecting to payment processor...</TITLE>
+  </HEAD>
+  <BODY>
+    <H1>Redirecting to payment processor...</H1>
+    <FORM ID="autoform" ENCTYPE="multipart/form-data" ACTION="<%= $url %>" METHOD="POST" STYLE="display:none">
+<%= foreach my $name (keys %post_params) {
+  my $value = encode_entities($post_params{$name});
+  $OUT .= '
+      <INPUT NAME="' . $name . '" TYPE="hidden" VALUE="' . $value . '">';
+} %>
+    <INPUT TYPE="submit" VALUE="submit">
+    </FORM>
+    <SCRIPT TYPE="text/javascript">
+window.onload = function() {
+  document.getElementById('autoform').submit();
 }
-%>
-
-<%=
-#<SCRIPT TYPE="text/javascript">
-#  function popcollect() {
-#    overlib( OLiframeContent('<%= $popup_url %>', 336, 550, 'Secure Payment Area', 0, 'auto' ), CAPTION, 'Pay now', STICKY, AUTOSTATUSCAP, MIDX, 0, MIDY, 0, DRAGGABLE, CLOSECLICK, BGCOLOR, '#333399', CGCOLOR, '#333399', CLOSETEXT, 'Close' );
-#    overlib( OLpostAJAX('<%= $popup_url %>', 
-#    return false;
-#  }
-#</SCRIPT>
-%>
-
-<%= include('footer') %>
+    </SCRIPT>
+  </BODY>
+</HTML>
index bf7ad77..795cc12 100644 (file)
@@ -1,4 +1,3 @@
-<%= $url = "$selfurl?session=$session_id;action="; ''; %>
 <%= include('header', 'Information updated successfully') %>
 <FONT SIZE=4>Information updated successfully.</FONT>
 <%= include('footer') %>
index 4eca91f..d16c460 100644 (file)
@@ -1,4 +1,3 @@
-<%= $url = "$selfurl?session=$session_id;action="; ''; %>
 <%= include('header', "Password changed" ) %>
 
 <FONT SIZE=4>Password changed for <%= $value %> <%= $label %>.</FONT>
index e399aea..8fb33b2 100644 (file)
@@ -1,4 +1,3 @@
-<%= $url = "$selfurl?session=$session_id;action="; ''; %>
 <%= include('header', 'Information updated successfully' ) %>
 <FONT SIZE=4>Information updated successfully.</FONT>
 <%= include('footer') %>
index bf15b6e..126e2a4 100644 (file)
@@ -1,4 +1,3 @@
-<%= $url = "$selfurl?session=$session_id;action="; ''; %>
 <%= include('header', 'Package change successful') %>
 
 <%= include('footer') %>
index bf7ad77..795cc12 100644 (file)
@@ -1,4 +1,3 @@
-<%= $url = "$selfurl?session=$session_id;action="; ''; %>
 <%= include('header', 'Information updated successfully') %>
 <FONT SIZE=4>Information updated successfully.</FONT>
 <%= include('footer') %>
index 649d920..b76dafb 100755 (executable)
@@ -1,4 +1,3 @@
-<%= $url = "$selfurl?session=$session_id;action="; ''; %>
 <%= include('header', 'Package order successful') %>
 
 <FONT SIZE=4>Package order successful.</FONT>
index 4a16ec5..659f110 100644 (file)
@@ -1,4 +1,3 @@
-<%= $url = "$selfurl?session=$session_id;action="; ''; %>
 <%= include('header', "$svc recharged successfully") %>
 
 <FONT SIZE=4><%= $svc %> recharged successfully.</FONT>
index d5c62f4..2a9805f 100644 (file)
@@ -1,3 +1,2 @@
-<%= $url = "$selfurl?session=$session_id;action="; ''; %>
 <%= include('header', 'Package suspended') %>
 <%= include('footer') %>
index d6515e7..48f6a85 100644 (file)
@@ -1,4 +1,3 @@
-<%= $url = "$selfurl?session=$session_id;action="; ''; %>
 <%= include('header', "$svc setup successfully") %>
 
 <FONT SIZE=4><%= $svc %> setup successfully.</FONT>
index c20aae0..48d70b0 100644 (file)
@@ -1,4 +1,3 @@
-<%= $url = "$selfurl?session=$session_id;action="; ''; %>
 <%= include('header', "$svc setup successfully") %>
 
 <FONT SIZE=4><%= $svc %> setup successfully.</FONT>
index d6515e7..48f6a85 100644 (file)
@@ -1,4 +1,3 @@
-<%= $url = "$selfurl?session=$session_id;action="; ''; %>
 <%= include('header', "$svc setup successfully") %>
 
 <FONT SIZE=4><%= $svc %> setup successfully.</FONT>
index cd8028a..808e4b5 100644 (file)
@@ -1,5 +1,4 @@
-<%= $url = "$selfurl?session=$session_id;action="; 
-    $heading1 = "Setup my services";
+<%= $heading1 = "Setup my services";
     $heading1 = "Package list" if $wholesale_view;
     $provision_list = "provision_list";
     $provision_list = "ws_list" if $wholesale_view;
index bae5730..c63a838 100644 (file)
@@ -1,4 +1,3 @@
-<%= $url = "$selfurl?session=$session_id;action="; ''; %>
 <%= include('header', 'Setup account') %>
 
 <%= include('svc_acct') %>
index 9a07e7d..9ac039d 100644 (file)
@@ -1,5 +1,4 @@
-<%= $url = "$selfurl?session=$session_id;action="; 
- $heading2 = $lnp ? "Port-In Number" : "Setup phone number";
+<%= $heading2 = $lnp ? "Port-In Number" : "Setup phone number";
  '';
 %>
 <%= include('header', $heading2) %>
@@ -15,8 +14,7 @@ if($error) {
 }
 %>
 
-<FORM name="OneTrueForm" action="<%= $url %>" METHOD="POST">
-<INPUT TYPE="hidden" NAME="session" VALUE="<%= $session_id %>">
+<FORM name="OneTrueForm" action="<%= $selfurl %>" METHOD="POST">
 <INPUT TYPE="hidden" NAME="action" VALUE="process_svc_phone">
 <INPUT TYPE="hidden" NAME="pkgnum" VALUE="<%= $pkgnum %>">
 <INPUT TYPE="hidden" NAME="svcpart" VALUE="<%= $svcpart %>">
index c716e82..e47f800 100644 (file)
@@ -1,8 +1,6 @@
-<%= $url = "$selfurl?session=$session_id;action="; ''; %>
 <%= include('header', 'Recharge with prepaid card') %>
 
 <FORM NAME="OneTrueForm" METHOD="POST" ACTION="<%=$selfurl%>" onSubmit="document.OneTrueForm.process.disabled=true">
-<INPUT TYPE="hidden" NAME="session" VALUE="<%=$session_id%>">
 <INPUT TYPE="hidden" NAME="action" VALUE="recharge_results">
 <TABLE BGCOLOR="#cccccc">
 <!--
index 147b66b..919977a 100644 (file)
@@ -1,4 +1,3 @@
-<%= $url = "$selfurl?session=$session_id;action="; ''; %>
 <%= include('header', 'Recharge results') %>
 
 <%= if ( $error ) {
index 40fe98a..ea2a40b 100755 (executable)
@@ -1,10 +1,11 @@
-#!/usr/bin/perl -Tw
+#!/usr/bin/perl -w
 
 use strict;
 use vars qw($DEBUG $cgi $session_id $form_max $template_dir);
 use subs qw(do_template);
 use CGI;
 use CGI::Carp qw(fatalsToBrowser);
+use CGI::Cookie;
 use Text::Template;
 use HTML::Entities;
 use Date::Format;
@@ -20,6 +21,7 @@ use FS::SelfService qw(
   myaccount_passwd list_invoices create_ticket get_ticket did_report
   adjust_ticket_priority
   mason_comp port_graph
+  start_thirdparty finish_thirdparty
 );
 
 $template_dir = '.';
@@ -29,49 +31,85 @@ $DEBUG = 0;
 $form_max = 255;
 
 $cgi = new CGI;
+my %cookies = CGI::Cookie->fetch;
 
-unless ( defined $cgi->param('session') ) {
-  my $login_info = login_info( 'agentnum' => scalar($cgi->param('agentnum')) );
+my $login_rv;
 
-  do_template('login', $login_info );
-  exit;
-}
+if ( exists($cookies{'session'}) ) {
 
-if ( $cgi->param('session') eq 'login' ) {
+  $session_id = $cookies{'session'}->value;
 
-  $cgi->param('username') =~ /^\s*([a-z0-9_\-\.\&]{0,$form_max})\s*$/i
-    or die "illegal username";
-  my $username = $1;
+  if ( $session_id eq 'login' ) {
+    # then we've just come back from the login page
 
-  $cgi->param('domain') =~ /^\s*([\w\-\.]{0,$form_max})\s*$/
-    or die "illegal domain";
-  my $domain = $1;
+    $cgi->param('username') =~ /^\s*([a-z0-9_\-\.\&]{0,$form_max})\s*$/i;
+    my $username = $1;
 
-  $cgi->param('password') =~ /^(.{0,$form_max})$/
-    or die "illegal password";
-  my $password = $1;
+    $cgi->param('domain') =~ /^\s*([\w\-\.]{0,$form_max})\s*$/;
+    my $domain = $1;
 
-  my $rv = login(
-    'username' => $username,
-    'domain'   => $domain,
-    '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 {
-    $cgi->param('session' => $rv->{session_id} );
-    $cgi->param('action'  => 'myaccount' );
-  }
+    $cgi->param('password') =~ /^(.{0,$form_max})$/;
+    my $password = $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 = {};
 }
 
-$session_id = $cgi->param('session');
+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(
@@ -87,6 +125,8 @@ my @actions = ( qw(
   make_term_payment
   make_thirdparty_payment
   post_thirdparty_payment
+  finish_thirdparty_payment
+  cancel_thirdparty_payment
   payment_results
   ach_payment_results
   recharge_prepay
@@ -120,10 +160,15 @@ my @actions = ( qw(
   customer_suspend_pkg
   process_suspend_pkg
 ));
-$cgi->param('action') =~ ( '^(' . join('|', @actions) . ')$' )
-  or die "unknown action ". $cgi->param('action');
-my $action = $1;
+
+my $action = 'myaccount'; # sensible default
+if ( $cgi->param('action') =~ /^(\w+)$/ ) {
+  if (grep {$_ eq $1} @actions) {
+    $action = $1;
+  } else {
+    warn "WARNING: unrecognized action '$1'\n";
+  }
+}
 
 warn "calling $action sub\n"
   if $DEBUG;
@@ -136,6 +181,7 @@ 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();
   do_template('login', $login_info);
   exit;
@@ -663,7 +709,13 @@ sub ach_payment_results {
 }
 
 sub make_thirdparty_payment {
-  payment_info('session_id' => $session_id);
+  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 {
@@ -673,17 +725,32 @@ sub post_thirdparty_payment {
   $cgi->param('amount') =~ /^(\d+(\.\d*)?)$/
     or die "illegal amount";
   my $amount = $1;
-  # realtime_collect() returns the result from FS::cust_main->realtime_collect
-  # which returns realtime_bop()
-  # which returns a hashref of popup_url, collectitems, and reference
-  my $result = realtime_collect( 
+  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";
@@ -933,54 +1000,63 @@ sub do_template {
   $cgi->delete_all();
   $fill_in->{'selfurl'} = $cgi->self_url;
   $fill_in->{'cgi'} = \$cgi;
+  $fill_in->{'error'} = $cgi->param('error') if $cgi->param('error');
 
-  my $access_info = $session_id
+  my $access_info = ($session_id and $session_id ne 'login')
                       ? access_info( 'session_id' => $session_id )
                       : {};
   $fill_in->{$_} = $access_info->{$_} foreach keys %$access_info;
 
-  
-    if($result && ref($result) && $result->{'format'} && $result->{'content'}
-       && $result->{'format'} eq 'csv') {
-       print $cgi->header('-expires' => 'now',
-               '-Content-Type' => 'text/csv',
-               '-Content-Disposition' => "attachment;filename=output.csv",
-               ),
-           $result->{'content'};
-    }
-    elsif($result && ref($result) && $result->{'format'} && $result->{'content'}
-        && $result->{'format'} eq 'xls') {
-       print $cgi->header('-expires' => 'now',
-                   '-Content-Type' => 'application/vnd.ms-excel',
-                   '-Content-Disposition' => "attachment;filename=output.xls",
-                   '-Content-Length' => length($result->{'content'}),
-                   ),
-                   $result->{'content'};
-    }
-    elsif($result && ref($result) && $result->{'format'} && $result->{'content'}
-        && $result->{'format'} eq 'png') {
-       print $cgi->header('-expires' => 'now',
-                   '-Content-Type' => 'image/png',
-                   ),
-                   $result->{'content'};
-    }
-    else {
-       my $source = "$template_dir/$name.html";
-        my $template = new Text::Template( TYPE       => 'FILE',
-                                        SOURCE     => $source,
-                                        DELIMITERS => [ '<%=', '%>' ],
-                                        UNTAINT    => 1,
-                                      )
-       or die $Text::Template::ERROR;
-
-       my $data = $template->fill_in( 
-           PACKAGE => 'FS::SelfService::_selfservicecgi',
-           HASH    => $fill_in,
-         ) || "Error processing template $source"; # at least print _something_
-         print $cgi->header( '-expires' => 'now' );
-         print $data;
+  # update the user's authentication
+  my $timeout = $access_info->{'timeout'} || '60';
+  my $cookie = CGI::Cookie->new('-name'     => 'session',
+                                '-value'    => $session_id,
+                                '-expires'  => '+'.$timeout,
+                                #'-secure'   => 1, # would be a good idea...
+                               );
+  if ( $name eq 'logout' ) {
+    $cookie->expires(0);
+  }
+
+  if ( $fill_in->{'format'} ) {
+    # then override content-type, and return $fill_in->{'content'} instead
+    # of filling in a template
+    if ( $fill_in->{'format'} eq 'csv') {
+      print $cgi->header('-expires' => 'now',
+        '-Content-Type' => 'text/csv',
+        '-Content-Disposition' => "attachment;filename=output.csv",
+      );
+    } elsif ( $fill_in->{'format'} eq 'xls' ) {
+      print $cgi->header('-expires' => 'now',
+        '-Content-Type' => 'application/vnd.ms-excel',
+        '-Content-Disposition' => "attachment;filename=output.xls",
+        '-Content-Length' => length($fill_in->{'content'}),
+      );
+    } elsif ( $fill_in->{'format'} eq 'png' ) {
+      print $cgi->header('-expires' => 'now',
+        '-Content-Type' => 'image/png',
+      );
     }
- }
+    print $fill_in->{'content'};
+  } else { # the usual case
+    my $source = "$template_dir/$name.html";
+    my $template = new Text::Template(
+      TYPE       => 'FILE',
+      SOURCE     => $source,
+      DELIMITERS => [ '<%=', '%>' ],
+      UNTAINT    => 1,
+    )
+      or die $Text::Template::ERROR;
+
+    my $data = $template->fill_in( 
+      PACKAGE => 'FS::SelfService::_selfservicecgi',
+      HASH    => $fill_in,
+    ) || "Error processing template $source"; # at least print _something_
+    print $cgi->header( '-cookie' => $cookie,
+                        '-expires' => 'now' );
+    print $data;
+  }
+}
 
 #*FS::SelfService::_selfservicecgi::include = \&Text::Template::fill_in_file;
 
@@ -1011,4 +1087,4 @@ sub include {
 
 }
 
-1;
+
index 0024438..09d9163 100644 (file)
@@ -5,7 +5,6 @@
           '</FONT><BR><BR>';
 } ''; %>
 <FORM ACTION="<%= $selfurl %>" METHOD=POST>
-<INPUT TYPE="hidden" NAME="session" VALUE="<%= $session_id %>">
 <INPUT TYPE="hidden" NAME="action" VALUE="process_svc_acct">
 <INPUT TYPE="hidden" NAME="custnum" VALUE="<%= $custnum %>">
 <INPUT TYPE="hidden" NAME="pkgnum" VALUE="<%= $pkgnum %>">
index 4333c4e..94043bf 100644 (file)
@@ -12,7 +12,6 @@ my $can_set_priority =
 if ( $can_set_priority ) {
 
   $OUT .= qq!<FORM ACTION="$selfurl" METHOD="POST">! .
-          qq!<INPUT TYPE="hidden" NAME="session" VALUE="$session_id">! .
           qq!<INPUT TYPE="hidden" NAME="action" VALUE="ticket_priority">!;
 }
 $date_format ||= '%Y-%m-%d';
index de7ff60..1e1ecb6 100644 (file)
@@ -1,4 +1,3 @@
-<%= $url = "$selfurl?session=$session_id;action="; ''; %>
 <%= include('header', 'Create a ticket') %>
 
 <%=
@@ -10,7 +9,6 @@ if ( $ticket_id ) {
     Please fill in both the subject and message
     <br><br>
     <FORM ACTION="$selfurl" METHOD=POST>
-    <input type="hidden" name="session" value="$session_id">
     <input type="hidden" name="action" value="tktcreate">
     <table>
        <tr>
index 72634fe..974dd6b 100644 (file)
@@ -1,4 +1,3 @@
-<%= $url = "$selfurl?session=$session_id;action="; ''; %>
 <%= include('header', "View ticket #$ticket_id") %>
 
 <%=
@@ -20,7 +19,6 @@ else {
 %>
 <BR><BR><BR>
 <FORM ACTION="<%=$selfurl%>" METHOD=POST>
-    <input type="hidden" name="session" value="<%=$session_id%>">
     <input type="hidden" name="ticket_id" value="<%=$ticket_id%>">
 <%= if ( $edit_ticket_subject ) { $OUT .= '
     Subject:<BR><input type="text" name="subject" value="' . 
index 0ee8e96..f396682 100644 (file)
@@ -1,4 +1,3 @@
-<%= $url = "$selfurl?session=$session_id;action="; ''; %>
 <%= include('header', ($inbound ? 'Received calls' : 'Dialed calls' ) . 
                        ' for '.
                        Date::Format::time2str('%b&nbsp;%o&nbsp;%Y', $beginning).
index 5bfb9b6..a40cd5a 100644 (file)
@@ -1,6 +1,5 @@
 <HTML><HEAD><TITLE>Reseller</TITLE></HEAD>
 <BODY BGCOLOR="#eeeeee"><FONT SIZE=5>Reseller</FONT><BR><BR>
-<%= $url = "$selfurl?session=$session_id;action="; ''; %>
 <TABLE BORDER=0 CELLPADDING=4><TR>
 <%= include('agent_menu') %>
 <TD VALIGN="top">
index 072a414..d49a466 100644 (file)
@@ -1,4 +1,3 @@
-<%= $url = "$selfurl?session=$session_id;action="; ''; %>
 <%= include('header', 'Invoice') %>
 
 <%= $invoice_html %>
index d42f405..0d32a88 100644 (file)
@@ -1,4 +1,4 @@
-<%= $url = "$selfurl?session=$session_id;action="; ''; %>
+<%= $url = "$selfurl?action="; ''; %>
 <%= include('header', "Service usage details for $start - $end") %>
 
 <%= if ( $error ) {
index 104b061..b401be4 100644 (file)
@@ -1,4 +1,4 @@
-<%= $url = "$selfurl?session=$session_id;action="; ''; %>
+<%= $url = "$selfurl?action="; ''; %>
 <%= include('header', 'Usage details') %>
 
 <FONT SIZE=4>Support usage details for
index 35d1289..f50f770 100644 (file)
@@ -1,4 +1,4 @@
-<%= $url = "$selfurl?session=$session_id;action=";
+<%= $url = "$selfurl?action=";
     %by_pkg_label = (); # not used yet, but I'm sure it will be...
     @svc_acct = ();
     @svc_phone = ();
@@ -196,8 +196,7 @@ foreach my $svc_port ( @svc_port ) {
   $OUT .= '<TR><TD>'. $svc_port->{'label'}. ': '. $svc_port->{'value'}.'</TD>';
   $OUT .= qq! <TD><FORM ACTION="$url" METHOD="GET">
                <INPUT TYPE="hidden" name="svcnum" value="$svcnum">
-               <INPUT TYPE="hidden" name="action" value="view_port_graph">  
-               <INPUT TYPE="hidden" name="session" value="$session_id">  !;
+               <INPUT TYPE="hidden" name="action" value="view_port_graph"> !; 
   $OUT .= preset_range($default_start,$default_end,'Last Day',$date_format,$svcnum)
        .' | '.preset_range($default_end-86400*7,$default_end,'Last Week',$date_format,$svcnum)
        .' | '.preset_range($default_end-86400*30,$default_end,'Last Month',$date_format,$svcnum)
index c4cc177..0388c2f 100644 (file)
@@ -1,4 +1,4 @@
-<%= $url = "$selfurl?session=$session_id;action="; ''; %>
+<%= $url = "$selfurl?;action="; ''; %>
 <%= include('header', 'Service usage details for '.
                       Date::Format::time2str('%b&nbsp;%o&nbsp;%Y', $beginning).
                       ' - '.
index 7cfab71..37618d6 100644 (file)
@@ -93,9 +93,10 @@ my %modules = (
     'WorldPay',
   ],
   'Business::OnlineThirdPartyPayment' => [
-    'eWayShared',
-    'Interswitchng',
+    #'eWayShared', support currently broken
+    #'Interswitchng',
     'PayPal',
+    'FCMB',
   ],
   'Business::BatchPayment' => [
     'KeyBank',