53 lines
1.6 KiB
Swift
53 lines
1.6 KiB
Swift
import Foundation
|
|
|
|
struct PaymvQrResult {
|
|
let account: String
|
|
let amount: String?
|
|
let merchantName: String?
|
|
let purpose: String?
|
|
}
|
|
|
|
enum PaymvQrParser {
|
|
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..<idEnd])
|
|
guard let len = Int(s[idEnd..<lenEnd]) else { break }
|
|
idx = lenEnd
|
|
guard s.distance(from: idx, to: s.endIndex) >= len else { break }
|
|
let valEnd = s.index(idx, offsetBy: len)
|
|
result[id] = String(s[idx..<valEnd])
|
|
idx = valEnd
|
|
}
|
|
return result
|
|
}
|
|
}
|