X-Git-Url: http://git.freeside.biz/gitweb/?a=blobdiff_plain;f=FS%2FFS%2Fcust_bill.pm;h=54641ee358ee97b8d919c60e927cd516ef507424;hb=88d237b8fe396b4e85a16e20eccfeb4e22e94e24;hp=d49657e2e71e61be120313bf96eb804afbccfdd5;hpb=27b1e8e41b7d4ace60b286ec02a171009aee83f2;p=freeside.git diff --git a/FS/FS/cust_bill.pm b/FS/FS/cust_bill.pm index d49657e2e..54641ee35 100644 --- a/FS/FS/cust_bill.pm +++ b/FS/FS/cust_bill.pm @@ -35,28 +35,7 @@ $FS::UID::callback{'FS::cust_bill'} = sub { $invoice_from = $conf->config('invoice_from'); $smtpmachine = $conf->config('smtpmachine'); - 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"; - } - $processor='cybercash3.2'; - } elsif ( $conf->exists('business-onlinepayment') ) { + if ( $conf->exists('business-onlinepayment') ) { ( $bop_processor, $bop_login, $bop_password, @@ -373,7 +352,11 @@ sub send { my @print_text = $self->print_text('', $template); my @invoicing_list = $self->cust_main->invoicing_list; - if ( grep { $_ ne 'POST' } @invoicing_list ) { #email invoice + 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; @@ -398,7 +381,7 @@ sub send { } - if ( ! @invoicing_list || grep { $_ eq 'POST' } @invoicing_list ) { #postal + if ( grep { $_ eq 'POST' } @invoicing_list ) { #postal open(LPR, "|$lpr") or return "Can't open pipe to $lpr: $!"; print LPR @print_text; @@ -443,23 +426,39 @@ first two fields (B and B) and the last five fields (B through B) are filled in. =item invnum - invoice number + =item custnum - customer number + =item _date - invoice date + =item charged - total invoice amount + =item first - customer first name + =item last - customer first name + =item company - company name + =item address1 - address line 1 + =item address2 - address line 1 + =item city + =item state + =item zip + =item country =item pkg - line item description -=item setup - line item setup fee (only or both of B and B will be defined) -=item recur - line item recurring fee (only or both of B and B will be defined) + +=item setup - line item setup fee (one or both of B and B will be defined) + +=item recur - line item recurring fee (one or both of B and B will be defined) + =item sdate - start date for recurring fee + =item edate - end date for recurring fee =back @@ -515,10 +514,13 @@ sub send_csv { 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) = - ( 'Tax', sprintf("%10.2f",$cust_bill_pkg->setup), '', '', '' ); + ( $itemdesc, sprintf("%10.2f",$cust_bill_pkg->setup), '', '', '' ); } $csv->combine( @@ -581,32 +583,48 @@ sub comp { =item realtime_card -Attempts to pay this invoice with a Business::OnlinePayment realtime gateway. -See http://search.cpan.org/search?mode=module&query=Business%3A%3AOnlinePayment -for supproted processors. +Attempts to pay this invoice with a credit card 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_card { my $self = shift; + $self->realtime_bop('CC', @_); +} + +=item realtime_ach + +Attempts to pay this invoice with an electronic check (ACH) 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_ach { + my $self = shift; + $self->realtime_bop('CHECK', @_); +} + +sub realtime_bop { + my $self = shift; + my $method = shift; my $cust_main = $self->cust_main; my $amount = $self->owed; unless ( $processor =~ /^Business::OnlinePayment::(.*)$/ ) { - return "Real-time card processing not enabled (processor $processor)"; + 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; - #fix exp. date - #$cust_main->paydate =~ /^(\d+)\/\d*(\d{2})$/; - $cust_main->paydate =~ /^\d{2}(\d{2})[\/\-](\d+)[\/\-]\d+$/; - my $exp = "$2/$1"; - my($payname, $payfirst, $paylast); - if ( $cust_main->payname ) { + if ( $cust_main->payname && $method ne 'CHECK' ) { $payname = $cust_main->payname; $payname =~ /^\s*([\w \,\.\-\']*)?\s+([\w\,\.\-\']+)\s*$/ or do { @@ -623,7 +641,7 @@ sub realtime_card { my @invoicing_list = grep { $_ ne 'POST' } $cust_main->invoicing_list; if ( $conf->exists('emailinvoiceauto') || ( $conf->exists('emailinvoiceonly') && ! @invoicing_list ) ) { - push @invoicing_list, $cust_main->default_invoicing_list; + push @invoicing_list, $cust_main->all_emails; } my $email = $invoicing_list[0]; @@ -644,11 +662,24 @@ sub realtime_card { $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 'CHECK' ) { + my($account_number,$routing_code) = $cust_main->payinfo; + ( $content{account_number}, $content{routing_code} ) = + split('@', $cust_main->payinfo); + $content{bank_name} = $cust_main->payname; + } my $transaction = new Business::OnlinePayment( $bop_processor, @bop_options ); $transaction->content( - 'type' => 'CC', + %content, + 'type' => $method, 'login' => $bop_login, 'password' => $bop_password, 'action' => $action1, @@ -664,8 +695,6 @@ sub realtime_card { 'state' => $cust_main->state, 'zip' => $cust_main->zip, 'country' => $cust_main->country, - 'card_number' => $cust_main->payinfo, - 'expiration' => $exp, 'referer' => 'http://cleanwhisker.420.am/', 'email' => $email, 'phone' => $cust_main->daytime || $cust_main->night, @@ -684,7 +713,8 @@ sub realtime_card { new Business::OnlinePayment( $bop_processor, @bop_options ); my %capture = ( - type => 'CC', + %content, + type => $method, action => $action2, login => $bop_login, password => $bop_password, @@ -692,8 +722,6 @@ sub realtime_card { amount => $amount, authorization => $auth, description => $description, - card_number => $cust_main->payinfo, - expiration => $exp, ); foreach my $field (qw( authorization_source_code returned_ACI transaction_identifier validation_code @@ -718,18 +746,23 @@ sub realtime_card { if ( $transaction->is_success() ) { + my %method2payby = ( + 'CC' => 'CARD', + 'CHECK' => 'CHEK', + ); + my $cust_pay = new FS::cust_pay ( { 'invnum' => $self->invnum, 'paid' => $amount, '_date' => '', - 'payby' => 'CARD', + '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 debited but database not updated - '. + my $e = 'WARNING: Card/ACH debited but database not updated - '. 'error applying payment, invnum #' . $self->invnum. " ($processor): $error"; warn $e; @@ -764,7 +797,7 @@ sub realtime_card { "Sender: $invoice_from", "Reply-To: $invoice_from", "Date: ". time2str("%a, %d %b %Y %X %z", time), - "Subject: Your credit card could not be processed", + "Subject: Your payment could not be processed", ] ); my $message = new Mail::Internet ( 'Header' => $header, @@ -784,84 +817,6 @@ sub realtime_card { } -=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 $processor 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' => "$processor:$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 @@ -914,7 +869,7 @@ sub print_text { # my $invnum = $self->invnum; my $cust_main = qsearchs('cust_main', { 'custnum', $self->custnum } ); $cust_main->payname( $cust_main->first. ' '. $cust_main->getfield('last') ) - unless $cust_main->payname; + unless $cust_main->payname && $cust_main->payby ne 'CHEK'; my( $pr_total, @pr_cust_bill ) = $self->previous; #previous balance # my( $cr_total, @cr_cust_credit ) = $self->cust_credit; #credits @@ -941,7 +896,9 @@ sub print_text { } #new charges - foreach ( $self->cust_bill_pkg ) { + foreach ( ( grep { $_->pkgnum } $self->cust_bill_pkg ), #packages first + ( grep { ! $_->pkgnum } $self->cust_bill_pkg ), #then taxes + ) { if ( $_->pkgnum ) { @@ -965,8 +922,11 @@ sub print_text { map { [ " ". $_->[0]. ": ". $_->[1], '' ] } $cust_pkg->labels; } - } else { #pkgnum Tax - push @buf,["Tax", $money_char. sprintf("%10.2f",$_->setup) ] + } else { #pkgnum tax + my $itemdesc = defined $_->dbdef_table->column('itemdesc') + ? ( $_->itemdesc || 'Tax' ) + : 'Tax'; + push @buf,[$itemdesc, $money_char. sprintf("%10.2f",$_->setup) ] if $_->setup != 0; } } @@ -1114,7 +1074,7 @@ sub print_text { =head1 VERSION -$Id: cust_bill.pm,v 1.42 2002-09-10 03:31:00 ivan Exp $ +$Id: cust_bill.pm,v 1.50 2002-10-15 09:54:24 ivan Exp $ =head1 BUGS