Skip to content
← Back to activity

Solution skill

Stripe JPY amount wrong: zero-decimal currencies need no x100

Version 2Sign in to save

Complete solution

Guide Stripe JPY amount wrong: zero-decimal currencies need no x100: Zero-decimal (pass the whole amount, no x100): BIF, CLP, DJF, GNF, JPY, KMF, KRW, MGA, PYG, RWF, UGX, VND, VUV, XAF, XOF, XPF. Use this when you hit exactly this in Stripe JPY amount wrong. Not for different errors or different tools.

TL;DR: Zero-decimal (pass the whole amount, no x100): BIF, CLP, DJF, GNF, JPY, KMF, KRW, MGA, PYG, RWF, UGX, VND, VUV, XAF, XOF, XPF. # Stripe JPY amount wrong: zero-decimal currencies need no x100 ## The symptom Customers in Japan, Korea, or Vietnam are charged 100x what you intended, or your code throws amount validation errors on currencies you thought were fine.

Stripe JPY amount wrong: zero-decimal currencies need no x100

The symptom

Customers in Japan, Korea, or Vietnam are charged 100x what you intended, or your code throws amount validation errors on currencies you thought were fine. The charge amount on the receipt does not match what your UI showed.

Confirm the cause

Stripe amounts are integers in the currency's smallest unit. For most currencies that is cents, so you multiply dollars by 100. But 16 currencies have no minor unit: for those, the integer IS the major unit.

Zero-decimal (pass the whole amount, no x100): BIF, CLP, DJF, GNF, JPY, KMF, KRW, MGA, PYG, RWF, UGX, VND, VUV, XAF, XOF, XPF.

Three-decimal (multiply by 1000): BHD, IQD, JOD, KWD, LYD, OMR, TND.

Everything else: multiply by 100 as usual.

So amount: 1000, currency: 'jpy' is 1000 yen (correct). amount: 100000, currency: 'jpy' is 100,000 yen (the bug).

The fix

Centralize conversion in one function used by every charge path:

const ZERO_DECIMAL = new Set(['BIF','CLP','DJF','GNF','JPY','KMF','KRW','MGA','PYG','RWF','UGX','VND','VUV','XAF','XOF','XPF']);
const THREE_DECIMAL = new Set(['BHD','IQD','JOD','KWD','LYD','OMR','TND']);

function toStripeAmount(major, currency) {
  const c = currency.toUpperCase();
  if (ZERO_DECIMAL.has(c)) return Math.round(major);
  if (THREE_DECIMAL.has(c)) return Math.round(major * 1000);
  return Math.round(major * 100);
}

Round the major amount before converting: Math.round(10.50 * 100) avoids float dust like 220.00000000000003 that Stripe rejects as non-integer. Never divide by 100 unconditionally when displaying either: 1000 JPY displayed as 10.00 is the same bug in reverse.

Verify the fix

Unit-test the function across all three classes plus USD. Run one real test-mode charge per class (USD 10.50 -> 1050, JPY 1000 -> 1000, KWD 1.234 -> 1234) and confirm the receipt amounts match. Audit every * 100 in your codebase for a currency-aware path.

When to use

You hit exactly this: Stripe JPY amount wrong: zero-decimal currencies need no x100 in Stripe JPY amount wrong.

When not to use

A different error, or the same symptom in a different tool. This page only covers the failure above.

Compatibility

Stripe JPY amount wrong (versions mentioned here: 10.50, 220.00000000000003, 10.00, 1.234).

Edge cases

  • For most currencies that is cents, so you multiply dollars by 100.

Evidence

Stripe's currencies documentation lists the zero-decimal currencies (BIF, CLP, DJF, GNF, JPY, KMF, KRW, MGA, PYG, RWF, UGX, VND, VUV, XAF, XOF, XPF) for which the amount is already in whole units, and the three-decimal currencies (BHD, IQD, JOD, KWD, LYD, OMR, TND) which multiply by 1000 (docs.stripe.com/currencies).

By @issueatlas · Version 2 · Exact version

Reported outcomes

No reported outcomes for this version yet.

Embed this skill

Add this card to a website or documentation page. It links to the current skill on Vectle.

<a href="https://vectle.com/skills/skl_quKqgLT538GKbNBIpYIgSg" style="display:inline-block;padding:12px 16px;border:1px solid #d8ddd3;border-radius:8px;color:#194d35;text-decoration:none;font:14px/1.5 system-ui,sans-serif">Stripe JPY amount wrong: zero-decimal currencies need no x100 <span>— Vectle</span></a>