EFT Canada batch format and scripts, #13628
[freeside.git] / FS / bin / freeside-eftca-download
1 #!/usr/bin/perl
2
3 use strict;
4 use Getopt::Std;
5 use Date::Format qw(time2str);
6 use File::Temp qw(tempdir);
7 use Net::SFTP::Foreign;
8 use Expect;
9 use FS::UID qw(adminsuidsetup datasrc);
10 use FS::Record qw(qsearch qsearchs);
11 use FS::pay_batch;
12 use FS::cust_pay_batch;
13 use FS::Conf;
14
15 use vars qw( $opt_v $opt_a );
16 getopts('va:');
17
18 #$Net::SFTP::Foreign::debug = -1;
19 sub HELP_MESSAGE { "
20   Usage:
21       freeside-eftca-download [ -v ] [ -a archivedir ] user\n
22 " }
23
24 my @fields = (
25   'tid',          # transaction ID
26   'paybatchnum',  # reference field
27   'returncode',   # status code
28   'returndate',
29   'paid',         # dollars and cents, with decimal
30   'type',
31   'first',
32   'last',
33   'account',
34   'bank',
35   'transit',
36 );
37
38 my $user = shift or die &HELP_MESSAGE;
39 adminsuidsetup $user;
40
41 if ( $opt_a ) {
42   die "no such directory: $opt_a\n"
43     unless -d $opt_a;
44   die "archive directory $opt_a is not writable by the freeside user\n"
45     unless -w $opt_a;
46 }
47
48 #my $tmpdir = File::Temp->newdir();
49 my $tmpdir = tempdir( CLEANUP => 1 ); #DIR=>somewhere?
50
51 my $conf = new FS::Conf;
52 my @batchconf = $conf->config('batchconfig-eft_canada');
53 # BIN, terminalID, merchantID, username, password
54 my $username = $batchconf[0] or die "no EFT Canada batch username configured\n";
55 my $password = $batchconf[1] or die "no EFT Canada batch password configured\n";
56
57 my $host = 'ftp.eftcanada.com';
58 print STDERR "Connecting to $username\@$host...\n" if $opt_v;
59
60 my $sftp = Net::SFTP::Foreign->new( host => $host,
61                                     user => $username,
62                                     password => $password,
63                                     timeout => 30,
64                                     );
65 die "failed to connect to '$username\@$host'\n(".$sftp->error.")\n" if $sftp->error;
66
67 $sftp->setcwd('/Returns');
68
69 my $files = $sftp->ls('.', wanted => qr/^ReturnFile/, names_only => 1);
70 die "no response files found\n" if !@$files;
71
72 FILE: foreach my $filename (@$files) {
73   print STDERR "Retrieving $filename\n" if $opt_v;
74   $sftp->get("$filename", "$tmpdir/$filename");
75   if($sftp->error) {
76     warn "failed to download $filename\n";
77     next FILE;
78   }
79
80   #move to server archive dir
81   $sftp->rename("$filename", "Archive/$filename");
82   if($sftp->error) {
83     warn "failed to archive $filename on server\n";
84   } # process it anyway though
85
86   #copy to local archive dir
87   if ( $opt_a ) {
88     print STDERR "Copying $tmpdir/$filename to archive dir $opt_a\n"
89       if $opt_v;
90     system 'cp', "$tmpdir/$filename", $opt_a;
91     warn "failed to copy $tmpdir/$filename to $opt_a: $@" if $@;
92   }
93
94   open my $fh, "<$tmpdir/$filename";
95   # Some duplication with FS::pay_batch::import_results, but we're really 
96   # doing something different here.
97   my $csv = new Text::CSV_XS ( { quote_char => undef, sep_char => '|' } );
98   my %hash;
99   while (my $line = <$fh>) {
100     next if $line =~ /^\s*$/;
101     $csv->parse($line) or do {
102       warn "can't parse $filename: ".$csv->error_input."\n";
103       next FILE; #parsing errors = reading the wrong kind of file
104     };
105     @hash{@fields} = $csv->fields();
106     print STDERR "voiding paybatchnum#$hash{paybatchnum}\n" if $opt_v;
107     my $cpb = qsearchs('cust_pay_batch', 
108                         { paybatchnum => $hash{'paybatchnum'} });
109     if ( !$cpb ) {
110       warn "can't find paybatchnum #$hash{paybatchnum} ($hash{first} $hash{last}, $hash{paid})\n";
111       next;
112     }
113     my $error = $cpb->decline("Returned payment ($hash{returncode})");
114     if ( $error ) {
115       warn "can't void paybatchnum #$hash{paybatchnum}: $error\n";
116     }
117   }
118   close $fh;
119 }
120
121 print STDERR "Finished!\n" if $opt_v;
122
123 =head1 NAME
124
125 freeside-eftca-download - Retrieve payment batch responses from EFT Canada.
126
127 =head1 SYNOPSIS
128
129   freeside-eftca-download [ -v ] [ -a archivedir ] user
130
131 =head1 DESCRIPTION
132
133 Command line tool to download returned payment reports from the EFT Canada 
134 gateway and void the returned payments.  Uses the login and password from 
135 'batchconfig-eft_canada'.
136
137 -v: Be verbose.
138
139 -a directory: Archive response files in the provided directory.
140
141 user: freeside username
142
143 =head1 BUGS
144
145 You need to manually SFTP to ftp.eftcanada.com from the freeside account 
146 and accept their key before running this script.
147
148 =head1 SEE ALSO
149
150 L<FS::pay_batch>
151
152 =cut
153
154 1;
155