/// <summary> /// Ответ OE /// </summary> public void MakeAnswer() { StringBuilder sb = new StringBuilder(); StringBuilder sb1 = new StringBuilder(); sb1.AppendFormat("\t<{0} code=\"{1}\">{2}</{0}>", "error", ErrCode, HttpUtility.HtmlEncode(ErrDesc)); if (!string.IsNullOrEmpty(Outtid)) { sb1.AppendFormat("\r\n\t<{0}>{1}</{0}>", "transaction", Outtid); } if (Acceptdate != DateTime.MinValue && (State == 6 || State == 10)) { sb1.AppendFormat("\r\n\t<{0}>{1}</{0}>", "accept-date", XConvert.AsDate(Acceptdate).Replace('T', ' ')); } if (!string.IsNullOrEmpty(Fio)) { sb1.AppendFormat("\r\n\t<{0}>{1}</{0}>", "fio", Fio); } if (!string.IsNullOrEmpty(Opname)) { sb1.AppendFormat("\r\n\t<{0}>{1}</{0}>", "opname", Opname); } if (!string.IsNullOrEmpty(Account)) { sb1.AppendFormat("\r\n\t<{0}>{1}</{0}>", "account", Account); } if (!string.IsNullOrEmpty(AddInfo)) { sb1.AppendFormat("\r\n\t<{0}>{1}</{0}>", "info", AddInfo.Length <= 250 ? HttpUtility.HtmlEncode(AddInfo) : HttpUtility.HtmlEncode(AddInfo.Substring(0, 250))); } if (Recpay != null) { sb1.AppendFormat("\r\n\t<{0}>{1}</{0}>", "recpay", XConvert.AsAmount(Recpay.Value)); } if (Balance != null) { sb1.AppendFormat("\r\n\t<{0}>{1}</{0}>", "balance", XConvert.AsAmount(Balance.Value)); } sb.AppendFormat("<{0}>\r\n{1}\r\n</{0}>\r\n", "response", sb1.ToString()); stResponse = sb.ToString(); if (tid > 0) { UpdateState(Tid, state: State, locked: 1); } // Log("Подготовлен ответ:\r\n{0}", stResponse); }
/// <summary> /// Создание шаблона comparePacket /// </summary> void MakeTemplate() { string format; // Прочитаем шаблон using (StreamReader stream = new StreamReader(Settings.Templates + "comparepacket-" + ProvidersSettings.Mts.Ott + "-" + ProvidersSettings.Mts.Xsd + ".tpl")) { format = stream.ReadToEnd(); } template = string.Format(format, ProvidersSettings.Mts.Timeout, ProvidersSettings.Mts.Contract, XConvert.AsDate(Datefrom), XConvert.AsDate(Dateto), totalPayments, Cur, XConvert.AsAmount(totalSum), XConvert.AsAmount(totalDebt), MakeBody()); }
/// <summary> /// Ответ OE /// </summary> public void MakeAnswer() { Log($"[MakeAnser] errCode={errCode} errDesc={errDesc}"); StringBuilder sb = new StringBuilder(); StringBuilder sb1 = new StringBuilder(); sb1.AppendFormat("\t<{0} code=\"{1}\">{2}</{0}>", "error", ErrCode, HttpUtility.HtmlEncode(ErrDesc)); if (!string.IsNullOrEmpty(resp.esppPayId)) { outtid = resp.esppPayId; sb1.AppendFormat("\r\n\t<{0}>{1}</{0}>", "transaction", resp.esppPayId); } if (resp.payStatus != null) { sb1.AppendFormat("\r\n\t<{0}>{1}</{0}>", "payStatus", XConvert.AsAmount(resp.payStatus)); } if (Acceptdate != DateTime.MinValue && (State == 6 || State == 10)) { sb1.AppendFormat("\r\n\t<{0}>{1}</{0}>", "accept-date", XConvert.AsDate(Acceptdate).Replace('T', ' ')); } if (!string.IsNullOrEmpty(Fio)) { sb1.AppendFormat("\r\n\t<{0}>{1}</{0}>", "fio", Fio); } if (!string.IsNullOrEmpty(Account)) { sb1.AppendFormat("\r\n\t<{0}>{1}</{0}>", "account", Account); } if (!string.IsNullOrEmpty(resp.errUsrMsg)) { sb1.AppendFormat("\r\n\t<{0}>{1}</{0}>", "addinfo", resp.errUsrMsg.Length <= 250 ? HttpUtility.HtmlEncode(resp.errUsrMsg) : HttpUtility.HtmlEncode(resp.errUsrMsg.Substring(0, 250))); } if (resp.payeeRecPay != null) { sb1.AppendFormat("\r\n\t<{0}>{1}</{0}>", "recpay", XConvert.AsAmount(resp.payeeRecPay)); } if (Balance != null) { sb1.AppendFormat("\r\n\t<{0}>{1}</{0}>", "balance", XConvert.AsAmount(balance)); } if (!string.IsNullOrEmpty(resp.clientInn)) { sb1.AppendFormat("\r\n\t<{0}>{1}</{0}>", "clientInn", resp.clientInn); } if (!string.IsNullOrEmpty(resp.clientType)) { sb1.AppendFormat("\r\n\t<{0}>{1}</{0}>", "clientType", resp.clientType); } if (!string.IsNullOrEmpty(resp.clientOrgName)) { sb1.AppendFormat("\r\n\t<{0}>{1}</{0}>", "clientOrgName", resp.clientOrgName); } sb.AppendFormat("<{0}>\r\n{1}\r\n</{0}>\r\n", "response", sb1.ToString()); // stResponse = JsonConvert.SerializeObject(resp); // Log($"Получен ответ от ЕСПП\r\n{stResponse}"); stResponse = sb.ToString(); if (tid > 0) { UpdateState(Tid, state: State, locked: 1); } Log($"[MakeAnser] Подготовлен ответ:\r\n{stResponse}"); }
/// <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> /// <param name="old_state">Статус (если не прошёл проверку 12)</param> /// <returns>0 - ОК, 1 - нет</returns> public new int MakeRequest(int old_state) { if (Settings.LogLevel.IndexOf("PARS") != -1) { RootLog("Параметры запроса:\r\nTimeout={0}\r\nPhone={1}\r\nAmount={2}\r\nCUR={3}\r\nService={4}\r\nTerminal={5}\r\nType={6}\r\nAS-VPS={7}\r\nContract={8}\r\nAccount={10}\r\nPrincipal={11}", TimeOut(), Phone, XConvert.AsAmount(Amount), Cur, Service, MtsTerminalId, TerminalType, Asvps, Contract, Account, Gateway); } switch (old_state) { case 0: using (StreamReader check = new StreamReader(Settings.Templates + (string.IsNullOrEmpty(Phone) ? "a": "p") + "-0104010-" + ProvidersSettings.Mts.Ott + "-" + ProvidersSettings.Mts.Xsd + ".tpl")) { checkTemplate = check.ReadToEnd(); } if (string.IsNullOrEmpty(Phone)) { stRequest = string.Format(checkTemplate, TimeOut(), XConvert.AsAmount(Amount), Cur, Service, MtsTerminalId, TerminalType, Asvps, Contract, Account, Gateway); } else { stRequest = string.Format(checkTemplate, TimeOut(), Phone, XConvert.AsAmount(Amount), Cur, Service, MtsTerminalId, TerminalType, Asvps, Contract, Gateway); } break; case 1: using (StreamReader pay = new StreamReader(Settings.Templates + (string.IsNullOrEmpty(Phone) ? "a" : "p") + "-0104090-" + ProvidersSettings.Mts.Ott + "-" + ProvidersSettings.Mts.Xsd + ".tpl")) { payTemplate = pay.ReadToEnd(); } controlCode = String.Format("{0}&{1}&{2}&{3}&{4}&{5}&{6}&{7}&{8}&{9}&{10}&{11}&{12}", Phone, XConvert.AsAmount(Amount), Cur, Service, Oid, Tid, XConvert.AsDate(Pcdate), Asvps, MtsTerminalId, TerminalType, XConvert.AsDateTZ(TerminalDate, Tz), string.IsNullOrEmpty(Phone)? Account: "", Gateway); if (Settings.LogLevel.IndexOf("DEBUG") != -1) { Log("DoPay: Cc=\"{0}\"", ControlCode); } using (Crypto sign = new Crypto(CommonName)) controlCode = sign.Sign(ControlCode); if (string.IsNullOrEmpty(Phone)) { stRequest = string.Format(payTemplate, XConvert.AsAmount(Amount), Cur, Service, Oid, MakeCheckNumber(), Tid, XConvert.AsDate(Pcdate), Outtid, Asvps, MtsTerminalId, TerminalType, Opcode, XConvert.AsDateTZ(TerminalDate, Tz), ControlCode, Contract, Account, Gateway); } else { stRequest = string.Format(payTemplate, Phone, XConvert.AsAmount(Amount), Cur, Service, Oid, MakeCheckNumber(), Tid, XConvert.AsDate(Pcdate), Outtid, Asvps, MtsTerminalId, TerminalType, Opcode, XConvert.AsDateTZ(TerminalDate, Tz), ControlCode, Contract, Gateway); } break; case 3: using (StreamReader status = new StreamReader(Settings.Templates + "0104085-" + ProvidersSettings.Mts.Ott + "-" + ProvidersSettings.Mts.Xsd + ".tpl")) { statusTemplate = status.ReadToEnd(); } stRequest = string.Format(statusTemplate, TimeOut(), Outtid, Asvps, Contract); break; } if (CheckXML(stRequest) != 0) { RootLog("Mts.MakeRequest {0}", ErrDesc); state = (byte)old_state; errCode = 11; } return(state == 12 ? 1 : 0); }
public void Run() { int Status = 0; int ErrCode = 0; string ErrDesc = ""; int State = 0; int CheckId = 0; // Tid в ГОРОДе string SubInnerTid = ""; // Номер транзакции (чека) Log("Производится сканирование БД с {0}", XConvert.AsDate(FromDate)); Console.WriteLine("Производится сканирование БД с {0}", XConvert.AsDate(FromDate)); /* * string RequestString = * @"select p.tid, d.ClientAccount, p.Card_number, p.Amount, p.Summary_Amount * FROM [Gorod].[dbo].[payment] p * inner join [Gorod].[dbo].[PD4] d on p.tid = d.tid * where p.datepay >= {0} and p.[state] = 12 and p.[result_text] = '[BLACK] Отменён вручную' * order by p.datepay;"; */ string RequestString = @"select p.DatePay, p.tid, p.template_tid, p.agent_oid, p.point_oid, d.ClientAccount, p.Card_number, p.Amount, p.Summary_Amount, p.User_id FROM [Gorod].[dbo].[payment] p (NOLOCK) inner join [Gorod].[dbo].[PD4] d (NOLOCK) on p.tid = d.tid where p.datepay >= {0} and p.[state] = 12 and p.[result_text] = '[BLACK] Отменён вручную' and not sub_inner_tid like 'card-%' and charindex('-', sub_inner_tid) > 0 order by p.datepay;" ; string PIN = ""; string Nick = ""; string Password = ""; string GetNickAndPasswordRequest = "SELECT [login],[password] FROM [Gorod].[dbo].[user] where user_id = {0}"; Log("Database: {0}", Properties.Settings.Default.GorodConnectionString); using (Gorod db = new Gorod(Properties.Settings.Default.GorodConnectionString)) { IEnumerable <Payment> Payments = db.ExecuteQuery <Payment>(RequestString, FromDate); foreach (Payment Row in Payments) { // string PIN = GetPIN(Row); // Console.Write("tid={0} card={1}", Row.Tid, Row.CardNumber); if (Row.Card_number > 0) { PIN = db.GetCardPIN(Row.Card_number, 1).First <PinResult>().PIN; } // Имя пользователя и пароль IEnumerable <User> Users = db.ExecuteQuery <User>(GetNickAndPasswordRequest, Row.User_id); User item = Users.First(); Nick = item.Login; Password = item.Password; Console.WriteLine("Tid={0} {1,12:f2} {2,12:f2} Account={3,20} AgentCard={4,7} PIN={5} Point={6,4} Agent={7,4} User={8} Nick={9} Password={10}", Row.Tid, Row.Summary_amount, Row.Amount, Row.ClientAccount, Row.Card_number, PIN, Row.Point_oid, Row.Agent_oid, Row.User_id, Nick, Password); Log("Tid={0} {1,12:f2} {2,12:f2} Account={3,20} AgentCard={4,7} PIN={5} Point={6,4} Agent={7,4} User={8} Nick={9} Password={10}", Row.Tid, Row.Summary_amount, Row.Amount, Row.ClientAccount, Row.Card_number, PIN, Row.Point_oid, Row.Agent_oid, Row.User_id, Nick, Password); string QueryString = string.Format("Agent_ID={0}&Point_ID={1}&Nick={2}&Password={3}&template_tid=193&ls=900080&SUMMARY_AMOUNT={4}&tid={5}", Row.Agent_oid, Row.Point_oid, Nick, Password, Row.Summary_amount.AsCurrency(), Outtid); string Response = Get(Properties.Settings.Default.SimpleHost, Properties.Settings.Default.Endpoint, QueryString); // Нет связи с платёжным сервисом if (string.IsNullOrEmpty(Response)) { break; } // Проверка статус и errCode StringBuilder sb = new StringBuilder(); Status = GetInt(Response, "/request/result/Status"); ErrCode = GetInt(Response, "/request/result/errCode"); sb.AppendFormat("Status={0} errCode={1}", Status, ErrCode); ErrDesc = GetString(Response, "/request/result/errDesc"); if (ErrCode != 0) { sb.AppendFormat(" errDesc={0}", ErrDesc); } if (Status == 0) { State = GetInt(Response, "/request/result/state"); CheckId = GetInt(Response, "/request/result/out_tid"); SubInnerTid = GetString(Response, "/request/result/tid"); sb.AppendFormat(" state={0} checkid={1} subinnertid={2}", State, CheckId, SubInnerTid); } Console.WriteLine(sb.ToString()); Log("{0}", sb.ToString()); // Если создан новый платёж (chrckid > 0) установить статус 10 для исходного платежа if (CheckId > 0) { db.SetStatePayment(Row.Tid, 10, 0, string.Format("Платёж перепроведён. Новый платёж {0}", CheckId)); // Вписать новый result_text в новый tid string ResultText = string.Format("Платёж перепроведён: Tid={0} Acc={1} Pnt={2} Agn={3} SA={4} S={5} Tpl={6}", Row.Tid, Row.ClientAccount, Row.Point_oid, Row.Agent_oid, Row.Summary_amount, Row.Amount, Row.Template_tid); db.ExecuteCommand(@"update [gorod].[dbo].[payment_history] set result_text = {1} where tid = {0} and old_state is null and new_state = 0 and try_state = 0" , CheckId, ResultText); Utility.Log(Properties.Settings.Default.RedoLogFile, "DATE={7} Tid={0} SUM={1,12:f2} AMN={2,12:f2} ACC={3,20} CRD={4,7} PNT={5,4} AGN={6,4}", Row.Tid, Row.Summary_amount, Row.Amount, Row.ClientAccount, Row.Card_number, Row.Point_oid, Row.Agent_oid, XConvert.AsDate(Row.DatePay).Replace('T', ' ')); } break; // Только одна итерация! } } }
/// <summary> /// Создание файла реестра, запись информации о реестре в таблицу RQueue /// </summary> /// <returns>0 - ОК</returns> public int MakeRegister() { FileStream fs = null; bool compressed = false; string stBase64; Log("Создаётся реестр платежей с {0} по {1}", XConvert.AsDate(Datefrom), XConvert.AsDate(Dateto)); Console.WriteLine("Создаётся реестр платежей с {0} по {1}", XConvert.AsDate(Datefrom), XConvert.AsDate(Dateto)); // Загрузим записи LoadRecors(); // Сделаем реестр MakeTemplate(); // Проверим шаблон // CheckXML(template); if (ErrCode == 400) { Log("Реестр: err={0} {1}", ErrCode, ErrDesc); Console.WriteLine("Реестр: err={0} {1}", ErrCode, ErrDesc); return(1); } byte[] buf = new UTF8Encoding(true).GetBytes(template); int len = buf.Length; // Запишем реестр в файл try { Console.WriteLine("Создаётся файл {0}", Makername("asc")); using (fs = new FileStream(Makername("asc"), FileMode.Create, FileAccess.Write, FileShare.None)) { fs.Write(buf, 0, len); // Если реестр блольше 1 Мб сожмем его if (len >= 1024 * 1024) { compressed = true; using (FileStream dflfs = new FileStream(Makername("pak"), FileMode.Create, FileAccess.ReadWrite, FileShare.None)) { using (DeflateStream dfl = new DeflateStream(dflfs, CompressionMode.Compress, true)) { dfl.Write(buf, 0, len); dfl.Flush(); dfl.Close(); } dflfs.Flush(); dflfs.Seek(0L, SeekOrigin.Begin); len = dflfs.Read(buf, 0, buf.Length); } } } Console.WriteLine("Создаётся base64 файл {0}", Makername("b64")); stBase64 = Convert.ToBase64String(buf, 0, len); // buf = new UTF8Encoding(true).GetBytes(stBase64); buf = new ASCIIEncoding().GetBytes(stBase64); len = buf.Length; using (fs = new FileStream(Makername("b64"), FileMode.Create, FileAccess.Write, FileShare.None)) { // Записываетя Base64 fs.Write(buf, 0, len); } // Готов для обработки - Nexttime установлен в текущую дату if (compressed) { UpdateRState(rid, Compress: compressed, Nexttime: DateTime.Now); } else { UpdateRState(rid, Nexttime: DateTime.Now); } } catch (Exception ex) { Log("{0}\r\n{1}", ex.Message, ex.StackTrace); Console.WriteLine("{0}\r\n{1}", ex.Message, ex.StackTrace); } return(0); }
/// <summary> /// Создание запроса. Скрывает базовый код. /// </summary> /// <param name="state"></param> /// <returns></returns> public override int MakeRequest(int state) { string acnt = !string.IsNullOrEmpty(Account) ? Account : !string.IsNullOrEmpty(Card) ? Card : Phone; if (State == 0) { if (string.IsNullOrEmpty(acnt) || string.IsNullOrEmpty(pointid) || string.IsNullOrEmpty(Gateway)) { state = 0; errCode = 2; errDesc = string.Format(Messages.Err_NoDefaults, state); RootLog($"Account=\"{Account}\"\r\nPhone=\"{Phone}\"\r\nCard=\"{Card}\"\r\nPointid=\"{pointid}\"\r\nGateway=\"{Gateway}\""); RootLog(ErrDesc); return(1); } if (Amount == decimal.MinusOne) { state = 0; errCode = 2; errDesc = Messages.Err_NoAmount; RootLog($"Pointid=\"{pointid}\"\r\nGateway=\"{Gateway}\""); RootLog(Messages.Err_NoAmount); return(1); } } if (Pcdate == DateTime.MinValue) { pcdate = DateTime.Now; } int lTz = Tz != -1? Tz: Settings.Tz; string sDate = XConvert.AsDate(pcdate) + string.Format("+{0:D2}00", lTz); string sAmount = Math.Round(Amount * 100).ToString(); string sAmountAll = Math.Round(AmountAll * 100).ToString(); string check = MakeCheckNumber(); string sAttributes = ""; stRequest = Properties.Resources.Template_XmlHeader + "\r\n"; if (state == 0) // Payment { /* * <request point="{0}"> * <payment account="{1}" service="{2}" sum="{3}" sum-in="{4}" id="{5}" check="{6}" date="{7}"> * <attribute name="id2" value="{8}" /> * </payment> * </request> */ if (!string.IsNullOrEmpty(Account) && !string.IsNullOrEmpty(Number)) // Атрибуты: id1 = account, id2 = number { if (Attributes == null) { attributes = new AttributesCollection(); } attributes.Add("id2", Number); } else if (!string.IsNullOrEmpty(Account) && !string.IsNullOrEmpty(Phone)) // Id1 и phone { if (Attributes == null) { attributes = new AttributesCollection(); } attributes.Add("phone", Phone); } foreach (string name in Attributes.Keys) { sAttributes += $@"<attribute name=""{name}"" value=""{Attributes[name]}"" />"; } stRequest += $@"<request point=""{pointid}"">"; stRequest += $@"<payment id=""{Tid}"" sum=""{sAmount}"" sum-in=""{sAmountAll}"" check=""{check}"" service=""{Gateway}"" account=""{acnt}"" date=""{sDate}"""; if (Terminal != int.MinValue) { stRequest += $@" terminal-vps-id=""{Terminal}"""; } stRequest += ">"; if (!string.IsNullOrEmpty(sAttributes)) { stRequest += $"{sAttributes}"; } stRequest += "</payment></request>"; /* * if (Gateway == "1668") * stRequest += string.Format(Properties.Resources.Template_Payment_1668, pointid, Card, Gateway, sAmount, sAmountAll, Tid, MakeCheckNumber(), sDate, Phone); * // Единый кошелёк * else if (Gateway == "458") * { * if (Account.Length > 10 || (Account.Length == 10 && Account.Substring(0) != "9")) // Лицевой счёт * stRequest += string.Format(Properties.Resources.Template_Id1, pointid, Account, Gateway, sAmount, sAmountAll, Tid, MakeCheckNumber(), sDate); * else // Номер телефона * stRequest += string.Format(Properties.Resources.Template_Id1, pointid, Gateway, sAmount, sAmountAll, Tid, MakeCheckNumber(), sDate, Account); * } * else if (!string.IsNullOrEmpty(Account) && !string.IsNullOrEmpty(Number)) // Атрибуты: id1 = account, id2 = number * stRequest += string.Format(Properties.Resources.Template_Payment_Id1Id2, pointid, Gateway, sAmount, sAmountAll, Tid, MakeCheckNumber(), sDate, Account, Number); * else * if (!string.IsNullOrEmpty(Account) && !string.IsNullOrEmpty(Phone)) // Id1 и phone * stRequest += string.Format(Properties.Resources.Template_Payment_Id1Phone, pointid, Gateway, sAmount, sAmountAll, Tid, MakeCheckNumber(), sDate, Account, Phone); * else if (string.IsNullOrEmpty(Account) && string.IsNullOrEmpty(Phone) && Attributes?.Count > 0) // Есть дополнительные атрибуты * { * StringBuilder sb = new StringBuilder(); * sb.Append($"<request point=\"{pointid}\">\r\n"); * sb.AppendFormat("\t<payment account=\"{0}\" service=\"{1}\" sum=\"{2}\" sum-in=\"{3}\" id=\"{4}\" check=\"{5}\" date={6}>\r\n", * string.IsNullOrEmpty(Phone) ? Account : Phone, // Номер телефона или счёта * Gateway, // Номер шлюза ЕКТ * sAmount, // amount * sAmountAll, // summary_amount * Tid.ToString(), * MakeCheckNumber(), // Номер чека * sDate // Время платежа * ); * // Добавляется коллекция атрибутов * foreach (string name in Attributes.Keys) * sb.Append($"\t\t<attribute name=\"{name}\" value=\"{Attributes[name]}\" />\r\n"); * sb.Append("\t/<payment>\r\n"); * sb.Append("/<request>"); * stRequest += sb.ToString(); * } * else * { * StringBuilder sb = new StringBuilder(); * // Добавляется коллекция атрибутов * foreach (string name in Attributes.Keys) * sb.Append($"\t\t<attribute name=\"{name}\" value=\"{Attributes[name]}\" />\r\n"); * stRequest += string.Format(Properties.Resources.Template_Payment, pointid, * string.IsNullOrEmpty(Phone) ? Account : Phone, Gateway, // Номер сервиса ЕКТ, * sAmount, * AmountAll == -1? sAmount: sAmountAll, * Tid, * MakeCheckNumber(), * sDate, * sb.ToString()); * } */ } else if (state == 3) // Status { stRequest += string.Format(Properties.Resources.Template_Status, pointid, Tid); } else { errDesc = string.Format(Messages.Err_UnknownState, state); state = 0; errCode = 2; RootLog(ErrDesc); return(1); } // ReportRequest(); return(0); }
/// <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="state"></param> /// <returns></returns> public override int MakeRequest(int state) { string acnt = !string.IsNullOrEmpty(Account) ? Account : !string.IsNullOrEmpty(Card) ? Card : Phone; if (State == 0) { if (string.IsNullOrEmpty(acnt) || string.IsNullOrEmpty(pointid) || string.IsNullOrEmpty(Gateway)) { state = 0; errCode = 2; errDesc = string.Format(ServerGateMessages.Err_NoDefaults, state); RootLog($"Account=\"{Account}\"\r\nPhone=\"{Phone}\"\r\nCard=\"{Card}\"\r\nPointid=\"{pointid}\"\r\nGateway=\"{Gateway}\""); RootLog(ErrDesc); return(1); } if (Amount == decimal.MinusOne) { state = 0; errCode = 2; errDesc = ServerGateMessages.Err_NoAmount; RootLog($"Pointid=\"{pointid}\"\r\nGateway=\"{Gateway}\""); RootLog(ServerGateMessages.Err_NoAmount); return(1); } } if (Pcdate == DateTime.MinValue) { pcdate = DateTime.Now; } int lTz = Tz != -1 ? Tz : Settings.Tz; string sDate = XConvert.AsDate(pcdate) + string.Format("+{0:D2}00", lTz); string sAmount = Math.Round(Amount * 100).ToString(); string sAmountAll = Math.Round(AmountAll * 100).ToString(); string check = MakeCheckNumber(); string sAttributes = ""; stRequest = @"<?xml version=""1.0"" encoding=""utf-8""?>"; if (state == 0) // Payment { if (!string.IsNullOrEmpty(Account) && !string.IsNullOrEmpty(Number)) // Атрибуты: id1 = account, id2 = number { if (Attributes == null) { attributes = new AttributesCollection(); } attributes.Add("id2", Number); } else if (!string.IsNullOrEmpty(Account) && !string.IsNullOrEmpty(Phone)) // Id1 и phone { if (Attributes == null) { attributes = new AttributesCollection(); } attributes.Add("phone", Phone); } foreach (string name in Attributes.Keys) { sAttributes += $@"<attribute name=""{name}"" value=""{Attributes[name]}"" />"; } stRequest += $@"<request point=""{pointid}"">"; stRequest += $@"<payment id=""{Tid}"" sum=""{sAmount}"" check=""{check}"" service=""{Gateway}"" account=""{acnt}"" date=""{sDate}"">"; if (!string.IsNullOrEmpty(sAttributes)) { stRequest += $"{sAttributes}"; } stRequest += "</payment></request>"; } else if (state == 3) // Status { stRequest += $"<request point=\"{pointid}\"><status id=\"{Tid}\" /></request>"; } else { errDesc = string.Format(ServerGateMessages.Err_UnknownState, state); state = 0; errCode = 2; RootLog(ErrDesc); return(1); } // ReportRequest(); return(0); }