无法将订阅价格设置为 $19.99

  • 使用 Discourse-Subscriptions
  • 尝试向产品添加定价方案
  • 在价格框中输入 19.99(这已经很困难了,因为输入行为非常奇怪)
  • 尝试提交
  • 收到错误“无效整数 1998.9999999999998”

我只在稳定版 3.5.3 上测试过这一点,但 beta 版的代码是相同的。

Code

  @computed("unit_amount")
  get amountDollars() {
    return parseFloat(this.get("unit_amount") / 100).toFixed(2);
  }

  set amountDollars(value) {
    const decimal = parseFloat(value) * 100;
    this.set("unit_amount", decimal);
  }

Javascript / IEEE-754 浮点数怪癖:

-> parseFloat("19.99")*100
<- 1998.9999999999998

建议的修复方法:const decimal = Math.round(Number(value) * 100)

我最大的疑问是:为什么没有人注意到?以前没有人将价格设置为 19.99 美元吗?

2 个赞

我立刻就知道了。这是我 40 多年前学到的关于计算机的又一件没有改变的事情。

或者使用 1 分整数?我想 Stripe 实际上就是这么做的。(但您的解决方案需要更改的代码少得多,所以我想它赢了。)

2 个赞

是的,它就是这么做的,unit_amount 是美分,而 amountDollars 是一个“XX.XX”的输入值。
“无效整数”错误甚至来自 Stripe API。

我想我们都老到足以知道 FDIV 错误 :wink:

3 个赞

老实说,我认为将此存储为浮点数是错误的,此列应为整数并以美分存储。

3 个赞

它是这样,parseFloat 用于将输入字段(“带有两位小数的货币”)转换为/从其转换。unit_amount 对象属性显然是无类型的,因此我建议使用 Math.round()

它不是服务器端的列,而是传递给 Stripe API 的。

1 个赞

对于货币 BCD 浮点数通常优于二进制浮点数。