use strict;
use Carp;
+use Business::OnlinePayment::HTTPS;
use Business::OnlinePayment::AuthorizeNet;
-use Net::SSLeay qw/make_form post_https make_headers/;
+use Business::OnlinePayment::AuthorizeNet::AIM::ErrorCodes '%ERRORS';
use Text::CSV_XS;
use vars qw($VERSION @ISA @EXPORT @EXPORT_OK);
-require Exporter;
-
-@ISA = qw(Exporter Business::OnlinePayment::AuthorizeNet);
-@EXPORT = qw();
-@EXPORT_OK = qw();
-$VERSION = '3.20';
+@ISA = qw(Business::OnlinePayment::AuthorizeNet Business::OnlinePayment::HTTPS);
+$VERSION = '3.24';
sub set_defaults {
my $self = shift;
- $self->server('secure.authorize.net') unless $self->server;
+ $self->server('secure2.authorize.net') unless $self->server;
$self->port('443') unless $self->port;
$self->path('/gateway/transact.dll') unless $self->path;
'post authorization' => 'PRIOR_AUTH_CAPTURE',
'void' => 'VOID',
);
- $content{'action'} = $actions{lc($content{'action'})} || $content{'action'};
+ $content{'action'} = $actions{lc($content{'action'} || '')} || $content{'action'};
# TYPE MAP
my %types = ('visa' => 'CC',
'discover' => 'CC',
'check' => 'ECHECK',
);
- $content{'type'} = $types{lc($content{'type'})} || $content{'type'};
+ $content{'type'} = $types{lc($content{'type'} || '')} || $content{'type'};
$self->transaction_type($content{'type'});
# ACCOUNT TYPE MAP
'business checking' => 'CHECKING',
'business savings' => 'SAVINGS',
);
- $content{'account_type'} = $account_types{lc($content{'account_type'})}
+ $content{'account_type'} = $account_types{lc($content{'account_type'} || '')}
|| $content{'account_type'};
- $content{'referer'} = defined( $content{'referer'} )
- ? make_headers( 'Referer' => $content{'referer'} )
- : "";
-
if (length $content{'password'} == 15) {
$content{'transaction_key'} = delete $content{'password'};
}
ship_state => 'x_Ship_To_State',
ship_zip => 'x_Ship_To_Zip',
ship_country => 'x_Ship_To_Country',
+ tax => 'x_Tax',
+ freight => 'x_Freight',
+ duty => 'x_Duty',
+ tax_exempt => 'x_Tax_Exempt',
+ po_number => 'x_Po_Num',
phone => 'x_Phone',
fax => 'x_Fax',
email => 'x_Email',
length $self->{_content}->{customer_org}
) {
push @required_fields, qw( customer_org customer_ssn );
- } else {
+ }
+ elsif ( defined $self->{_content}->{license_num} and
+ length $self->{_content}->{license_num}
+ ) {
push @required_fields, qw(license_num license_state license_dob);
}
x_Ship_To_Last_Name x_Ship_To_First_Name x_Ship_To_Company
x_Ship_To_Address x_Ship_To_City x_Ship_To_State x_Ship_To_Zip
x_Ship_To_Country
+ x_Tax x_Freight x_Duty x_Tax_Exempt x_Po_Num
x_Phone x_Fax x_Email x_Email_Customer x_Country
x_Currency_Code x_Trans_ID x_Duplicate_Window x_Track1 x_Track2/);
if ( $post_data{'x_Email_Customer'}
&& $post_data{'x_Email_Customer'} !~ /^FALSE$/i ) {
$post_data{'x_Email_Customer'} = 'TRUE';
- } else {
+ } elsif ( exists $post_data{'x_Email_Customer'} ) {
$post_data{'x_Email_Customer'} = 'FALSE';
}
+ my $data_string = join("", values %post_data);
+
+ my $encap_character;
+ # The first set of characters here are recommended by authorize.net in their
+ # encapsulating character example.
+ # The second set we made up hoping they will work if the first fail.
+ # The third chr(31) is the binary 'unit separator' and is our final last
+ # ditch effort to find something not in the input.
+ foreach my $char( qw( | " ' : ; / \ - * ), '#', qw( ^ + < > [ ] ~), chr(31) ){
+ if( index($data_string, $char) == -1 ){ # found one.
+ $encap_character = $char;
+ last;
+ }
+ }
+
+ if(!$encap_character){
+ $self->is_success(0);
+ $self->error_message(
+ "DEBUG: Input contains all encapsulating characters."
+ . " Please remove | or ^ from your input if possible."
+ );
+ return;
+ }
+
$post_data{'x_ADC_Delim_Data'} = 'TRUE';
$post_data{'x_delim_char'} = ',';
- $post_data{'x_encap_char'} = '"';
+ $post_data{'x_encap_char'} = $encap_character;
$post_data{'x_ADC_URL'} = 'FALSE';
$post_data{'x_Version'} = '3.1';
- my $pd = make_form(%post_data);
- my $s = $self->server();
- my $p = $self->port();
- my $t = $self->path();
- my $r = $self->{_content}->{referer};
- my($page,$server_response,%headers) = post_https($s,$p,$t,$r,$pd);
+ my $opt = defined( $self->{_content}->{referer} )
+ ? { 'headers' => { 'Referer' => $self->{_content}->{referer} } }
+ : {};
+
+ my($page, $server_response, %headers) =
+ $self->https_post( $opt, \%post_data );
+
#escape NULL (binary 0x00) values
$page =~ s/\x00/\^0/g;
#trim 'ip_addr="1.2.3.4"' added by eProcessingNetwork Authorize.Net compat
$page =~ s/,ip_addr="[\d\.]+"$//;
- my $csv = new Text::CSV_XS({ binary=>1, escape_char=>'' });
+ my $csv = new Text::CSV_XS({ binary=>1, escape_char=>'', quote_char => $encap_character });
$csv->parse($page);
my @col = $csv->fields();
$self->is_success(0);
$self->result_code($col[2]);
$self->error_message($col[3]);
- unless ( $self->result_code() ) { #additional logging information
+ if ( $self->result_code ) {
+ my $addl = $ERRORS{ $self->result_code };
+ $self->error_message( $self->error_message. ' - '. $addl->{notes})
+ if $addl && ref($addl) eq 'HASH' && $addl->{notes};
+ } else { #additional logging information
#$page =~ s/\x00/\^0/g;
$self->error_message($col[3].
" DEBUG: No x_response_code from server, ".
Business::OnlinePayment::AuthorizeNet::AIM - AuthorizeNet AIM backend for Business::OnlinePayment
-=head1 AUTHOR
-
-Jason Kohles, jason@mediabang.com
-
-Ivan Kohler <ivan-authorizenet@420.am> updated it for Authorize.Net protocol
-3.0/3.1 and is the current maintainer. Please send patches as unified diffs
-(diff -u).
-
-Jason Spence <jspence@lightconsulting.com> contributed support for separate
-Authorization Only and Post Authorization steps and wrote some docs.
-OST <services@ostel.com> paid for it.
-
-T.J. Mather <tjmather@maxmind.com> sent a number of CVV2 patches.
-
-Mike Barry <mbarry@cos.com> sent in a patch for the referer field.
-
-Yuri V. Mkrtumyan <yuramk@novosoft.ru> sent in a patch to add the void action.
-
-Paul Zimmer <AuthorizeNetpm@pzimmer.box.bepress.com> sent in a patch for
-card-less post authorizations.
-
-Daemmon Hughes <daemmon@daemmonhughes.com> sent in a patch for "transaction
-key" authentication as well support for the recurring_billing flag and the md5
-method that returns the MD5 hash which is returned by the gateway.
-
-Steve Simitzis contributed a patch for better compatibility with
-eProcessingNetwork's AuthorizeNet compatability mode.
-
=head1 SEE ALSO
perl(1). L<Business::OnlinePayment> L<Business::OnlinePayment::AuthorizeNet>.