Цены в долларах, на экране — местная валюта. Кажется логичным: один прайс для всех, честный курс, никаких ручных правок. На практике это разваливается на три отдельные проблемы, и каждая достаточна, чтобы переписать всю схему.
Команда Menuraq, платформы для фуд-бизнеса, долго держала цены в долларах и конвертировала их в местные валюты при отрисовке страницы. Для Западной Африки, где работает большая часть клиентов, это повседневность. Никакой экзотики. И именно там схема развалилась.
Почему живой курс ломает цену
Первое: цена меняется каждый день
Сегодня $29 — это ₵399, а через три дня уже ₵412. Клиент видит разницу и думает, что его обманывают. Менеджер не может назвать цену вслух: завтра она будет другой. Никто не может вписать её в презентацию или передать коллеге. Цена перестаёт быть фактом о продукте и превращается в биржевой тикер.
Цена — это обещание. Число из внешнего курса обещать не может.
Второе: показ и списание не совпадают
На странице цена отображается с округлением — никто не хочет видеть ₵412,37. Но в платёжку уходит сумма из сырой конвертации. Расхождение в несколько рублей или седи — достаточно, чтобы получить чарджбек и плохой отзыв.
Ошибка классическая: округление живёт во view-слое, а списание — в сервисном. Каждый слой по отдельности выглядит корректно, и заметить нестыковку почти невозможно. Если у вас есть функция «привести цену к красивому виду» — проверьте, не расходится ли она с тем, что реально спишется.
Третье: цена есть, а принять её нельзя
Валюта определялась по геолокации. Мерчант из Гамбии видел цену в даласи, но платёжный провайдер не умеет принимать даласи. То же с леоне, либерийским долларом и ещё несколькими валютами. Человек решает купить, доходит до оплаты — и оплата не проходит.
Вывод, который выходит за рамки валют: возможность показать цену и возможность провести платёж — разные вещи. Код должен знать, на какой из двух вопросов он отвечает.
Что поставили вместо конвертации
Авторский прайс-бук. Для каждой валюты — своя рукописная лестница цен, а не пересчёт. В коде это массив вида «для каждого уровня в USD — своя цена в местной валюте». Ключи — долларовые точки, значения — реальные цифры для рынка. При чтении нет никакой конвертации, просто возвращается готовое число.
За этим стоит якорный курс на валюту, но он не обновляется автоматически. Это продуктовое решение. Рынок тут ни при чём. Якорь нужен для новых ценовых точек, где лестница ещё не написана, и для деградации: если вдруг забыли добавить уровень — система вернёт число из якоря, а не упадёт и не возьмёт свежий курс.
Деградировать надо к «устаревшему и стабильному», а не к «свежему и прыгающему».
Ловушка с нулевым количеством десятичных знаков
Платёжные провайдеры принимают суммы в минимальных единицах. Самый частый код — умножить сумму на 100. Для доллара, найры и седи это верно. А у франка КФА (XOF) десятых нет вообще. Если умножить цену во франках на 100, клиент в Сенегале получит счёт в сто раз больше нужного.
XOF не одинок: иена, вона, донг, песо и исландская крона тоже нулевые. А у кувейтского динара и ещё пары валют — три знака после запятой. Один захардкоженный * 100 — и первый же покупатель в такой валюте получит переплату в сто раз.
| Валюта | Код | Экспонента |
|---|---|---|
| Доллар США | USD | 2 |
| Нигерийская найра | NGN | 2 |
| Ганский седи | GHS | 2 |
| Франк КФА | XOF | 0 |
| Японская иена | JPY | 0 |
| Кувейтский динар | KWD | 3 |
Отображение тоже должно соответствовать: XOF форматируется без дробной части, иначе мы показываем точность, которой у валюты нет.
Что делать сейчас
- Найдите в платёжном коде умножение на 100. Валюты с нулевым экспонентом исправьте первыми — это единственная ошибка из всех, которая реально переплачивает людям.
- Проверьте, совпадает ли число на странице с числом, которое уходит в платёжку. Это должно быть одно значение, а не два.
- Разделите «могу показать» и «могу принять». Уточните у провайдера список валют, которые он действительно обрабатывает, — он короче, чем кажется.
- И уже потом заменяйте конвертацию авторскими лестницами. Это самое большое изменение и оно наименее срочное.
Теперь добавить валюту в Menuraq — это пять шагов: якорный курс, лестница цен, региональные коды, экспонента и проверка, что провайдер реально умеет принимать эту валюту. Работы больше, чем при вызове курсового API. Но впервые эта схема не порождает тикеты в поддержку.
Неконвертируемая цена — это ещё и преимущество
Когда цены заданы руками, а не посчитаны, появляется возможность сознательно играть рынком. Ганская лестница у Menuraq стоит ниже паритета по якорю — это сознательное решение, принятое вручную. Случайность? нет. Оно о том, сколько должен платить небольшой ресторан в Гане, чтобы согласиться. Конвертационной функцией такое не выразить: у неё всегда одно мнение, и оно всегда рыночное, а не ваше.
Переход к авторским ценам занял время из-за трёх багов, но именно они и заставили пересмотреть подход. Если вы ещё не споткнулись — возможно, вы просто не дошли до валют, которые не умеет ваш провайдер.
Комментарии (0)
Войдите, чтобы комментировать.
Пока нет комментариев. Будьте первым.