This commit was generated by cvs2svn to compensate for changes in r3921,
[freeside.git] / fs_signup / FS-SignupClient / cgi / signup.cgi
1 #!/usr/bin/perl -T
2 #!/usr/bin/perl -Tw
3 #
4 # $Id: signup.cgi,v 1.54 2004-12-01 18:38:22 ivan Exp $
5
6 use strict;
7 use vars qw( @payby $cgi $locales $packages
8              $pops %pop %popnum2pop
9              $init_data $error
10
11              $last $first $ss $company $address1
12              $address2 $city $state $county
13              $country $zip $daytime $night $fax
14
15              $ship_last $ship_first $ship_ss $ship_company $ship_address1
16              $ship_address2 $ship_city $ship_state $ship_county
17              $ship_country $ship_zip $ship_daytime $ship_night $ship_fax
18
19              $invoicing_list $payby $payinfo
20              $paycvv $paydate $payname $referral_custnum $init_popstate
21              $pkgpart $username $password $password2 $sec_phrase $popnum
22              $agentnum $refnum
23              $ieak_file $ieak_template
24              $signup_html $signup_template
25              $success_html $success_template
26              $decline_html $decline_template
27              $ac $exch $loc
28              $email_name $pkg
29              $self_url
30            );
31 use subs qw( print_form print_okay print_decline
32              success_default decline_default
33            );
34 use CGI;
35 #use CGI::Carp qw(fatalsToBrowser);
36 use Text::Template;
37 use Business::CreditCard;
38 use HTTP::BrowserDetect;
39 use FS::SelfService qw( signup_info new_customer expselect );
40
41 #acceptable payment methods
42 #
43 #@payby = qw( CARD BILL COMP );
44 #@payby = qw( CARD BILL );
45 #@payby = qw( CARD );
46 @payby = qw( CARD PREPAY );
47
48 $ieak_file = '/usr/local/freeside/ieak.template';
49 $signup_html = -e 'signup.html'
50                  ? 'signup.html'
51                  : '/usr/local/freeside/signup.html';
52 $success_html = -e 'success.html'
53                   ? 'success.html'
54                   : '/usr/local/freeside/success.html';
55 $decline_html = -e 'decline.html'
56                   ? 'decline.html'
57                   : '/usr/local/freeside/decline.html';
58
59
60 if ( -e $ieak_file ) {
61   my $ieak_txt = Text::Template::_load_text($ieak_file)
62     or die $Text::Template::ERROR;
63   $ieak_txt =~ /^(.*)$/s; #untaint the template source - it's trusted
64   $ieak_txt = $1;
65   $ieak_txt =~ s/\r//g; # don't double \r on old templates
66   $ieak_txt =~ s/\n/\r\n/g;
67   $ieak_template = new Text::Template ( TYPE => 'STRING', SOURCE => $ieak_txt )
68     or die $Text::Template::ERROR;
69 } else {
70   $ieak_template = '';
71 }
72
73 $agentnum = '';
74 if ( -e $signup_html ) {
75   my $signup_txt = Text::Template::_load_text($signup_html)
76     or die $Text::Template::ERROR;
77   $signup_txt =~ /^(.*)$/s; #untaint the template source - it's trusted
78   $signup_txt = $1;
79   $signup_template = new Text::Template ( TYPE => 'STRING',
80                                           SOURCE => $signup_txt,
81                                           DELIMITERS => [ '<%=', '%>' ]
82                                         )
83     or die $Text::Template::ERROR;
84   if ( $signup_txt =~
85          /<\s*INPUT TYPE="?hidden"?\s+NAME="?agentnum"?\s+VALUE="?(\d+)"?\s*>/si
86   ) {
87     $agentnum = $1;
88   }
89 } else {
90   #too much maintenance hassle to keep in this file
91   die "can't find ./signup.html or /usr/local/freeside/signup.html";
92   #$signup_template = new Text::Template ( TYPE => 'STRING',
93   #                                        SOURCE => &signup_default,
94   #                                        DELIMITERS => [ '<%=', '%>' ]
95   #                                      )
96   #  or die $Text::Template::ERROR;
97 }
98
99 if ( -e $success_html ) {
100   my $success_txt = Text::Template::_load_text($success_html)
101     or die $Text::Template::ERROR;
102   $success_txt =~ /^(.*)$/s; #untaint the template source - it's trusted
103   $success_txt = $1;
104   $success_template = new Text::Template ( TYPE => 'STRING',
105                                            SOURCE => $success_txt,
106                                            DELIMITERS => [ '<%=', '%>' ],
107                                          )
108     or die $Text::Template::ERROR;
109 } else {
110   $success_template = new Text::Template ( TYPE => 'STRING',
111                                            SOURCE => &success_default,
112                                            DELIMITERS => [ '<%=', '%>' ],
113                                          )
114     or die $Text::Template::ERROR;
115 }
116
117 if ( -e $decline_html ) {
118   my $decline_txt = Text::Template::_load_text($decline_html)
119     or die $Text::Template::ERROR;
120   $decline_txt =~ /^(.*)$/s; #untaint the template source - it's trusted
121   $decline_txt = $1;
122   $decline_template = new Text::Template ( TYPE => 'STRING',
123                                            SOURCE => $decline_txt,
124                                            DELIMITERS => [ '<%=', '%>' ],
125                                          )
126     or die $Text::Template::ERROR;
127 } else {
128   $decline_template = new Text::Template ( TYPE => 'STRING',
129                                            SOURCE => &decline_default,
130                                            DELIMITERS => [ '<%=', '%>' ],
131                                          )
132     or die $Text::Template::ERROR;
133 }
134
135 $cgi = new CGI;
136
137 $init_data = signup_info( 'promo_code' => $cgi->param('promo_code') );
138 $error = $init_data->{'error'};
139 $locales = $init_data->{'cust_main_county'};
140 $packages = $init_data->{'part_pkg'};
141 $pops = $init_data->{'svc_acct_pop'};
142 @payby = @{$init_data->{'payby'}} if @{$init_data->{'payby'}};
143 $packages = $init_data->{agentnum2part_pkg}{$agentnum} if $agentnum;
144 %pop = ();
145 %popnum2pop = ();
146 foreach (@$pops) {
147   push @{ $pop{ $_->{state} }->{ $_->{ac} } }, $_;
148   $popnum2pop{$_->{popnum}} = $_;
149 }
150
151 if ( defined $cgi->param('magic') ) {
152   if ( $cgi->param('magic') eq 'process' ) {
153
154     if ( $cgi->param('state') =~ /^(\w*)( \(([\w ]+)\))? ?\/ ?(\w+)$/ ) {
155       $state = $1;
156       $county = $3 || '';
157       $country = $4;
158     } elsif ( $cgi->param('state') =~ /^(\w*)$/ ) {
159       $state = $1;
160       $cgi->param('county') =~ /^([\w ]*)$/
161         or die "illegal county: ". $cgi->param('county');
162       $county = $1;
163       $cgi->param('country') =~ /^(\w+)$/
164         or die "illegal country: ". $cgi->param('country');
165       $country = $1;
166     } else {
167       die "illegal state: ". $cgi->param('state');
168     }
169     if ( $cgi->param('ship_state') =~ /^(\w*)( \(([\w ]+)\))? ?\/ ?(\w+)$/ ) {
170       $ship_state = $1;
171       $ship_county = $3 || '';
172       $ship_country = $4;
173     } elsif ( $cgi->param('ship_state') =~ /^(\w*)$/ ) {
174       $ship_state = $1;
175       $cgi->param('ship_county') =~ /^([\w ]*)$/
176         or die "illegal county: ". $cgi->param('ship_county');
177       $ship_county = $1;
178       $cgi->param('ship_country') =~ /^(\w+)$/
179         or die "illegal ship_country: ". $cgi->param('ship_country');
180       $ship_country = $1;
181     #} else {
182     #  die "illegal ship_state: ". $cgi->param('ship_state');
183     }
184
185     $payby = $cgi->param('payby');
186     if ( $payby eq 'CHEK' || $payby eq 'DCHK' ) {
187       #$payinfo = join('@', map { $cgi->param( $payby. "_payinfo$_" ) } (1,2) );
188       $payinfo = $cgi->param($payby. '_payinfo1'). '@'. 
189                  $cgi->param($payby. '_payinfo2');
190     } else {
191       $payinfo = $cgi->param( $payby. '_payinfo' );
192     }
193     $paydate =
194       $cgi->param( $payby. '_month' ). '-'. $cgi->param( $payby. '_year' );
195     $payname = $cgi->param( $payby. '_payname' );
196     $paycvv = defined $cgi->param( $payby. '_paycvv' )
197                 ? $cgi->param( $payby. '_paycvv' )
198                 : '';
199
200     if ( $invoicing_list = $cgi->param('invoicing_list') ) {
201       $invoicing_list .= ', POST' if $cgi->param('invoicing_list_POST');
202     } else {
203       $invoicing_list = 'POST';
204     }
205
206     $error = '';
207
208     $last             = $cgi->param('last');
209     $first            = $cgi->param('first');
210     $ss               = $cgi->param('ss');
211     $company          = $cgi->param('company');
212     $address1         = $cgi->param('address1');
213     $address2         = $cgi->param('address2');
214     $city             = $cgi->param('city');
215     #$county,
216     #$state,
217     $zip              = $cgi->param('zip');
218     #$country,
219     $daytime          = $cgi->param('daytime');
220     $night            = $cgi->param('night');
221     $fax              = $cgi->param('fax');
222
223     $ship_last        = $cgi->param('ship_last');
224     $ship_first       = $cgi->param('ship_first');
225     $ship_ss          = $cgi->param('ship_ss');
226     $ship_company     = $cgi->param('ship_company');
227     $ship_address1    = $cgi->param('ship_address1');
228     $ship_address2    = $cgi->param('ship_address2');
229     $ship_city        = $cgi->param('ship_city');
230     #$ship_county,
231     #$ship_state,
232     $ship_zip         = $cgi->param('ship_zip');
233     #$ship_country,
234     $ship_daytime     = $cgi->param('ship_daytime');
235     $ship_night       = $cgi->param('ship_night');
236     $ship_fax         = $cgi->param('ship_fax');
237
238     #$payby,
239     #$payinfo,
240     #$paydate,
241     #$payname,
242     #$invoicing_list,
243     $referral_custnum = $cgi->param('ref');
244     $pkgpart          = $cgi->param('pkgpart');
245     $username         = $cgi->param('username');
246     $sec_phrase       = $cgi->param('sec_phrase');
247     $password         = $cgi->param('_password');
248     $popnum           = $cgi->param('popnum');
249     #$agentnum, #         = $cgi->param('agentnum'),
250     $agentnum         ||= $cgi->param('agentnum');
251     $init_popstate    = $cgi->param('init_popstate');
252     $refnum           = $cgi->param('refnum');
253
254     if ( $cgi->param('_password') ne $cgi->param('_password2') ) {
255       $error = $init_data->{msgcat}{passwords_dont_match}; #msgcat
256       $password  = '';
257       $password2 = '';
258     } else {
259       $password2 = $cgi->param('_password2');
260
261       if ( $payby =~ /^(CARD|DCRD)$/ && $cgi->param('CARD_type') ) {
262         $payinfo =~ s/\D//g;
263
264         $payinfo =~ /^(\d{13,16})$/
265           or $error ||= $init_data->{msgcat}{invalid_card}; #. $self->payinfo;
266         $payinfo = $1;
267         validate($payinfo)
268           or $error ||= $init_data->{msgcat}{invalid_card}; #. $self->payinfo;
269         cardtype($payinfo) eq $cgi->param('CARD_type')
270           or $error ||= $init_data->{msgcat}{not_a}. $cgi->param('CARD_type');
271       }
272
273       unless ( $error ) {
274
275         my $r = new_customer ( {
276           'last'             => $last,
277           'first'            => $first,
278           'ss'               => $ss,
279           'company'          => $company,
280           'address1'         => $address1,
281           'address2'         => $address2,
282           'city'             => $city,
283           'county'           => $county,
284           'state'            => $state,
285           'zip'              => $zip,
286           'country'          => $country,
287           'daytime'          => $daytime,
288           'night'            => $night,
289           'fax'              => $fax,
290           'ship_last'        => $ship_last,
291           'ship_first'       => $ship_first,
292           'ship_company'     => $ship_company,
293           'ship_address1'    => $ship_address1,
294           'ship_address2'    => $ship_address2,
295           'ship_city'        => $ship_city,
296           'ship_county'      => $ship_county,
297           'ship_state'       => $ship_state,
298           'ship_zip'         => $ship_zip,
299           'ship_country'     => $ship_country,
300           'ship_daytime'     => $ship_daytime,
301           'ship_night'       => $ship_night,
302           'ship_fax'         => $ship_fax,
303           'payby'            => $payby,
304           'payinfo'          => $payinfo,
305           'paycvv'           => $paycvv,
306           'paydate'          => $paydate,
307           'payname'          => $payname,
308           'invoicing_list'   => $invoicing_list,
309           'referral_custnum' => $referral_custnum,
310           'promo_code'       => $cgi->param('promo_code'),
311           'pkgpart'          => $pkgpart,
312           'username'         => $username,
313           'sec_phrase'       => $sec_phrase,
314           '_password'        => $password,
315           'popnum'           => $popnum,
316           'agentnum'         => $agentnum,
317           'refnum'           => $refnum,
318           map { $_ => $cgi->param($_) } grep { /^snarf_/ } $cgi->param
319         } );
320         $error ||= $r->{'error'};
321
322       }
323
324     }
325     
326     if ( $error eq '_decline' ) {
327       print_decline();
328     } elsif ( $error ) {
329       #fudge the snarf info
330       no strict 'refs';
331       ${$_} = $cgi->param($_) foreach grep { /^snarf_/ } $cgi->param;
332       print_form();
333     } else {
334       print_okay();
335     }
336
337   } else {
338     die "unrecognized magic: ". $cgi->param('magic');
339   }
340 } else {
341   #$error = '';
342   $last = '';
343   $first = '';
344   $ss = '';
345   $company = '';
346   $address1 = '';
347   $address2 = '';
348   $city = '';
349   $state = $init_data->{statedefault};
350   $county = '';
351   $country = $init_data->{countrydefault};
352   $zip = '';
353   $daytime = '';
354   $night = '';
355   $fax = '';
356   $ship_last = '';
357   $ship_first = '';
358   $ship_company = '';
359   $ship_address1 = '';
360   $ship_address2 = '';
361   $ship_city = '';
362   $ship_state = $init_data->{statedefault};
363   $ship_county = '';
364   $ship_country = $init_data->{countrydefault};
365   $ship_zip = '';
366   $ship_daytime = '';
367   $ship_night = '';
368   $ship_fax = '';
369   $invoicing_list = '';
370   $payby = '';
371   $payinfo = '';
372   $paydate = '';
373   $payname = '';
374   $pkgpart = '';
375   $username = '';
376   $password = '';
377   $password2 = '';
378   $sec_phrase = '';
379   $popnum = '';
380   $referral_custnum = $cgi->param('ref') || '';
381   $init_popstate = $cgi->param('init_popstate') || '';
382   $refnum = $init_data->{'refnum'};
383   print_form;
384 }
385
386 sub print_form {
387
388   $cgi->delete('ref');
389   $cgi->delete('init_popstate');
390   $self_url = $cgi->self_url;
391
392   $error = "Error: $error" if $error;
393
394   print $cgi->header( '-expires' => 'now' ),
395         $signup_template->fill_in();
396
397 }
398
399 sub print_decline {
400   print $cgi->header( '-expires' => 'now' ),
401         $decline_template->fill_in();
402 }
403
404 sub print_okay {
405   my $user_agent = new HTTP::BrowserDetect $ENV{HTTP_USER_AGENT};
406
407   $cgi->param('username') =~ /^(.+)$/
408     or die "fatal: invalid username got past FS::SelfService::new_customer";
409   my $username = $1;
410   $cgi->param('_password') =~ /^(.+)$/
411     or die "fatal: invalid password got past FS::SelfService::new_customer";
412   my $password = $1;
413   ( $cgi->param('first'). ' '. $cgi->param('last') ) =~ /^(.*)$/
414     or die "fatal: invalid email_name got past FS::SelfService::new_customer";
415   $email_name = $1; #global for template
416
417   my $pop = $popnum2pop{$cgi->param('popnum')};
418     #or die "fatal: invalid popnum got past FS::SelfService::new_customer";
419   if ( $pop ) {
420     ( $ac, $exch, $loc ) = ( $pop->{'ac'}, $pop->{'exch'}, $pop->{'loc'} );
421   } else {
422     ( $ac, $exch, $loc ) = ( '', '', ''); #presumably you're not using them.
423   }
424
425   #global for template
426   $pkg = ( grep { $_->{'pkgpart'} eq $pkgpart } @$packages )[0]->{'pkg'};
427
428   if ( $ieak_template && $user_agent->windows && $user_agent->ie ) {
429     #send an IEAK config
430     print $cgi->header('application/x-Internet-signup'),
431           $ieak_template->fill_in();
432   } else { #send a simple confirmation
433     print $cgi->header( '-expires' => 'now' ),
434           $success_template->fill_in();
435   }
436 }
437
438 sub success_default { #html to use if you don't specify a success file
439   <<'END';
440 <HTML><HEAD><TITLE>Signup successful</TITLE></HEAD>
441 <BODY BGCOLOR="#e8e8e8"><FONT SIZE=7>Signup successful</FONT><BR><BR>
442 Thanks for signing up!
443 <BR><BR>
444 Signup information for <%= $email_name %>:
445 <BR><BR>
446 Username: <%= $username %><BR>
447 Password: <%= $password %><BR>
448 Access number: (<%= $ac %>) / <%= $exch %> - <%= $local %><BR>
449 Package: <%= $pkg %><BR>
450 </BODY></HTML>
451 END
452 }
453
454 sub decline_default { #html to use if there is a decline
455   <<'END';
456 <HTML><HEAD><TITLE>Processing error</TITLE></HEAD>
457 <BODY BGCOLOR="#e8e8e8"><FONT SIZE=7>Processing error</FONT><BR><BR>
458 There has been an error processing your account.  Please contact customer
459 support.
460 </BODY></HTML>
461 END
462 }
463
464 # subs for the templates...
465
466 =item regionselector SELECTED_COUNTY, SELECTED_STATE, SELECTED_COUNTRY, PREFIX, ONCHANGE
467
468 =cut
469
470 sub regionselector {
471   my ( $selected_county, $selected_state, $selected_country,
472        $prefix, $onchange ) = @_;
473   signup_info() unless $init_data;
474   FS::SelfService::regionselector({
475     selected_county  => $selected_county,
476     selected_state   => $selected_state,
477     selected_country => $selected_country,
478     prefix           => $prefix,
479     onchange         => $onchange,
480     default_country  => $init_data->{countrydefault},
481     locales          => $init_data->{cust_main_county},
482   });
483     #default_state    => $init_data->{statedefault},
484 }
485
486 =item popselector 
487
488 =cut
489
490 sub popselector {
491   my( $popnum ) = @_;
492   signup_info() unless $init_data;
493   FS::SelfService::popselector({
494     popnum => $popnum,
495     pops   => $init_data->{svc_acct_pop},
496   });
497     #popac =>
498     #acstate =>
499 }
500