179 lines
6.3 KiB
Swift
Executable File
179 lines
6.3 KiB
Swift
Executable File
//
|
|
// TapCashApi.swift
|
|
// Emoney Info
|
|
//
|
|
// Created by Wira Irawan on 26/07/24.
|
|
//
|
|
|
|
import Foundation
|
|
import CoreNFC
|
|
|
|
public class TapCashApi : UnifiedNfcApi {
|
|
var emoney : Emoney = Emoney()
|
|
var tapCashData : TapCashData = TapCashData()
|
|
var riwayatList: [RiwayatCard] = []
|
|
var start = 0
|
|
var totalLog = 0
|
|
|
|
public override init() {}
|
|
|
|
public func checkBalance(){
|
|
apduRunner.exchangeApdu(apduCommand: EmoneyApduCommands.TAPCASH_APDU01, completionHandler: {response in
|
|
if (response.sw1 == 0x90 && response.sw2 == 0x00){
|
|
self.emoney.setCardLabel("BNI TapCash")
|
|
self.tapCashData.setPurseData(response.getData().bytes)
|
|
let balance = self.tapCashData.getPurseBalance()?.hexString().hex2decimal()
|
|
self.emoney.setBalance(balance!)
|
|
self.emoney.setCardNumber(self.tapCashData.getCAN()!.hexString())
|
|
self.totalLog = (self.tapCashData.getTotalRecords()?.hexString().hex2decimal())!
|
|
if (self.totalLog > 10){
|
|
self.totalLog = 10
|
|
}
|
|
debugLog("total log " + String(self.totalLog))
|
|
self.getHistory(index: 0)
|
|
} else {
|
|
self.emoney.setTampilRiwayat(false)
|
|
self.updateScreen()
|
|
self.apduRunner.sessionEx?.alertMessage = "readFinish".localizeString(string: self.langCode!)
|
|
self.apduRunner.invalidateSession()
|
|
}
|
|
})
|
|
}
|
|
|
|
private func getHistory(index : Int){
|
|
let st = String(index).leftPad(with: "0", length: 2)
|
|
//90 32 03 00 01 00 10
|
|
let TAPCASH_LOG = NFCISO7816APDU(instructionClass : 0x90, instructionCode : 0x32, p1Parameter : 0x03, p2Parameter : 0x00, data : Data(_ : st.stringToBytes()!), expectedResponseLength : 16)
|
|
debugLog(TAPCASH_LOG.toHexString())
|
|
apduRunner.exchangeApdu(apduCommand: TAPCASH_LOG, completionHandler: {response in
|
|
if (response.sw1 == 0x90 && response.sw2 == 0x00){
|
|
self.addRiwayatTransaksi(data: response.getData().bytes)
|
|
}
|
|
self.start+=1
|
|
if (self.start < (self.totalLog)){
|
|
self.getHistory(index: self.start)
|
|
} else {
|
|
self.updateScreen()
|
|
self.riwayatList = self.riwayatList.sorted(by: { $0.getTransationTime()?.compare($1.getTransationTime()!) == .orderedDescending })
|
|
|
|
if (self.riwayatList.count > 0){
|
|
self.emoney.setRiwayatList(self.riwayatList)
|
|
self.emoney.setTampilRiwayat(true)
|
|
}
|
|
self.apduRunner.sessionEx?.alertMessage = "readFinish".localizeString(string: self.langCode!)
|
|
self.apduRunner.invalidateSession()
|
|
}
|
|
})
|
|
}
|
|
|
|
private func updateScreen(){
|
|
if (self.apduRunner.callback != nil){
|
|
self.apduRunner.callback?.complete(emoney: self.emoney)
|
|
}
|
|
}
|
|
|
|
private func addRiwayatTransaksi(data: [UInt8]) {
|
|
let trxType = Array(data[0..<1])
|
|
let trxAmount = Array(data[1..<4])
|
|
let trxDateTimes = Array(data[4..<8])
|
|
//let trxUserData = Array(data[8..<16])
|
|
|
|
let title = trxType.hexString()
|
|
var amount: Int
|
|
if title.lowercased() == "01" || title.lowercased() == "05" || title.lowercased() == "07" || title.lowercased() == "10" || title.lowercased() == "20" {
|
|
amount = trxAmount.hexString().secondComplementsAmount()
|
|
} else {
|
|
amount = trxType.hexString().hex2decimal()
|
|
}
|
|
|
|
let riwayatCard = RiwayatCard()
|
|
riwayatCard.setTitle(getStatementTitle(header: trxType.hexString()))
|
|
riwayatCard.setProsesTipe(getTranscationType(header: trxType.hexString()))
|
|
riwayatCard.setAmount(amount)
|
|
let transactionTime = self.getTransactionTime(julian: trxDateTimes.hexString())
|
|
riwayatCard.setTransactionTime(transactionTime)
|
|
riwayatList.append(riwayatCard)
|
|
}
|
|
|
|
private func getStatementTitle(header: String) -> String {
|
|
var title = ""
|
|
switch header.uppercased() {
|
|
case "01":
|
|
title = "payment".localizeString(string: self.langCode!)
|
|
case "02":
|
|
title = "Black List Card"
|
|
case "03":
|
|
title = "topup".localizeString(string: self.langCode!)
|
|
case "04":
|
|
title = "topup".localizeString(string: self.langCode!)
|
|
case "05":
|
|
title = "statementFee".localizeString(string: self.langCode!)
|
|
case "06":
|
|
title = "updateBalance".localizeString(string: self.langCode!)
|
|
case "07":
|
|
title = "gracePeriod".localizeString(string: self.langCode!)
|
|
case "10":
|
|
title = "refund".localizeString(string: self.langCode!)
|
|
case "20":
|
|
title = "refund".localizeString(string: self.langCode!)
|
|
case "22":
|
|
title = "close".localizeString(string: self.langCode!)
|
|
case "F0":
|
|
title = "atu".localizeString(string: self.langCode!)
|
|
default:
|
|
break
|
|
}
|
|
return title
|
|
}
|
|
|
|
private func getTranscationType(header: String) -> Int {
|
|
switch header.uppercased() {
|
|
case "01":
|
|
return 1
|
|
case "02":
|
|
return 2
|
|
case "03":
|
|
return 0
|
|
case "04":
|
|
return 0
|
|
case "05":
|
|
return 1
|
|
case "06":
|
|
return 6
|
|
case "07":
|
|
return 7
|
|
case "10":
|
|
return 10
|
|
case "20":
|
|
return 20
|
|
case "22":
|
|
return 22
|
|
default:
|
|
break
|
|
}
|
|
return 0
|
|
}
|
|
|
|
func getTransactionTime(julian: String) -> Date {
|
|
let dec = julian.hex2decimal()
|
|
|
|
let cal = Calendar.current
|
|
// set to 1st January 1995
|
|
var dateComponents = DateComponents()
|
|
dateComponents.year = 1995
|
|
dateComponents.month = 1
|
|
dateComponents.day = 1
|
|
dateComponents.hour = 0
|
|
dateComponents.minute = 0
|
|
dateComponents.second = 0
|
|
|
|
if let date = cal.date(from: dateComponents) {
|
|
let newDate = date.addingTimeInterval(Double(dec))
|
|
return newDate
|
|
}
|
|
|
|
return Date()
|
|
}
|
|
|
|
}
|