// 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); }
/// <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); }
/// <summary> /// Gets the PinBlock and KeySerialNumber of a card using DUKPT mode /// </summary> /// <param name="cryptographyMode">Cryptography Mode</param> /// <param name="keyIndex">Pinpad Key Index</param> /// <param name="pan">Card Pan</param> /// <param name="pinMinLength">Card Pin Minimum length</param> /// <param name="pinMaxLength">Card Pin Maximum length</param> /// <param name="message">Pin Entry Message</param> /// <param name="pinBlock">Retrieved pin block or null on failure</param> /// <param name="ksn">Retrieved key serial number of null on failure</param> /// <returns>true on success, false on failure</returns> public bool GetDukptPin(CryptographyMode cryptographyMode, int keyIndex, string pan, int pinMinLength, int pinMaxLength, SimpleMessageProperty message, out HexadecimalData pinBlock, out HexadecimalData ksn) { // Creater GPN request: GpnRequest request = new GpnRequest(); request.GPN_METHOD.Value = new CryptographyMethod(KeyManagementMode.DerivedUniqueKeyPerTransaction, cryptographyMode); request.GPN_KEYIDX.Value = keyIndex; request.GPN_WKENC.Value = new HexadecimalData(new byte[0]); request.GPN_PAN.Value = pan; // Settings to capture PIN: GpnPinEntryRequest entry = new GpnPinEntryRequest(); entry.GPN_MIN.Value = pinMinLength; entry.GPN_MAX.Value = pinMaxLength; entry.GPN_MSG.Value = message; request.GPN_ENTRIES.Value.Add(entry); // Sends the request and gets it's response: GpnResponse response = this.Communication.SendRequestAndReceiveResponse <GpnResponse>(request); // If none response war received: if (response == null) { pinBlock = null; ksn = null; return(false); } // If a response was received: else { pinBlock = response.GPN_PINBLK.Value; ksn = response.GPN_KSN.Value; return(true); } }