Beispiel #1
0
        // Transaction Methods
        /// <summary>
        /// On Pinpad screen, alternates between "RETIRE O CARTÃO" and parameter 'message' received, until card removal.
        /// </summary>
        /// <param name="message">Message to be shown on pinpad screen. Must not exceed 16 characters. This message remains on Pinpad screen after card removal.</param>
        /// <param name="padding">Message alignment.</param>
        /// <returns></returns>
        public bool RemoveCard(string message, DisplayPaddingType padding)
        {
            RmcRequest request = new RmcRequest();

            // Assemblies RMC command.
            request.RMC_MSG.Value = new SimpleMessageProperty(message, padding);

            // Sends command and receive response
            GenericResponse response = null;

            while (response == null)
            {
                response = this.pinpadCommunication.SendRequestAndReceiveResponse <GenericResponse>(request);
            }

            // Getting legacy response status code:
            AbecsResponseStatus legacyStatus = AbecsResponseStatus.ST_OK;

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

            // Verifies if the command was executed.
            if (this.LastCommandStatus == ResponseStatus.Ok)
            {
                return(true);
            }
            else
            {
                return(false);
            }
        }
Beispiel #2
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="newTransactionType">New transaction type read throgh ABECS protocol.</param>
        /// <returns>Card basic info.</returns>
        /// <param name="cardBrands">Collection of supported brands.</param>
        /// <exception cref="ExpiredCardException">When an expired card is read.</exception>
        public CardEntry ReadCard(TransactionType transactionType, decimal amount,
                                  out TransactionType newTransactionType, IList <PinpadCardBrand> cardBrands)
        {
            AbecsResponseStatus status;
            CardEntry           cardRead;

            status = this.PerformCardReading(transactionType, amount, out cardRead,
                                             out newTransactionType, cardBrands);
            this.LastCommandStatus = ResponseStatusMapper.MapLegacyResponseStatus(status);

            // EMV tables are incompatible. Recharging tables:
            if (status == AbecsResponseStatus.ST_TABVERDIF ||
                status == AbecsResponseStatus.ST_CARDAPPNAV)
            {
                // TODO: FAZER UM TRATAMENTO DECENTE
                return(null);
            }
            else if (status == AbecsResponseStatus.ST_TIMEOUT && this.pinpadCommunication.OpenPinpadConnection() == false)
            {
                // Conection loss
                throw new PinpadDisconnectedException();
            }
            else if (status == AbecsResponseStatus.ST_TABERR)
            {
                throw new InvalidTableException("EMV table version could not be found.");
            }
            else if (status == (AbecsResponseStatus)23)
            {
                this.LastCommandStatus = ResponseStatus.InvalidEmvTable;
            }

            return(cardRead);
        }
        // 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);
        }
Beispiel #4
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);
        }
        // Methods
        /// <summary>
        /// Reads the card.
        /// </summary>
        /// <param name="communication">Pinpad facade, responsible for pinpad communication and plus.</param>
        /// <param name="amount">Transaction amount.</param>
        /// <param name="pin">Pin information read.</param>
        /// <returns>Operation status.</returns>
        internal ResponseStatus Read(IPinpadCommunication communication, decimal amount, out Pin pin)
        {
            pin = null;

            // Validating data
            this.Validate(communication, amount);

            // Using ABECS GOC command to communicate with pinpad.
            GocResponse commandResponse = this.SendGoc(communication, amount);

            if (commandResponse == null)
            {
                if (communication.Ping() == true)
                {
                    // Pinpad is connected. Time out.
                    return(ResponseStatus.TimeOut);
                }
                else
                {
                    // Pinpad loss conection.
                    throw new PinpadDisconnectedException("Não foi possível ler a senha.\nVerifique a conexão com o pinpad.");
                }
            }

            // Saving command response status:
            AbecsResponseStatus legacyStatus = commandResponse.RSP_STAT.Value;
            ResponseStatus      status       = ResponseStatusMapper.MapLegacyResponseStatus(legacyStatus);

            if (status != ResponseStatus.Ok)
            {
                return(status);
            }
            //if (status == ResponseStatus.OperationCancelled) { return status; }

            pin = new Pin();
            pin.ApplicationCryptogram = this.GetValueFromEmvData(
                commandResponse.GOC_EMVDAT.Value.DataString, EmvTagCode.ApplicationCryptogram);
            pin.CardholderNameExtended = this.GetValueFromEmvData(
                commandResponse.GOC_EMVDAT.Value.DataString, EmvTagCode.CardholderNameExtended);

            // Whether is a pin online authentication or not.
            if (commandResponse.GOC_PINONL.Value.HasValue == true)
            {
                pin.IsOnline = commandResponse.GOC_PINONL.Value.Value;
            }

            // If EMV data war not returned from the command:
            if (commandResponse.GOC_EMVDAT.HasValue == false)
            {
                return(ResponseStatus.PinBusy);
            }

            // Savind EMV data:
            if (commandResponse.GOC_EMVDAT.Value != null)
            {
                pin.EmvData = commandResponse.GOC_EMVDAT.Value.DataString;
            }

            if (pin.IsOnline == true && commandResponse.GOC_DECISION.Value == OfflineTransactionStatus.RequiresAuthorization)
            {
                // If it's an online transaction, that is, needs pin and ksn emv validation:
                pin.PinBlock        = commandResponse.GOC_PINBLK.Value.DataString;
                pin.KeySerialNumber = commandResponse.GOC_KSN.Value.DataString;
            }

            // Returns read pin block.
            return(status);
        }