Не удалось установить цену подписки $19.99

  • Использование Discourse-Subscriptions
  • Попытка добавить тарифный план к продукту
  • Введите 19.99 в поле цены (это уже сложно, так как поле ввода ведёт себя очень странно)
  • Попробуйте отправить форму
  • Получите ошибку «Invalid integer 1998.9999999999998»

Пока я тестировал это только на стабильной версии 3.5.3, но код в бета-версии тот же.

Код

  @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?

Кстати, я также часто получаю NaN, например, когда полностью очищаю поле ввода.

2 лайка

Я сразу понял. Ещё одна вещь, которую я узнал о компьютерах более 40 лет назад и которая не изменилась.

Или использовать целые числа в копейках? Кажется, именно так делает Stripe. (Но ваше решение требует значительно меньше изменений в коде, так что, думаю, оно побеждает.)

2 лайка

Да, именно так: unit_amount — это центы, а amountDollars — значение ввода в формате «XX.XX».
Ошибка «неверное целое число» даже приходит от API Stripe.

Похоже, мы оба достаточно стары, чтобы знать о баге FDIV :wink:

3 лайка

Честно говоря, я считаю, что хранение этого значения в float — ошибочное решение. Этот столбец должен быть типа int и храниться в копейках.

3 лайка

Да, parseFloat используется для конвертации из/в поле ввода, которое представляет собой «валюту с двумя знаками после запятой». Свойство объекта unit_amount, очевидно, не имеет строгого типа, поэтому я предлагаю использовать Math.round().

Это не столбец на стороне сервера, оно передается в Stripe API.

1 лайк

Для валюты BCD плавающая точка в целом предпочтительнее двоичной плавающей точки.

Спасибо @RGJ за отчет — это должно исправить проблему :+1:

2 лайка

Эта тема была автоматически закрыта через 2 дня. Новые ответы больше не принимаются.