RT#6583: Add get_returns method
authormark <mark>
Thu, 18 Feb 2010 03:51:25 +0000 (03:51 +0000)
committermark <mark>
Thu, 18 Feb 2010 03:51:25 +0000 (03:51 +0000)
Changes
lib/Business/OnlinePayment/Jety.pm

diff --git a/Changes b/Changes
index 8879c98..f237aef 100644 (file)
--- a/Changes
+++ b/Changes
@@ -1,5 +1,8 @@
 Revision history for Business-OnlinePayment-Jety
 
+0.06    Wed Feb 17 19:49:45 PST 2010
+        - Add get_returns method.
+
 0.05    unreleased
         - add a full timestamp to the 'ref' autogeneration to avoid collisions
 
index 11fc85c..f653e8a 100644 (file)
@@ -1,7 +1,7 @@
 package Business::OnlinePayment::Jety;
 
 use strict;
-use Carp;
+use Carp 'croak';
 use Business::OnlinePayment 3;
 use Business::OnlinePayment::HTTPS;
 use vars qw($VERSION @ISA $me $DEBUG);
@@ -10,45 +10,85 @@ use Date::Format;
 use Tie::IxHash;
 
 @ISA = qw(Business::OnlinePayment::HTTPS);
-$VERSION = '0.04';
+$VERSION = '0.06';
 $me = 'Business::OnlinePayment::Jety';
 
 $DEBUG = 0;
 
-my @fields = (qw(
-  username
+my %trans_type = (
+  'normal authorization' => 'echeck',
+  'void'                 => 'ereturn',
+  );
+
+my %map = (
+# 'function' will always be prepended
+'normal authorization' => [ # note array-ness
+  'username'      => 'login',
+  'password'      => 'password',
+  'firstname'     => 'first_name',
+  'lastname'      => 'last_name',
+  'address1'      => 'address',
+  'address2'      => 'address2',
+  'city'          => 'city',
+  'state'         => 'state',
+  'zip'           => 'zip',
+  'email'         => 'email',
+  'phone'         => 'phone',
+  'programdesc'   => 'description',
+  'ref'           => sub { my %c = @_; 
+                           $c{'order_number'} || 
+                           substr( time2str('%Y%m%d%H%M%S',time). int(rand(10000)), -15 ) 
+                           },
+  'bankname'      => 'bank_name',
+  'bankcity'      => 'bank_city',
+  'bankstate'     => 'bank_state',
+  'accountaba'    => 'routing_code',
+  'accountdda'    => 'account_number',
+  'amount'        => sub { my %c = @_; sprintf("%.02f",$c{'amount'}) },
+],
+'void' => [
+  'username'      => 'login',
+  'password'      => 'password',
+  'ref'           => 'order_number',
+  'accountdda'    => 'account_number',
+  'amount'        => sub { my %c = @_; sprintf("%.02f",$c{'amount'}) },
+],
+);
+
+my %defaults = ( # using the B:OP names
+  'phone'         => '111-111-1111',
+  'bank_name'     => 'unknown',
+  'bank_city'     => 'unknown',
+  'bank_state'    => 'XX',
+  );
+
+my %required = (
+'normal authorization' => [ qw(
+  type
+  action
+  login
   password
-  function
-  firstname
-  lastname
-  address1
-  address2
+  first_name
+  last_name
+  address
   city
   state
   zip
   email
-  phone
-  programdesc
-  ref
-  bankname
-  bankcity
-  bankstate
-  accountaba
-  accountdda
+  account_number
+  routing_code
   amount
-));
-
-my %map = (
-  'login'          => 'username',
-  'first_name'     => 'firstname',
-  'last_name'      => 'lastname',
-  'address'        => 'address1',
-  'bank_name'      => 'bankname',
-  'bank_city'      => 'bankcity',
-  'bank_state'     => 'bankstate',
-  'account_number' => 'accountdda',
-  'routing_code'   => 'accountaba',
-  'description'    => 'programdesc',
+  description
+) ],
+'void' => [ qw(
+  type
+  action
+  login
+  password
+  order_number
+  account_number
+  amount
+) ],
 );
 
 sub set_defaults {
@@ -59,30 +99,6 @@ sub set_defaults {
   return;
 }
 
-sub map_fields {
-  my $self = shift;
-  my $content = $self->{_content};
-
-  $self->remap_fields(%map);
-
-  die "Jety API only supports ECHECK payments.\n" 
-    if(lc($content->{type}) ne 'echeck');
-  die "Jety interface only supports Normal Authorization.\n"
-    if(lc($content->{action}) ne 'normal authorization');
-
-  $content->{'function'} = 'echeck';
-  $content->{'ref'} =
-    substr( time2str('%Y%m%d%H%M%S',time). int(rand(10000)), -15 );
-
-  $content->{'phone'} ||= '111-111-1111';
-
-  $content->{'bankname'} ||= 'unknown';
-  $content->{'bankcity'} ||= 'unknown';
-  $content->{'bankstate'} ||= 'XX';
-
-  return;
-}
-
 sub submit {
   my $self = shift;
   $Business::OnlinePayment::HTTPS::DEBUG = $DEBUG;
@@ -95,23 +111,30 @@ sub submit {
            $self->{_content}->{$_} eq '');
   }
 
-  $self->required_fields(qw(
-    type
-    action
-    first_name
-    last_name
-    address
-    city
-    state
-    zip
-    email
-    account_number
-    routing_code
-    amount
-    description
-  ));
-  $self->map_fields;
-  tie my %request, 'Tie::IxHash', map { $_ => $self->{_content}->{$_} } @fields;
+  my %content = $self->content();
+  my $action = lc($content{'action'});
+
+  croak "Jety only supports ECHECK payments.\n"
+    if( lc($content{'type'}) ne 'echeck' );
+  croak "Unsupported transaction type: '$action'\n"
+    if( !exists($trans_type{$action}) );
+
+  $self->required_fields(@{ $required{$action} });
+
+  my @fields = @{ $map{$action} } ;
+  tie my %request, 'Tie::IxHash', ( 'function' => $trans_type{$action} );
+  while(@fields) {
+    my ($key, $value) = (shift (@fields), shift (@fields));
+    if( ref($value) eq 'CODE' ) {
+      $request{$key} = $value->(%content);
+    }
+    elsif (defined($content{$value}) and $content{$value} ne '') {
+      $request{$key} = $content{$value};
+    }
+    elsif (exists($defaults{$value})) {
+      $request{$key} = $defaults{$value};
+    } # else do nothing
+  }
 
   $DB::single = $DEBUG;
   if($self->test_transaction()) {
@@ -147,6 +170,69 @@ sub submit {
   return;
 }
 
+sub get_returns {
+# Required parameters:
+# ftp_user, ftp_pass, ftp_host, ftp_path
+# Optional:
+# start, end
+  eval('use Date::Parse q!str2time!; use Net::FTP; use File::Temp q!tempdir!');
+  die $@ if $@;
+
+  my $self = shift;
+# $self->required_fields, for processor options
+  my @missing;
+  my ($user, $pass, $host, $path) = map {
+    if($self->can($_) and $self->$_) {
+      $self->$_ ;
+    } else {
+      push @missing, $_; '';
+    } 
+  } qw(ftp_user ftp_pass ftp_host);
+  die "missing gateway option(s): ".join(', ',@missing)."\n" if @missing;
+  my $ftp_path = $self->ftp_path if $self->can('ftp_path');
+
+  my $start = $self->{_content}->{start};
+  $start &&= str2time($start);
+  $start ||= time - 86400;
+  $start = time2str('%Y%m%d',$start);
+
+  my $end = $self->{_content}->{end};
+  $end &&= str2time($end);
+  $end ||= time;
+  $end = time2str('%Y%m%d',$end);
+  
+  my $ftp = Net::FTP->new($host) 
+    or die "FTP connection to '$host' failed.\n";
+  $ftp->login($user, $pass) or die "FTP login failed: ".$ftp->message."\n";
+  $ftp->cwd($path) or die "can't chdir to $path\n" if $path;
+  my $tmp = tempdir(CLEANUP => 1);
+  my @files;
+  foreach my $filename ($ftp->ls) {
+    if($filename =~ /^\w+_RET(\d{8}).csv$/ 
+      and $1 >= $start 
+      and $1 <= $end ) {
+      $ftp->get($filename, "$tmp/$1") or die "Failed to download $filename: ".$ftp->message."\n";
+      push @files, $1;
+    }
+  }
+  $ftp->close;
+
+  my @tids;
+  foreach my $filename (@files) {
+    open IN, '<', "$tmp/$filename";
+    my @fields = split ',',<IN>; #fetch header row
+    my ($i) = grep { $fields[$_] eq 'AccountToID' } 0..(scalar @fields - 1);
+    $i ||= 1;
+    while(<IN>) {
+      my @fields = split ',', $_;
+      push @tids, $fields[$i];
+    }
+    close IN;
+  }
+  return @tids;
+}
+
 1;
 __END__