Subject: | B:OP::AN reports a failure when fields contain the encapsulation character, even when the transaction succeeds |
Business::OnlinePayment::AuthorizeNet 3.15 (and all earlier versions)
will incorrectly report a transaction as failed when it actually has
succeeded if the AuthorizeNet gateway response contains double quotes
(") that are not used for encapsulation. This could happen if any
user-supplied field (e.g., the "company" field, or the "description"
field) contains the encapsulation character. For example, the
following company name will trigger this behavior:
"PerlShop" - for all your Perl needs
When the string is passed back in the response data, the double-quotes
will not be escaped, and Text::CSV_XS::parse will fail. Since
B::OP::AN does not check parse()'s return status, the transaction will
be reported as unsuccessful, even if the Authorize.Net backend
succeeded in debiting or crediting the account. The Perl module returns
an error_message value starting with:
DEBUG: No x_response_code from server, (HTTPS response: HTTP/1.1 200 OK)
The attached patch fixes this bug. It will check all of the supplied
user data to ensure that no instances of the encapsulation character
are submitted to Authorize.Net (outside of the x_encap_char field,
that is). The transaction will be aborted before Authorize.Net is
ever called. This is not an ideal solution -- ideally, we'd like
Authorize.Net to escape instances of the encapsulation character in
field data. However, Authorize.Net does not implement this.
I also considered silently stripping out the encapsulation character
from passed-in user data, but rejected this method on the grounds that
some applications may depend on receiving the same data back that was
originally submitted.
Comments are welcome,
- Paul
Business::OnlinePayment::AuthorizeNet 3.15 (and all earlier versions)
will incorrectly report a transaction as failed when it actually has
succeeded if the AuthorizeNet gateway response contains double quotes
(") that are not used for encapsulation. This could happen if any
user-supplied field (e.g., the "company" field, or the "description"
field) contains the encapsulation character. For example, the
following company name will trigger this behavior:
"PerlShop" - for all your Perl needs
When the string is passed back in the response data, the double-quotes
will not be escaped, and Text::CSV_XS::parse will fail. Since
B::OP::AN does not check parse()'s return status, the transaction will
be reported as unsuccessful, even if the Authorize.Net backend
succeeded in debiting or crediting the account. The Perl module returns
an error_message value starting with:
DEBUG: No x_response_code from server, (HTTPS response: HTTP/1.1 200 OK)
The following patch fixes this bug. It will check all of the supplied
user data to ensure that no instances of the encapsulation character
are submitted to Authorize.Net (outside of the x_encap_char field,
that is). The transaction will be aborted before Authorize.Net is
ever called. This is not an ideal solution -- ideally, we'd like
Authorize.Net to escape instances of the encapsulation character in
field data. However, Authorize.Net does not implement this.
I also considered silently stripping out the encapsulation character
from passed-in user data, but rejected this method on the grounds that
some applications may depend on receiving the same data back that was
originally submitted.
Comments are welcome,
- Paul
--- AuthorizeNet.pm.orig 2005-10-21 18:48:03.000000000 -0700
+++ AuthorizeNet.pm 2005-10-21 18:54:48.000000000 -0700
@@ -194,10 +194,33 @@
$post_data{'x_Test_Request'} = $self->test_transaction()?"TRUE":"FALSE";
$post_data{'x_ADC_Delim_Data'} = 'TRUE';
$post_data{'x_delim_char'} = ',';
- $post_data{'x_encap_char'} = '"';
+ $post_data{'x_encap_char'} = my $encap_char = '"';
$post_data{'x_ADC_URL'} = 'FALSE';
$post_data{'x_Version'} = '3.1';
+ # Abort the transaction if any instances of the encapsulation
+ # character occur in the content parameters that the user passed
+ # in. This is necessary since Authorize.Net will not properly
+ # escape the encapsulation character if it occurs within field
+ # data when it sends back its response. This can cause
+ # Text::CSV_XS to fail the response parse, which in turn can cause
+ # the caller to believe that a transaction has failed, when it
+ # actually has succeeded.
+ #
+ while (my ($k, $v) = each %post_data) {
+ next if $k eq 'x_encap_char';
+
+ if (index ($v, $encap_char) > -1) {
+ # Fail the request
+ $self->is_success(0);
+ $self->error_message("This transaction cannot be processed, ".
+ "since the $k field contains at least ".
+ "one $encap_char character. Please ".
+ "remove this character and resubmit.");
+ return;
+ };
+ };
+
my $pd = make_form(%post_data);
my $s = $self->server();
my $p = $self->port();
@@ -207,7 +230,7 @@
#escape NULL (binary 0x00) values
$page =~ s/\x00/\^0/g;
- my $csv = new Text::CSV_XS({ 'binary'=>1 });
+ my $csv = new Text::CSV_XS({ 'binary'=>1, 'quote_char'=>$encap_char });
$csv->parse($page);
my @col = $csv->fields();