Отметим: когда при конвертации 10 000 USD в USD из-за округления Float пропадает $1–1 — пользователь видит баг, а не фичу. Технически конвертер прост, но ошибки в арифметике, кэше или API-интеграции превращают его в источник жалоб. Разберём, как построить надёжный модуль с нуля: от выбора провайдера курсов до обработки краевых случаев с локалями и rounding. Наша команда — 7 лет в мобильной разработке, 30+ реализованных fintech-модулей. Мы знаем все подводные камни и гарантируем точность на всех устройствах.
Как выбрать API для курсов валют?
Выбор API зависит от требований к частоте обновления и набору валют. Сравним популярные варианты:
| API | Бесплатный план | Обновление | Особенности |
|---|---|---|---|
| ExchangeRate-API | 1500 запросов/мес | Ежедневно | Простой REST, 170+ валют |
| Open Exchange Rates | 1000 запросов/мес | Ежечасно | Исторические данные |
| Fixer.io | 100 запросов/мес | Ежечасно | EUR как базовая валюта |
| ЦБ РФ XML | Бесплатно | Ежедневно | Официальные курсы для USD |
| НБ РБ | Бесплатно | Ежедневно | Официальные курсы для BYN |
ExchangeRate-API в 3 раза дешевле Fixer.io на среднем объёме запросов. Для большинства приложений достаточно ежедневного обновления — ЦБ РФ отдаёт XML по адресу https://www.cbr.ru/scripts/XML_daily.asp, парсим через XMLParser на iOS или XmlPullParser на Android. Обратите внимание: ЦБ РФ использует кодировку windows-1251 и может менять формат ответа. Мы всегда применяем автоматические тесты регрессии на sandbox-данных и предусматриваем fallback на другой провайдер.
Почему Decimal, а не Float?
Никогда не используйте Float или Double для финансовых расчётов. Разница в копейках при конвертации крупных сумм будет заметна. Сравните точность:
| Тип | Точность | Пример ошибки |
|---|---|---|
| Float/Double | ~7-15 цифр | 0.1 + 0.2 = 0.30000000000000004 |
| Decimal (iOS) / BigDecimal (Android) | 28-38 цифр | 0.1 + 0.2 = 0.3 |
Для 1 000 000 USD расхождение в 0.01% даст ошибку в 100 USD. На iOS используем Decimal, на Android — BigDecimal. Они гарантируют точность до копейки и корректное округление по правилам финансовой математики. Подробнее о Decimal data type.
Офлайн-кэширование и фоновая синхронизация
Курсы сохраняем локально: Core Data / Room для возможности работы офлайн с последними известными значениями. Показываем метку времени последнего обновления — пользователь должен понимать, насколько актуальны данные. Для самых свежих курсов используем фоновую синхронизацию через WorkManager (Android) или BGTaskScheduler (iOS). На одном проекте мы реализовали TTL в 30 минут и кэш на 7 дней. Пользователь всегда видит актуальность данных, а при отсутствии сети — предупреждение.
Пример кода парсинга ЦБ РФ на Swift
import Foundation struct CurrencyRate: Decodable { let code: String let nominal: Int let value: Decimal } class CBRParser: NSObject, XMLParserDelegate { private var rates: [CurrencyRate] = [] private var currentElement = "" private var currentCode = "" private var currentNominal = "" private var currentValue = "" func parse(data: Data) -> [CurrencyRate] { let parser = XMLParser(data: data) parser.delegate = self parser.parse() return rates } func parser(_ parser: XMLParser, didStartElement elementName: String, namespaceURI: String?, qualifiedName qName: String?, attributes attributeDict: [String : String] = [:]) { currentElement = elementName } func parser(_ parser: XMLParser, foundCharacters string: String) { switch currentElement { case "CharCode": currentCode += string case "Nominal": currentNominal += string case "Value": currentValue += string default: break } } func parser(_ parser: XMLParser, didEndElement elementName: String, namespaceURI: String?, qualifiedName qName: String?) { if elementName == "Valute" { let rate = CurrencyRate(code: currentCode.trimmingCharacters(in: .whitespacesAndNewlines), nominal: Int(currentNominal.trimmingCharacters(in: .whitespacesAndNewlines)) ?? 1, value: Decimal(string: currentValue.trimmingCharacters(in: .whitespacesAndNewlines).replacingOccurrences(of: ",", with: ".")) ?? 0) rates.append(rate) currentCode = "" currentNominal = "" currentValue = "" } } } Процесс работы над конвертером
- Аналитика — сбор требований (валюты, точность, частота обновления) и выбор API.
- Проектирование — архитектура: слой данных, репозиторий, кэш, view model (MVVM + Clean Architecture).
- Реализация — кодовая база с юнит-тестами (20+ тестов на арифметику и кэширование).
- Интеграция — подключение выбранного API, обработка ошибок (нет сети, лимит запросов, смена формата).
- Тестирование — на 10 реальных устройствах с разными локалями и регионами.
- Деплой — публикация в App Store / Google Play с прохождением ревью.
Что входит в работу
- Исходный код на Swift (iOS) или Kotlin (Android) с комментариями.
- Документация API и инструкция по обновлению ключей.
- Настроенная схема кэширования (локальная БД) с TTL.
- Отчёт о тестировании с покрытием кода >80%.
- Поддержка в течение 2 недель после сдачи.
Сроки и стоимость
Срок реализации: от 3 до 7 рабочих дней. Стоимость фиксируется после согласования ТЗ и не меняется. Экономия на времени разработки до 30% при заказе комплексного решения. Свяжитесь с нами для оценки вашего проекта — мы подберём оптимальное решение под ваш бюджет.
Типичные ошибки при разработке конвертера
- Игнорирование Decimal: 95% багов в конвертерах связаны с округлением.
- Отсутствие обработки локали: на немецкой локали запятая — разделитель тысяч, что ломает парсинг.
- Жёсткая привязка к одному API: всегда предусматривайте возможность смены провайдера курсов.
- Нет проверки срока кэша: пользователь видит курс недельной давности без предупреждения.
Закажите разработку конвертера валют под ключ — получите готовое решение с исходниками и поддержкой.







