use strict;
use Carp;
-use Business::OnlinePayment
+use Business::OnlinePayment;
use Net::SSLeay qw(sslcat);
use vars qw($VERSION @ISA @EXPORT @EXPORT_OK $DEBUG);
require Exporter;
-@ISA - qw( Exporter AutoLoader Business::OnlinePayment);
+@ISA = qw( Exporter AutoLoader Business::OnlinePayment);
@EXPORT = qw();
@EXPORT_OK = qw();
$VERSION = '0.01';
$DEBUG = 0;
+my %pg_response_code = (
+ 'A01' => 'Transaction approved/completed',
+ 'U01' => 'Merchant not allowed to access customer account',
+ 'U02' => 'Customer account is in the ACH Direct "known bad" list',
+ 'U03' => 'Merchant daily limit exceeded',
+ 'U04' => 'Merchant monthly limit exceeded',
+ 'U05' => 'AVS state/zipcode check failed',
+ 'U06' => 'AVS state/area code check failed',
+ 'U07' => 'AVS anonymous email check failed',
+ 'U08' => 'Account has more transactions than the merchant\'s daily velocity'.
+ ' limit allows for',
+ 'U09' => 'Account has more transactions than the merchant\'s velocity'.
+ ' window allows for',
+ 'U10' => 'Transaction has the same attributes as another transaction'.
+ ' within the time set by the merchant',
+ 'U11' => '(RECUR TRANS NOT FOUND) Transaction types 40-42 only',
+ 'U12' => 'Original transaction not voidable or capture-able',
+ 'U13' => 'Transaction to be voided or captured was not found',
+ 'U14' => 'void/capture and original transaction types do not agree (CC/EFT)',
+ 'U18' => 'Void or Capture failed',
+ #'U19' => 'Account ABA number if invalid',
+ 'U19' => 'Account ABA number is invalid',
+ 'U20' => 'Credit card number is invalid',
+ 'U21' => 'Date is malformed',
+ 'U22' => 'Swipe data is malformed',
+ 'U23' => 'Malformed expiration date',
+ 'U51' => 'Merchant is not "live"',
+ 'U52' => 'Merchant not approved for transaction type (CC or EFT)',
+ 'U53' => 'Transaction amount exceeds merchant\'s per transaction limit',
+ 'U54' => 'Merchant\'s configuration requires updating call customer'.
+ ' support',
+ 'U80' => 'Transaction was declined due to preauthorization (ATM Verify)'.
+ ' result',
+ 'U84' => 'Preauthorizer not responding',
+ 'U85' => 'Preauthorizer error',
+ 'U83' => 'Transaction was declined due to authorizer declination',
+ 'U84' => 'Authorizer not responding',
+ 'U85' => 'Authorizer error',
+ 'U86' => 'Authorizer AVS check failed',
+ 'F01' => 'Required field is missing',
+ 'F03' => 'Name is not recognized',
+ 'F04' => 'Value is not allowed',
+ 'F05' => 'Field is repeated in message',
+ 'F07' => 'Fields cannot both be present',
+ #'E10' => 'Merchant id or password in incorrect',
+ 'E10' => 'Merchant id or password is incorrect',
+ 'E20' => 'Transaction message not received (I/O flush required?)',
+ 'E90' => 'Originating IP not on merchant\'s approved IP list',
+ 'E99' => 'An unspecified error has occurred',
+);
+
sub set_defaults {
my $self = shift;
- $self->server('');
- $self->port( 5050 + 1000 * $self->test_transaction() );
- #$self->build_subs();
+ $self->server('paymentsgateway.net');
+ $self->port( 5050 );
+ $self->build_subs(qw(test_transaction));
}
sub map_fields {
my $self = shift;
$self->map_fields();
- my %content = $self->content();
+ #my %content = $self->content();
$self->revmap_fields(
- 'pg_merchant_id' => 'login',
+ 'PG_MERCHANT_ID' => 'login',
'pg_password' => 'password',
'pg_transaction_type' => \($self->transaction_type()),
#'pg_merchant_data_1'
'ecom_payment_check_account_type' => \'C', #checking
#'ecom_payment_check_checkno' =>
);
+ my %content = $self->content();
# name (first_name & last_name ) ?
# fax
#account_number routing_code bank_name
- my @fields = qw( pg_merchant_id pg_password pg_transaction_type ),
- ( map { "pg_merchant_$_" } (1..9) ),
- qw( pg_total_amount pg_sales_tax_amount pg_consumer_id
- ecom_consumerorderid ecom_walletid
- pg_billto_postal_name_company
- ecom_billto_postal_name_first ecom_billto_postal_name_last
- ecom_billto_postal_street_line1
- ecom_billto_postal_street_line2
- ecom_billto_postal_city ecom_billto_postal_stateprov
- ecom_billto_postal_postalcode ecom_billto_postal_countrycode
- ecom_billto_telecom_phone_number ecom_billto_online_email
- pg_billto_ssn pg_billto_dl_number pg_billto_dl_state
- );
+ my @fields = (
+ qw( PG_MERCHANT_ID pg_password pg_transaction_type ),
+ ( map { "pg_merchant_$_" } ( 1 .. 9 ) ),
+ qw( pg_total_amount pg_sales_tax_amount pg_consumer_id
+ ecom_consumerorderid ecom_walletid
+ pg_billto_postal_name_company
+ ecom_billto_postal_name_first ecom_billto_postal_name_last
+ ecom_billto_postal_street_line1
+ ecom_billto_postal_street_line2
+ ecom_billto_postal_city ecom_billto_postal_stateprov
+ ecom_billto_postal_postalcode ecom_billto_postal_countrycode
+ ecom_billto_telecom_phone_number ecom_billto_online_email
+ pg_billto_ssn pg_billto_dl_number pg_billto_dl_state
+ )
+ );
if ( $content{'type'} =~ /^check$/i ) {
push @fields, qw( ecom_payment_check_trn
ecom_payment_check_account
ecom_payment_check_account_type );
} else {
- croak $content{$type}. ' not (yet) supported';
+ croak $content{'type'}. ' not (yet) supported';
}
- my $request = join("\n", map { "$_=$content{$_}" } @fields ). "\n";
+ my $request = join("\n", map { "$_=". $content{$_} }
+ grep { $content{$_} ne '' }
+ @fields ).
+ "\nendofdata\n";
+
+ warn $request if $DEBUG;
+
+ warn "TEST: ". $self->test_transaction(). "\n" if $DEBUG;
+
+ $self->port( $self->port() + 1000 ) if $self->test_transaction();
+
+ warn "SERVER ". $self->server(). "\n" if $DEBUG;
+ warn "PORT ". $self->port(). "\n" if $DEBUG;
my $reply = sslcat( $self->server(), $self->port(), $request );
+ die "no reply from server" unless $reply;
- my %response = map { /^(\w+)=(.*)$/
+ warn "reply from server: $reply\n" if $DEBUG;
+
+ my %response = map { /^(\w+)=(.*)$/ or /^(endofdata)()$/
or warn "can't parse response line: $_";
($1, $2);
} split(/\n/, $reply);
if ( $response{'pg_response_type'} eq 'A' ) {
$self->is_success(1);
- $self->response_code($response{'pg_response_code'});
+ $self->result_code($response{'pg_response_code'});
$self->authorization($response{'pg_authorization_code'});
} else {
$self->is_success(0);
- $self->response_code($response{'pg_response_code'});
- $self->error_message($response{'pg_response_description'});
+ $self->result_code($response{'pg_response_code'});
+ $self->error_message( $pg_response_code{$response{'pg_response_code'}}.
+ ': '. $response{'pg_response_description'} );
}
}
1;
-#pod goes here
+__END__
+
+=head1 NAME
+
+Business::OnlinePayment::PaymentsGateway - PaymentsGateway.Net backend for Business::OnlinePayment
+
+=head1 SYNOPSIS
+
+ use Business::OnlinePayment;
+
+ my $tx = new Business::OnlinePayment("PaymentsGateway");
+ $tx->content(
+ type => 'CHECK',
+ login => 'test',
+ password => 'test',
+ action => 'Normal Authorization',
+ description => 'Business::OnlinePayment test',
+ amount => '49.95',
+ invoice_number => '100100',
+ name => 'Tofu Beast',
+ account_number => '12345',
+ routing_code => '123456789',
+ bank_name => 'First National Test Bank',
+ );
+ $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
+
+This module only implements 'CHECK' (ACH) transactions at this time. Credit
+card transactions are not (yet) supported.
+
+=head1 COMPATIBILITY
+
+This module implements the interface documented in the
+"PaymentsGateway.net Integration Guide, Version 2.1, September 2002"
+
+=head1 AUTHOR
+
+Ivan Kohler <ivan-paymentsgateway@420.am>
+
+=head1 SEE ALSO
+
+perl(1). L<Business::OnlinePayment>
+
+=cut