Double-Charged at Checkout — JavaScript Bug Hunt
Inspired by the double-submit bugs every payments team has fought (and the idempotency keys Stripe popularised to kill them).
- Language: JavaScript
- Layer: Frontend
- Difficulty: Easy
- Concepts: Idempotency, Payments
- Modelled on: Stripe idempotency
- Visible tests: a repeated key charges exactly once; different keys create separate charges
- Reward: 50 XP for a complete fix
Briefing
Inspired by the double-submit bugs every payments team has fought (and the idempotency keys Stripe popularised to kill them). An impatient double-click sends the same request twice — the processor must charge exactly once per idempotency key.
Fix chargeProcessor.js.
Bug report
BUG-5150 · Priority: Critical · Reported by: support (chargebacks!)
Contract: process(key, amountCents) — a repeated key must be a no-op that returns the ORIGINAL charge (same id, same amount), creating nothing new.
Observed: double-clicks create two charges; the retry even returns a different charge id than the first attempt.
Logs
[charge] key=ck_1a2b amount=4999 -> ch_001
[charge] key=ck_1a2b amount=4999 -> ch_002 <- duplicate!The code as shipped
src/pay/chargeProcessor.js (editable)
// Charges with idempotency keys: one key, one charge — ever.
var charges = [];
var seenKeys = {};
var nextId = 1;
exports.process = function (key, amountCents) {
var charge = { id: "ch_" + nextId, amount: amountCents, key: key };
nextId++;
charges.push(charge);
if (!seenKeys[key]) {
seenKeys[key] = charge;
}
return seenKeys[key];
};
exports.allCharges = function () { return charges.slice(); };
exports.resetAll = function () { charges = []; seenKeys = {}; nextId = 1; };
Open the hunt to edit the files, run the visible tests and submit against the hidden ones. More JavaScript bug hunts.