I am using PHP cURL to make API calls to an accounting site, but some of our invoices are being duplicated. From a Fiddler report, I can see that the two calls are being made milliseconds apart.
This is how I have configured the logic:
check internal database if order is invoiced
stop if it is invoiced, continue if its not
gather all required variables (customer ID, product codes) from internal database
do first API call to get product descriptions & prices using product codes
do second API call to get customer details using Customer ID
do third API call to create new invoice using above details
get invoice ID and invoice document number
do fourth API call to email invoice to customer, using above details
update internal database - change order status to “invoiced”
It is the third and fourth API calls (creating invoice & sending email) that are periodically duplicated (about 1 in every 50 or so - the others don’t duplicate). I have made sure that the operator who triggers the process does not refresh their browser while waiting for the process to complete.
Is there any way that I can prevent this from happening (maybe with a delay between the calls)?
I have seen issues some time ago (and not in a PHP environment) where submitting a HTTP form can “bounce”, that is the same form gets submitted twice, only a very short time apart, similar to the way you are seeing. I can’t quite remember exactly what was causing it.
Can you “re-arrange” things so that after step 2, rather than doing the (relatively) time-consuming gathering of product information, you introduce a step “2a” which is to set a “pending” flag of some sort in the order table? That way, the second “hit” won’t go anywhere.
The way I read it is that the second attempt runs somewhere before the internal database status has been updated to show the order is invoiced, so anywhere between the start and step 6. There is significant time delay between your status check at step 2, and when you create the invoice at step 6.
What I was really thinking is:
check internal database if order is invoiced
stop if it is invoiced or pending, continue if its not
2a. change status of order in internal db to “pending”
gather all required variables (customer ID, product codes) from internal database
do first API call to get product descriptions & prices using product codes
do second API call to get customer details using Customer ID
do third API call to create new invoice using above details
get invoice ID and invoice document number
do fourth API call to email invoice to customer, using above details
update internal database - change order status to “invoiced”
If it’s already pending when the second instance checks, there’s surely no need to do any of the other steps because the first instance will be doing that.
The only issue is what the user sees, and I suspect that it would be along the lines of waiting a few seconds, checking that it has now changed to “invoiced” and display the confirmation from there.
Actually, reading your original post again, you may have a different issue to the one I had. In mine, the problem was that the “submit” from the web page form was coming in twice, which was firing the CGI code twice, hence the above solution would do it. If yours is not doing that, it may be no help. So I guess the question is, is it only duplicating those two steps, or is it actually duplicating all of them, from your local logs / debug?