/// <summary>
        /// Translates card track data into information.
        /// </summary>
        /// <param name="rawResponse">Raw response from pinpad GCR command.</param>
        /// <returns>Card information.</returns>
        /// <exception cref="System.InvalidOperationException">Thrown when womething went wrong internally.</exception>
        public CardEntry Read(GcrResponse rawResponse)
        {
            CardEntry mappedCard = new CardEntry();

            // Save all tracks:
            if (rawResponse.GCR_TRK1.HasValue == true)
            {
                mappedCard.Track1 = rawResponse.GCR_TRK1.Value;
            }
            if (rawResponse.GCR_TRK2.HasValue == true)
            {
                mappedCard.Track2 = rawResponse.GCR_TRK2.Value;
            }

            // Selecting existing track:
            string selectedTrack = this.MapValidTrack(rawResponse);

            // Selecting corresponding track field separator:
            char fieldSeparator = this.GetFieldSeparator(selectedTrack);

            // Get Service code:
            ServiceCode sc = this.MapServiceCode(selectedTrack, fieldSeparator);

            // Values that don't need to be mapped:
            mappedCard.BrandId = rawResponse.GCR_RECIDX.Value.Value;

            // Mapping PAN, cardholder name, card expiration date and Service Code:
            mappedCard.PrimaryAccountNumber = this.MapPan(selectedTrack, fieldSeparator);
            mappedCard.CardholderName       = this.MapCardholderName(selectedTrack, fieldSeparator);
            mappedCard.ExpirationDate       = this.MapExpirationDate(selectedTrack, fieldSeparator);
            mappedCard.NeedsPassword        = sc.IsPinRequired;
            mappedCard.Type = (sc.IsEmv == true) ? CardType.Emv : CardType.MagneticStripe;

            return(mappedCard);
        }
 public void Setup()
 {
     this.Track1      = "4761739001010036^TESTING CARD MAPPER^123456789987456321";
     this.Track2      = "4761739001010036=15122011184404889";
     this.Track3      = string.Empty;
     this.GcrResponse = GcrResponseInitializer();
 }
        internal GcrResponse GcrResponseInitializer()
        {
            GcrResponse response = new GcrResponse();

            response.GCR_RECIDX.Value  = 99;
            response.GCR_CHNAME.Value  = "TESTING CARD MAPPER";
            response.GCR_CARDEXP.Value = DateTime.Now;
            response.GCR_PAN.Value     = "4761739001010036";

            return(response);
        }
Пример #4
0
        public void DefaultMagneticStripeTrackReader_MapValidTrack_ShouldThrowException_IfInvalidTrack()
        {
            // Assert
            Assert.Throws <InvalidOperationException>(() =>
            {
                // Arrange
                GcrResponse response = new GcrResponse();

                // Act
                this.defaultReader.MapValidTrack(response);
            });
        }
        /// <summary>
        /// Selects a valid track (between track 1 and 2), giving priority to Track 1.
        /// </summary>
        /// <param name="rawResponse">Raw response from pinpad GCR command.</param>
        /// <returns>Valid track to be read.</returns>
        internal string MapValidTrack(GcrResponse rawResponse)
        {
            if (rawResponse.GCR_TRK1.HasValue == true)
            {
                return(rawResponse.GCR_TRK1.Value);
            }
            if (rawResponse.GCR_TRK2.HasValue == true)
            {
                return(rawResponse.GCR_TRK2.Value);
            }

            throw new InvalidOperationException("Invalid track received. Verify if data sent are according to ISO 7810/7811.");
        }
Пример #6
0
        /// <summary>
        /// Reads a magnetic stripe card.
        /// </summary>
        /// <param name="rawResponse">Response from GCR.</param>
        /// <returns>The card read.</returns>
        internal static CardEntry MapCardFromTrack(GcrResponse rawResponse)
        {
            IMagneticStripeTrackReader reader;
            CardEntry card = null;

            try
            {
                reader = new DefaultMagneticStripeTrackReader();
                card   = reader.Read(rawResponse);
            }
            catch (Exception)
            {
                reader = new TicketMagneticStripeTrackReader();
                card   = reader.Read(rawResponse);
            }

            return(card);
        }
Пример #7
0
        /// <summary>
        /// Takes a GCR Response from Pinpad and translates it into Card information.
        /// </summary>
        /// <param name="rawResponse">GCR original response from Pinpad.</param>
        /// <param name="cardBrands">List of supported brands.</param>
        /// <returns>CardEntry containing basic information about the card.</returns>
        internal static CardEntry MapCardFromTracks(GcrResponse rawResponse,
                                                    IList <PinpadCardBrand> cardBrands)
        {
            CardType  readingMode = CardMapper.GetCardType(rawResponse.GCR_CARDTYPE.Value);
            CardEntry card        = null;

            if (readingMode == CardType.Emv)
            {
                card = EmvTrackMapper.MapCardFromEmvTrack(rawResponse);
            }
            else
            {
                card = MagneticStripeTrackMapper.MapCardFromTrack(rawResponse);
            }

            card.BrandName = CardMapper.GetBrandName(card.PrimaryAccountNumber,
                                                     cardBrands);

            // Unknown card type:
            return(card);
        }
Пример #8
0
        /// <summary>
        /// Map all card properties from it's magnetic stripe tracks.
        /// </summary>
        /// <param name="rawResponse">Response from GCR.</param>
        /// <returns>The card read.</returns>
        public CardEntry Read(GcrResponse rawResponse)
        {
            // Save tracks:
            CardEntry mappedCard = new CardEntry();

            mappedCard.Track1 = rawResponse.GCR_TRK1.Value;
            mappedCard.Track2 = rawResponse.GCR_TRK2.Value;

            // Get service code:
            ServiceCode serviceCode = this.MapServiceCode(mappedCard.Track2);

            // Values that don't need to be mapped:
            mappedCard.BrandId = rawResponse.GCR_RECIDX.Value.Value;

            // Mapping PAN, cardholder name, card expiration date and Service Code:
            mappedCard.PrimaryAccountNumber = this.MapPan(mappedCard.Track2);
            mappedCard.CardholderName       = this.MapCardholderName(mappedCard.Track1);
            mappedCard.ExpirationDate       = this.MapExpirationDate(mappedCard.Track2);
            mappedCard.NeedsPassword        = serviceCode.IsPinMandatory;
            mappedCard.Type = (serviceCode.IsEmv == true) ? CardType.Emv : CardType.MagneticStripe;

            return(mappedCard);
        }
Пример #9
0
        internal static CardEntry MapCardFromEmvTrack(GcrResponse response)
        {
            CardEntry mappedCard = new CardEntry();

            if (response == null)
            {
                Debug.WriteLine("GCR response is null.");
            }

            mappedCard.Type = CardType.Emv;
            if (response.GCR_RECIDX.HasValue == true)
            {
                mappedCard.BrandId = response.GCR_RECIDX.Value.Value;
                Debug.WriteLine(mappedCard.BrandId);
            }
            else
            {
                Debug.WriteLine("GCR_RECIDX null.");
            }

            if (response.GCR_CHNAME.HasValue == true)
            {
                mappedCard.CardholderName = response.GCR_CHNAME.Value;
                Debug.WriteLine(mappedCard.CardholderName);
            }
            else
            {
                Debug.WriteLine("GCR_CHNAME null.");
            }

            if (response.GCR_CARDEXP.HasValue == true)
            {
                mappedCard.ExpirationDate = response.GCR_CARDEXP.Value.Value;
                Debug.WriteLine(mappedCard.ExpirationDate);
            }
            else
            {
                Debug.WriteLine("GCR_CARDEXP null.");
            }

            if (response.GCR_PAN.HasValue == true)
            {
                mappedCard.PrimaryAccountNumber = response.GCR_PAN.Value;
                Debug.WriteLine(mappedCard.PrimaryAccountNumber);
            }
            else
            {
                Debug.WriteLine("GCR_PAN null.");
            }

            if (response.GCR_PANSEQNO.HasValue == true)
            {
                mappedCard.PrimaryAccountNumberSequenceNumber = response.GCR_PANSEQNO.Value;
                Debug.WriteLine(mappedCard.PrimaryAccountNumberSequenceNumber);
            }
            else
            {
                mappedCard.PrimaryAccountNumberSequenceNumber = 0;
            }

            if (response.GCR_TRK1.HasValue == true)
            {
                mappedCard.Track1 = response.GCR_TRK1.Value;
            }
            if (response.GCR_TRK2.HasValue == true)
            {
                mappedCard.Track2 = response.GCR_TRK2.Value;
            }

            mappedCard.NeedsPassword = true;

            return(mappedCard);
        }
Пример #10
0
 public void Setup()
 {
     this.GcrResponse = GcrResponseInitializer();
 }
Пример #11
0
        /// <summary>
        /// Read basic card information, that is, brand id, card type, card primary account number (PAN), cardholder name and expiration date.
        /// If the card is removed in the middle of the process, returns CANCEL status.
        /// </summary>
        /// <param name="transactionType">Transaction type, that is, debit/credit.</param>
        /// <param name="amount">Transaction amount.</param>
        /// <param name="cardRead">Card to be read.</param>
        /// <param name="newTransactionType">New transaction type read throgh ABECS protocol.</param>
        /// <param name="cardBrands">List of brands supported.</param>
        /// <returns>Operation status.</returns>
        private AbecsResponseStatus PerformCardReading(TransactionType transactionType,
                                                       decimal amount, out CardEntry cardRead, out TransactionType newTransactionType,
                                                       IList <PinpadCardBrand> cardBrands)
        {
            cardRead = null;

            newTransactionType = transactionType;

            GcrRequest request = this.CreateGcrRequest(transactionType, amount);

            // There's no table version, therefore tables cannot be reached.
            if (request == null)
            {
                return(AbecsResponseStatus.ST_TABERR);
            }

            // Sending and receiving response.
            Debug.WriteLine("Sending GCR command <{0}>", request.CommandString);
            GcrResponse response = this.pinpadCommunication.SendRequestAndReceiveResponse <GcrResponse>(request);

            // If timeout was reached:
            if (response == null)
            {
                return(AbecsResponseStatus.ST_TIMEOUT);
            }
            // If an error occurred:
            else if (response.RSP_STAT.Value != AbecsResponseStatus.ST_OK)
            {
                return(response.RSP_STAT.Value);
            }
            // If the card has expired:
            else if (response.GCR_CARDTYPE.Value == ApplicationType.MagneticStripe)
            {
                CardEntry tempCard;

                // Verify if it is really a magnetic stripe card:
                tempCard = CardMapper.MapCardFromTracks(response, cardBrands);

                // TODO: Incluir o fallback nessa condição.
                if (tempCard.Type != response.GCR_CARDTYPE.Value.ToCardType())
                {
                    throw new CardHasChipException();
                }

                // Validate expired cards:
                DateTime expirationDate = tempCard.ExpirationDate;

                if (expirationDate < DateTime.Now)
                {
                    throw new ExpiredCardException(expirationDate);
                }
            }
            else if (response.GCR_CARDEXP.HasValue == false)
            {
                throw new ExpiredCardException(DateTime.MinValue);
            }

            // Saving the transaction type. This is handy if you have initiated the transaction without knowing the transaction type.
            // In this situation, the user will select transaction type throgh the pinpad.
            newTransactionType = (TransactionType)response.GCR_APPTYPE.Value;

            // Saving command response status.
            // Getting legacy response status code:
            AbecsResponseStatus legacyStatus = response.RSP_STAT.Value;

            // Mapping legacy status code into Pinpad.Sdk response status code.
            this.LastCommandStatus = ResponseStatusMapper.MapLegacyResponseStatus(legacyStatus);

            // Get card information and return it:
            cardRead = CardMapper.MapCardFromTracks(response, cardBrands);

            if (cardRead.Type == CardType.Emv)
            {
                if (this.EmvTable.AidTable.Count <= 0)
                {
                    throw new InvalidTableException("AID table is empty.");
                }

                int brandId = cardRead.BrandId;
                var aidVar  = this.EmvTable.AidTable.First(a => a.TAB_RECIDX.Value.Value == brandId);

                cardRead.ApplicationId = aidVar.T1_AID.Value.DataString;

                // If it is a EMV transaction, then the application SHOULD send a CNG to change EMV parameters:
                // TODO: Ver como o comando CNG funciona. Não retirar.
                //if (response.GCR_CARDTYPE.Value == ApplicationType.IccEmv)
                //{
                //	CngRequest cng = new CngRequest();
                //	cng.CNG_EMVDAT.Value = ((...))
                //	bool stats = this.pinpadCommunication.SendRequestAndVerifyResponseCode(cng);
                //}
            }

            return(AbecsResponseStatus.ST_OK);
        }