// 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);
            }
        }