use DateTime;
use XML::Writer;
use XML::Simple;
+use Try::Tiny;
use Moose;
with 'Business::BatchPayment::Processor';
my $self = shift;
my $batch = shift;
- # not doing anything with batch_id
- my $items = $batch->items;
- my $num_items = scalar @$items;
-
my $output;
my $xml = XML::Writer->new(
OUTPUT => \$output,
DATA_MODE => 1,
DATA_INDENT => 2,
);
+ $self->format_header($batch, $xml);
+ my $count = 1;
+ foreach my $item ( @{ $batch->items } ) {
+ try {
+ $self->format_item($item, $batch, $xml, $count);
+ $count++;
+ } catch {
+ $self->format_error($item, $_);
+ };
+ }
+ $self->format_trailer($batch, $xml, $count);
+ return $output;
+}
+
+sub format_header {
+ my ($self, $batch, $xml) = @_;
+ my $num_items = $batch->count;
+
$xml->startTag('transRequest', RequestCount => $num_items + 1);
$xml->startTag('batchFileID');
$xml->dataElement(userID => $self->login);
$xml->dataElement(fileDateTime => $self->fileDateTime);
$xml->dataElement(fileID => $self->fileDateTime);
$xml->endTag('batchFileID');
+}
- my $count = 1;
- foreach my $item (@$items) {
- if ( $item->action eq 'payment' ) {
- $xml->startTag('newOrder', BatchRequestNo => $count);
- my @order = (
- industryType => $self->industryType,
- transType => 'AC',
- bin => $self->bin,
- merchantID => $self->merchantID,
- terminalID => $self->terminalID,
+sub format_item {
+ my ($self, $item, $batch, $xml, $count) = @_;
+ if ( $item->action eq 'payment' ) {
+ $xml->startTag('newOrder', BatchRequestNo => $count);
+ my @order = (
+ industryType => $self->industryType,
+ transType => 'AC',
+ bin => $self->bin,
+ merchantID => $self->merchantID,
+ terminalID => $self->terminalID,
+ );
+ if ($item->payment_type eq 'CC') {
+ push @order, (
+ ccAccountNum => $item->card_number,
+ ccExp => $item->expiration,
);
- if ($item->payment_type eq 'CC') {
- push @order, (
- ccAccountNum => $item->card_number,
- ccExp => $item->expiration,
- );
- }
- elsif ( $item->payment_type eq 'ECHECK' ) {
- push @order, (
- cardBrand => 'EC',
- ecpCheckRT => $item->routing_code,
- ecpCheckDDA => $item->account_number,
- ecpBankAcctType => $BankAcctType{ $item->account_type },
- ecpDelvMethod => 'A',
- );
- }
- else {
- die "payment type ".$item->type." not supported";
- }
+ }
+ elsif ( $item->payment_type eq 'ECHECK' ) {
push @order, (
- avsZip => $item->zip,
- avsAddress1 => substr($item->address, 0, 30),
- avsAddress2 => substr($item->address2, 0, 30),
- avsCity => substr($item->city, 0, 20),
- avsState => $item->state,
- avsName => substr($item->first_name .' '. $item->last_name, 0, 30),
- avsCountryCode => $item->country,
- orderID => $item->tid,
- amount => int( $item->amount * 100 ),
+ cardBrand => 'EC',
+ ecpCheckRT => $item->routing_code,
+ ecpCheckDDA => $item->account_number,
+ ecpBankAcctType => $BankAcctType{ $item->account_type },
+ ecpDelvMethod => 'A',
);
- while (@order) {
- my $key = shift @order;
- my $value = shift @order;
- $xml->dataElement($key, $value);
- }
- $xml->endTag('newOrder');
- } # if action eq 'payment'
+ }
else {
- die "action ".$item->action." not supported";
+ die "payment type ".$item->type." not supported";
}
+ push @order, (
+ avsZip => $item->zip,
+ avsAddress1 => substr($item->address, 0, 30),
+ avsAddress2 => substr($item->address2, 0, 30),
+ avsCity => substr($item->city, 0, 20),
+ avsState => $item->state,
+ avsName => substr($item->first_name .' '. $item->last_name, 0, 30),
+ avsCountryCode => $item->country,
+ orderID => $item->tid,
+ amount => int( $item->amount * 100 ),
+ );
+ while (@order) {
+ my $key = shift @order;
+ my $value = shift @order;
+ $xml->dataElement($key, $value);
+ }
+ $xml->endTag('newOrder');
+ } # if action eq 'payment'
+ else {
+ die "action ".$item->action." not supported";
+ }
+ '';
+}
- $count++;
- } # foreach $item
-
+sub format_trailer {
+ my ($self, $batch, $xml, $count) = @_;
$xml->startTag('endOfDay', 'BatchRequestNo', $count);
$xml->dataElement('bin' => $self->bin);
$xml->dataElement('merchantID' => $self->merchantID);
$xml->dataElement('terminalID' => $self->terminalID);
$xml->endTag('endOfDay');
-
$xml->endTag('transRequest');
-
- return $output;
}
sub parse_response {
my $self = shift;
my $input = shift;
+ my $batch = Business::BatchPayment->create('Batch');
my $tree = XML::Simple::XMLin($input, KeepRoot => 1);
my $newOrderResp = $tree->{transResponse}->{newOrderResp};
unless defined $newOrderResp;
$newOrderResp = [ $newOrderResp ] if ref($newOrderResp) ne 'ARRAY';
- my $items;
foreach my $resp (@$newOrderResp) {
- my ($mon, $day, $year, $hour, $min, $sec) =
- $resp->{respDateTime} =~ /^(..)(..)(....)(..)(..)(..)$/;
- my $dt = DateTime->new(
- year => $year,
- month => $mon,
- day => $day,
- hour => $hour,
- minute => $min,
- second => $sec,
- );
-
- my $item = Business::BatchPayment->create(Item =>
- tid => $resp->{orderID},
- process_date => $dt,
- authorization => $resp->{authorizationCode},
- order_number => $resp->{txRefNum},
- approved => ($resp->{approvalStatus} == 1),
- error_message => $resp->{procStatusMessage},
- );
- push @$items, $item;
- }
- if ( @$items ) {
- return Business::BatchPayment->create(Batch => items => $items);
- } else {
- return;
+ try {
+ $batch->push( $self->parse_item($resp) );
+ } catch {
+ # parse_error needs a string representation of the
+ # input data...and if it 's failing because it wasn't valid
+ # XML, we wouldn't get this far.
+ $self->parse_error(XML::Simple::XMLout($resp), $_);
+ };
}
+ $batch;
+}
+
+sub parse_item {
+ my ($self, $resp) = @_;
+
+ my ($mon, $day, $year, $hour, $min, $sec) =
+ $resp->{respDateTime} =~ /^(..)(..)(....)(..)(..)(..)$/;
+ my $dt = DateTime->new(
+ year => $year,
+ month => $mon,
+ day => $day,
+ hour => $hour,
+ minute => $min,
+ second => $sec,
+ );
+
+ my $item = Business::BatchPayment->create(Item =>
+ tid => $resp->{orderID},
+ process_date => $dt,
+ authorization => $resp->{authorizationCode},
+ order_number => $resp->{txRefNum},
+ approved => ($resp->{approvalStatus} == 1),
+ error_message => $resp->{procStatusMessage},
+ );
+ $item;
}
package Business::BatchPayment::Paymentech::Transport;