/// <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); }
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."); }
/// <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); }
/// <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); }
/// <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); }
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); }
public void Setup() { this.GcrResponse = GcrResponseInitializer(); }
/// <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); }