/// <summary> /// Create a request for GCR. <seealso cref="GcrRequest"/> /// </summary> /// <param name="transactionType">Transaction type, e. g. credit/debit</param> /// <param name="amount">Transaction amount</param> /// <returns>A corresponding <see cref="GcrRequest"/></returns> private GcrRequest CreateGcrRequest(TransactionType transactionType, decimal amount) { // Assembling GCR command request: GcrRequest request = new GcrRequest(); // TODO: flag de acquirer. request.GCR_ACQIDXREQ.Value = (int)StoneIndexCode.Application; if (transactionType != TransactionType.Undefined) { request.GCR_APPTYPREQ.Value = (int)transactionType; } else { request.GCR_APPTYPREQ.Value = 99; } request.GCR_AMOUNT.Value = Convert.ToInt64(amount * 100); request.GCR_DATE_TIME.Value = DateTime.Now; // Retieving current EMV table version from pinpad: string emvTableVersion = this.EmvTable.GetEmvTableVersion(); Debug.WriteLine("EMV table version: <{0}>", emvTableVersion); if (emvTableVersion == null) { // There's no table version, therefore tables cannot be reached. return(null); } // If it's a valid EMV table version, then adds it to the command: request.GCR_TABVER.Value = emvTableVersion; return(request); }
/// <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); }