Відзначимо: при конвертації великих сум через округлення Float виникає похибка, яку користувач сприймає як баг. Технічно конвертер простий, але помилки в арифметиці, кеші або API-інтеграції перетворюють його на джерело скарг. Розберемо, як побудувати надійний модуль з нуля: від вибору провайдера курсів до обробки крайових випадків з локалями та rounding. Наша команда — 7 років у мобільній розробці, 30+ реалізованих fintech-модулів. Ми знаємо всі підводні камені та гарантуємо точність на всіх пристроях.
Як вибрати API для курсів валют?
Вибір API залежить від вимог до частоти оновлення та набору валют. Порівняємо популярні варіанти:
| API | Безкоштовний план | Оновлення | Особливості |
|---|---|---|---|
| ExchangeRate-API | 1500 запитів/міс | Щоденно | Простий REST, 170+ валют |
| Open Exchange Rates | 1000 запитів/міс | Щогодини | Історичні дані |
| Fixer.io | 100 запитів/міс | Щогодини | EUR як базова валюта |
| НБУ XML | Безкоштовно | Щоденно | Офіційні курси для UAH |
ExchangeRate-API в 3 рази дешевший за Fixer.io на середньому обсязі запитів. Для більшості додатків достатньо щоденного оновлення — НБУ віддає XML за адресою https://bank.gov.ua/NBUStatService/v1/statdirectory/exchange, парсимо через XMLParser на iOS або XmlPullParser на Android. Зверніть увагу: НБУ використовує UTF-8 і може змінювати формат відповіді. Ми завжди застосовуємо автоматичні тести регресії на 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 |
На iOS використовуємо Decimal, на Android — BigDecimal. Вони гарантують точність до копійки та коректне округлення за правилами фінансової математики. Детальніше про Тип даних Decimal.
Офлайн-кешування та фонова синхронізація
Курси зберігаємо локально: 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: завжди передбачайте можливість зміни провайдера курсів.
- Немає перевірки строку кешу: користувач бачить курс тижневої давності без попередження.
Замовте розробку конвертера валют під ключ — отримайте готове рішення з вихідниками та підтримкою.







