A payment provider confirms a charge succeeded. Your system tries to record it against an invoice — and can't, because the invoice was already fully paid, voided, or not found. What happens next must never be silence.
The trap is easy to fall into: log a warning, mark the event "skipped," return 200 OK, and move on. The customer has been charged, the money is sitting in the account, the invoice still reads unpaid, and no human has been told. That is a silent revenue-reconciliation gap — the kind that surfaces weeks later as an angry "I already paid this."
The two-part rule
- Alert a human. Emit a distinct "payment received but not recorded" event that drives an operator notification, carrying the invoice reference, the amount received, and the failure reason. Someone has to reconcile it by hand.
- Still acknowledge the provider. Return success so the provider stops retrying. A retry would re-attempt the same record against the same unresolved cause and fail identically — and the money is already captured. Resolution is operator-side, not provider-side.
Acknowledging the provider is not the same as pretending it worked. The acknowledgement is for the provider's retry logic; the alert is for the human who must fix the books.
Why this needs its own path, separate from "payment failed"
It is tempting to fold this into the generic "payment failed" alert, but the two are opposites. "Payment failed" means the customer was not charged — reassure them and let them retry. "Received but unrecorded" means the customer was charged but the books disagree — investigate immediately, and do not assume the invoice is unpaid. Different message, different urgency, different action. Collapsing them into one alert tells the operator the wrong story at the worst moment.