Пример #1
0
        private static SignalsEnum EntryPointRA(Kernel3Database database, CardResponse cardResponse, KernelQ qManager, CardQ cardQManager, Stopwatch sw, PublicKeyCertificateManager publicKeyCertificateManager, CardExceptionManager cardExceptionManager)
        {
            #region 5.2.2.2
            if (!cardResponse.ApduResponse.Succeeded)
            {
                TERMINAL_TRANSACTION_QUALIFIERS_9F66_KRN ttq = new TERMINAL_TRANSACTION_QUALIFIERS_9F66_KRN(database);
                if (cardResponse.ApduResponse.SW1 == 0x69 && cardResponse.ApduResponse.SW2 == 0x84 && ttq.Value.EMVModeSupported)
                {
                    return(CommonRoutines.PostOutcome(database, qManager,
                                                      KernelMessageidentifierEnum.INSERT_CARD,
                                                      KernelStatusEnum.PROCESSING_ERROR,
                                                      null,
                                                      Kernel2OutcomeStatusEnum.TRY_ANOTHER_INTERFACE,
                                                      Kernel2StartEnum.N_A,
                                                      true,
                                                      KernelMessageidentifierEnum.INSERT_CARD,
                                                      L1Enum.NOT_SET,
                                                      cardResponse.ApduResponse.SW12,
                                                      L2Enum.STATUS_BYTES,
                                                      L3Enum.NOT_SET));
                }
                if (cardResponse.ApduResponse.SW1 == 0x69 && cardResponse.ApduResponse.SW2 == 0x85)
                {
                    return(CommonRoutines.PostOutcome(database, qManager,
                                                      KernelMessageidentifierEnum.N_A,
                                                      KernelStatusEnum.N_A,
                                                      null,
                                                      Kernel2OutcomeStatusEnum.SELECT_NEXT,
                                                      Kernel2StartEnum.C,
                                                      null,
                                                      KernelMessageidentifierEnum.N_A,
                                                      L1Enum.NOT_SET,
                                                      null,
                                                      L2Enum.NOT_SET,
                                                      L3Enum.NOT_SET));
                }
                if (cardResponse.ApduResponse.SW1 == 0x69 && cardResponse.ApduResponse.SW2 == 0x86 && ttq.Value.EMVModeSupported)
                {
                    return(CommonRoutines.PostOutcome(database, qManager,
                                                      KernelMessageidentifierEnum.SEE_PHONE,
                                                      KernelStatusEnum.READY_TO_READ,
                                                      new byte[] { 0x00, 0x00, 0x0D },
                                                      Kernel2OutcomeStatusEnum.END_APPLICATION,
                                                      Kernel2StartEnum.B,
                                                      true,
                                                      KernelMessageidentifierEnum.SEE_PHONE,
                                                      L1Enum.NOT_SET,
                                                      cardResponse.ApduResponse.SW12,
                                                      L2Enum.STATUS_BYTES,
                                                      L3Enum.NOT_SET));
                }

                return(CommonRoutines.PostOutcome(database, qManager,
                                                  KernelMessageidentifierEnum.ERROR_OTHER_CARD,
                                                  KernelStatusEnum.PROCESSING_ERROR,
                                                  null,
                                                  Kernel2OutcomeStatusEnum.END_APPLICATION,
                                                  Kernel2StartEnum.N_A,
                                                  true,
                                                  KernelMessageidentifierEnum.ERROR_OTHER_CARD,
                                                  L1Enum.NOT_SET,
                                                  cardResponse.ApduResponse.SW12,
                                                  L2Enum.STATUS_BYTES,
                                                  L3Enum.NOT_SET));
            }
            #endregion

            bool parsingResult = false;
            if (cardResponse.ApduResponse.ResponseData.Length > 0 && cardResponse.ApduResponse.ResponseData[0] == 0x77)
            {
                EMVGetProcessingOptionsResponse response = cardResponse.ApduResponse as EMVGetProcessingOptionsResponse;
                parsingResult = database.ParseAndStoreCardResponse(response.ResponseData);
            }
            else
            {
                if (cardResponse.ApduResponse.ResponseData.Length > 0 && cardResponse.ApduResponse.ResponseData[0] == 0x80)
                {
                    EMVGetProcessingOptionsResponse response = cardResponse.ApduResponse as EMVGetProcessingOptionsResponse;
                    if (cardResponse.ApduResponse.ResponseData.Length < 6 ||
                        ((cardResponse.ApduResponse.ResponseData.Length - 2) % 4 != 0) ||
                        database.IsNotEmpty(EMVTagsEnum.APPLICATION_INTERCHANGE_PROFILE_82_KRN.Tag) ||
                        database.IsNotEmpty(EMVTagsEnum.APPLICATION_FILE_LOCATOR_AFL_94_KRN.Tag))
                    {
                        parsingResult = false;
                    }
                    else
                    {
                        database.AddToList(TLV.Create(EMVTagsEnum.APPLICATION_INTERCHANGE_PROFILE_82_KRN.Tag, response.GetResponseTags().Get(EMVTagsEnum.APPLICATION_INTERCHANGE_PROFILE_82_KRN.Tag).Value));
                        database.AddToList(TLV.Create(EMVTagsEnum.APPLICATION_FILE_LOCATOR_AFL_94_KRN.Tag, response.GetResponseTags().Get(EMVTagsEnum.APPLICATION_FILE_LOCATOR_AFL_94_KRN.Tag).Value));
                        parsingResult = true;
                    }
                }
            }

            if (!parsingResult)
            {
                return(K1K3.State_3_R1_CommonProcessing.DoInvalidReponse(database, qManager, L1Enum.NOT_SET, L2Enum.PARSING_ERROR, L3Enum.NOT_SET));
            }
            else
            {
                #region 5.4.1.1
                CommonRoutines.PostUIOnly(database, qManager, KernelMessageidentifierEnum.CLEAR_DISPLAY, KernelStatusEnum.CARD_READ_SUCCESSFULLY, true);
                #endregion

                if (!(database.IsNotEmpty(EMVTagsEnum.APPLICATION_INTERCHANGE_PROFILE_82_KRN.Tag)) &&
                    database.IsNotEmpty(EMVTagsEnum.APPLICATION_FILE_LOCATOR_AFL_94_KRN.Tag))
                {
                    return(K1K3.State_3_R1_CommonProcessing.DoInvalidReponse(database, qManager, L1Enum.NOT_SET, L2Enum.CARD_DATA_MISSING, L3Enum.NOT_SET));
                }
                else
                {
                    TERMINAL_TRANSACTION_QUALIFIERS_9F66_KRN ttq = new TERMINAL_TRANSACTION_QUALIFIERS_9F66_KRN(database);
                    if (ttq.Value.MagStripeModeSupported && !ttq.Value.EMVModeSupported)
                    {
                        return(K1K3.State_3_R1_CommonProcessing.DoInvalidReponse(database, qManager, L1Enum.NOT_SET, L2Enum.MAGSTRIPE_NOT_SUPPORTED, L3Enum.NOT_SET));
                    }
                    else
                    {
                        if (!ttq.Value.MagStripeModeSupported && ttq.Value.EMVModeSupported)
                        {
                            return(DoEMVMode(database, qManager, cardQManager, cardResponse, sw, publicKeyCertificateManager, cardExceptionManager));
                        }
                        else
                        {
                            return(K1K3.State_3_R1_CommonProcessing.DoInvalidReponse(database, qManager, L1Enum.NOT_SET, L2Enum.MAGSTRIPE_NOT_SUPPORTED, L3Enum.NOT_SET));
                        }
                    }
                }
            }
        }
        public static SignalsEnum DoCommonProcessing(string source, KernelDatabaseBase databaseIn, KernelQ qManager, CardQ cardQManager, Stopwatch sw, PublicKeyCertificateManager pkcm, CardExceptionManager cardExceptionManager)
        {
            Kernel3Database database = (Kernel3Database)databaseIn;

            if (database.NextCommandEnum == NextCommandEnum.READ_RECORD)
            {
                DoDEKIfNeeded(database, qManager);
                return(SignalsEnum.WAITING_FOR_EMV_READ_RECORD_RESPONSE);
            }

            DoDEKIfNeeded(database, qManager);

            //ReaderContactlessTransactionLimit exceeded
            if (database.ProcessingIndicatorsForSelected.ContactlessApplicationNotAllowed)
            {
                CommonRoutines.CreateEMVDiscretionaryData(database);
                return(CommonRoutines.PostOutcomeWithError(database, qManager, Kernel2OutcomeStatusEnum.SELECT_NEXT, Kernel2StartEnum.C, L1Enum.NOT_SET, L2Enum.MAX_LIMIT_EXCEEDED, L3Enum.NOT_SET));
            }

            #region 5.4.3.1
            TLV cidTLV = database.Get(EMVTagsEnum.CRYPTOGRAM_INFORMATION_DATA_9F27_KRN);
            if (cidTLV == null)
            {
                cidTLV = TLV.Create(EMVTagsEnum.CRYPTOGRAM_INFORMATION_DATA_9F27_KRN.Tag);
                cidTLV.Val.PackValue(cidTLV.Val.DataFormatter.GetMaxLength());
                byte iad = database.Get(EMVTagsEnum.ISSUER_APPLICATION_DATA_9F10_KRN).Value[4];
                Formatting.SetBitPosition(ref cidTLV.Value[0], Formatting.GetBitPosition(iad, 6), 8);
                Formatting.SetBitPosition(ref cidTLV.Value[0], Formatting.GetBitPosition(iad, 5), 7);
                database.AddToList(cidTLV);
            }
            #endregion

            #region 5.4.3.2
            byte cid = cidTLV.Value[0];
            cid = (byte)(cid >> 6);
            TERMINAL_TRANSACTION_QUALIFIERS_9F66_KRN ttq = new TERMINAL_TRANSACTION_QUALIFIERS_9F66_KRN(database);
            if (cid == (byte)ACTypeEnum.AAC)
            {
                database.DeclineRequiredByReaderIndicator = true;
            }
            if (cid == (byte)ACTypeEnum.ARQC || ttq.Value.OnlineCryptogramRequired)
            {
                database.OnlineRequiredByReaderIndicator = true;
            }
            if (cid != (byte)ACTypeEnum.AAC && cid != (byte)ACTypeEnum.ARQC && cid != (byte)ACTypeEnum.TC)
            {
                database.DeclineRequiredByReaderIndicator = true;
            }
            #endregion

            #region 5.4.2.1
            if (!database.DeclineRequiredByReaderIndicator)
            {
                if (!CheckMandatoryFields(database, pkcm))
                {
                    return(CommonRoutines.PostOutcome(database, qManager,
                                                      KernelMessageidentifierEnum.ERROR_OTHER_CARD,
                                                      KernelStatusEnum.PROCESSING_ERROR,
                                                      null,
                                                      Kernel2OutcomeStatusEnum.END_APPLICATION,
                                                      Kernel2StartEnum.N_A,
                                                      true,
                                                      KernelMessageidentifierEnum.ERROR_OTHER_CARD,
                                                      L1Enum.NOT_SET,
                                                      null,
                                                      L2Enum.CARD_DATA_ERROR,
                                                      L3Enum.NOT_SET));
                }
            }
            #endregion

            if (!database.DeclineRequiredByReaderIndicator && !database.OnlineRequiredByReaderIndicator)
            {
                #region 5.5.1.1 to 5.5.1.5
                SignalsEnum result = DoProcessingRestrictions(database, qManager, cardExceptionManager);
                if (result != SignalsEnum.NONE)
                {
                    return(result);
                }
                #endregion

                #region  5.6.1.1, 5.6.1.2 and 5.6.2.1, 5.6.2.1
                if (!DoOfflineAuth(database, qManager, pkcm))
                #endregion
                {
                    CARD_TRANSACTION_QUALIFIERS_CTQ_9F6C_KRN3 ctq = new CARD_TRANSACTION_QUALIFIERS_CTQ_9F6C_KRN3(database);
                    if (ctq.Value.GoOnlineIfOfflineDataAuthenticationFailsAndReaderIsOnlineCapable && !database.ProcessingIndicatorsForSelected.TTQ.Value.OfflineOnlyReader)
                    {
                        database.OnlineRequiredByReaderIndicator = true;
                    }
                    else if (ctq.Value.SwitchInterfaceIfOfflineDataAuthenticationFailsAndReaderSupportsVIS && database.ProcessingIndicatorsForSelected.TTQ.Value.EMVContactChipSupported)
                    {
                        return(CommonRoutines.PostOutcome(database, qManager,
                                                          KernelMessageidentifierEnum.INSERT_CARD,
                                                          KernelStatusEnum.PROCESSING_ERROR,
                                                          null,
                                                          Kernel2OutcomeStatusEnum.TRY_ANOTHER_INTERFACE,
                                                          Kernel2StartEnum.N_A,
                                                          true,
                                                          KernelMessageidentifierEnum.INSERT_CARD,
                                                          L1Enum.NOT_SET,
                                                          null,
                                                          L2Enum.TERMINAL_DATA_ERROR,
                                                          L3Enum.NOT_SET));
                    }
                    else
                    {
                        database.DeclineRequiredByReaderIndicator = true;
                    }
                }
            }


            #region 5.7.1.1, 5.7.1.2, 5.7.1.3
            KernelCVMEnum cvm = KernelCVMEnum.N_A;
            if (!database.DeclineRequiredByReaderIndicator)
            {
                cvm = DoCVMProcessing(database, (ACTypeEnum)Formatting.GetEnum(typeof(ACTypeEnum), cid));
                if (cvm == KernelCVMEnum.NO_CVM && ttq.Value.CVMRequired)
                {
                    database.DeclineRequiredByReaderIndicator = true;
                }
            }
            #endregion

            #region 4.3.1.1
            byte[]             currencyCode = null;
            byte[]             balance      = null;
            ValueQualifierEnum vq           = ValueQualifierEnum.NONE;
            if (database.Kernel3Configuration.DisplayAvailableSpendingAmount)
            {
                TLV balanceTLV = database.Get(EMVTagsEnum.AVAILABLE_OFFLINE_SPENDING_AMOUNT_AOSA_9F5D_KRN3);
                if (balanceTLV != null)
                {
                    vq           = ValueQualifierEnum.BALANCE;
                    balance      = balanceTLV.Value;
                    currencyCode = database.Get(EMVTagsEnum.TRANSACTION_CURRENCY_CODE_5F2A_KRN).Value;
                }
            }
            #endregion

            //#region support for Refunds
            //byte transactionType = database.Get(EMVTagsEnum.TRANSACTION_TYPE_9C_KRN).Value[0];
            //if (transactionType == (byte)TransactionTypeEnum.Refund)
            //    database.DeclineRequiredByReaderIndicator = true;
            //#endregion

            #region 5.8.1.1
            if (database.OnlineRequiredByReaderIndicator && !database.DeclineRequiredByReaderIndicator)
            {
                CommonRoutines.CreateEMVDataRecord(database);
                CommonRoutines.CreateEMVDiscretionaryData(database);
                return(CommonRoutines.PostOutcome(database, qManager,
                                                  KernelMessageidentifierEnum.AUTHORISING_PLEASE_WAIT,
                                                  KernelStatusEnum.NOT_READY,
                                                  null,
                                                  Kernel2OutcomeStatusEnum.ONLINE_REQUEST,
                                                  Kernel2StartEnum.N_A,
                                                  true,
                                                  KernelMessageidentifierEnum.N_A,
                                                  L1Enum.NOT_SET,
                                                  null,
                                                  L2Enum.NOT_SET,
                                                  L3Enum.NOT_SET,
                                                  vq,
                                                  balance,
                                                  currencyCode,
                                                  false,
                                                  cvm));
            }
            #endregion

            #region 5.9.1.1
            if (!database.OnlineRequiredByReaderIndicator && !database.DeclineRequiredByReaderIndicator)
            {
                CommonRoutines.CreateEMVDataRecord(database);
                CommonRoutines.CreateEMVDiscretionaryData(database);
                return(CommonRoutines.PostOutcome(database, qManager,
                                                  cvm == KernelCVMEnum.OBTAIN_SIGNATURE ? KernelMessageidentifierEnum.APPROVED_SIGN : KernelMessageidentifierEnum.APPROVED,
                                                  KernelStatusEnum.READY_TO_READ,
                                                  null,
                                                  Kernel2OutcomeStatusEnum.APPROVED,
                                                  Kernel2StartEnum.N_A,
                                                  true,
                                                  KernelMessageidentifierEnum.N_A,
                                                  L1Enum.NOT_SET,
                                                  null,
                                                  L2Enum.NOT_SET,
                                                  L3Enum.NOT_SET,
                                                  vq,
                                                  balance,
                                                  currencyCode,
                                                  false,
                                                  cvm));
            }
            #endregion

            CommonRoutines.CreateEMVDiscretionaryData(database);
            //#region support for Refunds
            //if (transactionType == (byte)TransactionTypeEnum.Refund)
            //#endregion
            //{
            //    //CommonRoutines.PostUIOnly(database, qManager, Kernel1MessageidentifierEnum.CLEAR_DISPLAY, Kernel1StatusEnum.N_A, true, new byte[] { 0x00, 0x00, 0x00 });

            //    CommonRoutines.CreateEMVDataRecord(database);
            //    return CommonRoutines.PostOutcome(database, qManager,
            //        KernelMessageidentifierEnum.N_A,
            //        KernelStatusEnum.N_A,
            //        null,
            //        Kernel2OutcomeStatusEnum.END_APPLICATION,
            //        Kernel2StartEnum.N_A,
            //        true,
            //        KernelMessageidentifierEnum.N_A,
            //        L1Enum.NOT_SET,
            //        null,
            //        L2Enum.NOT_SET,
            //        L3Enum.NOT_SET,
            //        ValueQualifierEnum.NONE,
            //        null,
            //        null,
            //        false,
            //        cvm);
            //}
            //else
            //{
            #region 5.9.1.2
            return(CommonRoutines.PostOutcome(database, qManager,
                                              KernelMessageidentifierEnum.DECLINED,
                                              KernelStatusEnum.READY_TO_READ,
                                              null,
                                              Kernel2OutcomeStatusEnum.DECLINED,
                                              Kernel2StartEnum.N_A,
                                              true,
                                              KernelMessageidentifierEnum.N_A,
                                              L1Enum.NOT_SET,
                                              null,
                                              L2Enum.NOT_SET,
                                              L3Enum.NOT_SET,
                                              vq,
                                              balance,
                                              currencyCode,
                                              false,
                                              cvm));

            #endregion
            //}
        }