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