Skip to content

Instantly share code, notes, and snippets.

@treastrain
Created December 10, 2019 17:19
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save treastrain/f4c4b0e8e0ea2c874d90cd07597549e4 to your computer and use it in GitHub Desktop.
Save treastrain/f4c4b0e8e0ea2c874d90cd07597549e4 to your computer and use it in GitHub Desktop.
Core NFC (iOS 13.0 以降) で楽天Edy、nanaco、WAON の残高を読み取る
//
// 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