Skip to content

Instantly share code, notes, and snippets.

@sbycrosz
Last active June 9, 2021 04:51
Show Gist options
  • Save sbycrosz/c4d8df09915ae1697ff0c0b5fe2eb77e to your computer and use it in GitHub Desktop.
Save sbycrosz/c4d8df09915ae1697ff0c0b5fe2eb77e to your computer and use it in GitHub Desktop.
React Native bridge for AndyQ/NFCPassportReader
//
// NFCPassportReader.m
// StashawayApp
//
// Created by Sam Aryasa on 3/6/20.
// Copyright © 2020 Facebook. All rights reserved.
//
#import "React/RCTBridgeModule.h"
@interface RCT_EXTERN_MODULE(RNNFCPassportReader, NSObject)
RCT_EXTERN_METHOD(
readPassport: (NSString *)mrzKey
customMessages: (NSDictionary *)customMessages
resolver: (RCTPromiseResolveBlock)resolve
rejecter: (RCTPromiseRejectBlock)reject)
@end
//
// NFCPassportReader.swift
// StashawayApp
//
// Created by Sam Aryasa on 3/6/20.
// Copyright © 2020 Facebook. All rights reserved.
//
import Foundation
import CoreNFC
import NFCPassportReader
@objc(RNNFCPassportReader)
class RNNFCPassportReader: NSObject {
private var passportReader: Any;
override init() {
guard #available(iOS 13, *) else {
passportReader = NSNull()
return;
}
passportReader = PassportReader()
}
@objc
static func requiresMainQueueSetup() -> Bool {
return true
}
@objc
func constantsToExport() -> [AnyHashable : Any]! {
guard #available(iOS 13, *) else {
return ["isSupported": false]
}
if NSClassFromString("NFCNDEFReaderSession") == nil {
return ["isSupported": false]
}
return ["isSupported": NFCNDEFReaderSession.readingAvailable]
}
func handleProgress(percentualProgress: Int) -> String {
let p = (percentualProgress/20)
let full = String(repeating: "🟢 ", count: p)
let empty = String(repeating: "⚪️ ", count: 6 - p)
return "\(full)\(empty)"
}
@objc
func readPassport(
_ mrzKey: NSString,
customMessages: NSDictionary,
resolver resolve: @escaping RCTPromiseResolveBlock,
rejecter reject: @escaping RCTPromiseRejectBlock
) -> Void {
guard #available(iOS 13, *) else {
reject("READ_PASSWORD_ERROR", "NFC_NOT_SUPPORTED", nil)
return
}
(passportReader as! PassportReader).readPassport(
mrzKey: mrzKey as String,
tags: [.COM, .DG1, .DG2],
customDisplayMessage: { (displayMessage) in
switch displayMessage {
case .requestPresentPassport:
let message = customMessages["requestPresentPassport"] as? String ?? "Hold your iPhone near an NFC enabled passport.";
return message
case .authenticatingWithPassport(let progress):
let message = customMessages["authenticatingWithPassport"] as? String ?? "Authenticating with passport.....";
let progressString = self.handleProgress(percentualProgress: progress)
return "\(message)\n\n\(progressString)"
case .readingDataGroupProgress(let dataGroup, let progress):
let message = customMessages["readingDataGroupProgress"] as? String ?? "Reading \(dataGroup).....";
let progressString = self.handleProgress(percentualProgress: progress)
return "\(message)\n\n\(progressString)"
case .error(let tagError):
let message = customMessages["error"] as? String ?? "Failed to read Passport NFC";
let errorKey = tagError.errorDescription ?? "UnknownError"
return "\(message) (\(errorKey))"
case .successfulRead:
let message = customMessages["successfulRead"] as? String ?? "Passport read successfully";
return message
}
},
completed: { (passport, error) in
if let passport = passport,
let photo = passport.passportImage,
let photoData = photo.pngData() {
let photoBase64 = "data:image/png;base64," + photoData.base64EncodedString()
let result: NSDictionary = [
"firstName" : passport.firstName,
"lastName" : passport.lastName,
"gender" : passport.gender,
"issuer" : passport.issuingAuthority,
"nationality" : passport.nationality,
"photo" : [
"base64": photoBase64,
"width": photo.size.width * photo.scale,
"height": photo.size.height * photo.scale,
],
]
resolve(result)
} else {
reject("READ_PASSWORD_ERROR", error?.localizedDescription, error)
}
})
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment