// Methods /// <summary> /// Read security information when card has no chip - magnetic stripe only. /// </summary> /// <param name="pinpadCommunication">Pinpad communication, through which c</param> /// <param name="pan">Primary Account Number printed on the card.</param> /// <param name="amount">Transaction amount.</param> /// <param name="pin">Pin read.</param> /// <returns>Wheter is an online transaction or not.</returns> /// <exception cref="System.InvalidOperationException">Thrown when parameter validation fails.</exception> internal ResponseStatus Read(IPinpadCommunication pinpadCommunication, string pan, decimal amount, out Pin pin) { pin = null; // Validating data try { this.Validate(pinpadCommunication, amount, pan); } catch (Exception ex) { throw new InvalidOperationException("Error while trying to read security info using magnetic stripe. Verify inner exception.", ex); } // Using ABECS GPN command to get pin block & KSN. GpnResponse response = this.SendGpn(pinpadCommunication, pan, amount); // Saving command response status: AbecsResponseStatus legacyStatus = response.RSP_STAT.Value; ResponseStatus status = ResponseStatusMapper.MapLegacyResponseStatus(legacyStatus); if (status == ResponseStatus.Ok) { // Magnetic stripe always validates pin online. pin = new Pin(); pin.PinBlock = response.GPN_PINBLK.Value.DataString; pin.KeySerialNumber = response.GPN_KSN.Value.DataString; pin.IsOnline = true; } pin.ApplicationCryptogram = null; return(status); }
// Validation /// <summary> /// Validates parameters sent to the constructor. /// </summary> /// <exception cref="System.ArgumentNullException">When one parameter is null.</exception> /// <exception cref="System.ArgumentException">When one parameter is not null, but contains invalid data.</exception> private void Validate(IPinpadCommunication pinpadFacade) { if (pinpadFacade == null) { throw new ArgumentNullException("pinpadCommunication"); } }
/// <summary> /// Sends reading command using ABECS in case of a magnetic stripe card. /// Unexpected behavior if amount is too large (over quadrillion). /// </summary> /// <param name="pinpadCommunication"></param> /// <param name="pan">Primary Account Number printed on the card.</param> /// <param name="amount">Transaction amount.</param> /// <returns>ABECS GPN command response.</returns> private GpnResponse SendGpn(IPinpadCommunication pinpadCommunication, string pan, decimal amount) { GpnRequest request = new GpnRequest(); // Assembling GPN command. request.GPN_METHOD.Value = new CryptographyMethod(KeyManagementMode.DerivedUniqueKeyPerTransaction, CryptographyMode.TripleDataEncryptionStandard); request.GPN_KEYIDX.Value = (int)StoneIndexCode.EncryptionKey; request.GPN_WKENC.Value = new HexadecimalData(""); request.GPN_PAN.Value = pan; // Assembling GPN mandatory entries to GPN command. GpnPinEntryRequest pinEntry = new GpnPinEntryRequest(); pinEntry.GPN_MIN.Value = PinReader.PASSWORD_MINIMUM_LENGTH; pinEntry.GPN_MAX.Value = PinReader.PASSWORD_MAXIMUM_LENGTH; pinEntry.GPN_MSG.Value.Padding = DisplayPaddingType.Left; pinEntry.GPN_MSG.Value.FirstLine = this.GetAmountLabel(amount); pinEntry.GPN_MSG.Value.SecondLine = PASSWORD_LABEL; // Adds the entry to list of entries supported by a GPN command. request.GPN_ENTRIES.Value.Add(pinEntry); GpnResponse response = pinpadCommunication.SendRequestAndReceiveResponse <GpnResponse>(request); return(response); }
// Constructor: /// <summary> /// Creates a pinpad table adapter. /// </summary> /// <param name="pinpadCommunication">Pinpad communication, through which is possible to communicate with the pinpad.</param> public PinpadTable(IPinpadCommunication pinpadCommunication) { if (pinpadCommunication == null) { throw new ArgumentNullException("pinpad communication cannot be null."); } this.PinpadCommunication = pinpadCommunication; this.tableCollection = new List <BaseTable>(); }
// Validation /// <summary> /// Validate all mandatory parameters. /// Throws an exception if the parameter is null or invalid. /// </summary> /// <param name="communication">Pinpad facade, through which pinpad communication are made.</param> /// <param name="amount">Transaction amount.</param> private void Validate(IPinpadCommunication communication, decimal amount) { if (communication == null) { throw new ArgumentNullException("pinpadCommunication cannot be null. Unable to communicate with the pinpad."); } if (amount <= 0) { throw new ArgumentException("amount shall be greater than 0."); } }
public void PinpadTable_Construction_ShouldThrowException_IfPinpadCommunicationIsNull() { // Assert Assert.Throws <ArgumentNullException>(() => { // Arrange IPinpadCommunication nullPinpadCommunication = null; // Act PinpadTable table = new PinpadTable(nullPinpadCommunication); }); }
public void PinReader_Read_ShouldThrowException_IfPinpadCommunicationIsNull() { // Assert Assert.Throws <InvalidOperationException>(() => { // Arrange IPinpadCommunication nullPinpadCommunication = null; // Act PinReader pinReader = new PinReader(nullPinpadCommunication); }); }
// ctor: /// <summary> /// Creates the instance mandatorily with a <see cref="IPinpadInfos"/> and <see cref="IPinpadCommunication"/>. /// Otherwise, throws exception. /// </summary> /// <param name="pinpadInformation">Informations about the device.</param> /// <param name="pinpadCommunication">Responsible for sending and receiving commands to and from the /// pinpad.</param> /// <exception cref="ArgumentException">If any parameters are null.</exception> public PinpadUpdateService(IPinpadInfos pinpadInformation, IPinpadCommunication pinpadCommunication) { if (pinpadInformation == null) { throw new ArgumentNullException(nameof(pinpadInformation)); } if (pinpadCommunication == null) { throw new ArgumentNullException(nameof(pinpadInformation)); } this.PinpadInfos = pinpadInformation; this.PinpadCommunication = pinpadCommunication; }
public void EmvPinReaderTest_Read_should_throw_exception_if_null_PinpadFacade() { // Assert Assert.Throws <ArgumentNullException>(() => { // Arrange IPinpadCommunication nullPinpadCommunication = null; decimal amount = 1001; // Act this.emvPinReader.Read(nullPinpadCommunication, amount, out this.dummyPin); }); }
// Constructor /// <summary> /// Reads pinblock and ksn and sets it's value into this class property. /// Is up to the user using these infos. /// </summary> /// <param name="pinpadCommunication">PinpadFacade mandatory to this class be able to communicate with the pinpad.</param> /// <exception cref="System.InvalidOperationException">Thrown when one parameter validation fails.</exception> internal PinReader(IPinpadCommunication pinpadCommunication) { try { this.Validate(pinpadCommunication); } catch (Exception ex) { this.CommandStatus = ResponseStatus.InvalidParameter; throw new InvalidOperationException("Could not read pinpad security infos. Verify inner exception.", ex); } this.pinpadCommunication = pinpadCommunication; this.CommandStatus = ResponseStatus.Ok; this.chipReader = new EmvPinReader(); this.magneticStripeReader = new MagneticStripePinReader(); }
public void UpdateService_Creation_ShouldThrowException_IfPinpadCommunicationIsNull() { // Assert Assert.Throws <ArgumentNullException>(() => { // Arrange IPinpadInfos infos = new Stubs.PinpadInfosStub(); IPinpadCommunication comm = null; // Act and assert PinpadUpdateService pinpadUpdateService = new PinpadUpdateService( infos, comm); }); }
public void MagneticStripePinReader_Read_ShouldThrowException_IfPinpadCommunicationIsNull() { // Assert Assert.Throws <InvalidOperationException>(() => { // Arrange IPinpadCommunication nullPinpadCommunication = null; // Act this.emvPinReader.Read(nullPinpadCommunication, pan: "1234567890123456", amount: 1000, pin: out this.dummyPin); }); }
// Validation /// <summary> /// Validates parameters used on internal processing. /// </summary> /// <exception cref="System.ArgumentNullException">When one parameter is null.</exception> /// <exception cref="System.ArgumentException">When one parameter is not null, but contains invalid data.</exception> private void Validate(IPinpadCommunication pinpadCommunication, decimal amount, string pan) { if (pinpadCommunication == null) { throw new ArgumentNullException("pinpadFacade cannot be null. Unable to communicate with the pinpad."); } if (amount <= 0) { throw new ArgumentException("amount should be greater than 0."); } if (pan == null) { throw new ArgumentNullException("pan"); } if (pan.Length <= 0) { throw new ArgumentException("pan should not be empty."); } }
// Used internally /// <summary> /// Sends reading command using ABECS when card have a chip. /// </summary> /// <param name="pinpadCommunication">Pinpad communication, through which the communication with the pinpad is made.</param> /// <param name="amount">Transaction amount.</param> /// <returns>ABECS GOC command response.</returns> private GocResponse SendGoc(IPinpadCommunication pinpadCommunication, decimal amount) { GocRequest request = new GocRequest(); request.GOC_AMOUNT.Value = Convert.ToInt64(amount * 100); request.GOC_CASHBACK.Value = 0; request.GOC_EXCLIST.Value = false; request.GOC_CONNECT.Value = true; request.GOC_METHOD.Value = new CryptographyMethod(KeyManagementMode.DerivedUniqueKeyPerTransaction, CryptographyMode.TripleDataEncryptionStandard); request.GOC_KEYIDX.Value = (int)StoneIndexCode.EncryptionKey; request.GOC_WKENC.Value = new HexadecimalData("00000000000000000000000000000000"); request.GOC_RISKMAN.Value = false; request.GOC_FLRLIMIT.Value = new HexadecimalData("00000000"); request.GOC_TPBRS.Value = 0; request.GOC_TVBRS.Value = new HexadecimalData("00000000"); request.GOC_MTPBRS.Value = 0; request.GOC_TAGS1.Value = new HexadecimalData(EmvTag.GetEmvTagsRequired()); request.GOC_TAGS2.Value = new HexadecimalData(string.Empty); GocResponse response = pinpadCommunication.SendRequestAndReceiveResponse <GocResponse>(request); return(response); }
/// <summary> /// Creates an instance of <see cref="IngenicoPinpadPrinter"/> with all it's properties. /// </summary> /// <param name="communication">Pinpad communication service.</param> /// <param name="infos">Real time pinpad information.</param> public IngenicoPinpadPrinter(IPinpadCommunication communication, IPinpadInfos infos) { this.Communication = communication; this.PinpadInformation = infos; this.ItemsToPrint = new Collection <PrinterItem>(); }
// Methods /// <summary> /// Reads the card. /// </summary> /// <param name="communication">Pinpad facade, responsible for pinpad communication and plus.</param> /// <param name="amount">Transaction amount.</param> /// <param name="pin">Pin information read.</param> /// <returns>Operation status.</returns> internal ResponseStatus Read(IPinpadCommunication communication, decimal amount, out Pin pin) { pin = null; // Validating data this.Validate(communication, amount); // Using ABECS GOC command to communicate with pinpad. GocResponse commandResponse = this.SendGoc(communication, amount); if (commandResponse == null) { if (communication.Ping() == true) { // Pinpad is connected. Time out. return(ResponseStatus.TimeOut); } else { // Pinpad loss conection. throw new PinpadDisconnectedException("Não foi possível ler a senha.\nVerifique a conexão com o pinpad."); } } // Saving command response status: AbecsResponseStatus legacyStatus = commandResponse.RSP_STAT.Value; ResponseStatus status = ResponseStatusMapper.MapLegacyResponseStatus(legacyStatus); if (status != ResponseStatus.Ok) { return(status); } //if (status == ResponseStatus.OperationCancelled) { return status; } pin = new Pin(); pin.ApplicationCryptogram = this.GetValueFromEmvData( commandResponse.GOC_EMVDAT.Value.DataString, EmvTagCode.ApplicationCryptogram); pin.CardholderNameExtended = this.GetValueFromEmvData( commandResponse.GOC_EMVDAT.Value.DataString, EmvTagCode.CardholderNameExtended); // Whether is a pin online authentication or not. if (commandResponse.GOC_PINONL.Value.HasValue == true) { pin.IsOnline = commandResponse.GOC_PINONL.Value.Value; } // If EMV data war not returned from the command: if (commandResponse.GOC_EMVDAT.HasValue == false) { return(ResponseStatus.PinBusy); } // Savind EMV data: if (commandResponse.GOC_EMVDAT.Value != null) { pin.EmvData = commandResponse.GOC_EMVDAT.Value.DataString; } if (pin.IsOnline == true && commandResponse.GOC_DECISION.Value == OfflineTransactionStatus.RequiresAuthorization) { // If it's an online transaction, that is, needs pin and ksn emv validation: pin.PinBlock = commandResponse.GOC_PINBLK.Value.DataString; pin.KeySerialNumber = commandResponse.GOC_KSN.Value.DataString; } // Returns read pin block. return(status); }
// Constructor /// <summary> /// Constructor that /// </summary> /// <param name="pinpadCommunication"></param> public PinpadTransaction(IPinpadCommunication pinpadCommunication) { this.pinReader = new PinReader(pinpadCommunication); this.pinpadCommunication = pinpadCommunication; this.EmvTable = new PinpadTable(pinpadCommunication); }
public void Setup() { this.mockedComm = new Stubs.PinpadCommunicationStub(); this.dummyPinpadFacade = Mock.Of <IPinpadFacade>(); this.emvPinReader = new EmvPinReader(); }