19 digit visa and discover cards
[freeside.git] / fs_selfservice / FS-SelfService / cgi / agent.cgi
1 #!/usr/bin/perl -T
2 #!/usr/bin/perl -Tw
3
4 #some false laziness w/selfservice.cgi
5
6 use strict;
7 use vars qw($DEBUG $me $cgi $session_id $form_max $template_dir);
8 use subs qw(do_template);
9 use CGI;
10 use CGI::Carp qw(fatalsToBrowser);
11 use Business::CreditCard;
12 use Text::Template;
13 #use HTML::Entities;
14 use FS::SelfService qw( agent_login agent_logout agent_info
15                         agent_list_customers
16                         signup_info new_customer
17                         customer_info list_pkgs order_pkg
18                         part_svc_info provision_acct provision_external
19                         unprovision_svc
20                       );
21
22 $DEBUG = 0;
23 $me = 'agent.cgi:';
24
25 $template_dir = '.';
26
27 $form_max = 255;
28
29 warn "$me starting\n" if $DEBUG;
30
31 warn "$me initializing CGI\n" if $DEBUG;
32 $cgi = new CGI;
33
34 unless ( defined $cgi->param('session') ) {
35   warn "$me no session defined, sending login page\n" if $DEBUG;
36   do_template('agent_login',{});
37   exit;
38 }
39
40 if ( $cgi->param('session') eq 'login' ) {
41
42   warn "$me processing login\n" if $DEBUG;
43
44   $cgi->param('username') =~ /^\s*([a-z0-9_\-\.\&]{0,$form_max})\s*$/i
45     or die "illegal username";
46   my $username = $1;
47
48   $cgi->param('password') =~ /^(.{0,$form_max})$/
49     or die "illegal password";
50   my $password = $1;
51
52   my $rv = agent_login(
53     'username' => $username,
54     'password' => $password,
55   );
56   if ( $rv->{error} ) {
57     do_template('agent_login', {
58       'error'    => $rv->{error},
59       'username' => $username,
60     } );
61     exit;
62   } else {
63     $cgi->param('session' => $rv->{session_id} );
64     $cgi->param('action'  => 'agent_main' );
65   }
66 }
67
68 $session_id = $cgi->param('session');
69
70 warn "$me checking action\n" if $DEBUG;
71 $cgi->param('action') =~
72    /^(agent_main|signup|process_signup|list_customers|view_customer|agent_provision|provision_svc|process_svc_acct|process_svc_external|delete_svc|agent_order_pkg|process_order_pkg|logout)$/
73   or die "unknown action ". $cgi->param('action');
74 my $action = $1;
75
76 warn "$me running $action\n" if $DEBUG;
77 my $result = eval "&$action();";
78 die $@ if $@;
79
80 if ( $result->{error} eq "Can't resume session" ) { #ick
81   do_template('agent_login',{});
82   exit;
83 }
84
85 warn "$me processing template $action\n" if $DEBUG;
86 do_template($action, {
87   'session_id' => $session_id,
88   %{$result}
89 });
90 warn "$me done processing template $action\n" if $DEBUG;
91
92 #-- 
93
94 sub logout {
95   $action = 'agent_logout';
96   agent_logout( 'session_id' => $session_id );
97 }
98
99 sub agent_main { agent_info( 'session_id' => $session_id ); }
100
101 sub signup { signup_info( 'session_id' => $session_id ); }
102
103 sub process_signup {
104
105   my $init_data = signup_info( 'session_id' => $session_id );
106   if ( $init_data->{'error'} ) {
107     if ( $init_data->{'error'} eq "Can't resume session" ) { #ick
108       do_template('agent_login',{});
109       exit;
110     } else { #?
111       die $init_data->{'error'};
112     }
113   }
114
115   my $error = '';
116
117   #false laziness w/signup.cgi, identical except for agentnum vs session_id
118   my $payby = $cgi->param('payby');
119   if ( $payby eq 'CHEK' || $payby eq 'DCHK' ) {
120     #$payinfo = join('@', map { $cgi->param( $payby. "_payinfo$_" ) } (1,2) );
121     $cgi->param('payinfo' => $cgi->param($payby. '_payinfo1'). '@'. 
122                              $cgi->param($payby. '_payinfo2')
123                );
124   } else {
125     $cgi->param('payinfo' => $cgi->param( $payby. '_payinfo' ) );
126   }
127   $cgi->param('paydate' => $cgi->param( $payby. '_month' ). '-'.
128                            $cgi->param( $payby. '_year' )
129              );
130   $cgi->param('payname' => $cgi->param( $payby. '_payname' ) );
131   $cgi->param('paycvv' => defined $cgi->param( $payby. '_paycvv' )
132                             ? $cgi->param( $payby. '_paycvv' )
133                             : ''
134              );
135
136   if ( $cgi->param('invoicing_list') ) {
137     $cgi->param('invoicing_list' => $cgi->param('invoicing_list'). ', POST')
138       if $cgi->param('invoicing_list_POST');
139   } else {
140     $cgi->param('invoicing_list' => 'POST' );
141   }
142
143   if ( $cgi->param('_password') ne $cgi->param('_password2') ) {
144     $error = $init_data->{msgcat}{passwords_dont_match}; #msgcat
145     $cgi->param('_password', '');
146     $cgi->param('_password2', '');
147   }
148
149   if ( $payby =~ /^(CARD|DCRD)$/ && $cgi->param('CARD_type') ) {
150     my $payinfo = $cgi->param('payinfo');
151     $payinfo =~ s/\D//g;
152
153     $payinfo =~ /^(\d{13,19}|\d{8,9})$/
154       or $error ||= $init_data->{msgcat}{invalid_card}; #. $self->payinfo;
155     $payinfo = $1;
156     validate($payinfo)
157       or $error ||= $init_data->{msgcat}{invalid_card}; #. $self->payinfo;
158     cardtype($payinfo) eq $cgi->param('CARD_type')
159       or $error ||= $init_data->{msgcat}{not_a}. $cgi->param('CARD_type');
160   }
161
162   unless ( $error ) {
163     my $rv = new_customer ( {
164       'session_id'       => $session_id,
165       map { $_ => scalar($cgi->param($_)) }
166         qw( last first ss company
167             address1 address2 city county state zip country
168             daytime night fax
169
170             ship_last ship_first ship_company
171             ship_address1 ship_address2 ship_city ship_county ship_state
172               ship_zip ship_country
173             ship_daytime ship_night ship_fax
174
175             payby payinfo paycvv paydate payname invoicing_list
176             referral_custnum promo_code reg_code
177             pkgpart username sec_phrase _password popnum refnum
178           ),
179         grep { /^snarf_/ } $cgi->param
180     } );
181     $error = $rv->{'error'};
182   }
183   #eslaf
184
185   if ( $error ) { 
186     $action = 'signup';
187     my $r = { 
188       $cgi->Vars,
189       %{$init_data},
190       'error' => $error,
191     };
192     #warn join('\n', map "$_ => $r->{$_}", keys %$r )."\n";
193     $r;
194   } else {
195     $action = 'agent_main';
196     my $agent_info = agent_info( 'session_id' => $session_id );
197     $agent_info->{'message'} = 'Signup successful';
198     $agent_info;
199   }
200
201 }
202
203 sub list_customers {
204
205   my $results = 
206     agent_list_customers( 'session_id' => $session_id,
207                           map { $_ => $cgi->param($_) }
208                             grep defined($cgi->param($_)),
209                                  qw(prospect active susp cancel),
210                                  'search',
211                         );
212
213   if ( scalar( @{$results->{'customers'}} ) == 1 ) {
214     $action = 'view_customer';
215     customer_info (
216       'agent_session_id' => $session_id,
217       'custnum'          => $results->{'customers'}[0]{'custnum'},
218     );
219   } else {
220     $results;
221   }
222
223 }
224
225 sub view_customer {
226
227   #my $init_data = signup_info( 'session_id' => $session_id );
228   #if ( $init_data->{'error'} ) {
229   #  if ( $init_data->{'error'} eq "Can't resume session" ) { #ick
230   #    do_template('agent_login',{});
231   #    exit;
232   #  } else { #?
233   #    die $init_data->{'error'};
234   #  }
235   #}
236   #
237   #my $customer_info =
238   customer_info (
239     'agent_session_id' => $session_id,
240     'custnum'          => $cgi->param('custnum'),
241   );
242   #
243   #return {
244   #  ( map { $_ => $init_data->{$_} }
245   #        qw( part_pkg security_phrase svc_acct_pop ),
246   #  ),
247   #  %$customer_info,
248   #};
249 }
250
251 sub agent_order_pkg {
252
253   my $init_data = signup_info( 'session_id' => $session_id );
254   if ( $init_data->{'error'} ) {
255     if ( $init_data->{'error'} eq "Can't resume session" ) { #ick
256       do_template('agent_login',{});
257       exit;
258     } else { #?
259       die $init_data->{'error'};
260     }
261   }
262
263   my $customer_info = customer_info (
264     'agent_session_id' => $session_id,
265     'custnum'          => $cgi->param('custnum'),
266   );
267
268   return {
269     ( map { $_ => $init_data->{$_} }
270           qw( part_pkg security_phrase svc_acct_pop ),
271     ),
272     %$customer_info,
273   };
274
275 }
276
277 sub agent_provision {
278   my $result = list_pkgs(
279     'agent_session_id' => $session_id,
280     'custnum'          => $cgi->param('custnum'),
281   );
282   die $result->{'error'} if exists $result->{'error'} && $result->{'error'};
283   $result;
284 }
285
286 sub provision_svc {
287
288   my $result = part_svc_info(
289     'agent_session_id' => $session_id,
290     map { $_ => $cgi->param($_) } qw( pkgnum svcpart custnum ),
291   );
292   die $result->{'error'} if exists $result->{'error'} && $result->{'error'};
293
294   $result->{'svcdb'} =~ /^svc_(.*)$/
295     #or return { 'error' => 'Unknown svcdb '. $result->{'svcdb'} };
296     or die 'Unknown svcdb '. $result->{'svcdb'};
297   $action .= "_$1";
298   $action = "agent_$action";
299
300   $result;
301 }
302
303 sub process_svc_acct {
304
305   my $result = provision_acct (
306     'agent_session_id' => $session_id,
307     map { $_ => $cgi->param($_) } qw(
308       custnum pkgnum svcpart username _password _password2 sec_phrase popnum )
309   );
310
311   if ( exists $result->{'error'} && $result->{'error'} ) { 
312     #warn "$result $result->{'error'}"; 
313     $action = 'provision_svc_acct';
314     $action = "agent_$action";
315     return {
316       $cgi->Vars,
317       %{ part_svc_info( 'agent_session_id' => $session_id,
318                         map { $_ => $cgi->param($_) } qw(pkgnum svcpart custnum)
319                       )
320       },
321       'error' => $result->{'error'},
322     };
323   } else {
324     #warn "$result $result->{'error'}"; 
325     $action = 'agent_provision';
326     return {
327       %{agent_provision()},
328       'message' => $result->{'svc'}. ' setup successfully.',
329     };
330   }
331
332 }
333
334 sub process_svc_external {
335
336   my $result = provision_external (
337     'agent_session_id' => $session_id,
338     map { $_ => $cgi->param($_) } qw( custnum pkgnum svcpart )
339   );
340
341   #warn "$result $result->{'error'}"; 
342   $action = 'agent_provision';
343   return {
344     %{agent_provision()},
345     'message' => $result->{'error'}
346                    ? '<FONT COLOR="#FF0000">'. $result->{'error'}. '</FONT>'
347                    : $result->{'svc'}. ' setup successfully'.
348                      ': serial number '.
349                      sprintf('%010d', $result->{'id'}). '-'. $result->{'title'}
350   };
351
352 }
353
354 sub delete_svc {
355   my $result = unprovision_svc(
356     'agent_session_id' => $session_id,
357     'custnum'          => $cgi->param('custnum'),
358     'svcnum'           => $cgi->param('svcnum'),
359   );
360
361   $action = 'agent_provision';
362
363   return {
364     %{agent_provision()},
365     'message' => $result->{'error'}
366                    ? '<FONT COLOR="#FF0000">'. $result->{'error'}. '</FONT>'
367                    : $result->{'svc'}. ' removed.'
368   };
369
370 }
371
372 sub process_order_pkg {
373
374   my $results = '';
375
376   unless ( length($cgi->param('_password')) ) {
377     my $init_data = signup_info( 'session_id' => $session_id );
378     #die $init_data->{'error'} if $init_data->{'error'};
379     $results = { 'error' => $init_data->{msgcat}{empty_password} };
380   }
381   if ( $cgi->param('_password') ne $cgi->param('_password2') ) {
382     my $init_data = signup_info( 'session_id' => $session_id );
383     $results = { 'error' => $init_data->{msgcat}{passwords_dont_match} };
384     $cgi->param('_password', '');
385     $cgi->param('_password2', '');
386   }
387
388   $results ||= order_pkg (
389     'agent_session_id' => $session_id,
390     map { $_ => $cgi->param($_) }
391         qw( custnum pkgpart username _password _password2 sec_phrase popnum )
392   );
393
394   if ( $results->{'error'} ) {
395     $action = 'agent_order_pkg';
396     return {
397       $cgi->Vars,
398       %{agent_order_pkg()},
399       #'message' => '<FONT COLOR="#FF0000">'. $results->{'error'}. '</FONT>',
400       'error' => '<FONT COLOR="#FF0000">'. $results->{'error'}. '</FONT>',
401     };
402   } else {
403     $action = 'view_customer';
404     #$cgi->delete( grep { $_ ne 'custnum' } $cgi->param );
405     return {
406       %{view_customer()},
407       'message' => 'Package order successful.',
408     };
409   }
410
411 }
412
413 #--
414
415 sub do_template {
416   my $name = shift;
417   my $fill_in = shift;
418   #warn join(' / ', map { "$_=>".$fill_in->{$_} } keys %$fill_in). "\n";
419
420   $cgi->delete_all();
421   $fill_in->{'selfurl'} = $cgi->self_url; #OLD
422   $fill_in->{'self_url'} = $cgi->self_url;
423   $fill_in->{'cgi'} = \$cgi;
424
425   my $template = new Text::Template( TYPE    => 'FILE',
426                                      SOURCE  => "$template_dir/$name.html",
427                                      DELIMITERS => [ '<%=', '%>' ],
428                                      UNTAINT => 1,                    )
429     or die $Text::Template::ERROR;
430
431   local $^W = 0;
432   print $cgi->header( '-expires' => 'now' ),
433         $template->fill_in( PACKAGE => 'FS::SelfService::_agentcgi',
434                             HASH    => $fill_in
435                           );
436 }
437
438 package FS::SelfService::_agentcgi;
439
440 use HTML::Entities;
441 use FS::SelfService qw(regionselector expselect popselector);
442
443 #false laziness w/selfservice.cgi
444 sub include {
445   my $name = shift;
446   my $template = new Text::Template( TYPE   => 'FILE',
447                                      SOURCE => "$main::template_dir/$name.html",
448                                      DELIMITERS => [ '<%=', '%>' ],
449                                      UNTAINT => 1,                   
450                                    )
451     or die $Text::Template::ERROR;
452
453   $template->fill_in( PACKAGE => 'FS::SelfService::_agentcgi',
454                       #HASH    => $fill_in
455                     );
456
457 }
458