vcatalano / py-authorize

A full-featured Python API for the Authorize.net payment gateway.
MIT License
42 stars 35 forks source link

Response_code 2 returned with no reason code... #11

Closed fredstluka closed 10 years ago

fredstluka commented 10 years ago

Vincent,

This may be related to ticket #8, where you are not parsing the response from authorize.net properly. Or it may not...

Sometimes when I call Transaction.sale(), no exception is raised, but the return value contains transaction_response.response_code == '2' instead of '1'. And it contains no response_reason_code or response_reason_text. So I have no idea why the transaction was declined.

If this really is a bug in py-authorize, what can I do as a workaround? Can I safely ignore the transaction_response.response_code since no exception was raised, and assume the transaction went through OK? Or do I need a different workaround?

If it is not a bug in py-authorize, can you suggest how I might figure out what error was reported by authorize.net?

Thanks again for all your help! --Fred

fredstluka commented 10 years ago

I dug into this a little deeper and found that the XML returned by authorize.net is:

<?xml version="1.0" encoding="utf-8"?>
<createTransactionResponse xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:xsd="http://www.w3.org/2001/XMLSchema" xmlns="AnetApi/xml/v1/schema/AnetApiSchema.xsd">
    <messages>
        <resultCode>Ok</resultCode>
        <message>
            <code>I00001</code>
            <text>Successful.</text>
        </message>
    </messages>
    <transactionResponse>
        <responseCode>2</responseCode>
        <authCode />
        <avsResultCode>P</avsResultCode>
        <cvvResultCode />
        <cavvResultCode />
        <transId>2202344167</transId>
        <refTransID />
        <transHash>9C89491B9AF93F5CF85207FBD754B8DF</transHash>
        <testRequest>0</testRequest>
        <accountNumber>XXXX2345</accountNumber>
        <accountType>eCheck</accountType>
        <errors>
            <error>
                <errorCode>2</errorCode>
                <errorText>This transaction has been declined.</errorText>
            </error>
        </errors>
    </transactionResponse>
</createTransactionResponse>

So, it really is returning exactly what py-authorize shows. Not a bug in py-authorize.

On the other hand, py-authorize uses the fact that resultCode == 'Ok' to decide to not raise AuthorizeResponseError, even though the transaction was declined. Is that a bug in py-authorize? Or at least a failure to deal with a screwy behavior of authorize.net? Or do I misunderstand how I'm supposed to use it?

Any suggestions on how to find out why the transaction is being declined?

Thanks! --Fred

vcatalano commented 10 years ago

Thanks for digging deeper into this, Fred.

That does seem very strange that the resultCode == 'Ok'. This might be due to the fact that this is a transaction for an eCheck account type. I received this error quite a few times myself in a particular situation and it was ultimately due to Authorize.net setting a limit on transaction amounts for eCheck transactions on the dev environment (http://community.developer.authorize.net/t5/Integration-and-Testing/E-Check-E00027-2-1-2-This-transaction-has-been-declined/td-p/35136). Do you know if that is the case?

fredstluka commented 10 years ago

Vincent,

Yes, I think you are exactly right. It's a problem with my dev authorize.net account.

I just figured out the pattern myself. I set up a new server today to test against our PROD account at authorize.net instead of our TEST (dev) account. It works fine but we have to remember to void all of the transactions.

I concluded that the echeck portion of my dev account had expired. But your answer may be more precisely correct. Perhaps I've hit a limit on number of echeck transactions for a dev account. Makes sense since authorize.net can't really validate echeck transaction without sending them to the bank and waiting for a bounce, right?

Here's what I added just 10 minutes ago to my JIRA bug tracking system to be seen by my testers and fellow developers (Janice and Hans). If you see anything incorrect here, please enlighten me. Thanks!

If not, the only change I would recommend to py-authorize in this matter is to try to recognize the pattern of weird behavior that you get from authorize.net when an account has expired or hit such a limit, and try to report to your users that they should make sure their account has not expired or hit a limit. Thanks again!

Here's what I posted to my JIRA system:


OK. I have a theory.

At webtest1, none of the echeck transactions at authorize.net seem to be working, but the credit card transactions work fine.

At webtest2, they both work fine.

I think I've been the victim of bad luck.

After I got the code basically working a few days ago, it suddenly started not working sometimes. After digging deeply into the code of the new py-authorize library and examining the XML sent to/from authorize.net by that library and reporting a couple of minor bugs to the author of py-authorize (he's working on fixing them now), and sending questions to the support team at authorize.net (no reply yet), I've finally realized the pattern...

Suddenly, 2 days ago, something went wrong with our test account at authorize.net. Before that it worked fine. Since then, it fails in strange ways for all echeck transactions. Hans mentioned recently that he signed up for the account exactly one year ago to the day.

I think our authorize.net test account has expired!!!!!

Or at least the echeck option of it.

We may have to do all of our testing against PROD for a while, via webtest2.

Hans can you look into this and decide if there's a way to get the authorize.net account to work again? Or sign up for a new one? I haven't tried both of your accounts today because:

  1. You probably signed up for both around the same time, right? So they may both be expired.
  2. I don't have the username/password for hth1, only hth2.
  3. I'm pretty sure I tried them both briefly yesterday and couldn't get them to work.

Janice, can you repeat your tests on webtest2 instead of webtest1? You'll have to void the transactions when you do. I have already used your personal checking account routing number and the bogus 12345 account number twice.

I don't think authorize.net has a way to know that an account number is invalid, or that it doesn't match the name, address, etc. It can validate the routing number, but not the account number. So, it just sends the transaction to the bank, and waits to see if it bounces. As Janice and Susan told me the other day, it can take up to 3 weeks (or more) for a transaction to be found to be invalid, and then we have to scramble to move the money back out of the patient's balance if they haven't already applied for a disbursement.

So, I've piled up 2 transactions at Janice's bank, that will be rejected eventually, if we don't void them at authorize before they go to the bank. I don't want to keep doing that, so I'm going to stop testing, and just fix all of the rest of the items in this JIRA ticket.

Okay? --Fred

vcatalano commented 10 years ago

eCheck transactions are limited to $100 for the development environments. Are the transactions that are failing greater than $100?

fredstluka commented 10 years ago

Vincent. Good question. Maybe. Definitely a problem with the dev account. Things are working much better when I use our PROD authorize.net account.

--Fred

fredstluka commented 10 years ago

Vincent,

Got a good reply from authorize.net.

tl;dr:

More details in e-mail below:

-------- Original Message --------
Subject:    Re: What would cause Authorize.net to return a status of Ok when declining a transaction?...
Date:   Thu, 28 Nov 2013 09:16:00 -0500
From:   Fred Stluka <fred@bristle.com>
Organization:   Bristle Software, Inc.
To:     Developer (Authorize.Net) <developer@Authorize.Net>

Joy,

Thanks for the quick reply!  And thanks for raising my limit.
And thanks for the explanation about resultCode only applying
to the transaction status, not the status of the API call.  Good
info!

The only additional change I would suggest is that perhaps
authorize could return a specific errorCode or resultCode to
indicate that a transaction is being declined due to a sandbox
limit.  Is there a tracking system where I could enter such a
feature request?  Thanks!

Happy Thanksgiving!

--Fred Fred Stluka -- mailto:fred@bristle.com -- http://bristle.com/~fred/
Bristle Software, Inc -- http://bristle.com -- Glad to be of service!
Open Source: Without walls and fences, we need no Windows or Gates.

On 11/27/13 2:51 PM, Developer (Authorize.Net) wrote:
>
> Hi Fred,
>
>  
>
> It is always important to check the errorCode  to see the transaction status.  The resultCode only indicates if the API request was successful but it does not pertain to the status of the transaction itself.
>
>  
>
> By default all sandbox has a limit of $100 per transaction, when you try to submit more than your limit you will get a general decline which is what is happening in your case because you are processing $500. I increased your limit to $1000000 so this should not be an issue anymore as long as you don’t try to process more than $1000000.
>
>  
>
> Authorize.​Net Test Account FAQs      Are you an Authorize.​Net Affiliate Reseller yet?      Why should I become an Authorize.​Net Certified Partner?
>
>  
>
> Thanks,
>
> Joy Martin | Integration Support
>
> Authorize.Net® |  a CyberSource solution
>
> 808 E. Utah Valley Drive | American Fork, UT 84003
>
> developer@authorize.net | www.authorize.net
>
>  
>
>  
>
>  
>
>  
>
> From: Fred Stluka [mailto:fred@bristle.com]
> Sent: Tuesday, November 26, 2013 8:32 PM
> To: Developer (Authorize.Net)
> Subject: What would cause Authorize.net to return a status of Ok when declining a transaction?...
>
>  
>
> Authorize.net support,
>
> 2 questions:
>
> 1. What would cause Authorize.net to return a status of Ok when
>     declining  a transaction?
>
>     I got back this XML response:
>
>     <?xml version="1.0" encoding="utf-8"?>
>     <createTransactionResponse xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:xsd="http://www.w3.org/2001/XMLSchema" xmlns="AnetApi/xml/v1/schema/AnetApiSchema.xsd">
>         <messages>
>             <resultCode>Ok</resultCode>
>             <message>
>                 <code>I00001</code>
>                 <text>Successful.</text>
>             </message>
>         </messages>
>         <transactionResponse>
>             <responseCode>2</responseCode>
>             <authCode />
>             <avsResultCode>P</avsResultCode>
>             <cvvResultCode />
>             <cavvResultCode />
>             <transId>2202344167</transId>
>             <refTransID />
>             <transHash>9C89491B9AF93F5CF85207FBD754B8DF</transHash>
>             <testRequest>0</testRequest>
>             <accountNumber>XXXX2345</accountNumber>
>             <accountType>eCheck</accountType>
>             <errors>
>                 <error>
>                     <errorCode>2</errorCode>
>                     <errorText>This transaction has been declined.</errorText>
>                 </error>
>             </errors>
>         </transactionResponse>
>     </createTransactionResponse>
>
> 2.  How can I figure out why the transaction was declined?
>
> Any help?  Thanks!
>
> --Fred
>
> Fred Stluka -- mailto:fred@bristle.com -- http://bristle.com/~fred/
> Bristle Software, Inc -- http://bristle.com -- Glad to be of service!
> Open Source: Without walls and fences, we need no Windows or Gates.