示例#1
0
        /// <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);
        }
示例#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="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);
        }