eWAYPayment / eway-rapid-php

Eway Rapid PHP library
https://www.eway.com.au
MIT License
14 stars 24 forks source link

'queryInvoiceReference' responds with V6170 when multiple transactions present with same reference #5

Closed danielb93 closed 8 years ago

danielb93 commented 8 years ago

Hi,

I've been busy building a 'close-loop' solution for transaction attempts that are left in an unknown state. The purpose of this solution is to determine if the transaction attempt occurred in eWay and if so, whether it was successful or not so I may update the record on my end to its respective status 'PAID' or 'FAILED'.

This has been a frequent scenario especially when payment attempts are made within a mobile application (iOS/Android) while on a shoddy mobile network connection. If the payment attempt times out, the payment status will be left in a limbo state (PENDING).

When a transaction attempt is initiated, a record will be created holding a 'PENDING' payment status and will be updated accordingly once the transaction response is received. If this response is never captured for whatever reason, the record remains in a PENDING status and it has been a manual task to move it to a 'happy' state (PAID or FAILED).

I rejoiced when I saw the addition of the 'queryInvoiceReference' into the SDK as this allowed me (or so I thought) to query eWay with the record's primary key (which I populate the 'InvoiceReference' field with on all transaction attempts pertaining to that record) and return any transactions associated with that key and determine the transaction status.

This solution works perfectly when there is a single transaction attempt but to my dismay, fails when there is multiple transaction attempts with the same reference (Error code: V6170). This renders my solution useless as all transaction attempts use the same reference (how else would you track the transactions for a record...?)

Real world scenario:

  1. Payment attempt is made (record's payment status == PENDING) and the payment fails with a response (bad card number), thus the record's payment status is updated to 'FAILED'.
  2. User notices bad card number and enters the correct one and attempts payment again.
  3. Payment status is moved back to PENDING prior to the second payment attempt.
  4. The transaction attempt times out however the payment was successful yet the status is unknown on my end and so the status remains as PENDING.

'queryInvoiceReference' will fail in this scenario as more than one transaction attempt has been made.

So my questions are:

  1. Why does this function not support the return of multiple transactions? (The response model nests the transaction result under the key 'Transactions' which is plural and within an array).
  2. Why does eWay allow you to perform a payment using a non-unique InvoiceReference when it throws errors in other functions?
  3. Can this be changed to return multiple transactions?

Apologies for the wall of text, I wanted to be thorough in my explanation to ensure my concern and my function's purpose is clear.

Thanks, Daniel

cainhopwood commented 8 years ago

Daniel,

The Search by InvoiceRef was added to allow customers to check status of transactions where a timeout meant that an AccessCode or TransactionID was not available to them to search on.

As you've seen in the format of the response, it is our intention to provide multiple transactions in the TransactionSearch API. But the choice to limit it at this point to just single transactions was intentional. We won't allow multiple transactions to be returned until we're confident that we have mechanisms in place to limit the impact of queries that would return potentially thousands of rows.

I'm talking about implementing paging and throttling here, which is currently in the pipeline. We also need to ensure that the backend systems are setup and indexed such that they can handle these types of queries.

It's easy to envisage a customer always using the same Invoice ref and and just paging through thousands of rows looking for a name. You might laugh at this, but not all developers take the considered, thoughtful approach to development that you do.

We have tens of thousands of active customers, processing hundreds of transaction a minute and we like to keep our servers running at single digit percent capacity untilisation if we can. Careful API design, i.e. design that ensures a single customer can't inadvertently load the system up and impact others, is a big part of that.

To address your specific questions;

  1. The model supports multiple transactions so that we can add filters that return multiple transactions in the future without changing the response models. Some frameworks (Java) are very brittle with respect to model changes. Even though they accept XML, they compile the WSDL and may throw exceptions if attributes are re-ordered, or unknown attribute are present. So we try to keep model changes to a minimum where we can.
  2. Requiring Invoice Ref to be unique would not be possible, and is not required, for the vast majority of customers. It wouldn't provide any benefit to them, and would unnecessarily restrict the payments they could make, forcing them to generate nonsense unique ID just to jump through API hoops.
  3. Yes it can. But as I described above, it won't be done until we have throttling and paging in place.

To addess your specific problem;

Is there a reason why you can't generate a new or unique ID after the payment attempt in Step #1 has failed? The transaction attempt in #1 and #4 are discreet transactions (from our perspective) If they had different ID's then you wouldn't have any trouble searching to determine status when communication failures occur.

e.g. you could leave the InvoiceNumber as your own internal unique ID, but add a "-1" to the InvoiceRef for the first attempt and "-2" on the second etc. Then you would be able to construct a TransactionSearch query on InvoiceRef that wouldn't return V6170. I don't know if you're aware that Both InvoiceNum and InvoiceRef can be searched on independently. They don't need to be the same value.

Kind Regards, Cain Hopwood, eWay developer.