default to a session cookie instead of setting an explicit timeout, weird timezone...
[freeside.git] / FS / bin / freeside-rbc-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); #0.19 for ->newdir() interface, not in 5.10.0
7 use Net::FTPSSL;
8 use FS::UID qw(adminsuidsetup dbh);
9 use FS::Record qw(qsearch qsearchs);
10 use FS::pay_batch;
11 use FS::Conf;
12
13 use vars qw( $opt_v $opt_a $opt_f $opt_n );
14 getopts('va:f:n');
15
16 #$Net::SFTP::Foreign::debug = -1;
17 sub usage { "
18   Usage:
19       freeside-rbc-download [ -v ] [ -n ] [ -a archivedir ] [ -f filename ] user\n
20 " }
21
22 sub debug {
23   print STDERR $_[0] if $opt_v;
24 }
25
26 my $user = shift or die &usage;
27 adminsuidsetup $user;
28
29 $FS::UID::AutoCommit = 0;
30 my $dbh = dbh;
31
32 if ( $opt_a ) {
33   die "no such directory: $opt_a\n"
34     unless -d $opt_a;
35   die "archive directory $opt_a is not writable by the freeside user\n"
36     unless -w $opt_a;
37 }
38
39 my $tmpdir = tempdir( CLEANUP => 1 ); #DIR=>somewhere?
40
41 my $conf = new FS::Conf;
42 my ($username, $password) = $conf->config('batchconfig-RBC-login');
43 $username and $password
44   or die "RBC FTP login not configured. Enter your username and password in 'batchconfig-rbc-login'.\n";
45
46 my $host = 'ftpssl.rbc.com';
47 debug "Connecting to $username\@$host...\n";
48
49 my $ftp = Net::FTPSSL->new($host,
50                            Timeout => 30,
51                            Debug => ($opt_v ? 1 : 0),
52                            Croak => 1, # rely on auto-rollback when dbh closes
53                           );
54 $ftp->login($username, $password);
55
56 # directory layout:
57 # ~/                          # upload to here
58 # ~/inbound
59 # ~/inbound/valid             # batches move here while being processed
60 # ~/outbound
61 # ~/outbound/XXXX             # string of four characters; results arrive here
62
63 $ftp->cwd('outbound');
64 for my $dir ( $ftp->nlst ) {
65   debug "Entering outbound/$dir\n";
66   $ftp->cwd($dir);
67   FILE: for my $filename ( $ftp->nlst ) {
68     debug "$filename...";
69     # filenames look like "RPT9999X.111".
70     # 9999 is the four-digit report type
71     # X is "P" for production or "T" for test
72     # 111 is the sequential file number
73     if ( $opt_f ) {
74       if ( $filename ne $opt_f ) {
75         debug "is not the requested file.\n";
76         next FILE;
77       }
78       # -f can be used to download/process any file, even one that doesn't fit
79       # the naming rule (e.g. those that are already downloaded).
80     } elsif ( $filename =~ /^RPT(\d{4})[PT]\.\d{3}$/ ) {
81       # fallthrough; don't currently reject files based on RPT type, because
82       # our parser should be able to figure it out
83     } else {
84       debug "skipped.\n";
85       next FILE;
86     }
87
88     debug "downloading.\n";
89     $ftp->get($filename, "$tmpdir/$filename");
90
91     #copy to archive dir
92     if ( $opt_a ) {
93       debug "Copying to archive dir $opt_a\n";
94       system 'cp', "$tmpdir/$filename", $opt_a;
95       warn "failed to copy $tmpdir/$filename to $opt_a: $!\n" if $!;
96     }
97
98     debug "Processing batch...";
99     open(my $fh, '<', "$tmpdir/$filename")
100       or die "couldn't read temp file: $!\n";
101
102     my $error = FS::pay_batch->import_results(
103       filehandle  => $fh,
104       format      => 'RBC',
105       no_close    => ($opt_n ? 1 : 0),
106     );
107
108     if ( $error ) {
109       die "Processing $filename failed:\n$error\n\n";
110     }
111
112     debug "done.\n";
113   } # FILE
114   $ftp->cdup();
115 } # $dir
116
117 debug "Finished.\n";
118 dbh->commit;
119 exit(0);
120
121 =head1 NAME
122
123 freeside-rbc-download - Retrieve payment batch responses from RBC.
124
125 =head1 SYNOPSIS
126
127   freeside-rbc-download [ -v ] [ -f filename ] [ -a archivedir ] user
128
129 =head1 DESCRIPTION
130
131 Command line tool to download payment batch responses from the Royal Bank of 
132 Canada ACH service. These files are fixed-width data files containing some
133 combination of valid, returned, or reversed payment records.
134
135 By default, the script will download any files with names like "RPT9999X.111"
136 where 9999 is a four-digit document type code (like "0900", all records), X is
137 the letter "P" for production or "T" for test mode, and 111 is a counter
138 incremented with each new response file. After the files are downloaded, RBC's
139 server will automatically rename them with the suffix '.downloaded%FTPS' to 
140 avoid double-processing them.
141
142
143 -v: Be verbose.
144
145 -f filename: Download a file with a specific name, instead of all files 
146 matching the pattern. This can be used to reprocess a specific file.
147
148 -a directory: Archive the files in the specified directory.
149
150 -n: Do not try to close batches after applying results.
151
152 user: freeside username
153
154 =head1 BUGS
155
156 =head1 SEE ALSO
157
158 L<FS::pay_batch>
159
160 =cut
161
162 1;
163