summaryrefslogtreecommitdiff
path: root/fs_selfservice/FS-SelfService
diff options
context:
space:
mode:
Diffstat (limited to 'fs_selfservice/FS-SelfService')
-rw-r--r--fs_selfservice/FS-SelfService/Makefile.PL4
-rw-r--r--fs_selfservice/FS-SelfService/SelfService.pm596
-rw-r--r--fs_selfservice/FS-SelfService/cgi/login.html12
-rw-r--r--fs_selfservice/FS-SelfService/cgi/make_payment.html120
-rw-r--r--fs_selfservice/FS-SelfService/cgi/myaccount.html16
-rw-r--r--fs_selfservice/FS-SelfService/cgi/payment_results.html18
-rw-r--r--fs_selfservice/FS-SelfService/cgi/selfservice.cgi85
-rw-r--r--fs_selfservice/FS-SelfService/cgi/view_invoice.html4
-rw-r--r--fs_selfservice/FS-SelfService/freeside-selfservice-clientd47
9 files changed, 846 insertions, 56 deletions
diff --git a/fs_selfservice/FS-SelfService/Makefile.PL b/fs_selfservice/FS-SelfService/Makefile.PL
index da0a0aa24..e5cbd1aef 100644
--- a/fs_selfservice/FS-SelfService/Makefile.PL
+++ b/fs_selfservice/FS-SelfService/Makefile.PL
@@ -8,7 +8,9 @@ WriteMakefile(
'INSTALLSCRIPT' => '/usr/local/sbin',
'INSTALLSITEBIN' => '/usr/local/sbin',
'PERM_RWX' => '750',
- 'PREREQ_PM' => {}, # e.g., Module::Name => 1.1
+ 'PREREQ_PM' => {
+ 'Storable' => 0,
+ }, # e.g., Module::Name => 1.1
($] >= 5.005 ? ## Add these new keywords supported since 5.005
(ABSTRACT_FROM => 'SelfService.pm', # retrieve abstract from module
AUTHOR => 'Ivan Kohler <ivan-freeside-selfservice@420.am>') : ()),
diff --git a/fs_selfservice/FS-SelfService/SelfService.pm b/fs_selfservice/FS-SelfService/SelfService.pm
index 9019ea4f8..715f935f3 100644
--- a/fs_selfservice/FS-SelfService/SelfService.pm
+++ b/fs_selfservice/FS-SelfService/SelfService.pm
@@ -1,7 +1,7 @@
package FS::SelfService;
use strict;
-use vars qw($VERSION @ISA @EXPORT_OK $socket %autoload );
+use vars qw($VERSION @ISA @EXPORT_OK $socket %autoload $tag);
use Exporter;
use Socket;
use FileHandle;
@@ -14,14 +14,25 @@ $VERSION = '0.03';
@ISA = qw( Exporter );
$socket = "/usr/local/freeside/selfservice_socket";
+$socket .= '.'.$tag if defined $tag && length($tag);
+#maybe should ask ClientAPI for this list
%autoload = (
- 'passwd' => 'passwd/passwd',
- 'chfn' => 'passwd/passwd',
- 'chsh' => 'passwd/passwd',
- 'login' => 'MyAccount/login',
- 'customer_info' => 'MyAccount/customer_info',
- 'invoice' => 'MyAccount/invoice',
+ 'passwd' => 'passwd/passwd',
+ 'chfn' => 'passwd/passwd',
+ 'chsh' => 'passwd/passwd',
+ 'login' => 'MyAccount/login',
+ 'customer_info' => 'MyAccount/customer_info',
+ 'edit_info' => 'MyAccount/edit_info',
+ 'invoice' => 'MyAccount/invoice',
+ 'cancel' => 'MyAccount/cancel',
+ 'payment_info' => 'MyAccount/payment_info',
+ 'process_payment' => 'MyAccount/process_payment',
+ 'list_pkgs' => 'MyAccount/list_pkgs',
+ 'order_pkg' => 'MyAccount/order_pkg',
+ 'cancel_pkg' => 'MyAccount/cancel_pkg',
+ 'signup_info' => 'Signup/signup_info',
+ 'new_customer' => 'Signup/new_customer',
);
@EXPORT_OK = keys %autoload;
@@ -35,29 +46,6 @@ $ENV{'BASH_ENV'} = '';
my $freeside_uid = scalar(getpwnam('freeside'));
die "not running as the freeside user\n" if $> != $freeside_uid;
-=head1 NAME
-
-FS::SelfService - Freeside self-service API
-
-=head1 SYNOPSIS
-
-=head1 DESCRIPTION
-
-Use this API to implement your own client "self-service" module.
-
-If you just want to customize the look of the existing "self-service" module,
-see XXXX instead.
-
-=head1 FUNCTIONS
-
-=over 4
-
-=item passwd
-
-Returns the empty value on success, or an error message on errors.
-
-=cut
-
foreach my $autoload ( keys %autoload ) {
my $eval =
@@ -98,6 +86,554 @@ sub simple_packet {
$return;
}
+=head1 NAME
+
+FS::SelfService - Freeside self-service API
+
+=head1 SYNOPSIS
+
+ # password and shell account changes
+ use FS::SelfService qw(passwd chfn chsh);
+
+ # "my account" functionality
+ use FS::SelfService qw( login customer_info invoice cancel payment_info process_payment );
+
+ my $rv = login( { 'username' => $username,
+ 'domain' => $domain,
+ 'password' => $password,
+ }
+ );
+
+ if ( $rv->{'error'} ) {
+ #handle login error...
+ } else {
+ #successful login
+ my $session_id = $rv->{'session_id'};
+ }
+
+ my $customer_info = customer_info( { 'session_id' => $session_id } );
+
+ #payment_info and process_payment are available in 1.5+ only
+ my $payment_info = payment_info( { 'session_id' => $session_id } );
+
+ #!!! process_payment example
+
+ #!!! list_pkgs example
+
+ #!!! order_pkg example
+
+ #!!! cancel_pkg example
+
+ # signup functionality
+ use FS::SelfService qw( signup_info new_customer );
+
+ my $signup_info = signup_info;
+
+ $rv = new_customer( {
+ 'first' => $first,
+ 'last' => $last,
+ 'company' => $company,
+ 'address1' => $address1,
+ 'address2' => $address2,
+ 'city' => $city,
+ 'state' => $state,
+ 'zip' => $zip,
+ 'country' => $country,
+ 'daytime' => $daytime,
+ 'night' => $night,
+ 'fax' => $fax,
+ 'payby' => $payby,
+ 'payinfo' => $payinfo,
+ 'paycvv' => $paycvv,
+ 'paydate' => $paydate,
+ 'payname' => $payname,
+ 'invoicing_list' => $invoicing_list,
+ 'referral_custnum' => $referral_custnum,
+ 'pkgpart' => $pkgpart,
+ 'username' => $username,
+ '_password' => $password,
+ 'popnum' => $popnum,
+ 'agentnum' => $agentnum,
+ }
+ );
+
+ my $error = $rv->{'error'};
+ if ( $error eq '_decline' ) {
+ print_decline();
+ } elsif ( $error ) {
+ reprint_signup();
+ } else {
+ print_success();
+ }
+
+=head1 DESCRIPTION
+
+Use this API to implement your own client "self-service" module.
+
+If you just want to customize the look of the existing "self-service" module,
+see XXXX instead.
+
+=head1 PASSWORD, GECOS, SHELL CHANGING FUNCTIONS
+
+=over 4
+
+=item passwd
+
+=item chfn
+
+=item chsh
+
+=back
+
+=head1 "MY ACCOUNT" FUNCTIONS
+
+=over 4
+
+=item login HASHREF
+
+Creates a user session. Takes a hash reference as parameter with the
+following keys:
+
+=over 4
+
+=item username
+
+=item domain
+
+=item password
+
+=back
+
+Returns a hash reference with the following keys:
+
+=over 4
+
+=item error
+
+Empty on success, or an error message on errors.
+
+=item session_id
+
+Session identifier for successful logins
+
+=back
+
+=item customer_info HASHREF
+
+Returns general customer information.
+
+Takes a hash reference as parameter with a single key: B<session_id>
+
+Returns a hash reference with the following keys:
+
+=over 4
+
+=item name
+
+Customer name
+
+=item balance
+
+Balance owed
+
+=item open
+
+Array reference of hash references of open inoices. Each hash reference has
+the following keys: invnum, date, owed
+
+=item small_custview
+
+An HTML fragment containing shipping and billing addresses.
+
+=item The following fields are also returned: first last company address1 address2 city county state zip country daytime night fax ship_first ship_last ship_company ship_address1 ship_address2 ship_city ship_state ship_zip ship_country ship_daytime ship_night ship_fax
+
+=back
+
+=item edit_info HASHREF
+
+Takes a hash reference as parameter with any of the following keys:
+
+first last company address1 address2 city county state zip country daytime night fax ship_first ship_last ship_company ship_address1 ship_address2 ship_city ship_state ship_zip ship_country ship_daytime ship_night ship_fax
+
+If a field exists, the customer record is updated with the new value of that
+field. If a field does not exist, that field is not changed on the customer
+record.
+
+Returns a hash reference with a single key, B<error>, empty on success, or an
+error message on errors
+
+=item invoice HASHREF
+
+Returns an invoice. Takes a hash reference as parameter with two keys:
+session_id and invnum
+
+Returns a hash reference with the following keys:
+
+=over 4
+
+=item error
+
+Empty on success, or an error message on errors
+
+=item invnum
+
+Invoice number
+
+=item invoice_text
+
+Invoice text
+
+=back
+
+=item cancel HASHREF
+
+Cancels this customer.
+
+Takes a hash reference as parameter with a single key: B<session_id>
+
+Returns a hash reference with a single key, B<error>, which is empty on
+success or an error message on errors.
+
+=item payment_info HASHREF
+
+Returns information that may be useful in displaying a payment page.
+
+Takes a hash reference as parameter with a single key: B<session_id>.
+
+Returns a hash reference with the following keys:
+
+=over 4
+
+=item error
+
+Empty on success, or an error message on errors
+
+=item balance
+
+Balance owed
+
+=item payname
+
+Exact name on credit card (CARD/DCRD)
+
+=item address1
+
+=item address2
+
+=item city
+
+=item state
+
+=item zip
+
+=item payby
+
+Customer's current default payment type.
+
+=item card_type
+
+For CARD/DCRD payment types, the card type (Visa card, MasterCard, Discover card, American Express card, etc.)
+
+=item payinfo
+
+For CARD/DCRD payment types, the card number
+
+=item month
+
+For CARD/DCRD payment types, expiration month
+
+=item year
+
+For CARD/DCRD payment types, expiration year
+
+=item cust_main_county
+
+County/state/country data - array reference of hash references, each of which has the fields of a cust_main_county record (see L<FS::cust_main_county>). Note these are not FS::cust_main_county objects, but hash references of columns and values.
+
+=item states
+
+Array reference of all states in the current default country.
+
+=item card_types
+
+Hash reference of card types; keys are card types, values are the exact strings
+passed to the process_payment function
+
+=item paybatch
+
+Unique transaction identifier (prevents multiple charges), passed to the
+process_payment function
+
+=back
+
+=item process_payment HASHREF
+
+Processes a payment and possible change of address or payment type. Takes a
+hash reference as parameter with the following keys:
+
+=over 4
+
+=item session_id
+
+=item save
+
+If true, address and card information entered will be saved for subsequent
+transactions.
+
+=item auto
+
+If true, future credit card payments will be done automatically (sets payby to
+CARD). If false, future credit card payments will be done on-demand (sets
+payby to DCRD). This option only has meaning if B<save> is set true.
+
+=item payname
+
+=item address1
+
+=item address2
+
+=item city
+
+=item state
+
+=item zip
+
+=item payinfo
+
+Card number
+
+=item month
+
+Card expiration month
+
+=item year
+
+Card expiration year
+
+=item paybatch
+
+Unique transaction identifier, returned from the payment_info function.
+Prevents multiple charges.
+
+=back
+
+Returns a hash reference with a single key, B<error>, empty on success, or an
+error message on errors
+
+=item list_pkgs
+
+Returns package information for this customer.
+
+Takes a hash reference as parameter with a single key: B<session_id>
+
+Returns a hash reference containing customer package information. The hash reference contains the following keys:
+
+=over 4
+
+=item cust_pkg HASHREF
+
+Array reference of hash references, each of which has the fields of a cust_pkg record (see L<FS::cust_pkg>). Note these are not FS::cust_pkg objects, but hash references of columns and values.
+
+=back
+
+=item order_pkg
+
+Orders a package for this customer.
+
+Takes a hash reference as parameter with the following keys:
+
+=over 4
+
+=item session_id
+
+=item pkgpart
+
+=item svcpart
+
+optional svcpart, required only if the package definition does not contain
+one svc_acct service definition with quantity 1 (it may contain others with
+quantity >1)
+
+=item username
+
+=item _password
+
+=item sec_phrase
+
+=item popnum
+
+=back
+
+Returns a hash reference with a single key, B<error>, empty on success, or an
+error message on errors. The special error '_decline' is returned for
+declined transactions.
+
+=item cancel_pkg
+
+Cancels a package for this customer.
+
+Takes a hash reference as parameter with the following keys:
+
+=over 4
+
+=item session_id
+
+=item pkgpart
+
+=back
+
+Returns a hash reference with a single key, B<error>, empty on success, or an
+error message on errors.
+
+=back
+
+=head1 SIGNUP FUNCTIONS
+
+=over 4
+
+=item signup_info
+
+Returns a hash reference containing information that may be useful in
+displaying a signup page. The hash reference contains the following keys:
+
+=over 4
+
+=item cust_main_county
+
+County/state/country data - array reference of hash references, each of which has the fields of a cust_main_county record (see L<FS::cust_main_county>). Note these are not FS::cust_main_county objects, but hash references of columns and values.
+
+=item part_pkg
+
+Available packages - array reference of hash references, each of which has the fields of a part_pkg record (see L<FS::part_pkg>). Each hash reference also has an additional 'payby' field containing an array reference of acceptable payment types specific to this package (see below and L<FS::part_pkg/payby>). Note these are not FS::part_pkg objects, but hash references of columns and values. Requires the 'signup_server-default_agentnum' configuration value to be set.
+
+=item agent
+
+Array reference of hash references, each of which has the fields of an agent record (see L<FS::agent>). Note these are not FS::agent objects, but hash references of columns and values.
+
+=item agentnum2part_pkg
+
+Hash reference; keys are agentnums, values are array references of available packages for that agent, in the same format as the part_pkg arrayref above.
+
+=item svc_acct_pop
+
+Access numbers - array reference of hash references, each of which has the fields of an svc_acct_pop record (see L<FS::svc_acct_pop>). Note these are not FS::svc_acct_pop objects, but hash references of columns and values.
+
+=item security_phrase
+
+True if the "security_phrase" feature is enabled
+
+=item payby
+
+Array reference of acceptable payment types for signup
+
+=over 4
+
+=item CARD (credit card - automatic)
+
+=item DCRD (credit card - on-demand - version 1.5+ only)
+
+=item CHEK (electronic check - automatic)
+
+=item DCHK (electronic check - on-demand - version 1.5+ only)
+
+=item LECB (Phone bill billing)
+
+=item BILL (billing, not recommended for signups)
+
+=item COMP (free, definately not recommended for signups)
+
+=item PREPAY (special billing type: applies a credit (see FS::prepay_credit) and sets billing type to BILL)
+
+=back
+
+=item cvv_enabled
+
+True if CVV features are available (1.5+ or 1.4.2 with CVV schema patch)
+
+=item msgcat
+
+Hash reference of message catalog values, to support error message customization. Currently available keys are: passwords_dont_match, invalid_card, unknown_card_type, and not_a (as in "Not a Discover card"). Values are configured in the web interface under "View/Edit message catalog".
+
+=item statedefault
+
+Default state
+
+=item countrydefault
+
+Default country
+
+=back
+
+=item new_customer HASHREF
+
+Creates a new customer. Takes a hash reference as parameter with the
+following keys:
+
+=over 4
+
+=item first - first name (required)
+
+=item last - last name (required)
+
+=item ss (not typically collected; mostly used for ACH transactions)
+
+=item company
+
+=item address1 (required)
+
+=item address2
+
+=item city (required)
+
+=item county
+
+=item state (required)
+
+=item zip (required)
+
+=item daytime - phone
+
+=item night - phone
+
+=item fax - phone
+
+=item payby - CARD, DCRD, CHEK, DCHK, LECB, BILL, COMP or PREPAY (see L</signup_info> (required)
+
+=item payinfo - Card number for CARD/DCRD, account_number@aba_number for CHEK/DCHK, prepaid "pin" for PREPAY, purchase order number for BILL
+
+=item paycvv - Credit card CVV2 number (1.5+ or 1.4.2 with CVV schema patch)
+
+=item paydate - Expiration date for CARD/DCRD
+
+=item payname - Exact name on credit card for CARD/DCRD, bank name for CHEK/DCHK
+
+=item invoicing_list - comma-separated list of email addresses for email invoices. The special value 'POST' is used to designate postal invoicing (it may be specified alone or in addition to email addresses),
+
+=item referral_custnum - referring customer number
+
+=item pkgpart - pkgpart of initial package
+
+=item username
+
+=item _password
+
+=item sec_phrase - security phrase
+
+=item popnum - access number (index, not the literal number)
+
+=item agentnum - agent number
+
+=back
+
+Returns a hash reference with the following keys:
+
+=over 4
+
+=item error Empty on success, or an error message on errors. The special error '_decline' is returned for declined transactions; other error messages should be suitable for display to the user (and are customizable in under Sysadmin | View/Edit message catalog)
+
+=back
+
+
=back
=head1 BUGS
diff --git a/fs_selfservice/FS-SelfService/cgi/login.html b/fs_selfservice/FS-SelfService/cgi/login.html
index dfbd0137a..5607de783 100644
--- a/fs_selfservice/FS-SelfService/cgi/login.html
+++ b/fs_selfservice/FS-SelfService/cgi/login.html
@@ -6,16 +6,22 @@
<TABLE BGCOLOR="#c0c0c0" BORDER=0 CELLSPACING=2 CELLPADDING=0>
<TR>
<TH ALIGN="right">Username </TH>
- <TD><INPUT TYPE="text" NAME="username" VALUE="<%= $username %>"></TD>
+ <TD>
+ <INPUT TYPE="text" NAME="username" VALUE="<%= $username %>">
+ </TD>
</TR>
<TR>
<TH ALIGN="right">Domain </TH>
- <TD><INPUT TYPE="text" NAME="domain" VALUE="<%= $domain %>"></TD>
+ <TD>
+ <INPUT TYPE="text" NAME="domain" VALUE="<%= $domain %>">
+ </TD>
</TR>
<!--<INPUT TYPE="hidden" NAME="domain" VALUE="myisp.com">-->
<TR>
<TH ALIGN="right">Password </TH>
- <TD><INPUT TYPE="password" NAME="password"></TD>
+ <TD>
+ <INPUT TYPE="password" NAME="password">
+ </TD>
</TR>
</TABLE>
<BR><BR><INPUT TYPE="submit" VALUE="Login">
diff --git a/fs_selfservice/FS-SelfService/cgi/make_payment.html b/fs_selfservice/FS-SelfService/cgi/make_payment.html
new file mode 100644
index 000000000..a1cda6d49
--- /dev/null
+++ b/fs_selfservice/FS-SelfService/cgi/make_payment.html
@@ -0,0 +1,120 @@
+<HTML><HEAD><TITLE>MyAccount</TITLE></HEAD>
+<BODY BGCOLOR="#eeeeee"><FONT SIZE=5>MyAccount</FONT><BR><BR>
+<%= $url = "$selfurl?session=$session_id;action="; ''; %>
+<TABLE BORDER=0 CELLPADDING=4><TR><TD VALIGN="top" HEIGHT=384 BGCOLOR="#dddddd">
+<A HREF="<%= $url %>myaccount">MyAccount</A><BR>
+<!-- <A HREF="<%= $url %>other">SomethingElse</A><BR> -->
+</TD><TD VALIGN="top">
+<FONT SIZE=4>Make a payment</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="payment_results">
+<TABLE BGCOLOR="#cccccc">
+<TR>
+ <TD ALIGN="right">Amount&nbsp;Due</TD>
+ <TD>
+ <TABLE><TR><TD BGCOLOR="#ffffff">
+ $<%=sprintf("%.2f",$balance)%>
+ </TD></TR></TABLE>
+ </TD>
+</TR>
+<TR>
+ <TD ALIGN="right">Payment&nbsp;amount</TD>
+ <TD>
+ <TABLE><TR><TD BGCOLOR="#ffffff">
+ $<INPUT TYPE="text" NAME="amount" SIZE=8 VALUE="<%=sprintf("%.2f",$balance)%>">
+ </TD></TR></TABLE>
+ </TD>
+</TR><TR>
+ <TD ALIGN="right">Card&nbsp;type</TD>
+ <TD>
+ <SELECT NAME="card_type"><OPTION></OPTION>
+ <%= foreach ( keys %card_types ) {
+ $selected = $card_type eq $card_types{$_} ? ' SELECTED' : '';
+ $OUT .= qq(<OPTION$selected VALUE="). $card_types{$_}. qq(">$_\n);
+ } %>
+ </SELECT>
+ </TD>
+</TD><TR>
+ <TD ALIGN="right">Card&nbsp;number</TD>
+ <TD>
+ <TABLE>
+ <TR>
+ <TD>
+ <INPUT TYPE="text" NAME="payinfo" SIZE=20 MAXLENGTH=19 VALUE="<%=$payinfo%>"> </TD>
+ <TD>Exp.</TD>
+ <TD>
+ <SELECT NAME="month">
+ <%= for ( ( map "0$_", 1 .. 9 ), 11, 12 ) {
+ $OUT .= '<OPTION'. ($_ eq $month ? ' SELECTED' : ''). ">$_\n";
+ } %>
+ </SELECT>
+ </TD>
+ <TD> / </TD>
+ <TD>
+ <SELECT NAME="year">
+ <%= for ( 2003 .. 2012 ) {
+ $OUT .= '<OPTION'. ($_ eq $year ? ' SELECTED' : ''). ">$_\n";
+ } %>
+ </SELECT>
+ </TD>
+ </TR>
+ </TABLE>
+ </TD>
+</TR><TR>
+ <TD ALIGN="right">Exact&nbsp;name&nbsp;on&nbsp;card</TD>
+ <TD><INPUT TYPE="text" SIZE=32 MAXLENGTH=80 NAME="payname" VALUE="<%=$payname%>"></TD>
+</TR><TR>
+ <TD ALIGN="right">Card&nbsp;billing&nbsp;address</TD>
+ <TD>
+ <INPUT TYPE="text" SIZE=40 MAXLENGTH=80 NAME="address1" VALUE="<%=$address1%>">
+ </TD>
+</TR><TR>
+ <TD ALIGN="right">Address&nbsp;line&nbsp;2</TD>
+ <TD>
+ <INPUT TYPE="text" SIZE=40 MAXLENGTH=80 NAME="address2" VALUE="<%=$address2%>">
+ </TD>
+</TR><TR>
+ <TD ALIGN="right">City</TD>
+ <TD>
+ <TABLE>
+ <TR>
+ <TD>
+ <INPUT TYPE="text" NAME="city" SIZE="12" MAXLENGTH=80 VALUE="<%=$city%>">
+ </TD>
+ <TD>State</TD>
+ <TD>
+ <SELECT NAME="state">
+ <%= for ( @states ) {
+ $OUT .= '<OPTION'. ($_ eq $state ? ' SELECTED' : '' ). ">$_\n";
+ } %>
+ </SELECT>
+ </TD>
+ <TD>Zip</TD>
+ <TD>
+ <INPUT TYPE="text" NAME="zip" SIZE=11 MAXLENGTH=10 VALUE="<%=$zip%>">
+ </TD>
+ </TR>
+ </TABLE>
+ </TD>
+</TR><TR>
+ <TD COLSPAN=2>
+ <INPUT TYPE="checkbox" CHECKED NAME="save" VALUE="1">
+ Remember this information
+ </TD>
+</TR><TR>
+ <TD COLSPAN=2>
+ <INPUT TYPE="checkbox"<%= $payby eq 'CARD' ? ' CHECKED' : '' %> NAME="auto" VALUE="1" onClick="if (this.checked) { document.OneTrueForm.save.checked=true; }">
+ Charge future payments to this card automatically
+ </TD>
+</TR>
+</TABLE>
+<BR>
+<INPUT TYPE="hidden" NAME="paybatch" VALUE="<%=$paybatch%>">
+<INPUT TYPE="submit" NAME="process" VALUE="Process payment"> <!-- onClick="this.disabled=true"> -->
+</FORM>
+</TD></TR></TABLE>
+<HR>
+<FONT SIZE="-2">powered by <a href="http://www.sisd.com/freeside">freeside</a></FONT>
+</BODY></HTML>
+
diff --git a/fs_selfservice/FS-SelfService/cgi/myaccount.html b/fs_selfservice/FS-SelfService/cgi/myaccount.html
index f8a916eea..f48fdedea 100644
--- a/fs_selfservice/FS-SelfService/cgi/myaccount.html
+++ b/fs_selfservice/FS-SelfService/cgi/myaccount.html
@@ -3,20 +3,20 @@
<%= $url = "$selfurl?session=$session_id;action="; ''; %>
<TABLE BORDER=0 CELLPADDING=4><TR><TD VALIGN="top" HEIGHT=384 BGCOLOR="#dddddd">
<A HREF="<%= $url %>myaccount">MyAccount</A><BR>
-<A HREF="<%= $url %>other">SomethingElse</A><BR>
+<!-- <A HREF="<%= $url %>other">SomethingElse</A><BR> -->
</TD><TD VALIGN="top">
Hello <%= $name %>!<BR><BR>
-Your customer number is <%= $custnum %><BR><BR>
-Your contact information<BR><%= $small_custview %>
-Your outstanding balance is $<%= $balance %><BR><BR>
-<!--<TABLE BORDER=1 CELLSPACING=0 CELLPADDING=2 BORDERCOLOR="#999999">
-<TR><TH>Invoice</TH><TH>Date</TH><TH>Owed</TH></TR>-->
+<%= $small_custview %>
+<BR>
+<%= if ( $balance > 0 ) {
+ $OUT .= qq! <B><A HREF="${url}make_payment">Make a payment</A></B><BR><BR>!;
+} %>
<%=
if ( @open_invoices ) {
$OUT .= '<TABLE BORDER=0 CELLSPACING=0 CELLPADDING=2 BGCOLOR="#eeeeee">'.
'<TR><TH BGCOLOR="#ff3333" COLSPAN=5>Open Invoices</TH><TD>';
- my $link = qq!<A HREF="<%= $selfurl %>?session=<%= $session_id %>;action=myaccount!;
+ my $link = qq!<A HREF="<%= $url %>myaccount!;
my $col1 = "ffffff";
my $col2 = "dddddd";
my $col = $col1;
@@ -40,7 +40,7 @@ Your outstanding balance is $<%= $balance %><BR><BR>
</TD></TR></TABLE>
<HR>
-<FONT SIZE="-2">small text</FONT>
+<FONT SIZE="-2">powered by <a href="http://www.sisd.com/freeside">freeside</a></FONT>
</BODY></HTML>
diff --git a/fs_selfservice/FS-SelfService/cgi/payment_results.html b/fs_selfservice/FS-SelfService/cgi/payment_results.html
new file mode 100644
index 000000000..92c8cf51b
--- /dev/null
+++ b/fs_selfservice/FS-SelfService/cgi/payment_results.html
@@ -0,0 +1,18 @@
+<HTML><HEAD><TITLE>MyAccount</TITLE></HEAD>
+<BODY BGCOLOR="#eeeeee"><FONT SIZE=5>MyAccount</FONT><BR><BR>
+<%= $url = "$selfurl?session=$session_id;action="; ''; %>
+<TABLE BORDER=0 CELLPADDING=4><TR><TD VALIGN="top" HEIGHT=384 BGCOLOR="#dddddd">
+<A HREF="<%= $url %>myaccount">MyAccount</A><BR>
+<!-- <A HREF="<%= $url %>other">SomethingElse</A><BR> -->
+</TD><TD VALIGN="top">
+<FONT SIZE=4>Payment results</FONT><BR><BR>
+<%= if ( $error ) {
+ $OUT .= qq!<FONT SIZE="+1" COLOR="#ff0000">Error processing your payment: $error</FONT>!;
+} else {
+ $OUT .= 'Your payment was processed sucessfully. Thank you.';
+} %>
+</TD></TR></TABLE>
+<HR>
+<FONT SIZE="-2">powered by <a href="http://www.sisd.com/freeside">freeside</a></FONT>
+</BODY></HTML>
+
diff --git a/fs_selfservice/FS-SelfService/cgi/selfservice.cgi b/fs_selfservice/FS-SelfService/cgi/selfservice.cgi
index eae373931..6d6716ddc 100644
--- a/fs_selfservice/FS-SelfService/cgi/selfservice.cgi
+++ b/fs_selfservice/FS-SelfService/cgi/selfservice.cgi
@@ -6,7 +6,8 @@ use subs qw(do_template);
use CGI;
use CGI::Carp qw(fatalsToBrowser);
use Text::Template;
-use FS::SelfService qw(login customer_info invoice);
+use FS::SelfService qw( login customer_info invoice payment_info
+ process_payment );
$template_dir = '.';
@@ -53,7 +54,8 @@ if ( $cgi->param('session') eq 'login' ) {
$session_id = $cgi->param('session');
-$cgi->param('action') =~ /^(myaccount|view_invoice)$/
+$cgi->param('action') =~
+ /^(myaccount|view_invoice|make_payment|payment_results)$/
or die "unknown action ". $cgi->param('action');
my $action = $1;
@@ -68,6 +70,7 @@ if ( $result->{error} eq "Can't resume session" ) { #ick
#warn $result->{'open_invoices'};
#warn scalar(@{$result->{'open_invoices'}});
+warn "processing template $action\n";
do_template($action, {
'session_id' => $session_id,
%{$result}
@@ -88,6 +91,82 @@ sub view_invoice {
}
+sub make_payment {
+ payment_info( 'session_id' => $session_id );
+}
+
+sub payment_results {
+
+ use Business::CreditCard;
+
+ $cgi->param('amount') =~ /^\s*(\d+(\.\d{2})?)\s*$/
+ or die "illegal amount"; #!!!
+ my $amount = $1;
+
+ my $payinfo = $cgi->param('payinfo');
+ $payinfo =~ s/\D//g;
+ $payinfo =~ /^(\d{13,16})$/
+ #or $error ||= $init_data->{msgcat}{invalid_card}; #. $self->payinfo;
+ or die "illegal card"; #!!!
+ $payinfo = $1;
+ validate($payinfo)
+ #or $error ||= $init_data->{msgcat}{invalid_card}; #. $self->payinfo;
+ or die "invalid card"; #!!!
+ cardtype($payinfo) eq $cgi->param('card_type')
+ #or $error ||= $init_data->{msgcat}{not_a}. $cgi->param('CARD_type');
+ or die "not a ". $cgi->param('card_type');
+
+ $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') =~ /^(.{2})$/ or die "illegal state";
+ my $state = $1;
+
+ $cgi->param('zip') =~ /^(.{0,10})$/ or die "illegal zip";
+ my $zip = $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,
+ 'amount' => $amount,
+ 'payinfo' => $payinfo,
+ 'month' => $month,
+ 'year' => $year,
+ 'payname' => $payname,
+ 'address1' => $address1,
+ 'address2' => $address2,
+ 'city' => $city,
+ 'state' => $state,
+ 'zip' => $zip,
+ 'save' => $save,
+ 'auto' => $auto,
+ 'paybatch' => $paybatch,
+ );
+
+}
+
#--
sub do_template {
@@ -95,7 +174,7 @@ sub do_template {
my $fill_in = shift;
$cgi->delete_all();
- $fill_in->{'self_url'} = $cgi->self_url;
+ $fill_in->{'selfurl'} = $cgi->self_url;
my $template = new Text::Template( TYPE => 'FILE',
SOURCE => "$template_dir/$name.html",
diff --git a/fs_selfservice/FS-SelfService/cgi/view_invoice.html b/fs_selfservice/FS-SelfService/cgi/view_invoice.html
index 33388de99..d2b012b5d 100644
--- a/fs_selfservice/FS-SelfService/cgi/view_invoice.html
+++ b/fs_selfservice/FS-SelfService/cgi/view_invoice.html
@@ -3,7 +3,7 @@
<%= $url = "$selfurl?session=$session_id;action="; ''; %>
<TABLE BORDER=0 CELLPADDING=4><TR><TD VALIGN="top" HEIGHT=384 BGCOLOR="#dddddd">
<A HREF="<%= $url %>myaccount">MyAccount</A><BR>
-<A HREF="<%= $url %>other">SomethingElse</A><BR>
+<!-- <A HREF="<%= $url %>other">SomethingElse</A><BR> -->
</TD><TD VALIGN="top">
<A HREF="<%= $url %>myaccount"><-- back to MyAccount</A><BR><BR>
@@ -14,7 +14,7 @@
</TD></TR></TABLE>
<HR>
-<FONT SIZE="-2">small text</FONT>
+<FONT SIZE="-2">powered by <a href="http://www.sisd.com/freeside">freeside</a></FONT>
</BODY></HTML>
diff --git a/fs_selfservice/FS-SelfService/freeside-selfservice-clientd b/fs_selfservice/FS-SelfService/freeside-selfservice-clientd
index 0c25c3407..925bce6d2 100644
--- a/fs_selfservice/FS-SelfService/freeside-selfservice-clientd
+++ b/fs_selfservice/FS-SelfService/freeside-selfservice-clientd
@@ -5,7 +5,7 @@
# This is run REMOTELY over ssh by freeside-selfservice-server
use strict;
-use subs qw(spawn logmsg);
+use subs qw(spawn logmsg lock_write unlock_write);
use Fcntl qw(:flock);
use POSIX qw(:sys_wait_h);
use Socket;
@@ -14,16 +14,20 @@ use IO::Handle qw(_IONBF);
use IO::Select;
use IO::File;
-STDOUT->setbuf('');
+#STDOUT->setbuf('');
+
+my $tag = scalar(@ARGV) ? '.'.shift : '';
use vars qw( $Debug );
-$Debug = 3; #2 will turn on child logging, 3 will log packet contents,
+$Debug = 2; #2 will turn on child logging, 3 will log packet contents,
#including potentially compromising information
-my $socket = "/usr/local/freeside/selfservice_socket";
+my $socket = "/usr/local/freeside/selfservice_socket$tag";
my $pid_file = "$socket.pid";
-my $log_file = "/usr/local/freeside/selfservice.log";
+my $log_file = "/usr/local/freeside/selfservice$tag.log";
+
+my $lock_file = "/usr/local/freeside/selfservice$tag.writelock";
#my $me = '[client]';
@@ -35,6 +39,9 @@ $SIG{__WARN__} = \&_logmsg;
#warn "$me Reading init data\n" if $Debug;
#my $signup_init =
+warn "Creating $lock_file\n" if $Debug;
+open(LOCKFILE,">$lock_file") or die "can't open $lock_file: $!";
+
warn "Creating $socket\n" if $Debug;
my $uaddr = sockaddr_un($socket);
my $proto = getprotobyname('tcp');
@@ -138,14 +145,22 @@ while (1) {
#handle some commands weirdly?
$packet->{_token}=$$;
- warn "[child-$$] sending packet to remote server" if $Debug > 1;
- flock(STDOUT, LOCK_EX) or die "FATAL: can't lock write stream: $!";
+ warn "[child-$$] locking write stream\n" if $Debug > 1;
+ lock_write;
+
+ warn "[child-$$] sending packet to remote server\n" if $Debug > 1;
nstore_fd($packet, \*STDOUT) or die "FATAL: can't send response: $!";
+
+ warn "[child-$$] flushing write stream\n" if $Debug > 1;
STDOUT->flush or die "FATAL: can't flush: $!";
- flock(STDOUT, LOCK_UN) or die "FATAL: can't release write lock: $!";
+
+ warn "[child-$$] releasing write lock\n" if $Debug > 1;
+ unlock_write;
+
+ warn "[child-$$] closing write stream\n" if $Debug > 1;
close STDOUT or die "FATAL: can't close write stream: $!"; #??!
- warn "[child-$$] waiting for response from parent" if $Debug > 1;
+ warn "[child-$$] waiting for response from parent\n" if $Debug > 1;
my $w = new IO::Select;
$w->add(\*STDIN);
until ( $w->can_read ) {
@@ -224,3 +239,17 @@ sub _logmsg {
flock($log, LOCK_UN);
close $log;
}
+
+sub lock_write {
+ #broken on freebsd?
+ #flock(STDOUT, LOCK_EX) or die "FATAL: can't lock write stream: $!";
+
+ flock(LOCKFILE, LOCK_EX) or die "FATAL: can't lock $lock_file: $!";
+}
+
+sub unlock_write {
+ #broken on freebsd?
+ #flock(STDOUT, LOCK_UN) or die "FATAL: can't release write lock: $!";
+
+ flock(LOCKFILE, LOCK_UN) or die "FATAL: can't unlock $lock_file: $!";
+}