new Intl.NumberFormat('ja-JP', {style:'currency', currency:'JPY'}).format(12800)
// ¥12,800

日元报价单显示 ¥12,800.00,网关回调 400 amount invalid,当天 27 笔日元订单全部失败。先别急着动参数,把报错原文和时间点记下来,顺序反了容易白折腾。

原因不复杂,金额格式化把小数位写死成 2,日元按 ISO 4217 是 0 位小数。序列化时又带着 .00 传给网关,对方按整数日元校验直接拒。数据库里存的是分,转换环节没有按币种查小数位。

围绕「币种小数位」排查时,命令行跑一遍比在面板里点十次有用,面板会替你做掉不少隐式操作。改完隔一天再看一次,当场正常不代表能稳住。

测试环境和线上的差别,往往就在版本号和那几行被忽略的配置上。线上出问题先对时间点,跟发布、备份、任务执行的时刻排一排,能省掉一半功夫。

处理上按这个顺序:按币种维护小数位表 从 CLDR 或 ISO 4217 取值;格式化用 Intl.NumberFormat 的 currency 选项 不手写 toFixed;传给网关前统一转最小货币单位整数;用 JPY、USD、KWD 各下一单 对比请求体金额。

改完只确认一件事:日元订单金额显示为 ¥12,800,网关返回 200,三笔不同币种订单金额都通过校验。

作者 9823189