enable CardFortress in test database, #71513
[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
53 my @agents;
54 if ( $conf->exists('batch-spoolagent') ) {
55   @agents = qsearch('agent', { 'disabled' => '' });
56 } else {
57   @agents = (1);
58 }
59
60 foreach my $agent (@agents) {
61
62   my @batchconf;
63   if ( $conf->exists('batch-spoolagent') ) {
64     @batchconf = $conf->config('batchconfig-eft_canada', $agent->agentnum, 1);
65     if ( !length($batchconf[0]) ) {
66       warn "agent '".$agent->agent."' has no batchconfig-eft_canada setting; skipped.\n";
67       next;
68     }
69   } else {
70     @batchconf = $conf->config('batchconfig-eft_canada');
71   }
72   # user, password, transaction code, delay days
73   my $user = $batchconf[0] or die "no EFT Canada batch username configured\n";
74   my $pass = $batchconf[1] or die "no EFT Canada batch password configured\n";
75
76   my $host = 'ftp.eftcanada.com';
77   print STDERR "Connecting to $user\@$host...\n" if $opt_v;
78
79   my $sftp = Net::SFTP::Foreign->new( host     => $host,
80                                       user     => $user,
81                                       password => $pass,
82                                       timeout  => 30,
83                                     );
84   die "failed to connect to '$user\@$host'\n(".$sftp->error.")\n" if $sftp->error;
85
86   $sftp->setcwd('/Returns');
87
88   my $files = $sftp->ls('.', wanted => qr/\.txt$/, names_only => 1);
89   die "no response files found\n" if !@$files;
90
91   FILE: foreach my $filename (@$files) {
92     print STDERR "Retrieving $filename\n" if $opt_v;
93     $sftp->get("$filename", "$tmpdir/$filename");
94     if($sftp->error) {
95       warn "failed to download $filename\n";
96       next FILE;
97     }
98
99     #move to server archive dir
100     $sftp->rename("$filename", "Archive/$filename");
101     if($sftp->error) {
102       warn "failed to archive $filename on server\n";
103     } # process it anyway though
104
105     #copy to local archive dir
106     if ( $opt_a ) {
107       print STDERR "Copying $tmpdir/$filename to archive dir $opt_a\n"
108         if $opt_v;
109       system 'cp', "$tmpdir/$filename", $opt_a;
110       warn "failed to copy $tmpdir/$filename to $opt_a: $@" if $@;
111     }
112
113     open my $fh, "<$tmpdir/$filename";
114     # Some duplication with FS::pay_batch::import_results, but we're really 
115     # doing something different here.
116     my $csv = new Text::CSV_XS ( { quote_char => undef, sep_char => '|' } );
117     my %hash;
118     while (my $line = <$fh>) {
119       next if $line =~ /^\s*$/;
120       $csv->parse($line) or do {
121         warn "can't parse $filename: ".$csv->error_input."\n";
122         next FILE; #parsing errors = reading the wrong kind of file
123       };
124       @hash{@fields} = $csv->fields();
125       print STDERR "voiding paybatchnum#$hash{paybatchnum}\n" if $opt_v;
126       my $cpb = qsearchs('cust_pay_batch', 
127                           { paybatchnum => $hash{'paybatchnum'} });
128       if ( !$cpb ) {
129         warn "can't find paybatchnum #$hash{paybatchnum} ($hash{first} $hash{last}, $hash{paid})\n";
130         next;
131       }
132       my $error = $cpb->decline("Returned payment ($hash{returncode})");
133       if ( $error ) {
134         warn "can't void paybatchnum #$hash{paybatchnum}: $error\n";
135       }
136     }
137     close $fh;
138   }
139
140 }
141
142 print STDERR "Finished!\n" if $opt_v;
143
144 =head1 NAME
145
146 freeside-eftca-download - Retrieve payment batch responses from EFT Canada.
147
148 =head1 SYNOPSIS
149
150   freeside-eftca-download [ -v ] [ -a archivedir ] user
151
152 =head1 DESCRIPTION
153
154 Command line tool to download returned payment reports from the EFT Canada 
155 gateway and void the returned payments.  Uses the login and password from 
156 'batchconfig-eft_canada'.
157
158 -v: Be verbose.
159
160 -a directory: Archive response files in the provided directory.
161
162 user: freeside username
163
164 =head1 BUGS
165
166 You need to manually SFTP to ftp.eftcanada.com from the freeside account 
167 and accept their key before running this script.
168
169 =head1 SEE ALSO
170
171 L<FS::pay_batch>
172
173 =cut
174
175 1;
176