Відзначимо: при конвертації великих сум через округлення 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: завжди передбачайте можливість зміни провайдера курсів.
- Немає перевірки строку кешу: користувач бачить курс тижневої давності без попередження.
Замовте розробку конвертера валют під ключ — отримайте готове рішення з вихідниками та підтримкою.







