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 //} }