don't send countries other than US/CA/GB/UK to paymentech, RT#20222
[freeside.git] / FS / FS / pay_batch / paymentech.pm
1 package FS::pay_batch::paymentech;
2
3 use strict;
4 use vars qw(@ISA %import_info %export_info $name);
5 use FS::Record 'qsearchs';
6 use Time::Local;
7 use Date::Format 'time2str';
8 use Date::Parse 'str2time';
9 use Tie::IxHash;
10 use FS::Conf;
11
12 my $conf;
13 my ($bin, $merchantID, $terminalID, $username, $password, $with_recurringInd);
14 $name = 'paymentech';
15
16 my $gateway;
17
18 %import_info = (
19   filetype    => 'XML',
20   xmlrow         => [ qw(transResponse newOrderResp) ],
21   fields      => [
22     'paybatchnum',
23     '_date',
24     'approvalStatus',
25     'order_number',
26     'authorization',
27     ],
28   xmlkeys     => [
29     'orderID',
30     'respDateTime',
31     'approvalStatus',
32     'txRefNum',
33     'authorizationCode',
34     ],
35   'hook'        => sub {
36       if ( !$gateway ) {
37         # find a gateway configuration that has the same merchantID 
38         # as the batch config, if there is one.  If not, leave 
39         # gateway out entirely.
40         my $merchant = (FS::Conf->new->config('batchconfig-paymentech'))[2];
41         my $g = qsearchs({
42               'table'     => 'payment_gateway',
43               'addl_from' => ' JOIN payment_gateway_option USING (gatewaynum) ',
44               'hashref'   => {  disabled    => '',
45                                 optionname  => 'merchant_id',
46                                 optionvalue => $merchant,
47                               },
48               });
49         $gateway = ($g ? $g->gatewaynum . '-' : '') . 'PaymenTech';
50       }
51       my ($hash, $oldhash) = @_;
52       my ($mon, $day, $year, $hour, $min, $sec) = 
53         $hash->{'_date'} =~ /^(..)(..)(....)(..)(..)(..)$/;
54       $hash->{'_date'} = timelocal($sec, $min, $hour, $day, $mon-1, $year);
55       $hash->{'paid'} = $oldhash->{'amount'};
56       $hash->{'paybatch'} = join(':', 
57         $gateway,
58         $hash->{'authorization'},
59         $hash->{'order_number'},
60       );
61     },
62   'approved'    => sub { my $hash = shift;
63                             $hash->{'approvalStatus'} 
64     },
65   'declined'    => sub { my $hash = shift;
66                             ! $hash->{'approvalStatus'} 
67     },
68 );
69
70 my %paytype = (
71   'personal checking' => 'C',
72   'personal savings'  => 'S',
73   'business checking' => 'X',
74   'business savings'  => 'X',
75 );
76
77 my %paymentech_countries = map { $_ => 1 } qw( US CA GB UK );
78
79 %export_info = (
80   init  => sub {
81 # Load this at run time
82     eval "use XML::Writer";
83     die $@ if $@;
84     my $conf = shift;
85     ($bin, $terminalID, $merchantID, $username, $password, $with_recurringInd) =
86        $conf->config('batchconfig-paymentech');
87     },
88 # Here we do all the work in the header function.
89   header => sub {
90     my $pay_batch = shift;
91     my @cust_pay_batch = @{(shift)};
92     my $count = 1;
93     my $output;
94     my $xml = new XML::Writer(OUTPUT => \$output, DATA_MODE => 1, DATA_INDENT => 2);
95     $xml->startTag('transRequest', RequestCount => scalar(@cust_pay_batch) + 1);
96     $xml->startTag('batchFileID');
97     $xml->dataElement(userID => $username);
98     $xml->dataElement(fileDateTime => time2str('%Y%m%d%H%M%S', time));
99     $xml->dataElement(fileID => 'FILEID');
100     $xml->endTag('batchFileID');
101
102     foreach (@cust_pay_batch) {
103       $xml->startTag('newOrder', BatchRequestNo => $count++);
104       my $status = $_->cust_main->status;
105       tie my %order, 'Tie::IxHash', (
106         industryType => 'EC',
107         transType    => 'AC',
108         bin          => $bin,
109         merchantID   => $merchantID,
110         terminalID   => $terminalID,
111         ($_->payby eq 'CARD') ? (
112           ccAccountNum => $_->payinfo,
113           ccExp        => $_->expmmyy,
114         ) : (
115           ecpCheckRT      => ($_->payinfo =~ /@(\d+)/),
116           ecpCheckDDA     => ($_->payinfo =~ /(\d+)@/),
117           ecpBankAcctType => $paytype{lc($_->cust_main->paytype)},
118           ecpDelvMethod   => 'A',
119         ),
120         avsZip          => substr($_->zip, 0, 10),
121         avsAddress1     => substr($_->address1, 0, 30),
122         avsAddress2     => substr($_->address2, 0, 30),
123         avsCity         => substr($_->city, 0, 20),
124         avsState        => $_->state,
125         avsName        => substr($_->first . ' ' . $_->last, 0, 30),
126         avsCountryCode => ( $paymentech_countries{ $_->country }
127                               ? $_->country
128                               : ''
129                           ),
130         orderID        => $_->paybatchnum,
131         amount         => $_->amount * 100,
132         );
133       # only do this if recurringInd is enabled in config, 
134       # and the customer has at least one non-canceled recurring package
135       if ( $with_recurringInd and $status =~ /^active|suspended|ordered$/ ) {
136         # then send RF if this is the first payment on this payinfo,
137         # RS otherwise.
138         $order{'recurringInd'} = $_->payinfo_used ? 'RS' : 'RF';
139       }
140       foreach my $key (keys %order) {
141         $xml->dataElement($key, $order{$key})
142       }
143       $xml->endTag('newOrder');
144     }
145     $xml->startTag('endOfDay', BatchRequestNo => $count);
146     $xml->dataElement(bin => $bin);
147     $xml->dataElement(merchantID => $merchantID);
148     $xml->dataElement(terminalID => $terminalID);
149     $xml->endTag('endOfDay');
150     $xml->endTag('transRequest');
151     return $output;
152   },
153   row => sub {},
154 );
155
156 # Including this means that there is a Business::BatchPayment module for
157 # this gateway and we want to upgrade it.
158 # Must return the name of the module, followed by a hash of options.
159
160 sub _upgrade_gateway {
161   my $conf = FS::Conf->new;
162   my @batchconfig = $conf->config('batchconfig-paymentech');
163   my %options;
164   @options{ qw(bin terminalID merchantID login password ) } = @batchconfig;
165   $options{'industryType'} = 'EC';
166   ( 'Paymentech', %options );
167 }
168
169 1;
170