import Foundation struct PaymvQrResult: Equatable { let account: String let amount: String? let merchantName: String? let purpose: String? } enum PaymvQrParser { static func extractBmlGatewayUrl(_ raw: String) -> String? { if raw.hasPrefix("https://pay.bml.com.mv/app/") { return raw } let root = parseTLV(raw) guard let bmlMerchantInfo = root["35"].flatMap({ parseTLV($0) }), let inner = bmlMerchantInfo["20"].flatMap({ parseTLV($0) }), let url = inner["01"], url.hasPrefix("https://pay.bml.com.mv/app/") else { return nil } return url } static func parse(_ qr: String) -> PaymvQrResult? { let tlvs = parseTLV(qr) // Tag 26: merchant account info — sub-tag 03 = account number var account: String? if let tag26 = tlvs["26"] { let sub = parseTLV(tag26) account = sub["03"] } guard let acc = account, !acc.isEmpty else { return nil } let amount = tlvs["54"] let name = tlvs["59"] // Tag 62: additional data — sub-tag 08 = purpose/reference var purpose: String? if let tag62 = tlvs["62"] { let sub = parseTLV(tag62) purpose = sub["08"] } return PaymvQrResult(account: acc, amount: amount, merchantName: name, purpose: purpose) } private static func parseTLV(_ s: String) -> [String: String] { var result: [String: String] = [:] var idx = s.startIndex while s.distance(from: idx, to: s.endIndex) >= 4 { let idEnd = s.index(idx, offsetBy: 2) let lenEnd = s.index(idEnd, offsetBy: 2) let id = String(s[idx..= len else { break } let valEnd = s.index(idx, offsetBy: len) result[id] = String(s[idx..