summaryrefslogtreecommitdiff
path: root/FS
diff options
context:
space:
mode:
authorivan <ivan>2003-05-19 12:00:45 +0000
committerivan <ivan>2003-05-19 12:00:45 +0000
commitfd9138f66cf7f3ab9557e0beebb4e2657a59e34c (patch)
tree255dab5a84bec7285dbde2205df559d9bf97431f /FS
parentf0afbc011e7b909a2e6ac54039c975710e76f341 (diff)
maintenance:
- add FS::Misc with send_email subroutine, remove all duplicate code from various modules - move the realtime_bop from cust_bill to cust_main & change usage slightly. invnum is no longer required. FS::cust_bill::realtime_bop remains as a wrapper. self-service: - fix some syntax errors, make payment UI (step one) really should be working now
Diffstat (limited to 'FS')
-rw-r--r--FS/FS/ClientAPI/MyAccount.pm16
-rw-r--r--FS/FS/Misc.pm95
-rw-r--r--FS/FS/cust_bill.pm298
-rw-r--r--FS/FS/cust_main.pm216
-rw-r--r--FS/FS/cust_pay.pm50
-rw-r--r--FS/FS/cust_pkg.pm49
-rw-r--r--FS/FS/svc_acct.pm32
-rw-r--r--FS/FS/svc_domain.pm6
-rw-r--r--FS/MANIFEST2
-rw-r--r--FS/t/Misc.t5
10 files changed, 394 insertions, 375 deletions
diff --git a/FS/FS/ClientAPI/MyAccount.pm b/FS/FS/ClientAPI/MyAccount.pm
index c750ada..a64cfb5 100644
--- a/FS/FS/ClientAPI/MyAccount.pm
+++ b/FS/FS/ClientAPI/MyAccount.pm
@@ -167,7 +167,7 @@ sub payment_info {
};
my $_date = time;
- $return{paybatch} = 'webui-MyAccount-$_date-$$-". rand() * 2**32
+ $return{paybatch} = "webui-MyAccount-$_date-$$-". rand() * 2**32;
return { 'error' => '',
%return,
@@ -175,6 +175,20 @@ sub payment_info {
};
+sub make_payment{
+ my $p = shift;
+
+ my $session = $cache->get($p->{'session_id'})
+ or return { 'error' => "Can't resume session" }; #better error message
+
+ my %return;
+
+ my $custnum = $session->{'custnum'};
+
+
+
+}
+
sub invoice {
my $p = shift;
my $session = $cache->get($p->{'session_id'})
diff --git a/FS/FS/Misc.pm b/FS/FS/Misc.pm
new file mode 100644
index 0000000..56dc72e
--- /dev/null
+++ b/FS/FS/Misc.pm
@@ -0,0 +1,95 @@
+package FS::Misc;
+
+use strict;
+use vars qw ( @ISA @EXPORT_OK );
+use Exporter;
+
+@ISA = qw( Exporter );
+@EXPORT_OK = qw( send_email );
+
+=head1 NAME
+
+FS::Misc - Miscellaneous subroutines
+
+=head1 SYNOPSIS
+
+ use FS::Misc qw(send_email);
+
+ send_email();
+
+=head1 DESCRIPTION
+
+Miscellaneous subroutines. This module contains miscellaneous subroutines
+called from multiple other modules. These are not OO or necessarily related,
+but are collected here to elimiate code duplication.
+
+=head1 SUBROUTINES
+
+=over 4
+
+=item send_email OPTION => VALUE ...
+
+Options:
+
+I<from> - (required)
+
+I<to> - (required) comma-separated scalar or arrayref of recipients
+
+I<subject> - (required)
+
+I<content-type> - (optional) MIME type
+
+I<body> - (required) arrayref of body text lines
+
+=cut
+
+use vars qw( $conf );
+use Date::Format;
+use Mail::Header;
+use Mail::Internet 1.44;
+use FS::UID;
+
+FS::UID->install_callback( sub {
+ $conf = new FS::Conf;
+} );
+
+sub send_email {
+ my(%options) = shift;
+
+ $ENV{MAILADDRESS} = $options{'from'};
+ my $to = ref($options{to}) ? join(', ', @{ $options{to} } ) : $options{to};
+ my @header = (
+ 'From: '. $options{'from'},
+ 'To: '. $to,
+ 'Sender: '. $options{'from'},
+ 'Reply-To: '. $options{'from'},
+ 'Date: '. time2str("%a, %d %b %Y %X %z", time),
+ 'Subject: '. $options{'subject'},
+ );
+ push @header, 'Content-Type: '. $options{'content-type'}
+ if exists($options{'content-type'});
+ my $header = new Mail::Header ( \@header );
+
+ my $message = new Mail::Internet (
+ 'Header' => $header,
+ 'Body' => $options{'body'},
+ );
+
+ my $smtpmachine = $conf->config('smtpmachine');
+ $!=0;
+ $message->smtpsend( 'Host' => $smtpmachine )
+ or $message->smtpsend( Host => $smtpmachine, Debug => 1 )
+ or return "can't send email to $to via server $smtpmachine with SMTP: $!";
+}
+
+=head1 BUGS
+
+This package exists.
+
+=head1 SEE ALSO
+
+L<FS::UID>, L<FS::CGI>, L<FS::Record>, the base documentation.
+
+=cut
+
+1;
diff --git a/FS/FS/cust_bill.pm b/FS/FS/cust_bill.pm
index a0634d9..a22f44b 100644
--- a/FS/FS/cust_bill.pm
+++ b/FS/FS/cust_bill.pm
@@ -2,18 +2,12 @@ package FS::cust_bill;
use strict;
use vars qw( @ISA $conf $money_char );
-use vars qw( $lpr $invoice_from $smtpmachine );
-use vars qw( $xaction $E_NoErr );
-use vars qw( $bop_processor $bop_login $bop_password $bop_action @bop_options );
-use vars qw( $ach_processor $ach_login $ach_password $ach_action @ach_options );
use vars qw( $invoice_lines @buf ); #yuck
-use vars qw( $quiet );
use Date::Format;
-use Mail::Internet 1.44;
-use Mail::Header;
use Text::Template;
use FS::UID qw( datasrc );
use FS::Record qw( qsearch qsearchs );
+use FS::Misc qw( send_email );
use FS::cust_main;
use FS::cust_bill_pkg;
use FS::cust_credit;
@@ -26,46 +20,10 @@ use FS::cust_bill_event;
@ISA = qw( FS::Record );
#ask FS::UID to run this stuff for us later
-$FS::UID::callback{'FS::cust_bill'} = sub {
-
+FS::UID->install_callback( sub {
$conf = new FS::Conf;
-
$money_char = $conf->config('money_char') || '$';
-
- $lpr = $conf->config('lpr');
- $invoice_from = $conf->config('invoice_from');
- $smtpmachine = $conf->config('smtpmachine');
-
- ( $bop_processor,$bop_login, $bop_password, $bop_action ) = ( '', '', '', '');
- @bop_options = ();
- ( $ach_processor,$ach_login, $ach_password, $ach_action ) = ( '', '', '', '');
- @ach_options = ();
-
- if ( $conf->exists('business-onlinepayment') ) {
- ( $bop_processor,
- $bop_login,
- $bop_password,
- $bop_action,
- @bop_options
- ) = $conf->config('business-onlinepayment');
- $bop_action ||= 'normal authorization';
- ( $ach_processor, $ach_login, $ach_password, $ach_action, @ach_options ) =
- ( $bop_processor, $bop_login, $bop_password, $bop_action, @bop_options );
- eval "use Business::OnlinePayment";
- }
-
- if ( $conf->exists('business-onlinepayment-ach') ) {
- ( $ach_processor,
- $ach_login,
- $ach_password,
- $ach_action,
- @ach_options
- ) = $conf->config('business-onlinepayment-ach');
- $ach_action ||= 'normal authorization';
- eval "use Business::OnlinePayment";
- }
-
-};
+} );
=head1 NAME
@@ -373,33 +331,20 @@ sub send {
if ( grep { $_ ne 'POST' } @invoicing_list or !@invoicing_list ) { #email
#better to notify this person than silence
- @invoicing_list = ($invoice_from) unless @invoicing_list;
-
- #false laziness w/FS::cust_pay::delete & fs_signup_server && ::realtime_card
- #$ENV{SMTPHOSTS} = $smtpmachine;
- $ENV{MAILADDRESS} = $invoice_from;
- my $header = new Mail::Header ( [
- "From: $invoice_from",
- "To: ". join(', ', grep { $_ ne 'POST' } @invoicing_list ),
- "Sender: $invoice_from",
- "Reply-To: $invoice_from",
- "Date: ". time2str("%a, %d %b %Y %X %z", time),
- "Subject: Invoice",
- ] );
- my $message = new Mail::Internet (
- 'Header' => $header,
- 'Body' => [ @print_text ], #( date)
+ @invoicing_list = ($conf->config('invoice_from')) unless @invoicing_list;
+
+ my $error = send_email(
+ 'from' => $conf->config('invoice_from'),
+ 'to' => [ grep { $_ ne 'POST' } @invoicing_list ],
+ 'subject' => 'Invoice',
+ 'body' => \@print_text,
);
- $!=0;
- $message->smtpsend( Host => $smtpmachine )
- or $message->smtpsend( Host => $smtpmachine, Debug => 1 )
- or return "(customer # ". $self->custnum. ") can't send invoice email".
- " to ". join(', ', grep { $_ ne 'POST' } @invoicing_list ).
- " via server $smtpmachine with SMTP: $!";
+ return "can't send invoice: $error" if $error;
}
if ( grep { $_ eq 'POST' } @invoicing_list ) { #postal
+ my $lpr = $conf->config('lpr');
open(LPR, "|$lpr")
or return "Can't open pipe to $lpr: $!";
print LPR @print_text;
@@ -610,15 +555,7 @@ for supported processors.
sub realtime_card {
my $self = shift;
- $self->realtime_bop(
- 'CC',
- $bop_processor,
- $bop_login,
- $bop_password,
- $bop_action,
- \@bop_options,
- @_
- );
+ $self->realtime_bop( 'CC', @_ );
}
=item realtime_ach
@@ -632,15 +569,7 @@ for supported processors.
sub realtime_ach {
my $self = shift;
- $self->realtime_bop(
- 'ECHECK',
- $ach_processor,
- $ach_login,
- $ach_password,
- $ach_action,
- \@ach_options,
- @_
- );
+ $self->realtime_bop( 'ECHECK', @_ );
}
=item realtime_lec
@@ -654,53 +583,15 @@ for supported processors.
sub realtime_lec {
my $self = shift;
- $self->realtime_bop(
- 'LEC',
- $bop_processor,
- $bop_login,
- $bop_password,
- $bop_action,
- \@bop_options,
- @_
- );
+ $self->realtime_bop( 'LEC', @_ );
}
sub realtime_bop {
- my( $self, $method, $processor, $login, $password, $action, $options ) = @_;
-
- #trim an extraneous blank line
- pop @$options if scalar(@$options) % 2 && $options->[-1] =~ /^\s*$/;
+ my( $self, $method ) = @_;
my $cust_main = $self->cust_main;
my $amount = $self->owed;
- my $address = $cust_main->address1;
- $address .= ", ". $cust_main->address2 if $cust_main->address2;
-
- my($payname, $payfirst, $paylast);
- if ( $cust_main->payname && $method ne 'ECHECK' ) {
- $payname = $cust_main->payname;
- $payname =~ /^\s*([\w \,\.\-\']*)?\s+([\w\,\.\-\']+)\s*$/
- or do {
- #$dbh->rollback if $oldAutoCommit;
- return "Illegal payname $payname";
- };
- ($payfirst, $paylast) = ($1, $2);
- } else {
- $payfirst = $cust_main->getfield('first');
- $paylast = $cust_main->getfield('last');
- $payname = "$payfirst $paylast";
- }
-
- my @invoicing_list = grep { $_ ne 'POST' } $cust_main->invoicing_list;
- if ( $conf->exists('emailinvoiceauto')
- || ( $conf->exists('emailinvoiceonly') && ! @invoicing_list ) ) {
- push @invoicing_list, $cust_main->all_emails;
- }
- my $email = $invoicing_list[0];
-
- my( $action1, $action2 ) = split(/\s*\,\s*/, $action );
-
my $description = 'Internet Services';
if ( $conf->exists('business-onlinepayment-description') ) {
my $dtempl = $conf->config('business-onlinepayment-description');
@@ -714,163 +605,12 @@ sub realtime_bop {
grep { $_->pkgnum } $self->cust_bill_pkg
);
$description = eval qq("$dtempl");
-
}
- my %content;
- if ( $method eq 'CC' ) {
- $content{card_number} = $cust_main->payinfo;
- $cust_main->paydate =~ /^\d{2}(\d{2})[\/\-](\d+)[\/\-]\d+$/;
- $content{expiration} = "$2/$1";
- } elsif ( $method eq 'ECHECK' ) {
- my($account_number,$routing_code) = $cust_main->payinfo;
- ( $content{account_number}, $content{routing_code} ) =
- split('@', $cust_main->payinfo);
- $content{bank_name} = $cust_main->payname;
- } elsif ( $method eq 'LEC' ) {
- $content{phone} = $cust_main->payinfo;
- }
-
- my $transaction =
- new Business::OnlinePayment( $processor, @$options );
- $transaction->content(
- 'type' => $method,
- 'login' => $login,
- 'password' => $password,
- 'action' => $action1,
- 'description' => $description,
- 'amount' => $amount,
- 'invoice_number' => $self->invnum,
- 'customer_id' => $self->custnum,
- 'last_name' => $paylast,
- 'first_name' => $payfirst,
- 'name' => $payname,
- 'address' => $address,
- 'city' => $cust_main->city,
- 'state' => $cust_main->state,
- 'zip' => $cust_main->zip,
- 'country' => $cust_main->country,
- 'referer' => 'http://cleanwhisker.420.am/',
- 'email' => $email,
- 'phone' => $cust_main->daytime || $cust_main->night,
- %content, #after
+ $cust_main->realtime_bop($method, $amount,
+ 'description' => $description,
+ 'invnum' => $self->invnum,
);
- $transaction->submit();
-
- if ( $transaction->is_success() && $action2 ) {
- my $auth = $transaction->authorization;
- my $ordernum = $transaction->can('order_number')
- ? $transaction->order_number
- : '';
-
- #warn "********* $auth ***********\n";
- #warn "********* $ordernum ***********\n";
- my $capture =
- new Business::OnlinePayment( $processor, @$options );
-
- my %capture = (
- %content,
- type => $method,
- action => $action2,
- login => $login,
- password => $password,
- order_number => $ordernum,
- amount => $amount,
- authorization => $auth,
- description => $description,
- );
-
- foreach my $field (qw( authorization_source_code returned_ACI transaction_identifier validation_code
- transaction_sequence_num local_transaction_date
- local_transaction_time AVS_result_code )) {
- $capture{$field} = $transaction->$field() if $transaction->can($field);
- }
-
- $capture->content( %capture );
-
- $capture->submit();
-
- unless ( $capture->is_success ) {
- my $e = "Authorization sucessful but capture failed, invnum #".
- $self->invnum. ': '. $capture->result_code.
- ": ". $capture->error_message;
- warn $e;
- return $e;
- }
-
- }
-
- if ( $transaction->is_success() ) {
-
- my %method2payby = (
- 'CC' => 'CARD',
- 'ECHECK' => 'CHEK',
- 'LEC' => 'LECB',
- );
-
- my $cust_pay = new FS::cust_pay ( {
- 'invnum' => $self->invnum,
- 'paid' => $amount,
- '_date' => '',
- 'payby' => $method2payby{$method},
- 'payinfo' => $cust_main->payinfo,
- 'paybatch' => "$processor:". $transaction->authorization,
- } );
- my $error = $cust_pay->insert;
- if ( $error ) {
- # gah, even with transactions.
- my $e = 'WARNING: Card/ACH debited but database not updated - '.
- 'error applying payment, invnum #' . $self->invnum.
- " ($processor): $error";
- warn $e;
- return $e;
- } else {
- return '';
- }
- #} elsif ( $options{'report_badcard'} ) {
- } else {
-
- my $perror = "$processor error, invnum #". $self->invnum. ': '.
- $transaction->result_code. ": ". $transaction->error_message;
-
- if ( !$quiet && $conf->exists('emaildecline')
- && grep { $_ ne 'POST' } $cust_main->invoicing_list
- ) {
- my @templ = $conf->config('declinetemplate');
- my $template = new Text::Template (
- TYPE => 'ARRAY',
- SOURCE => [ map "$_\n", @templ ],
- ) or return "($perror) can't create template: $Text::Template::ERROR";
- $template->compile()
- or return "($perror) can't compile template: $Text::Template::ERROR";
-
- my $templ_hash = { error => $transaction->error_message };
-
- #false laziness w/FS::cust_pay::delete & fs_signup_server && ::send
- $ENV{MAILADDRESS} = $invoice_from;
- my $header = new Mail::Header ( [
- "From: $invoice_from",
- "To: ". join(', ', grep { $_ ne 'POST' } $cust_main->invoicing_list ),
- "Sender: $invoice_from",
- "Reply-To: $invoice_from",
- "Date: ". time2str("%a, %d %b %Y %X %z", time),
- "Subject: Your payment could not be processed",
- ] );
- my $message = new Mail::Internet (
- 'Header' => $header,
- 'Body' => [ $template->fill_in(HASH => $templ_hash) ],
- );
- $!=0;
- $message->smtpsend( Host => $smtpmachine )
- or $message->smtpsend( Host => $smtpmachine, Debug => 1 )
- or return "($perror) (customer # ". $self->custnum.
- ") can't send card decline email to ".
- join(', ', grep { $_ ne 'POST' } $cust_main->invoicing_list ).
- " via server $smtpmachine with SMTP: $!";
- }
-
- return $perror;
- }
}
diff --git a/FS/FS/cust_main.pm b/FS/FS/cust_main.pm
index 608c5e3..b162622 100644
--- a/FS/FS/cust_main.pm
+++ b/FS/FS/cust_main.pm
@@ -10,6 +10,7 @@ use Date::Format;
use Business::CreditCard;
use FS::UID qw( getotaker dbh );
use FS::Record qw( qsearchs qsearch dbdef );
+use FS::Misc qw( send_email );
use FS::cust_pkg;
use FS::cust_bill;
use FS::cust_bill_pkg;
@@ -1408,6 +1409,221 @@ sub collect {
}
+=item realtime_bop METHOD AMOUNT [ OPTION => VALUE ... ]
+
+
+Runs a realtime credit card, ACH (electronic check) or phone bill transaction
+via a Business::OnlinePayment realtime gateway. See
+L<http://420.am/business-onlinepayment> for supported gateways.
+
+Available methods are: I<CC>, I<ECHECK> and I<LEC>
+
+Available options are: I<description>, I<invnum>, I<quiet>
+
+I<description> is a free-text field passed to the gateway. It defaults to
+"Internet services".
+
+If an I<invnum> is specified, this payment (if sucessful) is applied to the
+specified invoice. If you don't specify an I<invnum> you might want to
+call the B<apply_payments> method.
+
+I<quiet> can be set true to surpress email decline notices.
+
+(moved from cust_bill) (probably should get realtime_{card,ach,lec} here too)
+
+=cut
+
+sub realtime_bop {
+ my( $self, $method, $amount, %options ) = @_;
+ $options{'description'} ||= 'Internet services';
+
+ #pre-requisites
+ die "Real-time processing not enabled\n"
+ unless $conf->exists('business-onlinepayment');
+ eval "use Business::OnlinePayment";
+ die $@ if $@;
+
+ #load up config
+ my $bop_config = 'business-onlinepayment';
+ $bop_config .= '-ach'
+ if $method eq 'ECHECK' && $conf->exists($bop_config. '-ach');
+ my ( $processor, $login, $password, $action, @bop_options ) =
+ $conf->config($bop_config);
+ $action ||= 'normal authorization';
+ pop @bop_options if scalar(@bop_options) % 2 && $bop_options[-1] =~ /^\s*$/;
+
+ #massage data
+
+ my $address = $self->address1;
+ $address .= ", ". $self->address2 if $self->address2;
+
+ my($payname, $payfirst, $paylast);
+ if ( $self->payname && $method ne 'ECHECK' ) {
+ $payname = $self->payname;
+ $payname =~ /^\s*([\w \,\.\-\']*)?\s+([\w\,\.\-\']+)\s*$/
+ or return "Illegal payname $payname";
+ ($payfirst, $paylast) = ($1, $2);
+ } else {
+ $payfirst = $self->getfield('first');
+ $paylast = $self->getfield('last');
+ $payname = "$payfirst $paylast";
+ }
+
+ my @invoicing_list = grep { $_ ne 'POST' } $self->invoicing_list;
+ if ( $conf->exists('emailinvoiceauto')
+ || ( $conf->exists('emailinvoiceonly') && ! @invoicing_list ) ) {
+ push @invoicing_list, $self->all_emails;
+ }
+ my $email = $invoicing_list[0];
+
+ my %content;
+ if ( $method eq 'CC' ) {
+ $content{card_number} = $self->payinfo;
+ $self->paydate =~ /^\d{2}(\d{2})[\/\-](\d+)[\/\-]\d+$/;
+ $content{expiration} = "$2/$1";
+ } elsif ( $method eq 'ECHECK' ) {
+ my($account_number,$routing_code) = $self->payinfo;
+ ( $content{account_number}, $content{routing_code} ) =
+ split('@', $self->payinfo);
+ $content{bank_name} = $self->payname;
+ } elsif ( $method eq 'LEC' ) {
+ $content{phone} = $self->payinfo;
+ }
+
+ #transaction(s)
+
+ my( $action1, $action2 ) = split(/\s*\,\s*/, $action );
+
+ my $transaction =
+ new Business::OnlinePayment( $processor, @bop_options );
+ $transaction->content(
+ 'type' => $method,
+ 'login' => $login,
+ 'password' => $password,
+ 'action' => $action1,
+ 'description' => $options{'description'},
+ 'amount' => $amount,
+ 'invoice_number' => $options{'invnum'},
+ 'customer_id' => $self->custnum,
+ 'last_name' => $paylast,
+ 'first_name' => $payfirst,
+ 'name' => $payname,
+ 'address' => $address,
+ 'city' => $self->city,
+ 'state' => $self->state,
+ 'zip' => $self->zip,
+ 'country' => $self->country,
+ 'referer' => 'http://cleanwhisker.420.am/',
+ 'email' => $email,
+ 'phone' => $self->daytime || $self->night,
+ %content, #after
+ );
+ $transaction->submit();
+
+ if ( $transaction->is_success() && $action2 ) {
+ my $auth = $transaction->authorization;
+ my $ordernum = $transaction->can('order_number')
+ ? $transaction->order_number
+ : '';
+
+ my $capture =
+ new Business::OnlinePayment( $processor, @bop_options );
+
+ my %capture = (
+ %content,
+ type => $method,
+ action => $action2,
+ login => $login,
+ password => $password,
+ order_number => $ordernum,
+ amount => $amount,
+ authorization => $auth,
+ description => $options{'description'},
+ );
+
+ foreach my $field (qw( authorization_source_code returned_ACI transaction_identifier validation_code
+ transaction_sequence_num local_transaction_date
+ local_transaction_time AVS_result_code )) {
+ $capture{$field} = $transaction->$field() if $transaction->can($field);
+ }
+
+ $capture->content( %capture );
+
+ $capture->submit();
+
+ unless ( $capture->is_success ) {
+ my $e = "Authorization sucessful but capture failed, custnum #".
+ $self->custnum. ': '. $capture->result_code.
+ ": ". $capture->error_message;
+ warn $e;
+ return $e;
+ }
+
+ }
+
+ #result handling
+ if ( $transaction->is_success() ) {
+
+ my %method2payby = (
+ 'CC' => 'CARD',
+ 'ECHECK' => 'CHEK',
+ 'LEC' => 'LECB',
+ );
+
+ my $cust_pay = new FS::cust_pay ( {
+ 'invnum' => $self->invnum, #!!!!!!!!
+ 'paid' => $amount,
+ '_date' => '',
+ 'payby' => $method2payby{$method},
+ 'payinfo' => $self->payinfo,
+ 'paybatch' => "$processor:". $transaction->authorization,
+ } );
+ my $error = $cust_pay->insert;
+ if ( $error ) {
+ # gah, even with transactions.
+ my $e = 'WARNING: Card/ACH debited but database not updated - '.
+ 'error applying payment, invnum #' . $self->invnum.
+ " ($processor): $error";
+ warn $e;
+ return $e;
+ } else {
+ return '';
+ }
+
+ } else {
+
+ my $perror = "$processor error: ". $transaction->error_message;
+
+ if ( !$options{'quiet'} && $conf->exists('emaildecline')
+ && grep { $_ ne 'POST' } $self->invoicing_list
+ ) {
+ my @templ = $conf->config('declinetemplate');
+ my $template = new Text::Template (
+ TYPE => 'ARRAY',
+ SOURCE => [ map "$_\n", @templ ],
+ ) or return "($perror) can't create template: $Text::Template::ERROR";
+ $template->compile()
+ or return "($perror) can't compile template: $Text::Template::ERROR";
+
+ my $templ_hash = { error => $transaction->error_message };
+
+ my $error = send_email(
+ 'from' => $conf->config('invoice_from'),
+ 'to' => [ grep { $_ ne 'POST' } $self->invoicing_list ],
+ 'subject' => 'Your payment could not be processed',
+ 'body' => [ $template->fill_in(HASH => $templ_hash) ],
+ );
+
+ $perror .= " (also received error sending decline notification: $error)"
+ if $error;
+
+ }
+
+ return $perror;
+ }
+
+}
+
=item total_owed
Returns the total owed for this customer on all invoices
diff --git a/FS/FS/cust_pay.pm b/FS/FS/cust_pay.pm
index 79cf827..55f2fc4 100644
--- a/FS/FS/cust_pay.pm
+++ b/FS/FS/cust_pay.pm
@@ -1,13 +1,12 @@
package FS::cust_pay;
use strict;
-use vars qw( @ISA $conf $unsuspendauto $smtpmachine $invoice_from );
+use vars qw( @ISA $conf $unsuspendauto );
use Date::Format;
-use Mail::Header;
-use Mail::Internet 1.44;
use Business::CreditCard;
use FS::UID qw( dbh );
use FS::Record qw( dbh qsearch qsearchs dbh );
+use FS::Misc qw(send_email);
use FS::cust_bill;
use FS::cust_bill_pay;
use FS::cust_main;
@@ -15,14 +14,10 @@ use FS::cust_main;
@ISA = qw( FS::Record );
#ask FS::UID to run this stuff for us later
-$FS::UID::callback{'FS::cust_pay'} = sub {
-
+FS::UID->install_callback( sub {
$conf = new FS::Conf;
$unsuspendauto = $conf->exists('unsuspendauto');
- $smtpmachine = $conf->config('smtpmachine');
- $invoice_from = $conf->config('invoice_from');
-
-};
+} );
=head1 NAME
@@ -265,19 +260,12 @@ sub delete {
if ( $conf->config('deletepayments') ne '' ) {
my $cust_main = qsearchs('cust_main',{ 'custnum' => $self->custnum });
- #false laziness w/FS::cust_bill::send & fs_signup_server
- $ENV{MAILADDRESS} = $invoice_from; #??? well as good as any
- my $header = new Mail::Header ( [
- "From: $invoice_from",
- "To: ". $conf->config('deletepayments'),
- "Sender: $invoice_from",
- "Reply-To: $invoice_from",
- "Date: ". time2str("%a, %d %b %Y %X %z", time),
- "Subject: FREESIDE NOTIFICATION: Payment deleted",
- ] );
- my $message = new Mail::Internet (
- 'Header' => $header,
- 'Body' => [
+
+ my $error = send_email(
+ 'from' => $conf->config('invoice_from'), #??? well as good as any
+ 'to' => $conf->config('deletepayments'),
+ 'subject' => 'FREESIDE NOTIFICATION: Payment deleted',
+ 'body' => [
"This is an automatic message from your Freeside installation\n",
"informing you that the following payment has been deleted:\n",
"\n",
@@ -291,16 +279,12 @@ sub delete {
'paybatch: '. $self->paybatch. "\n",
],
);
- $!=0;
- $message->smtpsend( Host => $smtpmachine )
- or $message->smtpsend( Host => $smtpmachine, Debug => 1 )
- or do {
- $dbh->rollback if $oldAutoCommit;
- return "(customer # ". $self->custnum.
- ") can't send payment deletion email to ".
- $conf->config('deletepayments').
- " via server $smtpmachine with SMTP: $!";
- };
+
+ if ( $error ) {
+ $dbh->rollback if $oldAutoCommit;
+ return "can't send payment deletion notification: $error";
+ }
+
}
$dbh->commit or die $dbh->errstr if $oldAutoCommit;
@@ -406,7 +390,7 @@ sub unapplied {
=head1 VERSION
-$Id: cust_pay.pm,v 1.23 2002-11-19 09:51:58 ivan Exp $
+$Id: cust_pay.pm,v 1.24 2003-05-19 12:00:44 ivan Exp $
=head1 BUGS
diff --git a/FS/FS/cust_pkg.pm b/FS/FS/cust_pkg.pm
index bd3d1f5..9ab2695 100644
--- a/FS/FS/cust_pkg.pm
+++ b/FS/FS/cust_pkg.pm
@@ -5,6 +5,7 @@ use vars qw(@ISA $disable_agentcheck);
use vars qw( $quiet );
use FS::UID qw( getotaker dbh );
use FS::Record qw( qsearch qsearchs );
+use FS::Misc qw( send_email );
use FS::cust_svc;
use FS::part_pkg;
use FS::cust_main;
@@ -20,12 +21,8 @@ use FS::svc_domain;
use FS::svc_www;
use FS::svc_forward;
-# need all this for sending cancel emails in sub cancel
-
+# for sending cancel emails in sub cancel
use FS::Conf;
-use Date::Format;
-use Mail::Internet 1.44;
-use Mail::Header;
@ISA = qw( FS::Record );
@@ -304,38 +301,16 @@ sub cancel {
$dbh->commit or die $dbh->errstr if $oldAutoCommit;
my $conf = new FS::Conf;
-
- if ( !$quiet && $conf->exists('emailcancel')
- && grep { $_ ne 'POST' } $self->cust_main->invoicing_list) {
-
- my @invoicing_list = $self->cust_main->invoicing_list;
-
- my $invoice_from = $conf->config('invoice_from');
- my @print_text = map "$_\n", $conf->config('cancelmessage');
- my $subject = $conf->config('cancelsubject');
- my $smtpmachine = $conf->config('smtpmachine');
-
- if ( grep { $_ ne 'POST' } @invoicing_list ) { #email invoice
- #false laziness w/FS::cust_pay::delete & fs_signup_server && ::realtime_card
- #$ENV{SMTPHOSTS} = $smtpmachine;
- $ENV{MAILADDRESS} = $invoice_from;
- my $header = new Mail::Header ( [
- "From: $invoice_from",
- "To: ". join(', ', grep { $_ ne 'POST' } @invoicing_list ),
- "Sender: $invoice_from",
- "Reply-To: $invoice_from",
- "Date: ". time2str("%a, %d %b %Y %X %z", time),
- "Subject: $subject",
- ] );
- my $message = new Mail::Internet (
- 'Header' => $header,
- 'Body' => [ @print_text ],
- );
- $!=0;
- $message->smtpsend( Host => $smtpmachine )
- or $message->smtpsend( Host => $smtpmachine, Debug => 1 );
- #should this return an error?
- }
+ my @invoicing_list = grep { $_ ne 'POST' } $self->cust_main->invoicing_list;
+ if ( !$quiet && $conf->exists('emailcancel') && @invoicing_list ) {
+ my $conf = new FS::Conf;
+ my $error = send_email(
+ 'from' => $conf->config('invoice_from'),
+ 'to' => \@invoicing_list,
+ 'subject' => $conf->config('cancelsubject'),
+ 'body' => [ map "$_\n", $conf->config('cancelmessage') ],
+ );
+ #should this do something on errors?
}
''; #no errors
diff --git a/FS/FS/svc_acct.pm b/FS/FS/svc_acct.pm
index 8f2861b..497e59c 100644
--- a/FS/FS/svc_acct.pm
+++ b/FS/FS/svc_acct.pm
@@ -1024,36 +1024,28 @@ sub radius_groups {
=item send_email
+This is the FS::svc_acct job-queue-able version. It still uses
+FS::Misc::send_email under-the-hood.
+
=cut
sub send_email {
my %opt = @_;
- use Date::Format;
- use Mail::Internet 1.44;
- use Mail::Header;
+ eval "use FS::Misc qw(send_email)";
+ die $@ if $@;
$opt{mimetype} ||= 'text/plain';
$opt{mimetype} .= '; charset="iso-8859-1"' unless $opt{mimetype} =~ /charset/;
- $ENV{MAILADDRESS} = $opt{from};
- my $header = new Mail::Header ( [
- "From: $opt{from}",
- "To: $opt{to}",
- "Sender: $opt{from}",
- "Reply-To: $opt{from}",
- "Date: ". time2str("%a, %d %b %Y %X %z", time),
- "Subject: $opt{subject}",
- "Content-Type: $opt{mimetype}",
- ] );
- my $message = new Mail::Internet (
- 'Header' => $header,
- 'Body' => [ map "$_\n", split("\n", $opt{body}) ],
+ my $error = send_email(
+ 'from' => $opt{from},
+ 'to' => $opt{to},
+ 'subject' => $opt{subject},
+ 'content-type' => $opt{mimetype},
+ 'body' => [ map "$_\n", split("\n", $opt{body}) ],
);
- $!=0;
- $message->smtpsend( Host => $smtpmachine )
- or $message->smtpsend( Host => $smtpmachine, Debug => 1 )
- or die "can't send email to $opt{to} via $smtpmachine with SMTP: $!";
+ die $error if $error;
}
=item check_and_rebuild_fuzzyfiles
diff --git a/FS/FS/svc_domain.pm b/FS/FS/svc_domain.pm
index 81edc33..2e8866a 100644
--- a/FS/FS/svc_domain.pm
+++ b/FS/FS/svc_domain.pm
@@ -1,13 +1,11 @@
package FS::svc_domain;
use strict;
-use vars qw( @ISA $whois_hack $conf $smtpmachine
+use vars qw( @ISA $whois_hack $conf
@defaultrecords $soadefaultttl $soaemail $soaexpire $soamachine
$soarefresh $soaretry
);
use Carp;
-use Mail::Internet 1.44;
-use Mail::Header;
use Date::Format;
use Net::Whois 1.0;
use FS::Record qw(fields qsearch qsearchs dbh);
@@ -26,8 +24,6 @@ use FS::queue;
$FS::UID::callback{'FS::domain'} = sub {
$conf = new FS::Conf;
- $smtpmachine = $conf->config('smtpmachine');
-
@defaultrecords = $conf->config('defaultrecords');
$soadefaultttl = $conf->config('soadefaultttl');
$soaemail = $conf->config('soaemail');
diff --git a/FS/MANIFEST b/FS/MANIFEST
index 6397cc4..272b5b7 100644
--- a/FS/MANIFEST
+++ b/FS/MANIFEST
@@ -36,6 +36,7 @@ FS/ClientAPI/passwd.pm
FS/ClientAPI/MyAccount.pm
FS/Conf.pm
FS/ConfItem.pm
+FS/Misc.pm
FS/Record.pm
FS/SearchCache.pm
FS/UI/Base.pm
@@ -125,6 +126,7 @@ t/InitHandler.t
t/ClientAPI.t
t/Conf.t
t/ConfItem.t
+t/Misc.t
t/Record.t
t/UID.t
t/Msgcat.t
diff --git a/FS/t/Misc.t b/FS/t/Misc.t
new file mode 100644
index 0000000..cc7751a
--- /dev/null
+++ b/FS/t/Misc.t
@@ -0,0 +1,5 @@
+BEGIN { $| = 1; print "1..1\n" }
+END {print "not ok 1\n" unless $loaded;}
+use FS::Misc;
+$loaded=1;
+print "ok 1\n";