vcatalano / py-authorize

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

Optional Authorize.net parameters "required" by py-authorize #26

Closed diego-plan9 closed 10 years ago

diego-plan9 commented 10 years ago

(Tested under Py-Authorize==1.2.2.1 and colander==1.0a5, using an Authorize.net account in sandbox mode, authorize.Environment.TEST)

While testing the modification of an existing ARB subscription (authorize.Recurring.update), I noticed some behaviour which I'm unsure if it is by design or could be the hint of a bug. In particular, the actual XML request sent to Authorize.net includes some of the optional (per the official Authorize.net docs) fields with values generated by py-authorize, even if they are not specified by the user.

_(From the ARBGuide, section "Input Elements for ARBUpdateSubscriptionRequest"):

Required elements: subscriptionId ... All other fields are optional

For the following call:

result = authorize.Recurring.update(
            '123456789',
            {
             'amount': 123,
             'cycle': 1,
             'credit_card': {
                 'card_number': '1234-5678-9012-3456',
                 'expiration_date': '11-22',
                 'card_code': '123',
                 },
            }
        )

the following XML is passed to Authorize.net (taken as the result of the E.tostring(call) at _make_call, manually edited for privacy and highlighting):

<ABUpdateSubscriptionRequest xmlns="AnetApi/xml/v1/schema/AnetApiSchema.xsd">
<merchantAuthentication>...</merchantAuthentication>
<subscriptionId>123456789</subscriptionId>
<subscription>
    <paymentSchedule>
*        <startDate>2014-08-26 </startDate> # == now()
*        <totalOccurrences>9999</totalOccurrences>
    </paymentSchedule>
    <amount>123.00</amount>
    <payment>
        <creditCard>
            <cardNumber>1234567890123456</cardNumber>
            <expirationDate>2022-11</expirationDate>
            <cardCode>123</cardCode>
        </creditCard>
    </payment>
    <billTo>
*        <firstName>&lt;empty&gt;</firstName>
*        <lastName>&lt;empty&gt;</lastName>
    </billTo>
</subscription>
</ARBUpdateSubscriptionRequest>

The lines marked with an asterisk denote those field auto-generated by Py-Authorize. In the particular case of updating an existing subscription, the default of "startDate" is particularly troublesome as in subscriptions with at least one transaction completed Authorize.net will reject the update call (ie. "start date cannot be changed"). Plus, the "firstName" and "lastName" empty fields seem to overwrite the corresponding values on the Auth.net control panel.

I have circumvented this issue by providing the values to the auto-generated fields, but I'm wondering if you could take a deeper look in the issue as it might be relevant for other API calls as well. Perhaps it would be enough to just make a note on the documentation on which fields are required by Py-Authorize and which ones by Authorize.net or something similar?

As usual, thanks for your work and please let me know if you need more information on the issue, I'd be happy to help.

vcatalano commented 10 years ago

Thanks for looking into this issue, @diego-plan9. It appears that you have found a bug. When creating a new recurring transaction, Authorize.net does require the "firstName" and "lastName" fields, however, they are not necessary for setting up the transaction. Because of this, I use the values to bypass the validation. Also, for the "startDate" and "totalOccurrences" fields, I configured default values so that newly created subscriptions will always start immediately and never expire.

The bug you found is caused by the Py-Authorize setting these values when a subscription is being updated. This is a problem since this actually updates the current subscription's values and will cause errors like the ones you discovered. I have remedied this issue by only setting these four fields when a new subscription is created and NOT when a subscription is being updated.