private bool CheckIfCertInCertRevocationList(CAPublicKeyCertificate capk) { int found = RevokedCAPublicKeyCertificates.Count(x => { DateTime dt = DateTime.ParseExact(Formatting.BcdToString(x.ExpiryDate), "MMyy", System.Globalization.CultureInfo.InvariantCulture); if (x.RID == capk.RID && x.Index == capk.Index && dt < DateTime.Now) { return(true); } else { return(false); } }); if (found > 0) { Logger.Log("Certificate is revoked, index:" + Formatting.ByteArrayToHexString(new byte[] { capk.Index })); return(true); } else { return(false); } }
public string ConvertToString(byte[] data) { switch (Format) { //case DataFormats.UNKNOWN: //case DataFormats.VARIABLE_UNKNOWN: case DataFormats._BINARY: case DataFormats._BINARY_16: //case DataFormats._BINARY_MULTIPLE_OF_4: //case DataFormats.H: //case DataFormats.A: return(Formatting.ByteArrayToHexString(data)); case DataFormats._CN: case DataFormats._DATE_YYMMDD: case DataFormats._TIME_HHMMSS: case DataFormats._NUMERIC: return(Formatting.BcdToString(data)); case DataFormats._ALPHA: case DataFormats._ALPHA_NUMERIC: case DataFormats._ALPHA_NUMERIC_SPECIAL: case DataFormats._ALPHA_NUMERIC_SPACE: return(Formatting.ByteArrayToASCIIString(data)); default: throw new Exception("Unknown DataFormat:" + Format); } }
public override int Deserialize(byte[] rawTlv, int pos) { pos = base.Deserialize(rawTlv, pos); string input = Formatting.BcdToString(Value); string[] inputs = input.Split('D'); PAN = inputs[0]; ExpirationDate = inputs[1].Substring(0, 4); ServiceCode = inputs[1].Substring(4, 3); DiscretionaryData = inputs[1].Substring(7, inputs[1].Length - 7); return(pos); }
public override byte[] Serialize() { //List<byte[]> result = new List<byte[]>(); //result.Add(Formatting.StringToBcd(PAN,false)); //result.Add(new byte[] { (byte)'D' }); //result.Add(Formatting.StringToBcd(ExpirationDate, false)); //result.Add(Formatting.StringToBcd(ServiceCode, false)); //result.Add(DiscretionaryData); string output = PAN + 'D' + ExpirationDate + ServiceCode + Formatting.BcdToString(DiscretionaryData); Value = Formatting.StringToBcd(output, false); //Value = result.SelectMany(x => x).ToArray(); return(base.Serialize()); }
public DateTime FormatAsDateTime(byte[] value) { if (DataFormatter.Format != DataFormats._DATE_YYMMDD && DataFormatter.Format != DataFormats._TIME_HHMMSS) { throw new Exception("Cannot format value as DateTime"); } if (DataFormatter.Format == DataFormats._DATE_YYMMDD) { return(DateTime.ParseExact(Formatting.BcdToString(value), "yyMMdd", System.Globalization.CultureInfo.InvariantCulture)); } if (DataFormatter.Format == DataFormats._TIME_HHMMSS) { return(DateTime.ParseExact(Formatting.BcdToString(value), "HHmmss", System.Globalization.CultureInfo.InvariantCulture)); } throw new Exception("Cannot format value as DateTime"); }
private async void EmvTxCtl_TxCompleted(object sender, EventArgs e) { try { if ((e as TxCompletedEventArgs).EMV_Data.IsPresent()) { TLV data = (e as TxCompletedEventArgs).EMV_Data.Get(); string emvData = TLVasJSON.ToJSON(data); string uid = Formatting.BcdToString(data.Children.Get(EMVTagsEnum.APPLICATION_PRIMARY_ACCOUNT_NUMBER_PAN_5A_KRN.Tag).Value); await RegisterCard(SessionSingleton.Account.AccountNumberId, uid); Device.BeginInvokeOnMainThread(() => { SessionSingleton.Account.Cards.Add(new Card() { CardSerialNumberId = uid, }); lblStatusCard.Text = string.Format("Card {0} linked", uid); UpdateView(CardAdminViewState.CardAddStatus); }); } else { lblStatusCard.Text = "Card not linked"; UpdateView(CardAdminViewState.CardAddStatus); } } catch (Exception ex) { Device.BeginInvokeOnMainThread(() => { UpdateView(CardAdminViewState.CardAddStatus); lblStatusCard.Text = ex.Message; }); } }
/* * 14.6 */ private static SignalsEnum EntryPointRA(Kernel2Database database, CardResponse cardResponse, KernelQ qManager, CardQ cardQManager, TornTransactionLogManager tornTransactionLogManager, Stopwatch sw, PublicKeyCertificateManager publicKeyCertificateManager) { #region 14.9 if (!cardResponse.ApduResponse.Succeeded) #endregion { #region 14.10 CommonRoutines.UpdateErrorIndication(database, cardResponse, L1Enum.NOT_SET, L2Enum.STATUS_BYTES, L3Enum.NOT_SET); return(DoInvalidResponse(database, qManager)); #endregion } #region 14.11 bool parsingResult = false; if (cardResponse.ApduResponse.ResponseData.Length > 0 && cardResponse.ApduResponse.ResponseData[0] == 0x77) { EMVComputeCryptographicChecksumResponse response = cardResponse.ApduResponse as EMVComputeCryptographicChecksumResponse; parsingResult = database.ParseAndStoreCardResponse(response.ResponseData); } else { parsingResult = false; } #endregion #region 14.12 if (!parsingResult) #endregion { #region 14.13 CommonRoutines.UpdateErrorIndication(database, cardResponse, L1Enum.NOT_SET, L2Enum.PARSING_ERROR, L3Enum.NOT_SET); return(DoInvalidResponse(database, qManager)); #endregion } #region 14.12.1 CommonRoutines.PostUIOnly(database, qManager, KernelMessageidentifierEnum.CLEAR_DISPLAY, KernelStatusEnum.CARD_READ_SUCCESSFULLY, true); #endregion #region 14.14 if (database.IsEmpty(EMVTagsEnum.APPLICATION_TRANSACTION_COUNTER_ATC_9F36_KRN.Tag) || database.IsEmpty(EMVTagsEnum.POS_CARDHOLDER_INTERACTION_INFORMATION_DF4B_KRN2.Tag)) #endregion { #region 14.17 CommonRoutines.UpdateErrorIndication(database, cardResponse, L1Enum.NOT_SET, L2Enum.CARD_DATA_MISSING, L3Enum.NOT_SET); return(DoInvalidResponse(database, qManager)); #endregion } long nUN = 0; #region 14.15 if (database.IsNotEmpty(EMVTagsEnum.CVC3_TRACK2_9F61_KRN2.Tag)) #endregion { #region 14.16 if (database.IsNotEmpty(EMVTagsEnum.TRACK_1_DATA_56_KRN2.Tag) && (database.IsNotPresent(EMVTagsEnum.CVC3_TRACK1_9F60_KRN2.Tag) || database.IsEmpty(EMVTagsEnum.CVC3_TRACK1_9F60_KRN2.Tag))) #endregion { #region 14.17 CommonRoutines.UpdateErrorIndication(database, cardResponse, L1Enum.NOT_SET, L2Enum.CARD_DATA_MISSING, L3Enum.NOT_SET); return(DoInvalidResponse(database, qManager)); #endregion } #region 14.20 byte pcii = database.Get(EMVTagsEnum.POS_CARDHOLDER_INTERACTION_INFORMATION_DF4B_KRN2).Value[1]; #endregion if ((pcii & 0x10) == 0x10) //OD-CVM verification successful { #region 14.24 nUN = (nUN + 5) % 10; #endregion } else { #region 14.21 long aa = Formatting.BcdToLong(database.Get(EMVTagsEnum.AMOUNT_AUTHORISED_NUMERIC_9F02_KRN).Value); long rctl = database.ReaderContactlessTransactionLismit; if (aa > rctl) #endregion { #region 14.21.1 CommonRoutines.UpdateErrorIndication(database, cardResponse, L1Enum.NOT_SET, L2Enum.CARD_DATA_ERROR, L3Enum.NOT_SET); return(DoInvalidResponse(database, qManager)); #endregion } else { #region 14.25 nUN = (int)Formatting.ConvertToInt32(database.Get(EMVTagsEnum.UNPREDICTABLE_NUMBER_9F37_KRN).Value); #endregion } } #region 14.25.1 database.FailedMSCntr = 0; #endregion #region 14.26 TRACK_2_DATA_9F6B_KRN2 t2d = new TRACK_2_DATA_9F6B_KRN2(database); ushort t2 = Formatting.ConvertToInt16(database.Get(EMVTagsEnum.NATC_TRACK2_9F67_KRN2).Value); TLV PCVC3_TRACK2_9F65_KRN2 = database.Get(EMVTagsEnum.PCVC3_TRACK2_9F65_KRN2); MagBitmap bitmapPCVC3_TRACK2_9F65_KRN2 = new MagBitmap(PCVC3_TRACK2_9F65_KRN2.Value); TLV CVC3_TRACK2_9F61_KRN2 = database.Get(EMVTagsEnum.CVC3_TRACK2_9F61_KRN2); ushort cvc3T2AsShort = Formatting.ConvertToInt16(CVC3_TRACK2_9F61_KRN2.Value.Reverse().ToArray()); string q2LeastSigDigits = Convert.ToString(cvc3T2AsShort); q2LeastSigDigits = q2LeastSigDigits.Substring(q2LeastSigDigits.Length - bitmapPCVC3_TRACK2_9F65_KRN2.NonZeroCount); t2d.Value.DiscretionaryData = Formatting.StringToBcd(bitmapPCVC3_TRACK2_9F65_KRN2.ReplaceValues(Formatting.BcdToString(t2d.Value.DiscretionaryData), q2LeastSigDigits, bitmapPCVC3_TRACK2_9F65_KRN2.NonZeroCount, true), false); TLV PUNATC_TRACK2_9F66_KRN2 = database.Get(EMVTagsEnum.PUNATC_TRACK2_9F66_KRN2); MagBitmap bitmapPUNATC_TRACK2_9F66_KRN2 = new MagBitmap(PUNATC_TRACK2_9F66_KRN2.Value); uint unpredInt = Formatting.ConvertToInt32(database.Get(EMVTagsEnum.UNPREDICTABLE_NUMBER_NUMERIC_9F6A_KRN2).Value.Reverse().ToArray()); string unpredString = Convert.ToString(unpredInt); unpredString = unpredString.Substring(unpredString.Length - database.NUN); t2d.Value.DiscretionaryData = Formatting.StringToBcd(bitmapPUNATC_TRACK2_9F66_KRN2.ReplaceValues(Formatting.BcdToString(t2d.Value.DiscretionaryData), unpredString, database.NUN, true), false); if (t2 != 0) { TLV APPLICATION_TRANSACTION_COUNTER_ATC_9F36_KRN = database.Get(EMVTagsEnum.APPLICATION_TRANSACTION_COUNTER_ATC_9F36_KRN); uint atcAsShort = Formatting.ConvertToInt32(APPLICATION_TRANSACTION_COUNTER_ATC_9F36_KRN.Value.Reverse().ToArray()); string atcAsShortLeastSigDigits = Convert.ToString(atcAsShort); atcAsShortLeastSigDigits = atcAsShortLeastSigDigits.PadLeft(t2, '0').Substring(atcAsShortLeastSigDigits.Length - t2); t2d.Value.DiscretionaryData = Formatting.StringToBcd(bitmapPUNATC_TRACK2_9F66_KRN2.ReplaceValues(Formatting.BcdToString(t2d.Value.DiscretionaryData), atcAsShortLeastSigDigits, t2, false), false); } #endregion #region 14.27 StringBuilder dd = new StringBuilder(Formatting.BcdToString(t2d.Value.DiscretionaryData)); dd[dd.Length - 1] = Convert.ToString(nUN)[0]; t2d.Value.DiscretionaryData = Formatting.StringToBcd(dd.ToString(), false); #endregion t2d.Serialize(); //reserialize in case the length of discretionary data changed t2d.UpdateDB(); #region 14.28 if (database.IsNotEmpty(EMVTagsEnum.TRACK_1_DATA_56_KRN2.Tag)) #endregion { #region 14.29 TRACK_1_DATA_56_KRN2 t1d = new TRACK_1_DATA_56_KRN2(database); ushort t1 = Formatting.ConvertToInt16(database.Get(EMVTagsEnum.NATC_TRACK1_9F64_KRN2).Value); TLV PCVC3_TRACK1_9F62_KRN2 = database.Get(EMVTagsEnum.PCVC3_TRACK1_9F62_KRN2); MagBitmap bitmapPCVC3_TRACK1_9F62_KRN2 = new MagBitmap(PCVC3_TRACK1_9F62_KRN2.Value); TLV CVC3_TRACK1_9F60_KRN2 = database.Get(EMVTagsEnum.CVC3_TRACK1_9F60_KRN2); ushort cvc3T1AsShort = Formatting.ConvertToInt16(CVC3_TRACK1_9F60_KRN2.Value.Reverse().ToArray()); string q1LeastSigDigits = Convert.ToString(cvc3T1AsShort); q1LeastSigDigits = q1LeastSigDigits.Substring(q1LeastSigDigits.Length - bitmapPCVC3_TRACK1_9F62_KRN2.NonZeroCount); t1d.Value.DiscretionaryData = Formatting.ASCIIStringToByteArray(bitmapPCVC3_TRACK1_9F62_KRN2.ReplaceValues(Formatting.ByteArrayToASCIIString(t1d.Value.DiscretionaryData), q1LeastSigDigits, bitmapPCVC3_TRACK1_9F62_KRN2.NonZeroCount, true)); TLV PUNATC_TRACK1_9F63_KRN2 = database.Get(EMVTagsEnum.PUNATC_TRACK1_9F63_KRN2); MagBitmap bitmapPUNATC_TRACK1_9F63_KRN2 = new MagBitmap(PUNATC_TRACK1_9F63_KRN2.Value); t1d.Value.DiscretionaryData = Formatting.ASCIIStringToByteArray(bitmapPUNATC_TRACK1_9F63_KRN2.ReplaceValues(Formatting.ByteArrayToASCIIString(t1d.Value.DiscretionaryData), unpredString, database.NUN, true)); if (t2 != 0) { TLV APPLICATION_TRANSACTION_COUNTER_ATC_9F36_KRN = database.Get(EMVTagsEnum.APPLICATION_TRANSACTION_COUNTER_ATC_9F36_KRN); uint atcAsShort = Formatting.ConvertToInt32(APPLICATION_TRANSACTION_COUNTER_ATC_9F36_KRN.Value.Reverse().ToArray()); string atcAsShortLeastSigDigits = Convert.ToString(atcAsShort); atcAsShortLeastSigDigits = atcAsShortLeastSigDigits.PadLeft(t2, '0').Substring(atcAsShortLeastSigDigits.Length - t1); t2d.Value.DiscretionaryData = Formatting.ASCIIStringToByteArray(bitmapPUNATC_TRACK1_9F63_KRN2.ReplaceValues(Formatting.ByteArrayToASCIIString(t1d.Value.DiscretionaryData), atcAsShortLeastSigDigits, t1, false)); } #endregion #region 14.30 StringBuilder dd1 = new StringBuilder(Formatting.ByteArrayToASCIIString(t1d.Value.DiscretionaryData)); dd1[dd1.Length - 1] = Convert.ToString(nUN)[0]; t1d.Value.DiscretionaryData = Formatting.ASCIIStringToByteArray(dd1.ToString()); #endregion t1d.Serialize(); //reserialize in case the length of discretionary data changed t1d.UpdateDB(); } #region 14.32 Kernel2OutcomeStatusEnum k2OutcomeStatus = Kernel2OutcomeStatusEnum.ONLINE_REQUEST; KernelCVMEnum cvmEnum = KernelCVMEnum.N_A; bool receipt = false; pcii = database.Get(EMVTagsEnum.POS_CARDHOLDER_INTERACTION_INFORMATION_DF4B_KRN2).Value[1]; if ((pcii & 0x10) == 0x10) //OD-CVM verification successful #endregion { #region 14.34 cvmEnum = KernelCVMEnum.CONFIRMATION_CODE_VERIFIED; long aa = Formatting.BcdToLong(database.Get(EMVTagsEnum.AMOUNT_AUTHORISED_NUMERIC_9F02_KRN).Value); long rctl = database.ReaderContactlessTransactionLismit; if (aa > rctl) { receipt = true; } #endregion } else { #region 14.33 cvmEnum = KernelCVMEnum.NO_CVM; #endregion } CommonRoutines.CreateMSDiscretionaryDataRecord(database); CommonRoutines.CreateMSDataRecord(database); return(CommonRoutines.PostOutcomeOnly(database, qManager, k2OutcomeStatus, cvmEnum, receipt)); } else { #region 14.19.1 if (((int)Formatting.ConvertToInt32(database.Get(EMVTagsEnum.POS_CARDHOLDER_INTERACTION_INFORMATION_DF4B_KRN2).Value) & 0x00030F) != 0x000000) #endregion { KernelMessageidentifierEnum k2MessageIdentifier = KernelMessageidentifierEnum.DECLINED; KernelStatusEnum k2Status = KernelStatusEnum.READY_TO_READ; byte[] holdTime = new byte[] { 0x00, 0x00, 0x00 }; #region 14.22 PHONE_MESSAGE_TABLE_DF8131_KRN2 pmt = (PHONE_MESSAGE_TABLE_DF8131_KRN2)database.GetDefault(EMVTagsEnum.PHONE_MESSAGE_TABLE_DF8131_KRN2); foreach (PhoneMessageTableEntry_DF8131 entry in pmt.Value.Entries) { int pcii = (int)Formatting.ConvertToInt32(database.Get(EMVTagsEnum.POS_CARDHOLDER_INTERACTION_INFORMATION_DF4B_KRN2).Value); int pciMask = (int)Formatting.ConvertToInt32(entry.PCIIMask); int pciValue = (int)Formatting.ConvertToInt32(entry.PCIIValue); if ((pciMask & pcii) == pciValue) { k2MessageIdentifier = entry.MessageIdentifier; k2Status = entry.Status; holdTime = database.GetDefault(EMVTagsEnum.MESSAGE_HOLD_TIME_DF812D_KRN2).Value; break; } } #endregion #region 14.21.1 int waitTime = ((2 ^ database.FailedMSCntr) * 300); Task.Delay(TimeSpan.FromMilliseconds(waitTime)).Wait(); #endregion #region 14.21.2 database.FailedMSCntr = Math.Min(database.FailedMSCntr + 1, 5); #endregion #region 14.23 CommonRoutines.CreateMSDiscretionaryDataRecord(database); CommonRoutines.CreateMSDataRecord(database); return(CommonRoutines.PostOutcome(database, qManager, k2MessageIdentifier, k2Status, holdTime, Kernel2OutcomeStatusEnum.END_APPLICATION, Kernel2StartEnum.B, false, KernelMessageidentifierEnum.N_A, L1Enum.NOT_SET, null, L2Enum.NOT_SET, L3Enum.NOT_SET)); #endregion } else { #region 14.19.2.1 int waitTime = ((2 ^ database.FailedMSCntr) * 300); Task.Delay(TimeSpan.FromMilliseconds(waitTime)).Wait(); #endregion #region 14.19.2.2 database.FailedMSCntr = Math.Min(database.FailedMSCntr + 1, 5); #endregion #region 14.19.3 CommonRoutines.CreateMSDiscretionaryDataRecord(database); CommonRoutines.CreateMSDataRecord(database); return(CommonRoutines.PostOutcome(database, qManager, KernelMessageidentifierEnum.DECLINED, KernelStatusEnum.NOT_READY, database.GetDefault(EMVTagsEnum.MESSAGE_HOLD_TIME_DF812D_KRN2).Value, Kernel2OutcomeStatusEnum.END_APPLICATION, Kernel2StartEnum.N_A, true, KernelMessageidentifierEnum.N_A, L1Enum.NOT_SET, null, L2Enum.NOT_SET, L3Enum.NOT_SET)); #endregion } } }
private async void EmvTxCtl_TxCompleted(object sender, EventArgs e) { try { TransactionType transactionType; string fromAccountNumber = ""; string cardSerialNumberFrom = ""; string toAccountNumber = ""; string cardSerialNumberTo = ""; if ((e as TxCompletedEventArgs).EMV_Data.IsPresent()) { if ((e as TxCompletedEventArgs).TxResult == TxResult.Approved || (e as TxCompletedEventArgs).TxResult == TxResult.ContactlessOnline) { TLV data = (e as TxCompletedEventArgs).EMV_Data.Get(); byte[] panBCD; TLV _5A = data.Children.Get(EMVTagsEnum.APPLICATION_PRIMARY_ACCOUNT_NUMBER_PAN_5A_KRN.Tag); if (_5A != null) { panBCD = _5A.Value; } else { TLV _57 = data.Children.Get(EMVTagsEnum.TRACK_2_EQUIVALENT_DATA_57_KRN.Tag); if (_57 == null) { throw new Exception("No PAN found"); } String panString = Formatting.ByteArrayToHexString(_57.Value); panBCD = Formatting.StringToBcd(panString.Split('D')[0], false); } TLV _9F02 = data.Children.Get(EMVTagsEnum.AMOUNT_AUTHORISED_NUMERIC_9F02_KRN.Tag); if (_9F02 == null) { throw new Exception("No Amount found"); } long amount = Formatting.BcdToLong(_9F02.Value); switch (flowType) { case FlowType.SendMoneyFromCardToApp: toAccountNumber = SessionSingleton.Account.AccountNumberId; cardSerialNumberFrom = Formatting.BcdToString(panBCD); transactionType = TransactionType.SendMoneyFromCardToApp; break; case FlowType.SendMoneyFromAppToCard: fromAccountNumber = SessionSingleton.Account.AccountNumberId; cardSerialNumberTo = Formatting.BcdToString(panBCD); transactionType = TransactionType.SendMoneyFromAppToCard; break; default: throw new Exception("Unknown flow type:" + flowType); } try { await CallTransactByCardWebService(fromAccountNumber, toAccountNumber, cardSerialNumberFrom, cardSerialNumberTo, amount, transactionType, data); Device.BeginInvokeOnMainThread(() => { lblTransactSummary.Text = "Transaction Completed Succesfully"; UpdateView(ViewState.StepSummary); }); } catch { Device.BeginInvokeOnMainThread(() => { lblTransactSummary.Text = "Declined, could not go online."; UpdateView(ViewState.StepSummary); }); } } else { Device.BeginInvokeOnMainThread(() => { lblTransactSummary.Text = (e as TxCompletedEventArgs).TxResult.ToString(); UpdateView(ViewState.StepSummary); }); } } else if ((e as TxCompletedEventArgs).QR_Data.IsPresent()) { QRDEList data = (e as TxCompletedEventArgs).QR_Data.Get(); QRDE _26 = data.Get(EMVQRTagsEnum.MERCHANT_ACCOUNT_INFORMATION_TEMPLATE_26.Tag); QRDE _54 = data.Get(EMVQRTagsEnum.TRANSACTION_AMOUNT_54.Tag); QRDE gui = _26.Children.Get(EMVQRTagsEnum.GLOBALLY_UNIQUE_IDENTIFIER_00.Tag); QRDE tracking = _26.Children.Get(TagId._05); long amount = Convert.ToInt64(_54.Value); if ((e as TxCompletedEventArgs).TxResult == TxResult.QRCodeScanned) { switch (flowType) { case FlowType.SendMoneyFromCardToApp: throw new Exception("Invalid flow type for Scanned QR code"); case FlowType.SendMoneyFromAppToCard: fromAccountNumber = SessionSingleton.Account.AccountNumberId; toAccountNumber = gui.Value; transactionType = TransactionType.SendMoneyFromAppToCard; break; default: throw new Exception("Unknown flow type:" + flowType); } try { await CallTransactByQRCodeWebService(fromAccountNumber, toAccountNumber, amount, tracking.Value); Device.BeginInvokeOnMainThread(() => { lblTransactSummary.Text = "Transaction Completed Succesfully"; UpdateView(ViewState.StepSummary); }); } catch (Exception ex) { Device.BeginInvokeOnMainThread(() => { lblTransactSummary.Text = "Declined, could not go online."; UpdateView(ViewState.StepSummary); }); } } else if ((e as TxCompletedEventArgs).TxResult == TxResult.QRCodeToPoll) { switch (flowType) { case FlowType.SendMoneyFromCardToApp: break; case FlowType.SendMoneyFromAppToCard: throw new Exception("Invalid flow type for QR code"); default: throw new Exception("Unknown flow type:" + flowType); } try { bool success = await CallTransactGetStateWebService(tracking.Value); //bool success = await CallTransactGetStateWebService("929fa290b20647988f72f2ca762bc3e7"); if (success) { Device.BeginInvokeOnMainThread(() => { lblTransactSummary.Text = "Transaction Approved"; UpdateView(ViewState.StepSummary); }); } else { Device.BeginInvokeOnMainThread(() => { App.Current.MainPage.DisplayAlert("Info", "Transaction not found, try again if you believe the transaction was approved", "OK"); }); } } catch { Device.BeginInvokeOnMainThread(() => { App.Current.MainPage.DisplayAlert("Info", "Unknown, there is no connectivity to the server, try again if you believe the tx was approved", "OK"); }); } } else { Device.BeginInvokeOnMainThread(() => { lblTransactSummary.Text = (e as TxCompletedEventArgs).TxResult.ToString(); UpdateView(ViewState.StepSummary); }); } } else { Device.BeginInvokeOnMainThread(() => { lblTransactSummary.Text = "Declined"; UpdateView(ViewState.StepSummary); }); } } catch (Exception ex) { Device.BeginInvokeOnMainThread(() => { lblTransactSummary.Text = ex.Message; UpdateView(ViewState.StepSummary); }); } }
internal static IssuerPublicKeyCertificate BuildAndValidatePublicKey(KernelDatabaseBase database, byte[] caPublicKeyModulus, byte[] caPublicKeyExponent) { //section 6.3 EMV 4.3 Book 2 TLV issuerPublicKeyCertificate = database.Get(EMVTagsEnum.ISSUER_PUBLIC_KEY_CERTIFICATE_90_KRN); TLV issuerPublicKeyExponent = database.Get(EMVTagsEnum.ISSUER_PUBLIC_KEY_EXPONENT_9F32_KRN); TLV issuerPublicKeyRemainder = database.Get(EMVTagsEnum.ISSUER_PUBLIC_KEY_REMAINDER_92_KRN); if (issuerPublicKeyCertificate.Value.Length != caPublicKeyModulus.Length) { return(null); } byte[] decrypt = DecryptRSA(issuerPublicKeyCertificate.Value, caPublicKeyModulus, caPublicKeyExponent); IssuerPublicKeyCertificate issuerCertData = new IssuerPublicKeyCertificate(decrypt, caPublicKeyModulus.Length, issuerPublicKeyRemainder == null ? new byte[0] : issuerPublicKeyRemainder.Value, issuerPublicKeyExponent.Value); if (issuerCertData.RecoveredDataTrailer != 0xBC) { return(null); } if (issuerCertData.RecoveredDataHeader != 0x6A) { return(null); } if (issuerCertData.CertificateFormat != 0x02) { return(null); } if (!issuerCertData.ValidateHash()) { return(null); } string pan = Formatting.ByteArrayToHexString(database.Get(EMVTagsEnum.APPLICATION_PRIMARY_ACCOUNT_NUMBER_PAN_5A_KRN).Value); string issuerIdentifier = Formatting.ByteArrayToHexString(issuerCertData.IssuerIdentifier).Replace("FF", ""); if (!pan.StartsWith(issuerIdentifier)) { return(null); } DateTime expiry = DateTime.ParseExact(Formatting.BcdToString(issuerCertData.ExpiryDate), "MMyy", System.Globalization.CultureInfo.InvariantCulture); //TODO: if you have a test tool trying to use an expired cert then comment this test out or update your test tool //if (expiry <= DateTime.Now) //{ // Logger.Log("Error: Trying to use an expired issuer public key"); // return null; //} //step 10 optional if (issuerCertData.PublicKeyAlgorithmIndicator != 0x01) { return(null); } if (issuerPublicKeyRemainder != null) { issuerCertData.Modulus = Formatting.ConcatArrays(issuerCertData.UnpaddedIssuerPublicKeyorLeftmostDigitsofIssuerPublicKey, issuerPublicKeyRemainder.Value); } else { issuerCertData.Modulus = issuerCertData.UnpaddedIssuerPublicKeyorLeftmostDigitsofIssuerPublicKey; } return(issuerCertData); }
internal static IccPublicKeyCertificate BuildAndValidatePublicKey(KernelDatabaseBase database, StaticDataToBeAuthenticatedList staticDataToBeAuthenticated, byte[] issuerPublicKeyModulus, byte[] issuerPublicKeyExponent) { //section 6.4 EMV 4.3 Book 2 TLV iccPublicKeyCertificate = database.Get(EMVTagsEnum.INTEGRATED_CIRCUIT_CARD_ICC_PUBLIC_KEY_CERTIFICATE_9F46_KRN); TLV iccPublicKeyExponent = database.Get(EMVTagsEnum.INTEGRATED_CIRCUIT_CARD_ICC_PUBLIC_KEY_EXPONENT_9F47_KRN); TLV iccPublicKeyRemainder = database.Get(EMVTagsEnum.INTEGRATED_CIRCUIT_CARD_ICC_PUBLIC_KEY_REMAINDER_9F48_KRN); if (iccPublicKeyCertificate.Value.Length != issuerPublicKeyModulus.Length) { return(null); } byte[] decrypt = DecryptRSA(iccPublicKeyCertificate.Value, issuerPublicKeyModulus, issuerPublicKeyExponent); IccPublicKeyCertificate iccCertData = new IccPublicKeyCertificate(decrypt, issuerPublicKeyModulus.Length, iccPublicKeyRemainder == null ? new byte[0] : iccPublicKeyRemainder.Value, iccPublicKeyExponent.Value, database.StaticDataToBeAuthenticated.BuildStaticDataToBeAuthenticated()); if (iccCertData.RecoveredDataTrailer != 0xBC) { return(null); } if (iccCertData.RecoveredDataHeader != 0x6A) { return(null); } if (iccCertData.CertificateFormat != 0x04) { return(null); } if (!iccCertData.ValidateHash()) { return(null); } string pan = Formatting.ByteArrayToHexString(database.Get(EMVTagsEnum.APPLICATION_PRIMARY_ACCOUNT_NUMBER_PAN_5A_KRN).Value); string panToCompare = Formatting.ByteArrayToHexString(iccCertData.ApplicationPAN).Replace("FF", ""); if (!pan.StartsWith(panToCompare)) { return(null); } DateTime expiry = DateTime.ParseExact(Formatting.BcdToString(iccCertData.ExpiryDate), "MMyy", System.Globalization.CultureInfo.InvariantCulture); //TODO: if you have a test tool trying to use an expired cert then comment this test out or update your test tool //if (expiry <= DateTime.Now) //{ // Logger.Log("Error: Trying to use an expired issuer public key"); // return null; //} if (iccCertData.PublicKeyAlgorithmIndicator != 0x01) { return(null); } if (iccPublicKeyRemainder != null) { iccCertData.Modulus = Formatting.ConcatArrays(iccCertData.UnpaddedICCPublicKeyorLeftmostDigitsofIssuerPublicKey, iccPublicKeyRemainder.Value); } else { iccCertData.Modulus = iccCertData.UnpaddedICCPublicKeyorLeftmostDigitsofIssuerPublicKey; } return(iccCertData); }
internal static IccPinKeyCertificate BuildAndValidatePublicKey(KernelDatabaseBase database, byte[] issuerPublicKeyModulus, byte[] issuerPublicKeyExponent) { TLV iccPinKeyCertificate = database.Get(EMVTagsEnum.INTEGRATED_CIRCUIT_CARD_ICC_PIN_ENCIPHERMENT_PUBLIC_KEY_CERTIFICATE_9F2D_KRN); if (iccPinKeyCertificate == null) { return(null); } TLV iccPinKeyExponent = database.Get(EMVTagsEnum.INTEGRATED_CIRCUIT_CARD_ICC_PIN_ENCIPHERMENT_PUBLIC_KEY_EXPONENT_9F2E_KRN); if (iccPinKeyExponent == null) { return(null); } TLV iccPinKeyRemainder = database.Get(EMVTagsEnum.INTEGRATED_CIRCUIT_CARD_ICC_PIN_ENCIPHERMENT_PUBLIC_KEY_REMAINDER_9F2F_KRN); if (iccPinKeyRemainder == null) { return(null); } if (iccPinKeyCertificate.Value.Length != issuerPublicKeyModulus.Length) { return(null); } byte[] decrypt = DecryptRSA(iccPinKeyCertificate.Value, issuerPublicKeyModulus, issuerPublicKeyExponent); IccPinKeyCertificate iccCertData = new IccPinKeyCertificate(decrypt, issuerPublicKeyModulus.Length, iccPinKeyRemainder == null ? new byte[0] : iccPinKeyRemainder.Value, iccPinKeyExponent.Value); if (iccCertData.RecoveredDataTrailer != 0xBC) { return(null); } if (iccCertData.RecoveredDataHeader != 0x6A) { return(null); } if (iccCertData.CertificateFormat != 0x04) { return(null); } if (!iccCertData.ValidateHash()) { return(null); } string pan = Formatting.ByteArrayToHexString(database.Get(EMVTagsEnum.APPLICATION_PRIMARY_ACCOUNT_NUMBER_PAN_5A_KRN).Value); string panToCompare = Formatting.ByteArrayToHexString(iccCertData.ApplicationPAN).Replace("FF", ""); if (!pan.StartsWith(panToCompare)) { return(null); } DateTime expiry = DateTime.ParseExact(Formatting.BcdToString(iccCertData.ExpiryDate), "MMyy", System.Globalization.CultureInfo.InvariantCulture); if (expiry <= DateTime.Now) { return(null); } if (iccCertData.PublicKeyAlgorithmIndicator != 0x01) { return(null); } if (iccPinKeyRemainder != null) { iccCertData.Modulus = Formatting.ConcatArrays(iccCertData.UnpaddedICCPinKeyorLeftmostDigitsofIssuerPublicKey, iccPinKeyRemainder.Value); } else { iccCertData.Modulus = iccCertData.UnpaddedICCPinKeyorLeftmostDigitsofIssuerPublicKey; } return(iccCertData); }
public bool Validate(byte[] data) { switch (Format) { //case DataFormats.UNKNOWN: // throw new Exception("Unknown DataFormat:" + Format); //case DataFormats.VARIABLE_UNKNOWN: // throw new Exception("Unknown DataFormat:" + Format); case DataFormats._CN: case DataFormats._DATE_YYMMDD: case DataFormats._TIME_HHMMSS: case DataFormats._NUMERIC: string valueNumeric = Formatting.BcdToString(data); for (int i = 0; i < valueNumeric.Length; i++) { if (!Char.IsNumber(valueNumeric, i)) { return(false); } } return(true); case DataFormats._BINARY: return(true); //case DataFormats._BINARY_MULTIPLE_OF_4: // if (data.Length % 4 != 0) // return false; // else // return true; case DataFormats._ALPHA: string valueAlpha = Formatting.ByteArrayToASCIIString(data); for (int i = 0; i < valueAlpha.Length; i++) { if (!Char.IsLetter(valueAlpha, i)) { return(false); } } return(true); case DataFormats._ALPHA_NUMERIC: string valueAlphaNumeric = Formatting.ByteArrayToASCIIString(data); for (int i = 0; i < valueAlphaNumeric.Length; i++) { if (!Char.IsLetter(valueAlphaNumeric, i) && !Char.IsNumber(valueAlphaNumeric, i)) { return(false); } } return(true); case DataFormats._ALPHA_NUMERIC_SPECIAL: string valueAlphaNumericSpecial = Formatting.ByteArrayToASCIIString(data); for (int i = 0; i < valueAlphaNumericSpecial.Length; i++) { if (!Char.IsLetter(valueAlphaNumericSpecial, i) && !Char.IsNumber(valueAlphaNumericSpecial, i) && !Char.IsWhiteSpace(valueAlphaNumericSpecial, i) && !Char.IsPunctuation(valueAlphaNumericSpecial, i) && !Char.IsControl(valueAlphaNumericSpecial, i) && !Char.IsSymbol(valueAlphaNumericSpecial, i)) { return(false); } } return(true); case DataFormats._ALPHA_NUMERIC_SPACE: string valueAlphaNumericSpace = Formatting.ByteArrayToASCIIString(data); for (int i = 0; i < valueAlphaNumericSpace.Length; i++) { if (!Char.IsLetter(valueAlphaNumericSpace, i) && !Char.IsNumber(valueAlphaNumericSpace, i) && !Char.IsWhiteSpace(valueAlphaNumericSpace, i)) { return(false); } } return(true); //case DataFormats.H: // throw new Exception("Unknown DataFormat:" + Format); //case DataFormats.A: // throw new Exception("Unknown DataFormat:" + Format); default: throw new Exception("Unknown DataFormat:" + Format); } }
protected virtual EMVTerminalProcessingOutcome StartServiceQPRocess(KernelBase kernel) { while (1 == 1) { try { if (cancellationTokenForTerminalApplication.Token.IsCancellationRequested) { cancellationTokenForTerminalApplication.Dispose(); return(null); } if (kernel.KernelQ.GetOutputQCount() == 0) { Task.Run(async() => await Task.Delay(1)).Wait(); continue; } KernelResponseBase k2Response = kernel.KernelQ.DequeueFromOutput(true); if (k2Response == null) { Task.Run(async() => await Task.Delay(1)).Wait(); continue; } Logger.Log("Terminal received signal:" + k2Response.KernelReaderTerminalServiceResponseEnum); switch (k2Response.KernelReaderTerminalServiceResponseEnum) { case KernelReaderTerminalServiceResponseEnum.DEK: DATA_NEEDED_DF8106_KRN2 dataNeeded = ((KernelDEKResponse)k2Response).DataNeeded; DATA_TO_SEND_FF8104_KRN2 dataToSend = ((KernelDEKResponse)k2Response).DataToSend; TLVList requestInput = new TLVList(); //Logger.Log("------------------DEK Request Start-------------------"); foreach (string tag in dataNeeded.Value.Tags) { TLV found = terminalConfigurationData.TerminalConfigurationDataObjects.Get(tag); if (found == null) { Logger.Log("Tag Requested Of Terminal By Kernel Not Found:" + tag); throw new EMVTerminalException("cound not find tag for data needed: " + tag); } requestInput.AddToList(found); //int depth = 0; //Logger.Log("Tag Requested From Terminal:" + found.ToPrintString(ref depth)); } //Logger.Log("------------------DEK Request End-------------------"); KernelRequest request = new KernelRequest(KernelTerminalReaderServiceRequestEnum.DET, requestInput); kernel.KernelQ.EnqueueToInput(request); break; //continue processing case KernelReaderTerminalServiceResponseEnum.OUT: KernelOUTResponse outResponse = (KernelOUTResponse)k2Response; EMVTerminalProcessingOutcome processingOutcomeOUT = new EMVTerminalProcessingOutcome() { CVM = outResponse.OutcomeParameterSet_DF8129.Value.CVM }; switch (outResponse.OutcomeParameterSet_DF8129.Value.Start) { case Kernel2StartEnum.A: throw new Exception("Kernel2StartEnum.A Not Implemented"); case Kernel2StartEnum.B: if (outResponse.UserInterfaceRequest_DF8116 != null) { OnUserInterfaceRequest(CreateUIMessageEventArgs( outResponse.UserInterfaceRequest_DF8116.Value.KernelMessageidentifierEnum, outResponse.UserInterfaceRequest_DF8116.Value.KernelStatusEnum, Formatting.ConvertToInt32(outResponse.UserInterfaceRequest_DF8116.Value.HoldTime))); } else { OnUserInterfaceRequest(new UIMessageEventArgs(MessageIdentifiersEnum.TransmissionError, StatusEnum.EndProcessing)); } processingOutcomeOUT.NextProcessState = EMVTerminalPreProcessingStateEnum.ProtocolActivation_StartB; return(processingOutcomeOUT); case Kernel2StartEnum.C: processingOutcomeOUT.NextProcessState = EMVTerminalPreProcessingStateEnum.CombinationSelection_StartC; return(processingOutcomeOUT); case Kernel2StartEnum.D: throw new Exception("Kernel2StartEnum.D Not Implemented"); case Kernel2StartEnum.N_A: if (outResponse.UserInterfaceRequest_DF8116 != null) { string s1 = outResponse.UserInterfaceRequest_DF8116.Value.KernelMessageidentifierEnum.ToString(); string s2 = outResponse.UserInterfaceRequest_DF8116.Value.KernelStatusEnum.ToString(); string s3 = ""; if (outResponse.UserInterfaceRequest_DF8116.Value.ValueQualifierEnum != ValueQualifierEnum.NONE) { s3 = outResponse.UserInterfaceRequest_DF8116.Value.ValueQualifierEnum + " : " + Formatting.BcdToString(outResponse.UserInterfaceRequest_DF8116.Value.ValueQualifier); } string s4 = ""; if (outResponse.OutcomeParameterSet_DF8129.Value.CVM != KernelCVMEnum.NO_CVM) { s4 = outResponse.OutcomeParameterSet_DF8129.Value.CVM.ToString(); } OnUserInterfaceRequest(CreateUIMessageEventArgs( outResponse.UserInterfaceRequest_DF8116.Value.KernelMessageidentifierEnum, outResponse.UserInterfaceRequest_DF8116.Value.KernelStatusEnum, string.Format("{0}:{1}", s3, s4))); } processingOutcomeOUT.DataRecord = outResponse.DataRecord_FF8105; processingOutcomeOUT.DiscretionaryData = outResponse.DiscretionaryData_FF8106; int depth = 0; if (outResponse.UserInterfaceRequest_DF8116 != null) { Logger.Log(outResponse.UserInterfaceRequest_DF8116.ToPrintString(ref depth)); } depth = 0; Logger.Log(outResponse.OutcomeParameterSet_DF8129.ToPrintString(ref depth)); depth = 0; if (outResponse.ErrorIndication_DF8115 != null) { Logger.Log(outResponse.ErrorIndication_DF8115.ToPrintString(ref depth)); } depth = 0; if (outResponse.DataRecord_FF8105 != null) { Logger.Log(outResponse.DataRecord_FF8105.ToPrintString(ref depth)); } depth = 0; if (outResponse.DiscretionaryData_FF8106 != null) { Logger.Log(outResponse.DiscretionaryData_FF8106.ToPrintString(ref depth)); } processingOutcomeOUT.NextProcessState = EMVTerminalPreProcessingStateEnum.EndProcess; return(processingOutcomeOUT); default: throw new Exception("Unknown outResponse.OutcomeParameterSet_DF8129.Value.Start:" + outResponse.OutcomeParameterSet_DF8129.Value.Start.ToString()); } case KernelReaderTerminalServiceResponseEnum.UI: KernelUIResponse uiResponse = (KernelUIResponse)k2Response; if (uiResponse.UserInterfaceRequest_DF8116 != null) { string s1 = uiResponse.UserInterfaceRequest_DF8116.Value.KernelMessageidentifierEnum.ToString(); string s2 = uiResponse.UserInterfaceRequest_DF8116.Value.KernelStatusEnum.ToString(); OnUserInterfaceRequest(CreateUIMessageEventArgs( uiResponse.UserInterfaceRequest_DF8116.Value.KernelMessageidentifierEnum, uiResponse.UserInterfaceRequest_DF8116.Value.KernelStatusEnum, Formatting.ConvertToInt32(uiResponse.UserInterfaceRequest_DF8116.Value.HoldTime))); } int depthUI = 0; if (uiResponse.UserInterfaceRequest_DF8116 != null) { Logger.Log(uiResponse.UserInterfaceRequest_DF8116.ToPrintString(ref depthUI)); } break; case KernelReaderTerminalServiceResponseEnum.PIN: // display pin screen OnPinRequest(new EventArgs()); break; case KernelReaderTerminalServiceResponseEnum.TRM: OnTRMRequest(new EventArgs()); break; case KernelReaderTerminalServiceResponseEnum.ONLINE: KernelOnlineResponse onlineResponse = (KernelOnlineResponse)k2Response; OnOnlineRequest(new OnlineEventArgs(onlineResponse.data, onlineResponse.discretionaryData)); break; default: throw new Exception("Unknown Kernel1ReaderTerminalServiceResponseEnum:" + k2Response.KernelReaderTerminalServiceResponseEnum); } kernel.KernelQ.DequeueFromOutput(false); //only remove message when finished processing } catch (Exception ex) { OnExceptionOccured(ex); return(null); } } }
private async void EmvTxCtl_TxCompleted(object sender, EventArgs e) { try { if ((e as TxCompletedEventArgs).TxResult == TxResult.Approved || (e as TxCompletedEventArgs).TxResult == TxResult.ContactlessOnline) { long?amount = Convert.ToInt64(totalAmount.Total); TransactionType transactionType; string fromAccountNumber = ""; string cardSerialNumberFrom = ""; string toAccountNumber = ""; string cardSerialNumberTo = ""; if ((e as TxCompletedEventArgs).EMV_Data.IsPresent()) { if ((e as TxCompletedEventArgs).TxResult == TxResult.Approved || (e as TxCompletedEventArgs).TxResult == TxResult.ContactlessOnline) { TLV data = (e as TxCompletedEventArgs).EMV_Data.Get(); byte[] panBCD; TLV _5A = data.Children.Get(EMVTagsEnum.APPLICATION_PRIMARY_ACCOUNT_NUMBER_PAN_5A_KRN.Tag); if (_5A != null) { panBCD = _5A.Value; } else { TLV _57 = data.Children.Get(EMVTagsEnum.TRACK_2_EQUIVALENT_DATA_57_KRN.Tag); if (_57 == null) { throw new Exception("No PAN found"); } String panString = Formatting.ByteArrayToHexString(_57.Value); panBCD = Formatting.StringToBcd(panString.Split('D')[0], false); } switch (flowType) { case FlowType.SendMoneyFromCardToApp: toAccountNumber = SessionSingleton.Account.AccountNumberId; cardSerialNumberFrom = Formatting.BcdToString(panBCD); transactionType = TransactionType.SendMoneyFromCardToApp; break; default: throw new Exception("Unknown flow type:" + flowType); } try { await CallPosTransactWebService(fromAccountNumber, toAccountNumber, cardSerialNumberFrom, cardSerialNumberTo, amount, transactionType, data); Device.BeginInvokeOnMainThread(() => { lblTransactSummary.Text = "Transaction Completed Succesfully"; UpdateView(POSViewState.PaymentSummary); }); } catch { Device.BeginInvokeOnMainThread(() => { lblTransactSummary.Text = "Declined, could not go online."; UpdateView(POSViewState.PaymentSummary); }); } } else { Device.BeginInvokeOnMainThread(() => { lblTransactSummary.Text = (e as TxCompletedEventArgs).TxResult.ToString(); UpdateView(POSViewState.PaymentSummary); }); } } else { Device.BeginInvokeOnMainThread(() => { lblTransactSummary.Text = "Declined"; UpdateView(POSViewState.PaymentSummary); }); } } else { Device.BeginInvokeOnMainThread(() => { lblTransactSummary.Text = (e as TxCompletedEventArgs).TxResult.ToString(); UpdateView(POSViewState.PaymentSummary); }); } } catch (Exception ex) { Device.BeginInvokeOnMainThread(() => { lblTransactSummary.Text = ex.Message; UpdateView(POSViewState.PaymentSummary); }); } }
private async void Ta_ProcessCompleted(object sender, EventArgs e) { try { int?amount = Validate.AmountToCents(totalAmount.Total); TransactionType transactionType; string fromAccountNumber = ""; string cardSerialNumberFrom = ""; string toAccountNumber = ""; string cardSerialNumberTo = ""; TerminalProcessingOutcome tpo = (e as TerminalProcessingOutcomeEventArgs).TerminalProcessingOutcome; if (tpo == null)//error occurred, error displayed via Ta_ExceptionOccured { return; } if (tpo is EMVTerminalProcessingOutcome) { TLV dataRecord = ((EMVTerminalProcessingOutcome)tpo).DataRecord; TLV discretionaryData = ((EMVTerminalProcessingOutcome)tpo).DiscretionaryData; if (dataRecord != null) //error or decline { SetStatusLabel("Remove card"); if (discretionaryData != null) { dataRecord.Children.AddListToList(discretionaryData.Children); } string emvData = TLVasJSON.ToJSON(dataRecord); byte[] panBCD; TLV _5A = dataRecord.Children.Get(EMVTagsEnum.APPLICATION_PRIMARY_ACCOUNT_NUMBER_PAN_5A_KRN.Tag); if (_5A != null) { panBCD = _5A.Value; } else { TLV _57 = dataRecord.Children.Get(EMVTagsEnum.TRACK_2_EQUIVALENT_DATA_57_KRN.Tag); if (_57 == null) { throw new Exception("No PAN found"); } String panString = Formatting.ByteArrayToHexString(_57.Value); panBCD = Formatting.StringToBcd(panString.Split('D')[0], false); } switch (flowType) { case FlowType.SendMoneyFromCardToApp: toAccountNumber = SessionSingleton.Account.AccountNumberId; cardSerialNumberFrom = Formatting.BcdToString(panBCD); transactionType = TransactionType.SendMoneyFromCardToApp; break; default: throw new Exception("Unknown flow type:" + flowType); } try { await CallPosTransactWebService(fromAccountNumber, toAccountNumber, cardSerialNumberFrom, cardSerialNumberTo, amount, transactionType, emvData); Device.BeginInvokeOnMainThread(() => { lblTransactSummary.Text = "Transaction Completed Succesfully"; UpdateView(ViewState.Step3Summary); }); } catch (Exception ex) { Device.BeginInvokeOnMainThread(() => { lblTransactSummary.Text = "Declined, could not go online."; UpdateView(ViewState.Step3Summary); }); } } else { SetStatusLabel(string.Format("{0}\n{1}", tpo.UserInterfaceRequest.MessageIdentifier, tpo.UserInterfaceRequest.Status)); } } } catch (Exception ex) { Device.BeginInvokeOnMainThread(() => { lblTransactSummary.Text = ex.Message; UpdateView(ViewState.Step3Summary); }); } }