One of the amazing things about the design of the payment processing system is that it's easy to get into a situation where A) you know the customer's card is good; B) you've tried to charge them; and C) something has gone wrong and you don't know whether you've taken their money or not.
This happens to us every couple of weeks:
- Customer places an order.
- Us to bank: "Can I charge $30?"
- Bank to us: "Yes".
- Us to bank: "Ok, do it."
- ...radio silence.
If response #3 never comes, we get to show the customer an error, and that's fine. But if that response #5 times out and doesn't come back, which happens regularly, we have no idea whether the failure was that step #4 was not received, or that step #4 was received but reply #5 was lost. Sometimes it's one, sometimes it's the other. In the former case, the customer wasn't charged, and in the latter case they were! We have to fix these by hand, and there's no easy way to automate it. It sucks.
If banks understood TCP/IP, it would go like this:
- Customer places an order.
- SYN: Can I charge $30?
- SYN/ACK: Yes.
- ACK + SYN: Do it.
- SYN/ACK: I am gonna do it.
- ACK: I see that you're gonna do it.
If that was their model, then at no point does a communication failure cause a charge to be in an ambiguous state. If I never get the message in #5, the customer is not charged. If I get the message in #5 and my response in #6 is not received, the customer is not charged.
If #6 is sent but not received, then I would think the customer was charged when they were not, but the converse can't happen. There's only one possible failure mode and not two, and that failure mode is the safer one.
This is orthogonal to the complete flying clusterfuck that is AVS, unfortunately, where they put a hold on the money before validating the billing address, and then if that didn't match, often fail to release that hold. Double-you tee fuck.