AfRApay/AfRApay.Web/Controllers/CardTransaction.cs
embr 0bf9843c1f AfRApay.Web: Make transactions idempotent
First rule of networking is the network is unreliable. Sometimes things get
lost, sometimes it gets found multiple times for TCP reasons or because a
browser tries to be clever.

And when you're dealing with money, even if it's monopoly money, you don't
want a duplicated request to mean a double-debit. The easiest way to do this
is to simply include an idempotency key with each request - if that key is
repeated, the request is ignored.
2023-02-09 00:24:11 +01:00

33 lines
885 B
C#

using AfRApay.Web.Backend;
using LinqToDB;
using Microsoft.AspNetCore.Mvc;
namespace AfRApay.Web.Controllers;
[ApiController, Route("/api/card/transaction")]
public class CardTransaction : Controller {
[HttpGet]
public string Get([FromQuery] string card, [FromQuery] decimal amount, [FromQuery] string ik) {
var db = new Database.DbConn();
if (db.Cards.Any(p => p.CardId == card)) {
var userId = db.Cards.First(p => p.CardId == card).UserId;
var user = db.Users.First(p => p.Id == userId);
// If an idempotency key is given, disregard duplicate requests.
if (ik == "" || ik != user.LastIdempotencyKey) {
if (user.Balance - amount < -50) {
return "E:Balance too low!";
}
user.Balance -= amount;
user.LastIdempotencyKey = ik;
db.Update(user);
}
return $"S:{user.Nickname}: {user.Balance:N2}";
}
return "E:Unknown card.";
}
}