Gunakan URLSession untuk jaringan dan Codable untuk JSON. Simpan kunci di server, bukan di aplikasi iOS, macOS, atau watchOS.
- Tentukan model respons: Simpan rates, source, market_session, dan data_updated_at; gunakan Decimal untuk perhitungan nilai uang.
- Simpan kunci di server: Aplikasi mobile memanggil backend Anda, lalu backend menambahkan Authorization. Swift di server dapat membaca kunci dari environment.
- Tangani status dan kesegaran: Periksa status HTTP sebelum decode dan bedakan 401 dari 429. Tampilkan waktu dan sumber pengamatan.
Tentukan model respons
Simpan rates, source, market_session, dan data_updated_at; gunakan Decimal untuk perhitungan nilai uang.
import Foundationfinal class NoRedirects: NSObject, URLSessionTaskDelegate { func urlSession(_ session: URLSession, task: URLSessionTask, willPerformHTTPRedirection response: HTTPURLResponse, newRequest request: URLRequest, completionHandler: @escaping (URLRequest?) -> Void) { completionHandler(nil) }}struct Latest: Decodable { let base: String let source: String let marketSession: String let dataUpdatedAt: String let rates: [String: Decimal]}struct ExchangeRateClient { let session: URLSession let apiKey: String? func latest(base: String) async throws -> Latest { let normalizedBase = base.uppercased() guard normalizedBase.count == 3, normalizedBase.allSatisfy({ $0.isASCII && $0.isLetter }) else { throw URLError(.badURL) } guard var components = URLComponents(string: "https://api.exchangerate.dev/v1/latest/\(normalizedBase)") else { throw URLError(.badURL) } components.queryItems = [URLQueryItem(name: "symbols", value: "EUR,GBP,JPY")] guard let url = components.url else { throw URLError(.badURL) } var request = URLRequest(url: url) request.timeoutInterval = 10 if let apiKey { request.setValue("Bearer \(apiKey)", forHTTPHeaderField: "Authorization") } let (data, response) = try await session.data(for: request) guard let http = response as? HTTPURLResponse, (200..<300).contains(http.statusCode) else { throw URLError(.badServerResponse) } let decoder = JSONDecoder() decoder.keyDecodingStrategy = .convertFromSnakeCase return try decoder.decode(Latest.self, from: data) }}Simpan kunci di server
Aplikasi mobile memanggil backend Anda, lalu backend menambahkan Authorization. Swift di server dapat membaca kunci dari environment.
let key = ProcessInfo.processInfo.environment["EXCHANGERATE_API_KEY"]let session = URLSession(configuration: .ephemeral, delegate: NoRedirects(), delegateQueue: nil)let client = ExchangeRateClient( session: session, apiKey: key)let latest = try await client.latest(base: "USD")print(latest.rates["EUR"] as Any, latest.source, latest.dataUpdatedAt)Tangani status dan kesegaran
Periksa status HTTP sebelum decode dan bedakan 401 dari 429. Tampilkan waktu dan sumber pengamatan.
Laporan harian cukup sekali sehari, sedangkan dashboard operasional bisa tiap jam. Saat menerima 429, kurangi jadwal dan jangan membuat loop retry.
- Simpan kurs bersama sumber dan waktu.
- Gunakan untuk otomasi dan analisis.
- Jangan perlakukan sebagai kuotasi eksekusi.