public string SendPipeMessage(CardOperationType cardType, string message, int timeout, bool canWrite = true) { using (NamedPipeClientStream stream = new NamedPipeClientStream("mrkpipe")) { stream.Connect(0x1388); stream.ReadMode = PipeTransmissionMode.Message; byte[] bytes = this._encoder.GetBytes(message); stream.Write(bytes, 0, bytes.Length); stream.Flush(); this.WriteEntry(string.Format("{0} ++++++++++ PipeClient. Запрос: [{2}] ++++++++++ {0}{1}", Environment.NewLine, message, cardType), canWrite); Thread.Sleep(100); this._thread = new Thread(new ParameterizedThreadStart(this.ReadFunction)); this._thread.Start(stream); string str = string.Format("{0} ++++++++++ PipeClient. Ответ от МРК на запрос [{1}] ++++++++++ {0}", Environment.NewLine, cardType); bool flag = false; if (!this._thread.Join(timeout)) { flag = true; this._incommingMessage = string.Empty; stream.Close(); this.Dispose(); } if (this._incommingMessage == string.Empty) { str = str + (flag ? string.Format("MRK_TIME_OUT. PipeClient. МРК не ответил за отведенное время, прерываем поток чтения. Таймаут для этой операции {0} мс. ", timeout) : "MRK_NULL. PipeClient. Прочитана нулевая строка."); this.WriteEntry(str, canWrite); throw new WtfException("WTF"); } this.WriteEntry(string.Format("{0}{1}", str, this._incommingMessage), canWrite); return(this._incommingMessage); } }
public OnCardChanged([NotNull] Card card, [NotNull] CardOperationType cardOperationType, string remark = null) : base() { AccountId = card.AccountId; CardType = card.CardType; CardNo = card.CardNo; CardOperationType = cardOperationType.Key; Remark = remark; }
public static int OperationSelector(CardOperationType type, IntPtr objRef, IntPtr serialNumber, IntPtr cardImage, IntPtr operation) { switch (type) { case CardOperationType.Credit: return(Credit(objRef, serialNumber, cardImage, operation)); //case CardOperationType.Debit: // return Debit(objRef, serialNumber, cardImage); case CardOperationType.Sale: return(Sale(objRef, serialNumber, cardImage, operation)); //case CardOperationType.Refund: // return Refund(objRef, serialNumber, cardImage/*, operation*/); case CardOperationType.Return: return(Return(objRef, serialNumber, cardImage, operation)); default: return(-2000); } }
public static OpCode OperationSelector(CardOperationType type) { switch (type) { case CardOperationType.Credit: return(OpCode.OpCredit); case CardOperationType.Debit: return(OpCode.OpDebit); case CardOperationType.Sale: return(OpCode.OpDebit); case CardOperationType.Refund: return(OpCode.OpRefund); case CardOperationType.Return: return(OpCode.OpAnnulate); default: return(OpCode.OpAuthorization); } }
private void StartPooling(CardOperationType cardOperaionType) { //Thread _thread = new Thread(new ParameterizedThreadStart(this.WorkFunction)); //_thread.Start(cardOperaionType); this.WorkFunction(cardOperaionType); }
private void WorkFunction(object poolingType) { lock (_lockObject) { AnsStatus status; decimal maxBalance; string str; object[] objArray; decimal num3; int num = 0; this._cancel = false; do { try { str = new PipeClient().SendPipeMessage(CardOperationType.reqStatus, "<?xml version='1.0' encoding='windows-1251'?>\r\n<TCLib version='3.04'>\r\n\t<info>\r\n\t\t<reqStatus/>\r\n\t</info>\r\n</TCLib>", 0x1388, false); status = (AnsStatus)this.ExtractMessage(str, typeof(AnsStatus)); maxBalance = status.info.MrkStatus.MaxBalance; //base.CallBack("LiveSignal", ""); } catch (Exception exception1) { Exception exception = exception1; Logger("ERROR! Pooling exception: " + exception.Message, EventEntryType.Error); goto Label_05A4; } Thread.Sleep(0x3e8); if (++num > 20) { Logger("20 секунд прошло, а карту так и не приложили для чтения. Высылаем МРК команду \"Cancel\"", EventEntryType.Event); this.SendCancelCommand(true); goto Label_05A4; } }while (!status.info.MrkStatus.CardPresent); CardOperationType type = (CardOperationType)poolingType; string arg = (type == CardOperationType.Info) ? "Пожалуйста, подождите. Получаем выписку по карте..." : "this._readCardMessage"; //base.CallBack("SetStartPooling", arg); //base.CallBack("LiveSignal", ""); cardInfo cardInfo = null; string str3 = string.Empty; string str4 = string.Empty; try { AnsWait wait; PipeClient client = new PipeClient(); client.Logger = Logger; if (type == CardOperationType.Info) { str = client.SendPipeMessage(CardOperationType.Info, string.Format("<?xml version='1.0' encoding='Windows-1251'?>\r\n<TCLib version='3.04'>\r\n\t<card>\r\n\t\t<reqWaitCard>\r\n\t\t\t<timeout>{0}</timeout>\r\n\t\t\t<application>1</application>\r\n\t\t\t<getInfo>2</getInfo>\r\n\t\t</reqWaitCard>\r\n\t</card>\r\n</TCLib>", "30"), 0x30d40, true); wait = (AnsWait)this.ExtractMessage(str, typeof(AnsWait)); str4 = "this.CreateInfo(wait)"; //this.SetAccountInfo(wait.card.AnsWaitCard.CardInfo); } else { str = client.SendPipeMessage(CardOperationType.reqWaitCard, string.Format("<?xml version='1.0' encoding='Windows-1251'?>\r\n<TCLib version='3.04'>\r\n\t<card>\r\n\t\t<reqWaitCard>\r\n\t\t\t<timeout>{0}</timeout>\r\n\t\t\t<application>1</application>\r\n\t\t\t<getInfo>1</getInfo>\r\n\t\t</reqWaitCard>\r\n\t</card>\r\n</TCLib>", "30"), 0x9c40, true); wait = (AnsWait)this.ExtractMessage(str, typeof(AnsWait)); cardInfo = wait.card.AnsWaitCard.CardInfo; string[] strArray = cardInfo.Description.Split(new char[] { ',' }); string str5 = (strArray.Length > 1) ? (", " + strArray[1]) : string.Empty; this._maxValue = (maxBalance - cardInfo.Balance) / 100M; objArray = new object[4]; objArray[0] = Environment.NewLine; num3 = cardInfo.Balance / 100M; objArray[1] = num3.ToString("F").Replace(",", ".") + " руб." + str5; objArray[2] = cardInfo.Pan; objArray[3] = this.CreateDate(cardInfo.Date); str3 = string.Format("Текущий баланс: {1}{0}Номер карты: {2}{0}Срок действия: {3}{0}", objArray) + ((this._maxValue > 0M) ? string.Format("Максимальная сумма пополнения: {0} руб.", this._maxValue) : "Карта пополнена на максимальную сумму"); } } catch (MrkErrorException exception2) { string message = string.Format("Ошибка ожидания карты: {0}", exception2.Error.Description); Logger(message, EventEntryType.Error); if (exception2.Error.Code == 0x68) { this.SendCancelCommand(true); } else { //base.CallBack("SetCrashScreen", message); Logger(string.Format("{0}: {1}", "SetCrashScreen", message), EventEntryType.Error); } goto Label_05A4; } catch (Exception exception4) { //this.SetErrorScreen("Unexpected. Ошибка ожидания карты: " + exception4.ToString(), "Ошибка ожидания карты.", true); Logger("Unexpected. Ошибка ожидания карты: " + exception4.ToString() + " Ошибка ожидания карты.", EventEntryType.Error); goto Label_05A4; } switch (type) { case CardOperationType.reqWriteCard: Logger("Пополнение. Дождались карту: " + Environment.NewLine + str3, EventEntryType.Event); //this.SetAccountInfo(cardInfo); //base.CallBack("SetWaitCardResult", str3); Logger(String.Format("{0}; {1}", "SetWaitCardResult", str3), EventEntryType.Event); if (this._maxValue > 0M) { //base.CallBack("SetButtonNext", ""); } break; case CardOperationType.Balance: Logger("Просмотр баланса. Дождались карту: " + str3, EventEntryType.Event); //base.CallBack("SetBalanceResult", str3); break; case CardOperationType.reqChangePin: Logger("Смена пинкода. Дождались карту: " + str3, EventEntryType.Event); //base.CallBack("StartChangePin", string.Empty); break; case CardOperationType.reqPayment: objArray = new object[4]; objArray[0] = Environment.NewLine; num3 = cardInfo.Balance / 100M; objArray[1] = num3.ToString("F").Replace(",", "."); objArray[2] = cardInfo.Pan; objArray[3] = this.CreateDate(cardInfo.Date); str3 = string.Format("Доступная для оплаты сумма: {1} руб.{0}Номер карты: {2}{0}Срок действия: {3}{0}", objArray); Logger("Оплата по карте. Дождались карту: " + str3, EventEntryType.Event); //base.CallBack("SetPan", cardInfo.Pan); //base.CallBack("SetWaitCardResult", str3); //base.CallBack("SetButtonNext", ""); break; case CardOperationType.Info: //base.CallBack("SetDataGrid", str4); break; } Label_05A4 :; } }
public DisppenserStatus SendAction(CardOperationType cardOperationType) { DisppenserStatus result = DisppenserStatus.DispenserError; PipeClient client = new PipeClient(); client.Logger = Logger; string message = client.SendPipeMessage(CardOperationType.reqStatus, reqStatus, PipeClient.CONNECT_TIMEOUT, true); AnsStatus status = (AnsStatus)this.ExtractMessage(message, typeof(AnsStatus)); MrkStatuses mrkStatus = status.info.MrkStatus; if (!mrkStatus.MrkReady) { //this.SetErrorScreen("status.MrkReady == false", "МРК не готов к работе.", true); textLoger.Text += "МРК не готов к работе."; } else if (cardOperationType != CardOperationType.reqSaleCard) { if (mrkStatus.ReaderReady == 0) { //base.CallBack("SetInfoWithMainMenu", this._readerErrorMessage); Logger("Ошибка", EventEntryType.Error); } else { client.SendPipeMessage(CardOperationType.reqControl_reader_1, "<?xml version='1.0' encoding='Windows-1251'?>\r\n<TCLib version='3.04'>\r\n\t<service>\r\n\t\t<reqControl>\r\n\t\t\t<reader>1</reader>\r\n\t\t</reqControl>\r\n\t</service>\r\n</TCLib>", PipeClient.CONNECT_TIMEOUT, true); //base.CallBack("SetInfoWithMainMenu", this._waitCardMessage); this.StartPooling(cardOperationType); Logger("Ждем", EventEntryType.Event); } } else { DisppenserStatus dispenserStatus = (DisppenserStatus)mrkStatus.DispenserStatus; string str2 = "Продажа карт запрещена: "; string format = "Стоимость карты при получении: {0} РУБ.{1}Наличие карт в терминале: {2}"; decimal num = mrkStatus.CardPrice / 100M; switch (dispenserStatus) { case DisppenserStatus.DispenserError: Logger(str2 + "диспенсер не работает", EventEntryType.Error); result = DisppenserStatus.DispenserError; break; case DisppenserStatus.NoCard: Logger(string.Format(format, num, Environment.NewLine, "НЕТ"), EventEntryType.Warning); result = DisppenserStatus.NoCard; break; case DisppenserStatus.FewCard: case DisppenserStatus.ManyCard: if (!(mrkStatus.CardPrice == 0M)) { Logger(string.Format(format, num, Environment.NewLine, "ЕСТЬ"), EventEntryType.Event); result = (DisppenserStatus)mrkStatus.DispenserStatus; break; } Logger(str2 + "цена карты не определена.", EventEntryType.Warning); break; } } return(result); }
// ОПЕРАЦИЯ ПО КАРТЕ /// <summary> /// ОПЕРАЦИЯ ПО КАРТЕ /// </summary> /// <param name="type">тип операции</param> /// <param name="terminal">терминал (азс)</param> /// <param name="transact">номер транзакции</param> /// <param name="opItem">параметры операции</param> /// <returns></returns> public static ServioCardInfo CardOperationExecute(CardOperationType type, int terminal, long transact, CardOperationItem opItem) { ServioCardInfo res = new ServioCardInfo { ErrorCore = -1, CardNumber = "", IssuerID = -1 }; IntPtr obj = new IntPtr(); IntPtr serialNumberPtr = Marshal.AllocHGlobal(sizeof(SerialnumberT)); IntPtr cardImagePtr = Marshal.AllocHGlobal(sizeof(Mf1S70T)); IntPtr operationPtr = CardOperation_Create(); try { if ((res.ErrorCore = InitInternal(_config, ref obj)) != (int)ErrorCodes.ESuccess) { if (res.ErrorCore == (int)ErrorCodes.ECancel) { return(res); } throw new CardShellException("Error Init No" + res, res.ErrorCore); } UnMemory <byte> .SaveInMemArr(new byte[Mf1S70T.Size], ref cardImagePtr); if ((res.ErrorCore = ReadCard(obj, serialNumberPtr, cardImagePtr, false)) != (int)ErrorCodes.ESuccess) { if (res.ErrorCore == (int)ErrorCodes.ECancel) { return(res); } throw new CardShellException("Error ReadCard No" + res, res.ErrorCore); } var operation = UnMemory <CardOperation> .ReadInMem(operationPtr); SerialnumberT serialNumber = UnMemory <SerialnumberT> .ReadInMem(serialNumberPtr); operation.Size = sizeof(CardOperation); operation.OpCode = (byte)OperationSelector(type); operation.POS = terminal; // Номер АЗС или терминала operation.OpTime = DateTime.Now.ToOADate(); // Реальное время с вашего терминала operation.TransactID = transact; // Тут желательно ваш код код транзакции указать operation.CardType = (int)CardType.CtPayment; // Предположим что тип карты неизвестен operation.SerialNumber = serialNumber; // Указать серийный номер, считанный с метки operation.IssuerID = -1; // Указать -1, программа сама переопределит. Если указать другой код - программа будет использовать его operation.CardNumber = ""; // Не указывать !!! operation.AddPrefixZeros = 0; // Нужна доп. настройка. Аналогичная нашей опции в обработчиках operation.ItemCount = 1; // При аутентификации позиции не заполнять. IntPtr pItem1 = Marshal.AllocHGlobal(sizeof(CardOperationItem)); UnMemory <CardOperationItem> .SaveInMem(opItem, ref pItem1); IntPtr ppItem1 = Marshal.AllocHGlobal(sizeof(IntPtr)); UnMemory <IntPtr> .SaveInMem(pItem1, ref ppItem1); operation.Items = ppItem1; UnMemory <CardOperation> .SaveInMem(operation, ref operationPtr); if ((res.ErrorCore = OperationSelector(type, obj, serialNumberPtr, cardImagePtr, operationPtr)) != (int)ErrorCodes.ESuccess) { throw new CardShellException("Error Operation No" + res, res.ErrorCore); } // флаг указывает на то что образ карты был изменен в процессе операции // и нужно записать его обратно. // Нужно для пополнения карты при просмотре информации operation = UnMemory <CardOperation> .ReadInMem(operationPtr); if (operation.CardImageChanged != 0) { // при ошибке можно попробовать повторить операцию несколько раз 3-10... // если не проходит то это патовая ситуация и для её дальнейшего // разрешения нужно сохранить SerialNumber, CardImage и CardInfo // В теории, сохранённый SerialNumber и CardImage можно попробовать // записать обратно даже при перезапуске ПО, но до следующего // обслуживания по карте. Чтобы решить ситуацию можно сохранить CardInfo // чтобы в офисе уменьшили или увеличили баланс карты на соотв. значение. if ((res.ErrorCore = WriteCard(obj, serialNumberPtr, cardImagePtr)) != (int)ErrorCodes.ESuccess) { throw new CardShellException("Error WriteCard No" + res, res.ErrorCore); } } operation = (CardOperation)Marshal.PtrToStructure(operationPtr, typeof(CardOperation)); res.CardInfo = operation.CheckImage; return(res); } finally { //CardOperation_Free(operationPtr); UnMemory.FreeIntPtr(serialNumberPtr); UnMemory.FreeIntPtr(cardImagePtr); //MarshalHelper.UnMemory.FreeIntPtr(operationPtr); } }