Created
December 10, 2019 17:19
-
-
Save treastrain/f4c4b0e8e0ea2c874d90cd07597549e4 to your computer and use it in GitHub Desktop.
Core NFC (iOS 13.0 以降) で楽天Edy、nanaco、WAON の残高を読み取る
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
// | |
// ViewController.swift | |
// emoneyReader | |
// | |
// Created by treastrain on 2019/12/11. | |
// Copyright © 2019 treastrain / Tanaka Ryoga. All rights reserved. | |
// | |
import UIKit | |
import CoreNFC | |
class ViewController: UIViewController, NFCTagReaderSessionDelegate { | |
var session: NFCTagReaderSession? | |
override func viewDidLoad() { | |
super.viewDidLoad() | |
guard NFCTagReaderSession.readingAvailable else { | |
print("NFC タグの読み取りに非対応のデバイス") | |
return | |
} | |
self.session = NFCTagReaderSession(pollingOption: .iso18092, delegate: self) | |
self.session?.alertMessage = "カードの上に iPhone の上部を載せてください" | |
self.session?.begin() | |
} | |
func tagReaderSessionDidBecomeActive(_ session: NFCTagReaderSession) { | |
print("tagReaderSessionDidBecomeActive(_:)") | |
} | |
func tagReaderSession(_ session: NFCTagReaderSession, didInvalidateWithError error: Error) { | |
let readerError = error as! NFCReaderError | |
print(readerError.code, readerError.localizedDescription) | |
} | |
func tagReaderSession(_ session: NFCTagReaderSession, didDetect tags: [NFCTag]) { | |
print("tagReaderSession(_:didDetect:)") | |
let tag = tags.first! | |
session.connect(to: tag) { (error) in | |
if let error = error { | |
session.invalidate(errorMessage: error.localizedDescription) | |
return | |
} | |
guard case NFCTag.feliCa(let feliCaTag) = tag else { | |
session.invalidate(errorMessage: "FeliCa ではない") | |
return | |
} | |
session.alertMessage = "カードを読み取っています…" | |
let idm = feliCaTag.currentIDm.map { String(format: "%.2hhx", $0) }.joined() | |
print("IDm:", idm) | |
/// FeliCa サービスコード | |
let rakutenEdyServiceCode = Data([0x13, 0x17].reversed()) | |
let nanacoServiceCode = Data([0x55, 0x97].reversed()) | |
let waonServiceCode = Data([0x68, 0x17].reversed()) | |
let serviceCodeList = [rakutenEdyServiceCode] | |
/// ブロック数 | |
let blocks = 1 | |
let blockList = (0..<blocks).map { (block) -> Data in | |
Data([0x80, UInt8(block)]) | |
} | |
feliCaTag.readWithoutEncryption(serviceCodeList: serviceCodeList, blockList: blockList) { (status1, status2, blockData, error) in | |
if let error = error { | |
session.invalidate(errorMessage: error.localizedDescription) | |
return | |
} | |
guard status1 == 0x00, status2 == 0x00 else { | |
print("ステータスフラグがエラーを示しています", status1, status2) | |
session.invalidate(errorMessage: "ステータスフラグがエラーを示しています s1:\(status1), s2:\(status2)") | |
return | |
} | |
let data = blockData.first! | |
let balance = data.toIntReversed(0, 3) | |
print(data as NSData) | |
print("残高: ¥\(balance)") | |
session.alertMessage = "残高: ¥\(balance)" | |
session.invalidate() | |
} | |
} | |
} | |
} | |
extension Data { | |
/// https://github.com/treastrain/TRETJapanNFCReader/blob/master/TRETJapanNFCReader/Extensions.swift#L112 | |
func toIntReversed(_ startIndex: Int, _ endIndex: Int) -> Int { | |
var s = 0 | |
for (n, i) in (startIndex...endIndex).enumerated() { | |
s += Int(self[i]) << (n * 8) | |
} | |
return s | |
} | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment