/// <summary> /// Reads the file pointed by the SFI found in the FCI of the application. /// </summary> /// <returns>Last status word.</returns> public UInt16 Read() { BeforeReadEvent.Raise(this, new EmvEventArgs()); var tlvSfi = TlvFci.GetTag(0x88); if (tlvSfi == null) { throw new Exception(String.Format("PSE: no tag 88 (sfi) found in FCI [{0}]", TlvFci)); } var sfi = new ShortFileIdentifier(tlvSfi); byte recordNumber = 0; do { recordNumber++; var crp = new CommandResponsePair { CApdu = new EMVReadRecordCommand(recordNumber, sfi.Sfi, 0) }; crp.Transmit(_cardChannel); _lastStatusWord = crp.RApdu.StatusWord; if (crp.RApdu.StatusWord == 0x9000) { _tlvRecords.Add(new TlvData(crp.RApdu.Udr)); } } while (_lastStatusWord == 0x9000); AfterReadEvent.Raise(this, new EmvEventArgs()); return(_lastStatusWord); }
/// <summary> /// Process the GET PROCESSING OPTIONS phase of an EMV transaction. /// </summary> /// <returns>Last status word.</returns> public UInt16 GetProcessingOptions() { BeforeGetProcessingOptionsEvent.Raise(this, new EmvEventArgs()); // If PDOL 9F38 is not supplied in FCI, then used 8300 as UDC; if supplied: build the PDOL in tag 83 L V byte[] pdolDataValue; if (TlvFci.HasTag(0x9F38)) { // Use PDOL to build tag 83 value var pdol = new DataObjectList(TlvFci.GetTag(0x9F38).Value); var tlvAll = new List <TlvData> { TlvFci }; tlvAll.AddRange(TlvTerminalData); pdolDataValue = pdol.BuildData(tlvAll); } else { pdolDataValue = new byte[0]; } // Build tag 83 with computed value var tlvPdolData = new TlvData(0x83, (uint)pdolDataValue.Length, pdolDataValue); // Execute GET PROCESSING OPTIONS var cAPDU = new CommandAPDU(0x80, 0xA8, 0x00, 0x00, tlvPdolData.Length + 2, tlvPdolData.ToByteArray(), 0); var crp = new CommandResponsePair(cAPDU); crp.Transmit(_cardChannel); _lastStatusWord = crp.RApdu.StatusWord; // If GET RESPONSE needed, do it if (crp.RApdu.Sw1 == 0x61) { _tlvProcessingOptions = new TlvData(); crp = new CommandResponsePair(new GetResponseCommand(crp.RApdu.Sw2)); crp.Transmit(_cardChannel); _lastStatusWord = crp.RApdu.StatusWord; } // Finally, store result if (crp.RApdu.StatusWord == 0x9000) { _tlvProcessingOptions = new TlvData(crp.RApdu.Udr); } AfterGetProcessingOptionsEvent.Raise(this, new EmvEventArgs()); return(_lastStatusWord); }