big update for customer self-service: add provisioning/unprovisioning of purchased...
[freeside.git] / fs_selfservice / FS-SelfService / cgi / selfservice.cgi
1 #!/usr/bin/perl -Tw
2
3 use strict;
4 use vars qw($cgi $session_id $form_max $template_dir);
5 use subs qw(do_template);
6 use CGI;
7 use CGI::Carp qw(fatalsToBrowser);
8 use Text::Template;
9 use FS::SelfService qw( login customer_info invoice
10                         payment_info process_payment 
11                         list_pkgs
12                         part_svc_info provision_acct unprovision_svc
13                       );
14
15 $template_dir = '.';
16
17 $form_max = 255;
18
19 $cgi = new CGI;
20
21 unless ( defined $cgi->param('session') ) {
22   do_template('login',{});
23   exit;
24 }
25
26 if ( $cgi->param('session') eq 'login' ) {
27
28   $cgi->param('username') =~ /^\s*([a-z0-9_\-\.\&]{0,$form_max})\s*$/i
29     or die "illegal username";
30   my $username = $1;
31
32   $cgi->param('domain') =~ /^\s*([\w\-\.]{0,$form_max})\s*$/
33     or die "illegal domain";
34   my $domain = $1;
35
36   $cgi->param('password') =~ /^(.{0,$form_max})$/
37     or die "illegal password";
38   my $password = $1;
39
40   my $rv = login(
41     'username' => $username,
42     'domain'   => $domain,
43     'password' => $password,
44   );
45   if ( $rv->{error} ) {
46     do_template('login', {
47       'error'    => $rv->{error},
48       'username' => $username,
49       'domain'   => $domain,
50     } );
51     exit;
52   } else {
53     $cgi->param('session' => $rv->{session_id} );
54     $cgi->param('action'  => 'myaccount' );
55   }
56 }
57
58 $session_id = $cgi->param('session');
59
60 #order|pw_list XXX ???
61 $cgi->param('action') =~
62     /^(myaccount|view_invoice|make_payment|payment_results|logout|change_bill|change_ship|provision|provision_svc|process_svc_acct|delete_svc)$/
63   or die "unknown action ". $cgi->param('action');
64 my $action = $1;
65
66 my $result = eval "&$action();";
67 die $@ if $@;
68
69 if ( $result->{error} eq "Can't resume session" ) { #ick
70   do_template('login',{});
71   exit;
72 }
73
74 #warn $result->{'open_invoices'};
75 #warn scalar(@{$result->{'open_invoices'}});
76
77 warn "processing template $action\n";
78 do_template($action, {
79   'session_id' => $session_id,
80   %{$result}
81 });
82
83 #--
84
85 sub myaccount { customer_info( 'session_id' => $session_id ); }
86
87 sub view_invoice {
88
89   $cgi->param('invnum') =~ /^(\d+)$/ or die "illegal invnum";
90   my $invnum = $1;
91
92   invoice( 'session_id' => $session_id,
93            'invnum'     => $invnum,
94          );
95
96 }
97
98 sub make_payment {
99   payment_info( 'session_id' => $session_id );
100 }
101
102 sub payment_results {
103
104   use Business::CreditCard;
105
106   $cgi->param('amount') =~ /^\s*(\d+(\.\d{2})?)\s*$/
107     or die "illegal amount"; #!!!
108   my $amount = $1;
109
110   my $payinfo = $cgi->param('payinfo');
111   $payinfo =~ s/\D//g;
112   $payinfo =~ /^(\d{13,16})$/
113     #or $error ||= $init_data->{msgcat}{invalid_card}; #. $self->payinfo;
114     or die "illegal card"; #!!!
115   $payinfo = $1;
116   validate($payinfo)
117     #or $error ||= $init_data->{msgcat}{invalid_card}; #. $self->payinfo;
118     or die "invalid card"; #!!!
119   cardtype($payinfo) eq $cgi->param('card_type')
120     #or $error ||= $init_data->{msgcat}{not_a}. $cgi->param('CARD_type');
121     or die "not a ". $cgi->param('card_type');
122
123   $cgi->param('month') =~ /^(\d{2})$/ or die "illegal month";
124   my $month = $1;
125   $cgi->param('year') =~ /^(\d{4})$/ or die "illegal year";
126   my $year = $1;
127
128   $cgi->param('payname') =~ /^(.{0,80})$/ or die "illegal payname";
129   my $payname = $1;
130
131   $cgi->param('address1') =~ /^(.{0,80})$/ or die "illegal address1";
132   my $address1 = $1;
133
134   $cgi->param('address2') =~ /^(.{0,80})$/ or die "illegal address2";
135   my $address2 = $1;
136
137   $cgi->param('city') =~ /^(.{0,80})$/ or die "illegal city";
138   my $city = $1;
139
140   $cgi->param('state') =~ /^(.{2})$/ or die "illegal state";
141   my $state = $1;
142
143   $cgi->param('zip') =~ /^(.{0,10})$/ or die "illegal zip";
144   my $zip = $1;
145
146   my $save = 0;
147   $save = 1 if $cgi->param('save');
148
149   my $auto = 0;
150   $auto = 1 if $cgi->param('auto');
151
152   $cgi->param('paybatch') =~ /^([\w\-\.]+)$/ or die "illegal paybatch";
153   my $paybatch = $1;
154
155   process_payment(
156     'session_id' => $session_id,
157     'amount'     => $amount,
158     'payinfo'    => $payinfo,
159     'month'      => $month,
160     'year'       => $year,
161     'payname'    => $payname,
162     'address1'   => $address1,
163     'address2'   => $address2,
164     'city'       => $city,
165     'state'      => $state,
166     'zip'        => $zip,
167     'save'       => $save,
168     'auto'       => $auto,
169     'paybatch'   => $paybatch,
170   );
171
172 }
173
174 sub logout {
175   FS::SelfService::logout( 'session_id' => $session_id );
176 }
177
178 sub provision {
179   list_pkgs( 'session_id' => $session_id );
180 }
181
182 sub provision_svc {
183
184   my $result = part_svc_info(
185     'session_id' => $session_id,
186     map { $_ => $cgi->param($_) } qw( pkgnum svcpart ),
187   );
188   die $result->{'error'} if exists $result->{'error'} && $result->{'error'};
189
190   $result->{'svcdb'} =~ /^svc_(.*)$/
191     #or return { 'error' => 'Unknown svcdb '. $result->{'svcdb'} };
192     or die 'Unknown svcdb '. $result->{'svcdb'};
193   $action .= "_$1";
194
195   $result;
196 }
197
198 sub process_svc_acct {
199
200   my $result = provision_acct (
201     'session_id' => $session_id,
202     map { $_ => $cgi->param($_) } qw(
203       pkgnum svcpart username _password _password2 sec_phrase popnum )
204   );
205
206   if ( exists $result->{'error'} && $result->{'error'} ) { 
207     warn "$result $result->{'error'}"; 
208     $action = 'provision_svc_acct';
209     return {
210       $cgi->Vars,
211       %{ part_svc_info( 'session_id' => $session_id,
212                         map { $_ => $cgi->param($_) } qw( pkgnum svcpart )
213                       )
214       },
215       'error' => $result->{'error'},
216     };
217   } else {
218     warn "$result $result->{'error'}"; 
219     return $result;
220   }
221
222 }
223
224 sub delete_svc {
225   unprovision_svc(
226     'session_id' => $session_id,
227     'svcnum'     => $cgi->param('svcnum'),
228   );
229 }
230
231 #--
232
233 sub do_template {
234   my $name = shift;
235   my $fill_in = shift;
236
237   $cgi->delete_all();
238   $fill_in->{'selfurl'} = $cgi->self_url;
239   $fill_in->{'cgi'} = \$cgi;
240
241   my $template = new Text::Template( TYPE    => 'FILE',
242                                      SOURCE  => "$template_dir/$name.html",
243                                      DELIMITERS => [ '<%=', '%>' ],
244                                      UNTAINT => 1,                    )
245     or die $Text::Template::ERROR;
246
247   print $cgi->header( '-expires' => 'now' ),
248         $template->fill_in( PACKAGE => 'FS::SelfService::_selfservicecgi',
249                             HASH    => $fill_in
250                           );
251 }
252
253 #*FS::SelfService::_selfservicecgi::include = \&Text::Template::fill_in_file;
254
255 package FS::SelfService::_selfservicecgi;
256
257 #use FS::SelfService qw(regionselector expselect popselector);
258 use FS::SelfService qw(popselector);
259
260 sub include {
261   my $name = shift;
262   my $template = new Text::Template( TYPE   => 'FILE',
263                                      SOURCE => "$main::template_dir/$name.html",
264                                      DELIMITERS => [ '<%=', '%>' ],
265                                      UNTAINT => 1,                   
266                                    )
267     or die $Text::Template::ERROR;
268
269   $template->fill_in();
270
271 }
272