For anyone else struggling with this I thought I would share my (moderately torturous) workaround:
- Receive webhook request
- Store request details along with hash of JSON.
- Wait 1 second
- Check if any other request have been stored in that time, if so, check:
– Does it have the same transaction ID
– Is it a transaction.updated type
– Does it contain as much or more information (I’m using a slightly hacky approach for this of serialising the JSON data and then comparing string length.) - If a newer request matches all the above stop here, otherwise:
- Check if a stored request for this transaction has already been processed and if so check if the hash of the stored request differs from that of the new request. If not stop here.
- Mark as processed with timestamp.
- Process transaction (in my application I use the information about whether this is the first processed request for the transaction or an update in subsequent processing steps)
There are some potential flaws with this:
- All the duplicate requests arrive instantaneously and not in the correct order (I know because I sometimes get a transaction.updated before a transaction.created) so if I get two transaction.updated requests in the wrong order and the serialised data from the more up to date one is shorter (eg if the transaction amount has decreased by an order of magnitude) I will process the older information and ignore the update. In practice the only difference I’ve seen in these simultaneous requests is where a user specified category is applied. Luckily this always results in a longer JSON because the category is added to an object that is empty in the initial request. I’m working on the assumption that the transaction amount (or anything that causes a similar problem) won’t change instantly.
- New requests after one second where the hash differs are all treated as an update. More logic will be needed to determine what has changed and whether additional processing is appropriate.
I’m very keen to hear if anyone else has a more straight forward way of dealing with this. Obviously it will be application specific to some extent but I’m looking to keep my options open to apply any kind of automation triggered by the creation or update of a transaction.