X-Git-Url: http://git.freeside.biz/gitweb/?a=blobdiff_plain;f=FS%2FFS%2Fpay_batch%2Fpaymentech.pm;h=47be4eb31ebe5042c786183b64c74da972fae386;hb=61097b876e692dbf5571a17b9aa415949607085f;hp=c1e9c9a599cf9ea611c4549c225af49682161984;hpb=978cc3533b38efa38c63898fa7814a4b38efdee3;p=freeside.git diff --git a/FS/FS/pay_batch/paymentech.pm b/FS/FS/pay_batch/paymentech.pm index c1e9c9a59..47be4eb31 100644 --- a/FS/FS/pay_batch/paymentech.pm +++ b/FS/FS/pay_batch/paymentech.pm @@ -2,15 +2,19 @@ package FS::pay_batch::paymentech; use strict; use vars qw(@ISA %import_info %export_info $name); +use FS::Record 'qsearchs'; use Time::Local; use Date::Format 'time2str'; use Date::Parse 'str2time'; +use Tie::IxHash; use FS::Conf; my $conf; -my ($bin, $merchantID, $terminalID, $username); +my ($bin, $merchantID, $terminalID, $username, $password, $with_recurringInd); $name = 'paymentech'; +my $gateway; + %import_info = ( filetype => 'XML', xmlrow => [ qw(transResponse newOrderResp) ], @@ -18,18 +22,49 @@ $name = 'paymentech'; 'paybatchnum', '_date', 'approvalStatus', + 'order_number', + 'auth', + 'procStatus', + 'procStatusMessage', + 'respCodeMessage', ], xmlkeys => [ 'orderID', 'respDateTime', 'approvalStatus', + 'txRefNum', + 'authorizationCode', + 'procStatus', + 'procStatusMessage', + 'respCodeMessage', ], 'hook' => sub { + if ( !$gateway ) { + # find a gateway configuration that has the same merchantID + # as the batch config, if there is one. If not, leave + # gateway out entirely. + my $merchant = (FS::Conf->new->config('batchconfig-paymentech'))[2]; + $gateway = qsearchs({ + 'table' => 'payment_gateway', + 'addl_from' => ' JOIN payment_gateway_option USING (gatewaynum) ', + 'hashref' => { disabled => '', + optionname => 'merchant_id', + optionvalue => $merchant, + }, + }); + } my ($hash, $oldhash) = @_; + $hash->{'gatewaynum'} = $gateway->gatewaynum if $gateway; + $hash->{'processor'} = 'PaymenTech'; my ($mon, $day, $year, $hour, $min, $sec) = $hash->{'_date'} =~ /^(..)(..)(....)(..)(..)(..)$/; $hash->{'_date'} = timelocal($sec, $min, $hour, $day, $mon-1, $year); $hash->{'paid'} = $oldhash->{'amount'}; + if ( $hash->{'procStatus'} == 0 ) { + $hash->{'error_message'} = $hash->{'respCodeMessage'}; + } else { + $hash->{'error_message'} = $hash->{'procStatusMessage'}; + } }, 'approved' => sub { my $hash = shift; $hash->{'approvalStatus'} @@ -44,71 +79,99 @@ my %paytype = ( 'personal savings' => 'S', 'business checking' => 'X', 'business savings' => 'X', - ); +); + +my %paymentech_countries = map { $_ => 1 } qw( US CA GB UK ); %export_info = ( init => sub { # Load this at run time - eval "use XML::Simple"; + eval "use XML::Writer"; die $@ if $@; my $conf = shift; - ($bin, $terminalID, $merchantID, $username) = + ($bin, $terminalID, $merchantID, $username, $password, $with_recurringInd) = $conf->config('batchconfig-paymentech'); }, # Here we do all the work in the header function. header => sub { my $pay_batch = shift; my @cust_pay_batch = @{(shift)}; - my $count = 0; - XML::Simple::XMLout( { - transRequest => { - RequestCount => scalar(@cust_pay_batch), - batchFileID => { - userID => $username, - fileDateTime => time2str('%Y%m%d%H%M%s',time), - fileID => 'FILEID', - }, - newOrder => [ map { { - # $_ here refers to a cust_pay_batch record. - BatchRequestNo => $count++, - industryType => 'EC', - transType => 'AC', - bin => $bin, - merchantID => $merchantID, - terminalID => $terminalID, - ($_->payby eq 'CARD') ? ( - # Credit card stuff - ccAccountNum => $_->payinfo, - ccExp => time2str('%y%m',str2time($_->exp)), - ) : ( - # ECP (electronic check) stuff - ecpCheckRT => ($_->payinfo =~ /@(\d+)/), - ecpCheckDDA => ($_->payinfo =~ /(\d+)@/), - ecpBankAcctType => $paytype{lc($_->cust_main->paytype)}, - ecpDelvMethod => 'B' - ), - avsZip => $_->zip, - avsAddress1 => $_->address1, - avsAddress2 => $_->address2, - avsCity => $_->city, - avsState => $_->state, - avsName => $_->first . ' ' . $_->last, - avsCountryCode => $_->country, - orderID => $_->paybatchnum, - amount => $_->amount * 100, - } } @cust_pay_batch - ], - endOfDay => { - BatchRequestNo => $count++, - bin => $bin, - merchantID => $merchantID, - terminalID => $terminalID - }, - } - }, KeepRoot => 1, NoAttr => 1); + my $count = 1; + my $output; + my $xml = new XML::Writer(OUTPUT => \$output, DATA_MODE => 1, DATA_INDENT => 2); + $xml->startTag('transRequest', RequestCount => scalar(@cust_pay_batch) + 1); + $xml->startTag('batchFileID'); + $xml->dataElement(userID => $username); + $xml->dataElement(fileDateTime => time2str('%Y%m%d%H%M%S', time)); + $xml->dataElement(fileID => 'FILEID'); + $xml->endTag('batchFileID'); + + foreach (@cust_pay_batch) { + $xml->startTag('newOrder', BatchRequestNo => $count++); + my $status = $_->cust_main->status; + tie my %order, 'Tie::IxHash', ( + industryType => 'EC', + transType => 'AC', + bin => $bin, + merchantID => $merchantID, + terminalID => $terminalID, + ($_->payby eq 'CARD') ? ( + ccAccountNum => $_->payinfo, + ccExp => $_->expmmyy, + ) : ( + ecpCheckRT => ($_->payinfo =~ /@(\d+)/), + ecpCheckDDA => ($_->payinfo =~ /(\d+)@/), + ecpBankAcctType => $paytype{lc($_->cust_main->paytype)}, + ecpDelvMethod => 'A', + ), + avsZip => substr($_->zip, 0, 10), + avsAddress1 => substr($_->address1, 0, 30), + avsAddress2 => substr($_->address2, 0, 30), + avsCity => substr($_->city, 0, 20), + avsState => substr($_->state, 0, 2), + avsName => substr($_->first. ' '. $_->last, 0, 30), + avsCountryCode => ( $paymentech_countries{ $_->country } + ? $_->country + : '' + ), + orderID => $_->paybatchnum, + amount => $_->amount * 100, + ); + # only do this if recurringInd is enabled in config, + # and the customer has at least one non-canceled recurring package + if ( $with_recurringInd and $status =~ /^active|suspended|ordered$/ ) { + # then send RF if this is the first payment on this payinfo, + # RS otherwise. + $order{'recurringInd'} = $_->payinfo_used ? 'RS' : 'RF'; + } + foreach my $key (keys %order) { + $xml->dataElement($key, $order{$key}) + } + $xml->endTag('newOrder'); + } + $xml->startTag('endOfDay', BatchRequestNo => $count); + $xml->dataElement(bin => $bin); + $xml->dataElement(merchantID => $merchantID); + $xml->dataElement(terminalID => $terminalID); + $xml->endTag('endOfDay'); + $xml->endTag('transRequest'); + return $output; }, row => sub {}, ); +# Including this means that there is a Business::BatchPayment module for +# this gateway and we want to upgrade it. +# Must return the name of the module, followed by a hash of options. + +sub _upgrade_gateway { + my $conf = FS::Conf->new; + my @batchconfig = $conf->config('batchconfig-paymentech'); + my %options; + @options{ qw(bin terminalID merchantID login password ) } = @batchconfig; + $options{'industryType'} = 'EC'; + ( 'Paymentech', %options ); +} + 1;