Urgent.News

What's breaking now, across thousands of outlets.

Tech

How to Stop Double Charges: Idempotency Keys in ASP.NET Core Payment APIs

A customer taps "Pay", the mobile connection stalls, and the app retries. Your server processed the first request, so now there are two charges. This is not a rare edge case. Any API that mutates money, inventory or orders will see duplicate requests from retries, double-clicks and proxy timeouts. The standard fix is an idempotency key: the client sends a unique Idempotency-Key header with every…

Double charges can occur when a customer taps Pay and the mobile connection stalls, causing the app to retry the request. This is not an uncommon issue, as any API that modifies money, inventory, or orders may receive duplicate requests from retries, double-clicks, and proxy timeouts. The solution is to use an idempotency key, which is a unique identifier sent by the client in the Idempotency-Key header with every write operation.

The server ensures that the same key produces the same result, regardless of how many times it arrives.

To implement idempotency keys in an ASP.NET Core payment API, create a class to store the key, request hash, response body, and status code. Define a unique constraint in the database on the ClientId and Key fields, which handles locking for simultaneous requests. In the endpoint logic, retrieve the key from the request headers, generate a hash of the request body, and attempt to add a new IdempotencyRecord to the database.

If a record already exists with the same key and body, return the stored response. If the key exists but the body is different, return an HTTP 422 error. If the previous request is still running, return HTTP 409.

Handle pitfalls such as crashes between insert and update by scheduling a background job to periodically re-check records older than a few minutes against the payment provider's idempotency support. Set an expiry time for the records, typically 24 hours to a few days, to prevent unbounded growth. Avoid hashing volatile fields, such as timestamps, as this may result in a 422 error for legitimate retries. Additionally, consider storing validation errors to ensure correct behavior when replaying errors.

Testing the implementation involves firing 20 parallel requests with the same key using a small script or load tool. Exactly one charge should be created, and all 20 responses should be identical (or 409 while in flight). If two charges are generated, the key is not part of a uniqueness constraint. Implementing idempotency keys on day one is inexpensive and prevents painful retrofits after double-charge incidents.

It creates a predictable contract for payment-adjacent .NET projects, as my team at QllmSoft does on every project.

Written by urgent.news from Dev.to's reporting — not their text. Machine-written — may contain errors; check the original before relying on it.

Read the original at dev.to →

More in Tech

Knowing the Words Isn't Knowing the Language

You've got a 200-day Duolingo streak. The owl is proud of you. Then you land in Rome, sit down in a trattoria, and order. Every word is owl-approved. The grammar too. You think.

  • Knowing words doesn't equate to language fluency
  • Code abstraction solves human-computer language gap
  • AI code review crucial for quality assurance

ACH vs RTP vs FedNow vs Fedwire: US Rails Guide

Of the eight pages Google currently ranks for "ACH vs RTP vs FedNow", five quote a FedNow limit that has been wrong since November 2025, two still say the RTP cap is $1m, and one claims FedNow only…

More from Wednesday 7 October →