public virtual void Run(Object state) { TaskState stateInfo = (TaskState)state; // ManualResetEvent[] manualEvents = new ManualResetEvent[64]; Log(Properties.Resources.MsgRedoRunning); Console.WriteLine(Properties.Resources.MsgRedoRunning); // Читать отложенные платежи while (!Canceling) { try { // Добавляем событие отмены в // manualEvents[1] = new ManualResetEvent(false); DoRedo(); } catch (Exception ex) { Log("Redo: {0}\r\n{1}", ex.Message, ex.StackTrace); } // Ожидать 60 сек. Thread.Sleep(60000); } // Завершение дочерних процессов if (processes > 0) { Log("Redo: Процесс {0}[{1}] завершается. Выполняется {2} процессов допроведения", Thread.CurrentThread.ManagedThreadId, Name, processes); Console.WriteLine("{3} Redo: Процесс {0}[{1}] завершается. Выполняется {2} процессов допроведения", Thread.CurrentThread.ManagedThreadId, Name, processes, XConvert.AsDate2(DateTime.Now)); } // Ожидаем допроведения всех платежей while (processes > 0) { Console.WriteLine("{1} Работающих процессов: {0}", processes, XConvert.AsDate2(DateTime.Now)); Log($"{XConvert.AsDate2(DateTime.Now)} Работающих процессов: {processes}"); // Ждем 1 секунду Thread.Sleep(1000); } Console.WriteLine("Redo: Процесс {0} завершен", Name); Log("Redo: Процесс {0} завершен", Name); stateInfo.CancelEvent.Set(); }
/// <summary> /// Выполнение запроса /// </summary> /// <param name="host">Хост (не используется)</param> /// <param name="old_state">Текущее состояние 0 - check, 1 - pay, 3 - staus</param> /// <param name="try_state">Состояние, присваиваемое при успешном завершении операции</param> /// <returns></returns> public override int DoPay(byte old_state, byte try_state) { // Создадим платеж с статусом=0 и locId = 1 // state 0 - новый // state 1 - получено разрешение int retcode = 0; // Создание шаблона сообщения check/pay/status pcdate = DateTime.Now.AddHours(-1); terminalDate = pcdate; tz = 6; RootLog("{3} Корректировка времени PC={0} old TD={1} new TD={2}", XConvert.AsDateTZ(Pcdate, Settings.Tz), XConvert.AsDateTZ(TerminalDate, Tz), XConvert.AsDateTZ(pcdate + TimeSpan.FromHours(Tz - Settings.Tz), Tz), Tid); if (Exec("UpdateTime", Tid, pcdate: Pcdate, terminalDate: terminalDate) != 0) { return(-1); } // Проверка времени создания платежа // Если платёж кис больше часа, скорректировать время /* * if (old_state == 0 && DateTime.Now.Ticks - Pcdate.Ticks > TimeSpan.TicksPerHour * 1) * { * pcdate = DateTime.Now; * * // Корректировка времени -1 * pcdate = pcdate.AddHours(-1); * * Random rnd = new Random((int)DateTime.Now.Ticks); * DateTime time = new DateTime(pcdate.Ticks - TimeSpan.TicksPerSecond * (long)(rnd.NextDouble() * 10.0)); * RootLog("{3} Корректировка времени PC={0} old TD={1} new TD={2}", * XConvert.AsDateTZ(Pcdate, Settings.Tz), * XConvert.AsDateTZ(TerminalDate, Tz), * XConvert.AsDateTZ(time + TimeSpan.FromHours(Tz - Settings.Tz), Tz), * Tid); * if (Exec("UpdateTime", Tid, pcdate :Pcdate, terminalDate :terminalDate) != 0) * return -1; * } */ // БД уже доступна, не будем её проверять if (MakeRequest(old_state) == 0) { // retcode = 0 - OK // retcode = 1 - TCP-error // retcode = 2 - Message sends, but no answer recieved. // retcode < 0 - System error if ((retcode = SendRequest(Host)) == 0) { if ((retcode = ParseAnswer(stResponse)) == 0) // Ответ получен и разобран; 1 - Timeout { if (old_state == 0) { errDesc = "Разрешение на платёж получено"; state = 1; errCode = 1; // ReportRequest("check "); // ReportCheck(); } else { state = 6; errCode = 3; // errCode = 3; errDesc = "Платёж проведён"; } UpdateState(tid, state: state, errCode: errCode, errDesc: errDesc, opname: Opname, opcode: Opcode, fio: fio, outtid: Outtid, account: Account, limit: Limit, limitEnd: XConvert.AsDate(LimitDate), acceptdate: XConvert.AsDate2(Acceptdate), acceptCode: AcceptCode, locked: state == 6 ? (byte)0 : (byte)1); // Разблокировать если проведён // ReportRequest("DoPay"); return(0); } } } // Запрос на разрешение платежа switch (retcode) { case 1: case 502: // Истекло время обработки state = old_state; break; case 358: // Нет запроса на прием платежа state = 0; break; case 103: // "Домашняя" БС абонента на профилактике или недоступна. case 106: // ЦМ не доступен state = times > 20 ? (byte)12 : old_state; break; case 200: // Прием платежа невозможен. Прием платежа запрещен (без детализации причины) case 201: // Номер телефона в БС не найден. case 202: // Приложение обслуживания не найдено. case 203: // Счет неактивен. case 205: // Описание клиента не найдено. case 206: // Абонент не найден // state = Pcdate.AddDays(1.0) <= DateTime.Now ? (byte)12 : old_state; // state = times > 20 ? (byte)12 : old_state; state = 12; break; case 301: // Нет денег state = 0; break; case 354: // Терминал не зарегистрирован // state = Pcdate.AddDays(1.0) <= DateTime.Now ? (byte)12 : old_state; state = old_state == 0? (byte)0: (byte)12; break; case 66: // ПЦ ЕСПП. Техническая ошибка сервера приложений state = 12; break; case 362: case 501: // Превышена пропускная способность case 367: // Номер уже обработан в ЕСПП case -20367: state = 11; break; case 357: // Платеж уже существует case 398: // Истекло время акцептования документа case 651: // Платеж в требуемом состоянии не найден if (old_state == 3 && lastcode == 357) { state = 12; } else { state = times > 20? (byte)12: (byte)3; } break; case 363: // Запрещен прием платежей с будущей датой операции вне допустимого диапазона RootLog("Дата вне диапазона Now={0} Pc={1} TD={2}", XConvert.AsDate2(DateTime.Now), XConvert.AsDate2(Pcdate), TerminalDate != null? XConvert.AsDate2(TerminalDate.Value): XConvert.AsDate2(DateTime.Now) ); state = 0; break; case 650: // Не определено состояние платежа state = 1; // разрешение получено, отпарвить зфн break; default: state = 12; break; } UpdateState(tid, state: state, errCode: retcode, errDesc: errDesc, locked: 0); return(1); }
/// <summary> /// Запрос на проведение платежа /// </summary> /// <returns></returns> public override int DoPay(byte old_state, byte try_state) { // Создадим платеж с статусом=0 и locId = 1 // state 0 - новый // state 1 - получено разрешение string host; state = old_state; switch (old_state) { case 0: host = CheckHost; break; case 1: host = PayHost; break; case 3: host = StatusHost; break; default: host = StatusHost; break; } Log($"\r\n{Service}/{Gateway} {Session} Host: {host}"); // Создание шаблона сообщения pay_check try { if (MakeRequest(status: old_state == 3? true: false) == 0) { if (SendRequest(host) == 0) { if (ParseAnswer(stResponse) == 0) { Log($"DoPay: old_state={old_state} try_tate={try_state} error={errCode} result={result}"); if (old_state == 0 || old_state == 1) { /* * // Сессия с таким номером существует установим статус 11 * if (result == 1 && errCode == 1 && Session == "-OLDIGW" + tid.ToString()) * { * errCode = 2; * state = 11; * errDesc = "Сессия существует. требует вмешательства oператора"; * UpdateState(tid :Tid, state :state, errCode :ErrCode, errDesc :ErrDesc, result :result, * outtid :outtid, acceptdate :XConvert.AsDate2(acceptdate), * price :price, addinfo :addinfo); * RootLog("Tid={0} Result={1} Error={1} Session={2} {3}", Tid, Result, errCode, Session, errDesc); * // Log("Обработан: {0}", ToString()); * return 0; * } */ if (result == 0 && errCode == 0) { errCode = 0; state = try_state; errDesc = old_state == 0 ? "Разрешение на платеж получено" : "Платеж отправлен"; // PrintParams("DoPay"); UpdateState(tid: Tid, state: state, errCode: ErrCode, errDesc: ErrDesc, result: result, outtid: outtid, acceptdate: XConvert.AsDate2(acceptdate), price: price, addinfo: addinfo); // Log("Обработан: {0}", ToString()); return(0); } } else if (old_state == 3) { if (errCode == 0) { if (result == 7) { state = 6; errDesc = "Платеж проведен"; // PrintParams("DoPay"); UpdateState(tid: Tid, state: state, errCode: ErrCode, errDesc: ErrDesc, result: result, acceptCode: acceptCode, acceptdate: XConvert.AsDate2(acceptdate)); // Log("Обработан: {0}", ToString()); } if (result == 1) // Платеж не зарегистраирован { state = 0; errDesc = "Платеж не зарегистрирован"; // PrintParams("DoPay"); UpdateState(tid: Tid, state: state, errCode: ErrCode, errDesc: ErrDesc, result: result); // Log("Обработан: {0}", ToString()); } else if (result != 7) { state = 3; errDesc = "Платеж проводится"; // PrintParams("DoPay"); UpdateState(tid: Tid, state: state, errCode: ErrCode, errDesc: ErrDesc, result: result); // Log("Обработан: {0}", ToString()); } errCode = 0; return(0); } ChangeState(old_state); // state 1 или 0 или 12 // PrintParams("DoPay"); UpdateState(tid: Tid, state: state, errCode: ErrCode, errDesc: ErrDesc, result: result); // Log("Не обработан: {0}", ToString()); return(1); } } } } } catch (Exception ex) { errCode = 6; errDesc = string.Format("Check: {0}", ex.Message); state = 12; } // Изменим состояние платежа ChangeState(old_state); if (old_state == 0 && ErrCode != 0 && !string.IsNullOrEmpty(AddInfo)) { errDesc += errDesc + ": " + AddInfo; } UpdateState(tid: Tid, state: state, errCode: ErrCode, errDesc: ErrDesc, acceptCode: acceptCode, outtid: outtid, acceptdate: XConvert.AsDate2(acceptdate), price: price, addinfo: addinfo); errCode = state == 12 ? 6 : 1; return(1); }
/// <summary> /// Выполнение запроса /// </summary> /// <param name="host">Хост (не используется)</param> /// <param name="old_state">Текущее состояние 0 - check, 1 - pay, 3 - staus</param> /// <param name="try_state">Состояние, присваиваемое при успешном завершении операции</param> /// <returns></returns> public override int DoPay(byte old_state, byte try_state) { // Создадим платеж с статусом=0 и locId = 1 // state 0 - новый // state 1 - получено разрешение int retcode = 0; state = 3; errCode = 1; // Создание шаблона сообщения check/pay/status // БД уже доступна, не будем её проверять if ((retcode = MakeRequest(old_state)) == 0) { // retcode = 0 - OK // retcode = 1 - TCP-error // retcode = 2 - Message sends, but no answer recieved. // retcode = 10 - SSL error // retcode < 0 - System error // if (Settings.LogLevel.IndexOf("REQ") != -1) // Log("\r\nПодготовлен запрос к: {0}\r\n{1}", Host, stRequest); if ((retcode = SendRequest(Host)) == 0) { // Разберем ответ ParseAnswer(stResponse); switch (result.state) { case 10: // Финансовый контроль errCode = 11; state = 3; break; /* * case 40: * if (result.substate == 7) * errCode = 11; * else * state = 3; * errCode = 1; * break; */ case 80: if (result.code == 30) // Нет денег - длиный интервал { errCode = 12; state = old_state == 0? (byte)0: (byte)3; } else { errCode = 6; state = 12; } break; case -2: // Платёж не найден при проверке статуса. Отменяем платёж errCode = 6; state = 12; break; case 60: errCode = 3; state = 6; break; default: errCode = 1; state = 3; break; } } else if ((WebExceptionStatus)retcode == WebExceptionStatus.SecureChannelFailure) // Ошибка SSL { if (Attempt < 3) { Attempt++; Log("{0} - {1} / 3 Повтор после ошибки SSL", Tid, Attempt); return(DoPay(old_state, try_state)); } errCode = 11; state = old_state; } else if (retcode > 0) // Ошибка TCP или таймаут { errCode = 11; state = old_state; } else { errCode = 2; state = 11; } } else { errCode = retcode; state = 12; } if (retcode == 0) { byte l = 0; if (old_state == 0 && errCode == 1) { retcode = 0; l = 1; } else { retcode = 1; } UpdateState(tid, state: state, errCode: errCode, errDesc: errDesc, opname: Opname, opcode: Opcode, fio: fio, outtid: Outtid, account: Account, limit: Limit, limitEnd: XConvert.AsDate(LimitDate), acceptdate: XConvert.AsDate2(Acceptdate), acceptCode: AcceptCode, locked: l); // Разблокировать если проведён return(retcode); } else { // if (Settings.LogLevel.IndexOf("DEBUG") != -1) // RootLog("Ответ провайдера: Tid={0} State={1}, Substate={2}, Code={3}", Tid, result.state, result.substate, result.code); UpdateState(tid, state: state, errCode: retcode, errDesc: errDesc, locked: 0); return(1); } }
/// <summary> /// Выполнение запроса /// </summary> /// <param name="host">Хост (не используется)</param> /// <param name="old_state">Текущее состояние 0 - check, 1 - pay, 3 - staus</param> /// <param name="try_state">Состояние, присваиваемое при успешном завершении операции</param> /// <returns></returns> public override int DoPay(byte old_state, byte try_state) { // Создадим платеж с статусом=0 и locId = 1 // state 0 - новый // state 1 - получено разрешение int retcode = 0; state = 3; errCode = 1; // Создание шаблона сообщения check/pay/status // БД уже доступна, не будем её проверять if ((retcode = MakeRequest(old_state)) == 0) { // retcode = 0 - OK // retcode = 1 - TCP-error // retcode = 2 - Message sends, but no answer recieved. // retcode < 0 - System error Log("\r\nПодготовлен запрос к: {0}", Host + "?" + stRequest); // Эмуляция положительного ответа /* * RootLog("Tid={0} эмуляция. Номер билета {1}", Tid, Account); * state = 6; * errCode = 3; * errDesc = string.Format("Tid={0} эмуляция. Номер билета {1}", Tid, Account); */ if ((retcode = SendRequest(Host + "?" + stRequest)) == 0) { // Разберем ответ if (stResponse.Substring(0, 2) == "OK") { state = 6; errCode = 3; acceptdate = DateTime.Now; BuyTicket(); SmsMessage sms = new SmsMessage(Tid, "Regplat", Phone, string.Format(Sign, Account)); // ThreadPool.QueueUserWorkItem(new WaitCallback(sms.SendSms), sms); SmsPool.Add(sms); } else { state = 12; errCode = 6; errDesc = string.Format("Ошибка: {0}", stResponse); } } else // Ошибка TCP или таймаут { state = 3; errCode = 1; } } UpdateState(tid, state: state, errCode: errCode, errDesc: errDesc, acceptdate: XConvert.AsDate2(Acceptdate), locked: 0); // Разблокировать если проведён return(retcode); }