Fix tip retry amount guard false 400 on non-exact pence values
The pending-retry amount guard compared pence via int64(pounds*100), which truncates instead of rounding. For non-exact pound values (e.g. £1.14 stored as the float64 1.1399999999999999) the truncation yields 113 != 114, falsely rejecting a legitimate same-amount retry with 400. Since the frontend reuses the idempotency key on same-amount retries, every retry was rejected, permanently stranding the pending record (and any orphaned Square charge) with no recovery path. Fix: compare in pence via math.Round — the existing pattern already used in refunds.go — so non-exact values round to the true pence. Also applied the same correction to the sibling lossy conversions: - CreateTipPayment / CreateBookingPayment completed-dedup responses (would have reported 113p for a 114p payment) - BuyGiftCard retry amount guard (latent: £10/£20/£50 are float-exact so it never bit, but the identical trap is now closed) Tests: - TestTipPayment_RetryPending_NonExactAmountSucceeds: 114p pending record + same-amount retry completes and charges 114p (failed on the old truncation with 400) - TestTipPayment_RetryPending_AmountMismatchRejected: a same-key retry at a different amount is still rejected with 400 and the pending record is left untouched Verified: full backend suite green (25/25 packages, 0 failures), -race clean on handlers/payments, go build + go vet clean.
This commit is contained in:
@@ -8,6 +8,7 @@ import (
|
||||
"fmt"
|
||||
"log"
|
||||
"log/slog"
|
||||
"math"
|
||||
"net/http"
|
||||
"strconv"
|
||||
"strings"
|
||||
@@ -944,7 +945,7 @@ func BuyGiftCard(w http.ResponseWriter, r *http.Request) {
|
||||
// Guard the amount: a retry with a different amount must not
|
||||
// reuse the pending record (gift card would be issued at the
|
||||
// new amount against the old charge record).
|
||||
if int64(existing.Amount*100) != req.Amount {
|
||||
if int64(math.Round(existing.Amount*100)) != req.Amount {
|
||||
log.Printf("Gift card retry amount mismatch: pending record %s has %.2f, request has %d pence", existing.ID, existing.Amount, req.Amount)
|
||||
http.Error(w, "Amount does not match the pending gift card payment", http.StatusBadRequest)
|
||||
return
|
||||
|
||||
Reference in New Issue
Block a user