package Business::OnlinePayment::PXPost;

use strict;
use Carp;
use Tie::IxHash;
use Business::OnlinePayment 3;
use Business::OnlinePayment::HTTPS 0.03;
use vars qw($VERSION $DEBUG @ISA);

@ISA = qw(Business::OnlinePayment::HTTPS);
$VERSION = '0.01';
$DEBUG = 0;

sub set_defaults {
    my $self = shift;

    $self->server('www.paymentexpress.com');
    $self->port('443');
    $self->path('/pxpost.asp');

    $self->build_subs(qw( order_number ));
     #avs_code order_type md5 cvv2_response cavv_response
}

sub submit {
    my($self) = @_;

    $self->remap_fields(
        'login'       => 'PostUsername',
        'password'    => 'PostPassword',
        'name'        => 'CardHolderName',
        'card_number' => 'CardNumber',
        #'expiration'  => 'DateExpiry',
        'amount'      => 'Amount',
        'cvv2'        => 'Cvc2',
        'action'      => 'TxnType',
        'currency'    => 'InputCurrency',
        #''            => 'TxnId',
        #''            => 'MerchantReference',
        #''            => 'TxnData1',
        #''            => 'TxnData2',
        #''            => 'TxnData3',
        #''            => 'DpsTxnRef', #XXX
        #''            => 'DpsBillingId',
        #''            => 'BillingId',
        #''            => 'EnableAddBillCard',
    );

    my $action = $self->{_content}{'TxnType'};
    if ( $action =~ /^\s*normal\s*authorization\s*$/i ) {
      $action = 'Purchase';
    } elsif ( $action =~ /^\s*authorization\s*only\s*$/i ) {
      $action = 'Auth';
    } elsif ( $action =~ /^\s*post\s*authorization\s*$/i ) {
      $action = 'Complete';
    } elsif ( $action =~ /^\s*void\s*$/i ) {
      die "DPS PXPost does not support void transactions\n";
    } elsif ( $action =~ /^\s*credit\s*$/i ) {
      $action = 'Refund';
    }
    $self->{_content}{'TxnType'} = $action;

    if ( $action =~ /^(Purchase|Auth)$/ ) {
#
      $self->required_fields(
        qw( login password name card_number expiration amount )
      );

      #exp
      $self->{_content}{'expiration'} =~ /^(\d+)\D+\d*(\d{2})$/
        or croak "unparsable expiration ". $self->{_content}{expiration};
      my( $month, $year ) = ( $1, $2 );
      $month = '0'. $month if $month =~ /^\d$/;
      $self->{_content}{'DateExpiry'} = $month.$year;

    } elsif ( $action eq 'Complete' || $action eq 'Refund' ) {

      $self->required_fields(
        qw( login password name order_number amount )
      );

    }


    tie my %fields, 'Tie::IxHash', $self->get_fields( $self->fields );
    my $post_data = join("\n",
      '<Txn>',
      ( map "<$_>$fields{$_}</$_>", keys %fields ),
      '</Txn>',
    ). "\n";

    warn $post_data if $DEBUG > 1;

    my( $page, $response, @reply_headers ) = $self->https_post( $post_data );

    $self->server_response($page);

    my $result = $self->GetXMLProp($page, 'Authorized');

    if ( $result =~ /^\s*1\s*$/ ) {
      $self->is_success(1);
      $self->result_code( $self->GetXMLProp( $page, 'ReCo' ) );
      $self->authorization( $self->GetXMLProp( $page, 'AuthCode' ) );
      $self->order_number( $self->GetXMLProp( $page, 'DpsTxnRef' ) );
    } elsif ( $result =~ /^\s*0\s*$/ ) {
      $self->is_success(0);
      $self->result_code( $self->GetXMLProp( $page, 'ReCo' ) );
      $self->error_message( $self->GetXMLProp( $page, 'ResponseText' ). ': '.
                            $self->GetXMLProp( $page, 'HelpText'     )
                          );
    } else {
      die "unparsable response received from gateway (response $result)".
          ( $DEBUG ? ": $page" : '' );
    }

}

sub fields {
        my $self = shift;

        #order is important to this processor
        qw(
          PostUsername
          PostPassword
          CardHolderName
          CardNumber
          DateExpiry
          Amount
          Cvc2
          TxnType
          InputCurrency
          TxnId
          MerchantReference
          TxnData1
          TxnData2
          TxnData3
          DpsTxnRef
          DpsBillingId
          BillingId
          EnableAddBillCard
        );
}

sub GetXMLProp {
        my( $self, $raw, $prop ) = @_;
        local $^W=0;

        my $data;
        ($data) = $raw =~ m"<$prop>(.*?)</$prop>"gsi;
        #$data =~ s/<.*?>/ /gs;
        chomp $data;
        return $data;
}

1;

__END__

=head1 NAME

Business::OnlinePayment::PXPost - Direct Payment Solutions PX Post backend module for Business::OnlinePayment

=head1 SYNOPSIS

  use Business::OnlinePayment;

  ####
  # One step transaction, the simple case.
  ####

  my $tx = new Business::OnlinePayment("PXPost");
  $tx->content(
      type           => 'VISA',
      login          => 'PXPost Username',
      password       => 'PXPost Password',
      action         => 'Normal Authorization',
      #description    => 'Business::OnlinePayment test',
      amount         => '49.95',
      name           => 'Tofu Beast',
      card_number    => '4005550000000019',
      expiration     => '08/06',
      cvv2           => '1234', #optional
  );
  $tx->submit();

  if($tx->is_success()) {
      print "Card processed successfully: ".$tx->authorization."\n";
  } else {
      print "Card was rejected: ".$tx->error_message."\n";
  }

=head1 SUPPORTED TRANSACTION TYPES

=head2 CC, Visa, MasterCard, American Express, Discover

Content required: type, login, password, action, amount, card_number, expiration, name.

=head1 PREREQUISITES

  URI::Escape
  Tie::IxHash

  Net::SSLeay _or_ ( Crypt::SSLeay and LWP )

=head1 DESCRIPTION

For detailed information see L<Business::OnlinePayment>.

=head1 NOTE

=head1 AUTHOR

Ivan Kohler <ivan-pxpost@420.am>

=head1 SEE ALSO

perl(1). L<Business::OnlinePayment>.

=cut

