İçeriğe geç

NFC çip okuma

T.C. kimlik kartı ve pasaportlardaki çip, PassportReader ile okunur. Çipe erişmek için belgenin seri numarası, doğum tarihi ve son geçerlilik tarihi gerekir; bunları belge tarama sonucundan (capturedData) alıp kullanıcıya onaylatın.

Okuma sırasında iOS kendi NFC penceresini gösterir; penceredeki metinleri SDK ayarlar. Önce NFC yeteneğini ekleyin.

import passport_reader
import ProveIDApiClient
final class NFCViewController: UIViewController {
var transactionId = ""
var documentNumber = "" // capturedData.sno
var birthDate = "" // capturedData.bdat, gg.AA.yyyy
var expireDate = "" // capturedData.edat, gg.AA.yyyy
private var passportReader: PassportReader?
override func viewDidLoad() {
super.viewDidLoad()
PassportReader.PACE_ENABLED = true
LocalNFCCommandTransmitter.NFC_START_MESSAGE =
"Kimliğinizi, ortası telefonun üst kısmına gelecek şekilde yerleştirin ve hareket ettirmeyin."
passportReader = PassportReader(commandTransmitter: LocalNFCCommandTransmitter(),
progressMessage: { input in
ProgressMessageOutput(alertMessage: "Okunuyor…")
},
errorMessage: { input in
ErrorMessageOutput(alertMessage: "Okuma başarısız.", suppressError: false)
})
startReading()
}
}

progressMessage ve errorMessage, iOS NFC penceresindeki metni belirler. input.nfcOperationType ve input.progress okumanın ne kadar ilerlediğini, input.error ise hatayı verir (bkz. Hatalar).

Aktif kimlik doğrulama için Prove ID’den işleme özel bir nonce alıp okumayı başlatın:

func startReading() {
IDServiceAPI.generateNonce(body: NonceGeneratorModel(transactionId: transactionId)) { result in
switch result {
case .success(let response):
DispatchQueue.main.async { self.read(nonce: response.nonce) }
case .failure(let error):
showError(error)
}
}
}
func read(nonce: String?) {
let formatter = DateFormatter()
formatter.dateFormat = "dd.MM.yyyy"
formatter.timeZone = TimeZone(secondsFromGMT: 0)
guard let birth = formatter.date(from: birthDate),
let expire = formatter.date(from: expireDate) else {
// Kullanıcıdan tarihleri düzeltmesini isteyin
return
}
passportReader?.read(documentNumber: documentNumber,
birthDate: birth,
expireDate: expire,
nonce: nonce,
callback: self)
}
extension NFCViewController: PassportReaderCallback {
func result(passportModel: PassportModel) {
// Çip verisini doğrulamaya gönderin (aşağıda)
}
func progress(progressType: NFCOperationType, progress: Double) {
// START, AUTHENTICATION, DG1, DG2, DG11, DG12, DG14, DG15, SOD, ACTIVE_AUTHENTICATON, CHIP_AUTHENTICATION, SUCCESS
}
func error(error: Error) {
// bkz. Hatalar
}
}
let validation = IDValidationModel(dg1: passportModel.getDg1()!,
dg2: passportModel.getDg2()!,
sod: passportModel.getSod()!,
dg11: passportModel.getDg11(),
dg12: passportModel.getDg12(),
dg14: passportModel.getDg14(),
dg15: passportModel.getDg15(),
nonce: passportModel.getNonce(),
signedData: passportModel.getSignedData(),
mseResp: passportModel.getCaMseResponse(),
gaResp: passportModel.getCaGaResponse(),
probeResp: passportModel.getCaProbeResponse(),
accessProtocol: passportModel.getAccessProtocol()?.value)
let body = ValidationInputModel(validationInformation: validation,
idType: "IDCARD",
transactionId: transactionId)
IDServiceAPI.validateAndSaveIDCard(body: body) { result in
switch result {
case .success(let response):
let controls = response.controlResults
showNfcResult(controls)
case .failure(let error):
showError(error)
}
}

Çip doğrulama ile çip, gerçek olduğunu ve kopyalanmadığını kanıtlar. Bunun için gereken anahtarlar uygulamada değil, Prove ID’de tutulur: SDK komutları hazırlamak için sizin ChipAuthenticationBackend nesnenize başvurur, siz de isteği Prove ID’ye iletirsiniz.

final class ChipAuthenticationBackendImpl: ChipAuthenticationBackend {
var transactionId = ""
func prepareCA(dg14Bytes: String,
completed: @escaping (ChipAuthenticationPlan?, Error?) -> Void) {
let body = CAPrepareInputModel(transactionId: transactionId, dg14: dg14Bytes)
IDServiceAPI.prepareCA(body: body) { result in
switch result {
case .success(let output):
guard let mse = output.mseApdu, let ga = output.gaApdu, let probe = output.probeApdu else {
completed(nil, NSError(domain: "ChipAuthentication", code: -1,
userInfo: [NSLocalizedDescriptionKey: output.message ?? ""]))
return
}
completed(ChipAuthenticationPlan(mseApdu: mse, gaApdu: ga, smProbeApdu: probe), nil)
case .failure(let error):
completed(nil, error)
}
}
}
}
let backend = ChipAuthenticationBackendImpl() // güçlü bir referansla tutun
backend.transactionId = transactionId
PassportReader.DO_CHIP_AUTHENTICATION = true
PassportReader.CHIP_AUTHENTICATION_BACKEND = backend

Çip doğrulama yanıtları, çip verisiyle birlikte IDValidationModel içinde (mseResp, gaResp, probeResp) gönderilir.

Ayar Açıklama
PassportReader.PACE_ENABLED Belge destekliyorsa çipe PACE ile erişir
PassportReader.DO_CHIP_AUTHENTICATION Çip doğrulamayı çalıştırır
PassportReader.CHIP_AUTHENTICATION_BACKEND Sizin ChipAuthenticationBackend nesneniz
PassportReader.SUPPRESS_ACTIVE_AUTH Aktif kimlik doğrulama başarısız olsa da okumaya devam eder
PassportReader.SUPPRESS_CHIP_AUTHENTICATION Çip doğrulama başarısız olsa da okumaya devam eder
LocalNFCCommandTransmitter.NFC_START_MESSAGE Okuma başlarken iOS NFC penceresinde gösterilen metin
PassportReaderEvent.logLevel SDK’nın log seviyesi (canlıda .none)
PassportReaderEvent.listener SDK’nın log olaylarını alan EventListener