Now that we have reached a point where we have something working, I think it's time to pause and reflect on what we've learnt. Speaking for myself, I've learnt quite a lot.
Mental Model
First off, my mental model has shifted considerably. In part this is because I was basically thinking of what I wanted to do as a conversation between equals. This is very much not what NFC implements.The expectation of the designers is that the terminal will be fairly smart and connected to a wider network (at least a data centre if not the internet). As such, it is in charge of the conversation and directing what happens. The card, on the other hand, while it is "smarter" than just a static bar code or magnetic stripe (it has a microprocessor, after all) is basically a passive device which does what it is told, and quite possibly even needs the reader to supply it with power.
The protocol reflects this: it is a "half-duplex" protocol between a superior and an inferior. I hesitate to call it "client/server" because the terms are almost the wrong way round: the terminal is in the "client" role inasmuch as it is performing the requests, but it has all the characteristics of a classic "server" - it has all the connectivity, resources and computing power. Intuitively, most of us would see the "card" in the role of the client, and the "terminal" in the role of server.
It would seem that at some point there was a move towards a more equal, "peer to peer" NFC design, and this is reflected in Android Beam, and possibly the NDEF protocol. But none of that is relevant to the worldview I have in which I am looking at applications with a fairly fixed, stationary PoS-style terminal and a "visiting" smartphone.
So we are left in a world in which most of the time, the phone wants to be in the "superior" role, in which cards come to it and it interacts with them. Instead, we need to specifically ask the phone to "pretend" that it is a card and instruct Android to monitor application selection requests and forward them to a specific service.
Protocols
In my view of the world right now, there seem to be four "separate" protocols over NFC, although they are clearly related to each other:- ATR - this isn't really a protocol as such, but presumably because people in the industry spend so much time "down in the weeds", it seems to get a lot of attention. The "Answer to Reset" is information about a card which enables the reader to interact with it in the most efficient way possible, just as baud negotiation used to work with old-fashioned modems.
- APDU - the basic protocol that is used to communicate between terminals and cards and is a very clear standard defined by ISO, so that cards and readers around the world can be 100% compatible.
- EMV - I haven't really talked about this much, in part because it's not really relevant to what I'm trying to acheive here, but it would seem that there is an extension(?) to APDU which is specific to payment processing called EMV.
- NDEF - NDEF is a protocol that it would seem is part of an attempt to use NFC in a peer-to-peer setting that has the ability to encode messages in a more complex format. My first thought was that this was the simplest thing to do on Android, but I am now much less convinced. By the time I have had to emulate a card, I am already dragged into the APDU format, so that's the simplest thing to use.
Cards
There are also a number of different card technologies, most of which I have to say I don't understand, but among them we have- Contact cards - where you actually insert the card into the reader (CHIP&PIN would be a good example)
- SAM cards - some kind of "secure access module" cards. I have some of these, but I don't really understand them, and I'm not really interested.
- PICC cards - "Proximity Integrated Circuit Cards" - i.e. contactless cards with a microprocessor which can be reasonably extended to cover Android devices.
Where we Go from Here
I left off the previous episode by saying it now came down to a simple matter of programming, but we all know that programming is never simple. But it is getting to the point where I need to take what I'm doing more seriously rather than just messing around. So, I see myself having the following tasks to do:- I want to write something "serious" in Go on the terminal side. I want to keep using the library that I've been using, because it obviously works (at least on Linux) but I want to replace the example code with an actual server.
- This should be in a loop waiting for a PICC card to turn up and then it tries to SELECT AID F1676D6D61706F77656C6C2D61707031. This may fail, of course, particularly with a 6A 82 indicating that the card is either not a phone at all, or does not have the receipt app loaded on it. Either of these is fine and the terminal just keeps on keeping on.
- If the AID can be selected, the terminal goes into "writing" mode: it sends across whatever "receipt" is has to hand, listing all the various items that are important. When it is done, it (somehow) communicates that fact to the phone (for now, I expect there will be a specific record that it writes that is the final record; but it could be that there is an APDU "close" command as well - I think I saw something about that in the documentation for onDeactivated).
- The Android app needs to be able to receive multiple APDU commands (actually, it already does this) and understand that they form part of a single transaction. It needs to parse them out into actual instructions and make a list of them. It then needs to be able to process this to build a final receipt and only then should it send a notification to the user.
- The User needs to be able to interact with the notification, bringing up the receipt.
- Ideally, all the receipts will be stored in a database or something somewhere on the device and then there can be a screen that enables the user to see all the receipts on the device and view them. However, this is starting to move away from "proving the technology can do the job" and into "writing a real-world app" and we're not here to do that ...
No comments:
Post a Comment