diff options
Diffstat (limited to 'fs_selfservice/FS-SelfService')
-rw-r--r-- | fs_selfservice/FS-SelfService/Makefile.PL | 4 | ||||
-rw-r--r-- | fs_selfservice/FS-SelfService/SelfService.pm | 596 | ||||
-rw-r--r-- | fs_selfservice/FS-SelfService/cgi/login.html | 12 | ||||
-rw-r--r-- | fs_selfservice/FS-SelfService/cgi/make_payment.html | 120 | ||||
-rw-r--r-- | fs_selfservice/FS-SelfService/cgi/myaccount.html | 16 | ||||
-rw-r--r-- | fs_selfservice/FS-SelfService/cgi/payment_results.html | 18 | ||||
-rw-r--r-- | fs_selfservice/FS-SelfService/cgi/selfservice.cgi | 85 | ||||
-rw-r--r-- | fs_selfservice/FS-SelfService/cgi/view_invoice.html | 4 | ||||
-rw-r--r-- | fs_selfservice/FS-SelfService/freeside-selfservice-clientd | 47 |
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 Due</TD> + <TD> + <TABLE><TR><TD BGCOLOR="#ffffff"> + $<%=sprintf("%.2f",$balance)%> + </TD></TR></TABLE> + </TD> +</TR> +<TR> + <TD ALIGN="right">Payment 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 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 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 name on card</TD> + <TD><INPUT TYPE="text" SIZE=32 MAXLENGTH=80 NAME="payname" VALUE="<%=$payname%>"></TD> +</TR><TR> + <TD ALIGN="right">Card billing address</TD> + <TD> + <INPUT TYPE="text" SIZE=40 MAXLENGTH=80 NAME="address1" VALUE="<%=$address1%>"> + </TD> +</TR><TR> + <TD ALIGN="right">Address line 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: $!"; +} |