+package Business::OnlinePayment::eWay;
+
+use strict;
+use Carp;
+use Business::OnlinePayment;
+use Business::CreditCard;
+use Net::SSLeay qw( post_https );
+use XML::Simple;
+use vars qw($VERSION @ISA @EXPORT @EXPORT_OK $DEBUG);
+
+require Exporter;
+
+@ISA = qw(Exporter AutoLoader Business::OnlinePayment);
+@EXPORT = qw();
+@EXPORT_OK = qw();
+$VERSION = '0.01';
+
+$DEBUG = 1;
+
+my $default_path = '/gateway/xmlpayment.asp';
+my $default_cvn_path = '/gateway_cvn/xmlpayment.asp';
+my $default_test_path = '/gateway/xmltest/testpage.asp';
+my $default_cvn_test_path = '/gateway_cvn/xmltest/testpage.asp';
+
+sub set_defaults {
+ my $self = shift;
+ $self->server('www.eway.com.au');
+ $self->port('443');
+ $self->path($default_path);
+}
+
+sub revmap_fields {
+ my($self,%map) = @_;
+ my %content = $self->content();
+ foreach(keys %map) {
+ $content{$_} = ref($map{$_})
+ ? ${ $map{$_} }
+ : (exists($content{$map{$_}})
+ ? $content{$map{$_}}
+ : ''
+ );
+ }
+ $self->content(%content);
+}
+
+sub get_fields {
+ my($self,@fields) = @_;
+
+ my %content = $self->content();
+ my %new = ();
+ foreach( grep defined $content{$_}, @fields) { $new{$_} = $content{$_}; }
+ return %new;
+}
+
+sub submit {
+ my($self) = @_;
+ my %content = $self->content;
+
+ my $action = lc($content{'action'});
+ die 'eSec only supports "Normal Authorization" transactions'
+ unless $action eq 'normal authorization';
+
+ $content{'expiration'} =~ /^(\d+)\D+(\d+)$/
+ or croak "unparsable expiration $content{expiration}";
+ my ($month, $year) = ( $1, $2 );
+ $month += 0;
+ $year %= 100; #not y2.1k safe
+
+ $content{'amount'} =~ /^(\d+\.+\d{0,2})$/
+ or croak "unparsable amount $content{amount}";
+ my $amount = $1*100;
+
+ my $address = $content{'address'} if exists $content{'address'};
+ $address .= $content{'city'} if exists $content{'city'};
+ $address .= $content{'state'} if exists $content{'state'};
+ $address .= '';
+
+ $self->revmap_fields(
+ ewayCustomerID => 'login',
+ ewayTotalAmount => \$amount,
+ ewayCustomerFirstName => 'first_name',
+ ewayCustomerLastName => 'last_name',
+ ewayCustomerEmail => 'email',
+ ewayCustomerAddress => \$address,
+ ewayCustomerPostcode => 'zip',
+ ewayCustomerInvoiceDescription => 'description',
+ ewayCustomerInvoiceRef => 'invoice_number',
+ ewayCardHoldersName => 'name',
+ ewayCardNumber => 'card_number',
+ ewayCardExpiryMonth => \$month,
+ ewayCardExpiryYear => \$year,
+ ewayTrxnNumber => 'transaction_number',
+ ewayOption1 => 'option1',
+ ewayOption2 => 'option1',
+ ewayOption3 => 'option1',
+ ewayCVN => 'cvv2',
+ );
+ %content = $self->content;
+ if ( $DEBUG ) {
+ warn "content:$_ => $content{$_}\n" foreach keys %content;
+ }
+
+ if ($self->transaction_type() eq 'CC' ) {
+ $self->required_fields(qw/action login amount name card_number expiration/);
+ } else {
+ croak("eWay can't handle transaction type: ".
+ $self->transaction_type());
+ }
+
+ my %post_data = $self->get_fields( map "$_", qw(
+ ewayCustomerID ewayTotalAmount ewayCustomerFirstName ewayCustomerLastName
+ ewayCustomerEmail ewayCustomerAddress ewayCustomerPostcode
+ ewayCustomerInvoiceDescription ewayCustomerInvoiceRef ewayCardHoldersName
+ ewayCardNumber ewayCardExpiryMonth ewayCardExpiryYear ewayTrxnNumber
+ ewayOption1 ewayOption2 ewayOption3 ewayCVN
+ ) );
+ if ( $DEBUG ) {
+ warn "post_data:$_ => $post_data{$_}\n" foreach keys %post_data;
+ }
+
+ my $pd = XMLout({%post_data}, 'NoAttr' => 1, 'RootName' => 'ewaygateway');
+ if ( $DEBUG ) {
+ warn $pd,"\n";
+ }
+ my $server = $self->server();
+ my $port = $self->port();
+ my $path = $self->path();
+ if ($post_data{ewayCVN} && $path eq $default_path){
+ $path = $default_cvn_path;
+ }
+ if ($self->test_transaction) {
+ if ($path eq $default_path) {
+ $path = $default_test_path;
+ }elsif ($path eq $default_cvn_path){
+ $path = $default_cvn_test_path;
+ }else{
+ croak "Test mode not supported for path: $path\n";
+ }
+ }
+
+ my($page,$server_response) =
+ post_https($server,$port,$path,'',$pd);
+ if ( $DEBUG ) {
+ warn $page,"\n";
+ }
+
+ my $response;
+ if ($server_response =~ /HTTP\/1\.1 200 OK/){
+ $response = XMLin($page);
+ }else{
+ $response->{ewayTrxnError} = $server_response;
+ }
+
+ if ( $response->{ewayTrxnStatus} =~ /^True/ ) {
+ $self->is_success(1);
+ $self->authorization($response->{ewayAuthCode});
+ } else {
+ $self->is_success(0);
+ }
+ $self->error_message($response->{ewayTrxnError});
+ $self->server_response($response);
+}
+
+1;
+__END__
+
+=head1 NAME
+
+Business::OnlinePayment::eWay - eWay backend for Business::OnlinePayment
+
+=head1 SYNOPSIS
+
+ use Business::OnlinePayment;
+
+ my $tx = new Business::OnlinePayment("eWay");
+ $tx->content(
+ login => '87654321', #ewayCustomerID
+ action => 'Normal Authorization',
+ description => 'Business::OnlinePayment test',
+ amount => '49.95',
+ invoice_number => '100100',
+ name => 'Tofu Beast',
+ card_number => '46464646464646',
+ expiration => '11/08',
+ );
+ $tx->submit();
+
+ if($tx->is_success()) {
+ print "Card processed successfully: ".$tx->authorization."\n";
+ } else {
+ print "Card was rejected: ".$tx->error_message."\n";
+ }
+
+=head1 DESCRIPTION
+
+For detailed information see L<Business::OnlinePayment>.
+
+=head1 NOTE
+
+=head1 COMPATIBILITY
+
+This module implements eWay's XML API. See
+http://www.eway.com.au/support/xml.aspx for details.
+
+=head1 AUTHOR
+
+Jeff Finucane <jeff@cmh.net>
+
+=head1 SEE ALSO
+
+perl(1). L<Business::OnlinePayment>.
+
+=cut
+