use strict;
use vars qw( @ISA $conf $money_char );
use vars qw( $lpr $invoice_from $smtpmachine );
-use vars qw( $processor );
+use vars qw( $cybercash );
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;
$invoice_from = $conf->config('invoice_from');
$smtpmachine = $conf->config('smtpmachine');
- if ( $conf->exists('business-onlinepayment') ) {
+ ( $bop_processor,$bop_login, $bop_password, $bop_action ) = ( '', '', '', '');
+ @bop_options = ();
+ ( $ach_processor,$ach_login, $ach_password, $ach_action ) = ( '', '', '', '');
+ @ach_options = ();
+
+ if ( $conf->exists('cybercash3.2') ) {
+ require CCMckLib3_2;
+ #qw($MCKversion %Config InitConfig CCError CCDebug CCDebug2);
+ require CCMckDirectLib3_2;
+ #qw(SendCC2_1Server);
+ require CCMckErrno3_2;
+ #qw(MCKGetErrorMessage $E_NoErr);
+ import CCMckErrno3_2 qw($E_NoErr);
+
+ my $merchant_conf;
+ ($merchant_conf,$xaction)= $conf->config('cybercash3.2');
+ my $status = &CCMckLib3_2::InitConfig($merchant_conf);
+ if ( $status != $E_NoErr ) {
+ warn "CCMckLib3_2::InitConfig error:\n";
+ foreach my $key (keys %CCMckLib3_2::Config) {
+ warn " $key => $CCMckLib3_2::Config{$key}\n"
+ }
+ my($errmsg) = &CCMckErrno3_2::MCKGetErrorMessage($status);
+ die "CCMckLib3_2::InitConfig fatal error: $errmsg\n";
+ }
+ $cybercash='cybercash3.2';
+ } elsif ( $conf->exists('business-onlinepayment') ) {
( $bop_processor,
$bop_login,
$bop_password,
@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";
- $processor="Business::OnlinePayment::$bop_processor";
}
};
my @print_text = $self->print_text('', $template);
my @invoicing_list = $self->cust_main->invoicing_list;
- if ( grep { $_ ne 'POST' } @invoicing_list or !@invoicing_list ) { #email
+ if ( grep { $_ ne 'POST' } @invoicing_list or !@invoicing_list ) { #email
#better to notify this person than silence
@invoicing_list = ($invoice_from) unless @invoicing_list;
time2str("%x", $cust_bill_pkg->edate),
);
- } else { #pkgnum tax
+ } else { #pkgnum Tax
next unless $cust_bill_pkg->setup != 0;
- my $itemdesc = defined $cust_bill_pkg->dbdef_table->column('itemdesc')
- ? ( $cust_bill_pkg->itemdesc || 'Tax' )
- : 'Tax';
($pkg, $setup, $recur, $sdate, $edate) =
- ( $itemdesc, sprintf("%10.2f",$cust_bill_pkg->setup), '', '', '' );
+ ( 'Tax', sprintf("%10.2f",$cust_bill_pkg->setup), '', '', '' );
}
$csv->combine(
sub realtime_card {
my $self = shift;
- $self->realtime_bop('CC', @_);
+ $self->realtime_bop(
+ 'CC',
+ $bop_processor,
+ $bop_login,
+ $bop_password,
+ $bop_action,
+ \@bop_options,
+ @_
+ );
}
=item realtime_ach
sub realtime_ach {
my $self = shift;
- $self->realtime_bop('ECHECK', @_);
+ $self->realtime_bop(
+ 'ECHECK',
+ $ach_processor,
+ $ach_login,
+ $ach_password,
+ $ach_action,
+ \@ach_options,
+ @_
+ );
}
-sub realtime_bop {
+=item realtime_lec
+
+Attempts to pay this invoice with phone bill (LEC) payment via a
+Business::OnlinePayment realtime gateway. See
+http://search.cpan.org/search?mode=module&query=Business%3A%3AOnlinePayment
+for supported processors.
+
+=cut
+
+sub realtime_lec {
my $self = shift;
- my $method = shift;
+ $self->realtime_bop(
+ 'LEC',
+ $bop_processor,
+ $bop_login,
+ $bop_password,
+ $bop_action,
+ \@bop_options,
+ @_
+ );
+}
+
+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 $cust_main = $self->cust_main;
my $amount = $self->owed;
- unless ( $processor =~ /^Business::OnlinePayment::(.*)$/ ) {
- return "Real-time card/ACH processing not enabled (processor $processor)";
- }
- my $bop_processor = $1; #hmm?
-
my $address = $cust_main->address1;
$address .= ", ". $cust_main->address2 if $cust_main->address2;
}
my $email = $invoicing_list[0];
- my( $action1, $action2 ) = split(/\s*\,\s*/, $bop_action );
+ my( $action1, $action2 ) = split(/\s*\,\s*/, $action );
my $description = 'Internet Services';
if ( $conf->exists('business-onlinepayment-description') ) {
$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
+ 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( $bop_processor, @bop_options );
+ new Business::OnlinePayment( $processor, @$options );
$transaction->content(
- %content,
'type' => $method,
- 'login' => $bop_login,
- 'password' => $bop_password,
+ 'login' => $login,
+ 'password' => $password,
'action' => $action1,
'description' => $description,
'amount' => $amount,
'referer' => 'http://cleanwhisker.420.am/',
'email' => $email,
'phone' => $cust_main->daytime || $cust_main->night,
+ %content, #after
);
$transaction->submit();
#warn "********* $auth ***********\n";
#warn "********* $ordernum ***********\n";
my $capture =
- new Business::OnlinePayment( $bop_processor, @bop_options );
+ new Business::OnlinePayment( $processor, @$options );
my %capture = (
%content,
type => $method,
action => $action2,
- login => $bop_login,
- password => $bop_password,
+ login => $login,
+ password => $password,
order_number => $ordernum,
amount => $amount,
authorization => $auth,
my %method2payby = (
'CC' => 'CARD',
'ECHECK' => 'CHEK',
+ 'LEC' => 'LECB',
);
my $cust_pay = new FS::cust_pay ( {
'invnum' => $self->invnum,
'paid' => $amount,
'_date' => '',
- 'payby' => method2payby{$method},
+ 'payby' => $method2payby{$method},
'payinfo' => $cust_main->payinfo,
'paybatch' => "$processor:". $transaction->authorization,
} );
my $perror = "$processor error, invnum #". $self->invnum. ': '.
$transaction->result_code. ": ". $transaction->error_message;
- if ( $conf->exists('emaildecline')
+ if ( !$quiet && $conf->exists('emaildecline')
&& grep { $_ ne 'POST' } $cust_main->invoicing_list
) {
my @templ = $conf->config('declinetemplate');
}
+=item realtime_card_cybercash
+
+Attempts to pay this invoice with the CyberCash CashRegister realtime gateway.
+
+=cut
+
+sub realtime_card_cybercash {
+ my $self = shift;
+ my $cust_main = $self->cust_main;
+ my $amount = $self->owed;
+
+ return "CyberCash CashRegister real-time card processing not enabled!"
+ unless $cybercash eq 'cybercash3.2';
+
+ my $address = $cust_main->address1;
+ $address .= ", ". $cust_main->address2 if $cust_main->address2;
+
+ #fix exp. date
+ #$cust_main->paydate =~ /^(\d+)\/\d*(\d{2})$/;
+ $cust_main->paydate =~ /^\d{2}(\d{2})[\/\-](\d+)[\/\-]\d+$/;
+ my $exp = "$2/$1";
+
+ #
+
+ my $paybatch = $self->invnum.
+ '-' . time2str("%y%m%d%H%M%S", time);
+
+ my $payname = $cust_main->payname ||
+ $cust_main->getfield('first').' '.$cust_main->getfield('last');
+
+ my $country = $cust_main->country eq 'US' ? 'USA' : $cust_main->country;
+
+ my @full_xaction = ( $xaction,
+ 'Order-ID' => $paybatch,
+ 'Amount' => "usd $amount",
+ 'Card-Number' => $cust_main->getfield('payinfo'),
+ 'Card-Name' => $payname,
+ 'Card-Address' => $address,
+ 'Card-City' => $cust_main->getfield('city'),
+ 'Card-State' => $cust_main->getfield('state'),
+ 'Card-Zip' => $cust_main->getfield('zip'),
+ 'Card-Country' => $country,
+ 'Card-Exp' => $exp,
+ );
+
+ my %result;
+ %result = &CCMckDirectLib3_2::SendCC2_1Server(@full_xaction);
+
+ if ( $result{'MStatus'} eq 'success' ) { #cybercash smps v.2 or 3
+ my $cust_pay = new FS::cust_pay ( {
+ 'invnum' => $self->invnum,
+ 'paid' => $amount,
+ '_date' => '',
+ 'payby' => 'CARD',
+ 'payinfo' => $cust_main->payinfo,
+ 'paybatch' => "$cybercash:$paybatch",
+ } );
+ my $error = $cust_pay->insert;
+ if ( $error ) {
+ # gah, even with transactions.
+ my $e = 'WARNING: Card debited but database not updated - '.
+ 'error applying payment, invnum #' . $self->invnum.
+ " (CyberCash Order-ID $paybatch): $error";
+ warn $e;
+ return $e;
+ } else {
+ return '';
+ }
+# } elsif ( $result{'Mstatus'} ne 'failure-bad-money'
+# || $options{'report_badcard'}
+# ) {
+ } else {
+ return 'Cybercash error, invnum #' .
+ $self->invnum. ':'. $result{'MErrMsg'};
+ }
+
+}
+
=item batch_card
Adds a payment for this invoice to the pending credit card batch (see
}
#new charges
- foreach ( ( grep { $_->pkgnum } $self->cust_bill_pkg ), #packages first
- ( grep { ! $_->pkgnum } $self->cust_bill_pkg ), #then taxes
- ) {
+ foreach ( $self->cust_bill_pkg ) {
if ( $_->pkgnum ) {
map { [ " ". $_->[0]. ": ". $_->[1], '' ] } $cust_pkg->labels;
}
- } else { #pkgnum tax
- my $itemdesc = defined $_->dbdef_table->column('itemdesc')
- ? ( $_->itemdesc || 'Tax' )
- : 'Tax';
- push @buf,[$itemdesc, $money_char. sprintf("%10.2f",$_->setup) ]
+ } else { #pkgnum Tax
+ push @buf,["Tax", $money_char. sprintf("%10.2f",$_->setup) ]
if $_->setup != 0;
}
}
or die "cannot load config file $templatefile";
$invoice_lines = 0;
my $wasfunc = 0;
- foreach ( grep /invoice_lines\(\d+\)/, @invoice_template ) { #kludgy
- /invoice_lines\((\d+)\)/;
- $invoice_lines += $1;
+ foreach ( grep /invoice_lines\(\d*\)/, @invoice_template ) { #kludgy
+ /invoice_lines\((\d*)\)/;
+ $invoice_lines += $1 || scalar(@buf);
$wasfunc=1;
}
die "no invoice_lines() functions in template?" unless $wasfunc;
#setup template variables
package FS::cust_bill::_template; #!
- use vars qw( $invnum $date $page $total_pages @address $overdue @buf );
+ use vars qw( $invnum $date $page $total_pages @address $overdue @buf $agent );
$invnum = $self->invnum;
$date = $self->_date;
$page = 1;
+ $agent = $self->cust_main->agent->agent;
if ( $FS::cust_bill::invoice_lines ) {
$total_pages =
# );
#and subroutine for the template
-
sub FS::cust_bill::_template::invoice_lines {
- my $lines = shift or return @buf;
+ my $lines = shift || scalar(@buf);
map {
scalar(@buf) ? shift @buf : [ '', '' ];
}
( 1 .. $lines );
}
-
#and fill it in
$FS::cust_bill::_template::page = 1;
my $lines;
=head1 VERSION
-$Id: cust_bill.pm,v 1.48 2002-10-12 10:15:55 ivan Exp $
+$Id: cust_bill.pm,v 1.41.2.20 2003-01-10 07:42:39 ivan Exp $
=head1 BUGS