vcatalano / py-authorize

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

Transaction.Refund requires additional parameters? #3

Closed diego-plan9 closed 10 years ago

diego-plan9 commented 10 years ago

It seems that the authorize.Transaction.Refund API call (ie. the one that can be used for refunding a transaction originally processed by the Auth.net payment gateway) requires more parameters than the currently specified on py-authorize (_transactionid). Currently, executing the example on the documentation [1] results in an error:

result = authorize.Transaction.refund('0123456789')
AttrDict: {
  "messages": {
    "message": {
      "text": "The transaction was unsuccessful.", 
      "code": "E00027"
    }, 
    "result_code": "Error"
  }, 
  "transaction_response": {
    "errors": {
      "error": {
        "error_code": "5", 
        "error_text": "A valid amount is required."
      }
    }, 
    ...
  }
}

After digging into the problem, it seems that the cause is that the official Authorize.net AIM documentation [2] [3] states:

The unique element values for a Credit (Refund) are:
<transactionType>refundTransaction</transactionType>
<refTransId> transaction ID here</refTransId>
<cardNumber>Full credit card number or last 4 digits here</cardNumber>

I did not test it thoroughly, but it seems that the <amount> and <expirationDate> fields are required as well, even if not declared as required on the documentation. I have temporarily resorted to instantiating a __baserequest and adding those XML elements manually, but if you could please take a look at the issue to verify that it is indeed a bug and (if that is the case) implement a proper solution it would be great.

For the record, this is the minimal sample xml request that seems to be valid:

<createTransactionRequest xmlns="AnetApi/xml/v1/schema/AnetApiSchema.xsd">
  <merchantAuthentication>
    <name>xxxxxxx</name>
    <transactionKey>yyyyyy</transactionKey>
  </merchantAuthentication>
<transactionRequest>
  <amount>ZZZ</amount>
  <transactionType>refundTransaction</transactionType>
  <payment>
    <creditCard>
      <cardNumber>XXXX</cardNumber>
      <expirationDate>YYYYYY</cardNumber>
    </creditCard>
  </payment>
  <refTransId>xxxxxxxxxxx</refTransId>
</transactionRequest>
</createTransactionRequest>

Finally, thanks for the making the library available as open source!

[1] https://py-authorize.readthedocs.org/en/latest/transaction.html#refund [2] http://www.authorize.net/support/AIM_guide.pdf [3] http://www.authorize.net/support/AIM_guide_XML.pdf

vcatalano commented 10 years ago

It appears that Authorize.net has updated some of the required fields for this API call. I will have a look at this issue tonight and update it ASAP.

diego-plan9 commented 10 years ago

Thanks for the prompt reply - please let me know if there is anything else I can help with, it would be my pleasure.

A couple of more notes found during additional testing, in case they help:

At the moment I did not have the chance to test those issues with real transactions yet, but if the <expirationdate> can indeed be "ignored" it might be theoretically possible to refund a transaction using only the transaction id (as the credit card last 4 digits and the amount can be retrieved via an authorize.Transaction.details call).

vcatalano commented 10 years ago

Thanks for the additional information! I was able to duplicate this issue last night when I attempted a refund on a prior transaction. Looking through the unit tests last night, I realized that I don't have a live test for testing refund transactions. Unfortunately, this is because it can take up to a few days for a transaction to actually settle so I couldn't test against any transactions that are newly created. Hopefully, I will get the fix pushed in the next day or two.

vcatalano commented 10 years ago

Thanks for your research into this issue, @diego-plan9! I've updated the function to handle the additionally required parameters.