Ran into this when a merchant added Japan and Kuwait to their storefront. Our amount helper did one thing: multiply by 100, round, send as an integer. Fine for USD and EUR, so nobody looked at it for two years.
JPY has zero decimal places in ISO 4217. A 1,000 yen basket went out as 100000, and the gateway read it as 100,000 yen. The 3DS challenge showed the customer the wrong number, which is the only reason we caught it in staging and not in a dispute queue.
KWD and BHD are the opposite: three decimals. A 12.500 KWD order sent as 1250 is 1.250 KWD. The charge succeeds, the customer is undercharged by 90%, and nothing errors. Nothing in the response tells you the exponent was wrong, because the amount is a valid integer either way.
The fix was boring: a lookup table of currency exponents, one function that converts to minor units, and a hard failure on unknown codes instead of a default of 2. We also added a test that round-trips every ISO 4217 code with a nonzero amount.
Two side effects: our reconciliation export had the same hard-coded divisor, and a couple of acquirers cap amounts per currency in minor units, so the cap check was wrong too.
Do you pull the exponent from a library, or maintain your own table? And how do you handle the currencies where the acquirer's exponent differs from ISO?
Top comments (0)