A mobile app retries a payment POST after a timeout. How do you prevent a double charge?
Options
- Use GET instead of POST for the payment requests of the app
- Send an
Idempotency-Keyheader; the server returns the first result (Correct option) - Disable all the retries in the mobile app after a timeout
- Return a 500 error to the client on the second call
Answer
Have the client send an Idempotency-Key header; the server stores the key and returns the original result on repeats
Why
The timeout might have happened AFTER the server charged the card, so the client cannot know if the first try worked.
The client generates a unique key (a UUID) per payment attempt and sends it with every retry.
The server saves the key with the result. If the same key arrives again, it returns the saved result instead of charging again. Stripe's API works this way.
Remember
Retries of POST → Idempotency-Key.